Util应用框架基础(六) - 日志记录(四) - 写入 Exceptionless
本文是Util应用框架日志记录的第四篇,介绍安装和写入 Exceptionless 日志系统的配置方法.
Exceptionless 是一个日志管理系统,使用 Asp.Net Core 开发,比 Seq 的模糊搜索能力弱,使用它可能需要一些技巧.
Util应用框架目前主要使用 Seq 和 Exceptionless 管理日志.
你可以从中选择一个合适的.
本节介绍使用 Docker 简单安装 Exceptionless,用于开发测试,部署到生产环境请参考官方文档.
安装 Exceptionless
创建 exceptionless-data 卷, 运行命令.
docker volume create exceptionless-data
创建 Exceptionless 容器, 运行命令.
docker run --name exceptionless -d --restart=always -v exceptionless-data:/usr/share/elasticsearch/data -p 5480:80 exceptionless/exceptionless:8.0.0-elasticsearch7
容器名称: exceptionless
连接端口: 5480
安装成功后,Docker容器列表出现 exceptionless 容器.

运行 Exceptionless
打开 http://localhost:5480 ,可以看到 Exceptionless 管理界面.
Exceptionless 启动需要一些时间,请稍后刷新页面.
如果 Exceptionless 持续无法启动,请删除 exceptionless-data 卷,并重新安装.

创建 Exceptionless 用户
点击 Signup 按钮进入注册页面.

使用下面的信息注册,或按你自己的喜好设置.
名称: admin
邮箱: admin@a.com
密码: admin123
点击创建我的帐户按钮,进入管理界面.
创建 Exceptionless 项目
填写组织名称,范例: Util
填写项目名称,范例: Demo
点击创建项目按钮.
选择顶部菜单的所有项目 ,点击Demo项目设置按钮.

在 Demo 项目设置界面,选择 API密钥 选项卡.

项目开发时,配置以下信息将日志写入 Exceptionless.
API密钥: 复制你的API密钥,如上图所示.
Exceptionless服务地址: http://localhost:5480
日志配置
引用Nuget包
Nuget包名: Util.Logging.Serilog.Exceptionless
AddExceptionless
使用 AddExceptionless 扩展方法启用 Exceptionless 日志操作.
默认不带参数,你可以在配置文件中指定 Exceptionless 的配置信息.
var builder = WebApplication.CreateBuilder( args );
builder.AsBuild().AddExceptionless();
如果要清除默认设置的日志提供程序,传入 true.
Asp.Net Core 默认日志提供程序会把消息输出到控制台,你可以清除它们.
builder.AsBuild().AddExceptionless( true );
设置应用程序名称.
对于微服务应用,记录产生日志的应用名称,能方便排查问题.
builder.AsBuild().AddExceptionless( "权限服务" );
指定Api密钥和服务地址.
builder.AsBuild().AddExceptionless( t => {
t.ApiKey = "";
t.ServerUrl = "";
} );
指定Api密钥和服务地址并清除默认设置的日志提供程序.
builder.AsBuild().AddExceptionless( t => {
t.ApiKey = "";
t.ServerUrl = "";
}, true );
添加 appsettings 配置节
在 appsettings.json 配置文件添加 Exceptionless 配置节.
{
"Logging": {
"LogLevel": {
"Default": "Trace"
}
},
"Exceptionless": {
"ApiKey": "8JtknZBV1NRC7bdsv6SF5cbBFrMZipWMkARZxkxo",
"ServerUrl": "http://localhost:5480"
}
}
ApiKey 指定 API 密钥.
ServerUrl 指定 Exceptionless 服务地址.
最简化配置仅需设置 API 密钥和 Exceptionless 服务地址.
本教程 Exceptionless 安装示例使用 5480 端口.
API 密钥替换成你自己的.
其它参数请参考 Exceptionless 文档.
查看 Exceptionless
配置完成后,可以启动你的项目,查看 Exceptionless 日志界面.
可以看到由 Asp.Net Core 写入的系统日志.

结构化日志支持
下面的示例比较结构化日志与普通日志的差别.
范例使用 ILog 接口写入日志,你也可以使用 ILogger 替代.
先记录普通日志消息,方便后续比较.
_log.Message( "用户admin已删除" ).LogInformation();

查看扩展属性.

结构化日志语法
{}
{} 用来定义日志属性.
范例:
_log.Message( "用户{User}已删除", "admin" ).LogInformation();
{User} 定义了名为 User 的字符串属性.
查看 Exceptionless 扩展属性界面, 可以看到已经添加了 User 属性.

识别出了 User 属性,就可以使用它进行搜索.
搜索框输入下面的表达式.
data.User:"admin"
User 是一个扩展属性,Exceptionless 要求扩展属性前加上 data.
属性名与属性值使用 : 分隔,表示相等,即 属性名=属性值 .
字符串值可以放进双引号中,比如 "admin"
字符串值也可不带双引号,比如 admin.
但是不能放在单引号中, 比如 'admin' .

Exceptionless 的模糊匹配能力有限,只支持头匹配,类似 like 'xx%' ,不能完全模糊搜索.
Exceptionless 使用 * 进行模糊匹配,只能放在参数值右方, 比如 adm* .
带 * 的参数值不能放在双引号中 .
范例:
以 adm 开头模糊搜索 User 扩展属性.
data.User:adm*
注意: 不要将结构化日志 {} 与 .Net 字符串语法 $"{}" 混淆.
var user = "admin";
_log.Message( $"用户{user}已删除" ).LogInformation();
$"" 中的 {user} 将被 user 变量值 'admin' 替换, 等效于.
_log.Message( "用户admin已删除" ).LogInformation();
它仅是普通日志消息,不是结构化日志.
{@} 用来定义日志属性,并强制序列化对象.
前面的示例使用简单的字符串参数,如果传入对象参数是什么结果?
范例:
定义 User 对象.
namespace Demo; public class User {
public int Id { get; set; }
public string Name { get; set; }
}
现在传入 User 对象.
var user = new User { Id = 1, Name = "a" };
_log.Message( "用户{User}已删除", user ).LogInformation();

{User} 被替换为字符串 "Demo.User" ,这是通过调用 User 对象的 ToString() 方法得到的.
这与我们的预期不符合,我们希望序列化 User 对象,从而获取对象的结构进行搜索.
Serilog 对 {} 参数的处理有一套内置规则,如果传入对象,有些结构能序列化,比如字典 Dictionary<string,int> ,有些则不能.
不应该依赖 Serilog 自动序列化的能力,而是应明确指定是否序列化.
{@} 强制序列化对象,从而保留对象结构,以方便日志系统展示和搜索.
var user = new User { Id = 1, Name = "a" };
_log.Message( "用户{@User}已删除", user ).LogInformation();

遗憾的是, Exceptionless 无法搜索对象属性.
虽然 Exceptionless 对扩展属性的搜索支持有限,但它内置了很多搜索语法,可以参考官方文档.
{$} 用来定义日志属性,并强制字符串化.
{$} 让 Serilog 以明确的方式显示对象的字符串表示.
var user = new User { Id = 1, Name = "a" };
_log.Message( "用户{$User}已删除", user ).LogInformation();
{$User} 调用user对象的 ToString() 方法显示为字符串.
Util应用框架基础(六) - 日志记录(四) - 写入 Exceptionless的更多相关文章
- 从零开始编写自己的C#框架(20)——框架异常处理及日志记录
最近很忙,杂事也多,所以开发本框架也是断断续续的,终于在前两天将前面设定的功能都基本完成了,剩下一些小功能遗漏的以后发现再补上.接下来的章节主要都是讲解在本框架的基础上进行开发的小巧. 本框架主要有四 ...
- [编程基础] Python日志记录库logging总结
Python日志记录教程展示了如何使用日志记录模块在Python中进行日志记录. 文章目录 1 介绍 1.1 背景 1.2 Python日志记录模块 1.3 根记录器 2 Python logging ...
- Android WiFi 日志记录(四次握手)
记录一下四次握手的log. PMK: PMK(Pairwise Master Key,成对主密钥 STA和AP得到PMK后,将进行密匙派生以得到PTK.最后,PTK被设置到硬件中, 用于数据的加解密. ...
- Gin 框架 - 使用 logrus 进行日志记录
目录 概述 日志格式 Logrus 使用 推荐阅读 概述 上篇文章分享了 Gin 框架的路由配置,这篇文章分享日志记录. 查了很多资料,Go 的日志记录用的最多的还是 github.com/sirup ...
- 在android中配置 slf4j + log4j 日志记录框架
需求: 在项目开发中,需要记录 操作日志 .起初自己写了个简单的日志记录文本写入到文本的方法,后来随着项目的膨胀,需要考虑更多的操作,开始考虑性能问题. 实现: 考虑使用 slf4j + log4j ...
- slf4j+log4j在Java中实现日志记录
小Alan今天来跟大家聊聊开发中既简单又常用但必不可少的一样东西,那是什么呢?那就是日志记录,日志输出,日志保存. 后面就统一用日志记录四个字来形容啦. 日志记录是项目的开发中必不可少的一个环节,特别 ...
- PHP框架中的日志系统
现在在一家公司做PHP后台开发程序猿(我们组没有前端,做活动时会做前端的东西),刚开始到公司的时候花2个周赶出了一个前端加后台的活动(记得当时做不出来周末加了两天班...),到现在过去4个多月了,可以 ...
- Asp.Net Core 2.0 项目实战(9) 日志记录,基于Nlog或Microsoft.Extensions.Logging的实现及调用实例
本文目录 1. Net下日志记录 2. NLog的使用 2.1 添加nuget引用NLog.Web.AspNetCore 2.2 配置文件设置 2.3 依赖配置及调用 ...
- 如何定制.NET6.0的日志记录
在本章中,也就是整个系列的第一部分将介绍如何定制日志记录.默认日志记录仅写入控制台或调试窗口,这在大多数情况下都很好,但有时需要写入到文件或数据库,或者,您可能希望扩展日志记录的其他信息.在这些情况下 ...
- 《手把手教你》系列基础篇(八十四)-java+ selenium自动化测试-框架设计基础-TestNG日志-上篇(详解教程)
1.简介 TestNG还为我们提供了测试的记录功能-日志.例如,在运行测试用例期间,用户希望在控制台中记录一些信息.信息可以是任何细节取决于目的.牢记我们正在使用Selenium进行测试,我们需要有助 ...
随机推荐
- 2021-09-27 Core初步实战
中间件Progarm的定义添加Logging public static IHostBuilder CreateHostBuilder(string[] args) => Host.Create ...
- JDBC:使用IDEA配置JDBC
IDEA使用Jar包 操作流程 步骤1:创建lib路径 步骤2:复制jar包 步骤3:必须要做的一步 参考链接 https://blog.csdn.net/upup1006/article/detai ...
- 王道oj/problem21
网址:oj.lgwenda.problem/21 思路:先序遍历,中序遍历,后序遍历用递归实现:层序遍历用一个链队实现,出队一个元素,顺序入队他的左孩子和右孩子 代码: #define _CRT_SE ...
- 一文理解GIT的代码冲突
对于GIT,不知道有没有人和我一样,很长时间都是小心翼翼.紧张兮兮,生怕一不小心,自己辛苦写的代码没了. 特别是代码冲突,更是难到我无法理解,每次都要求助于百度,跟着人家的教程一步步解决,下一次还是这 ...
- 渗透小tis
知己知彼,百战不殆 1.如果提示缺少参数,如{msg:params error},可尝使用字典模糊测试构造参数,进一步攻击. 2.程序溢出,int最大值为2147483647,可尝试使用该值进行整数溢 ...
- 百亿补贴通用H5导航栏方案
背景 在移动端页面中,由于屏幕空间有限,导航条扮演着非常重要的角色,提供了快速导航到不同页面或功能的方式.用户也通常会在导航条中寻找他们感兴趣的内容,因此导航条的曝光率较高.在这样的背景下,提供一个动 ...
- 4.go语言复合类型简述
目录 1. 本章前瞻 2.来自leetcode的例题 描述 分析 题解 3. 复合类型新版本的变化 3.1 string和[]byte的高效转化 3.2 内置函数clear 4. 复合类型概述 4.1 ...
- 文心一言 VS 讯飞星火 VS chatgpt (87)-- 算法导论8.2 4题
四.用go语言,设计一个算法,它能够对于任何给定的介于0到 k 之间的 n 个整数先进行预处理,然后在 O(1)时间内回答输入的 n个整数中有多少个落在区间[a..b]内.你设计的算法的预处理时间应为 ...
- padans 常用的统计方法
#coding=utf-8import pandas as pdimport numpy as npfile="./IMDB-Movie-Data.csv"data=pd.read ...
- Blazor Server 发起HttpPost请求,但是多参数
一.介绍 今天突然想起之前工作上遇到的一个问题,在做Blazor 开发时后端给的一个接口请求方式是Post ,但是他需要携带多个参数,新建一个公共类又觉得麻烦,我就尝试着怎么在Post请求中携带多个参 ...