java自学教程|www.konglongmei.com

作者: 我爱萨其马虞co
查看: 7|回复: 0

more +社区更新Forums

more +随机图赏Gallery

疯狂Java讲义(第4版) PDF 电子书 百度云 网盘下载疯狂Java讲义(第4版) PDF 电子书 百度云 网盘下载
价值825元 牛客算法通关课程视频教程 第六期 百度云 网盘下载价值825元 牛客算法通关课程视频教程 第六期 百度云 网盘下载
Spring 5核心原理与30个类手写实战 PDF 电子书 百度云 网盘下载Spring 5核心原理与30个类手写实战 PDF 电子书 百度云 网盘下载
Spring 5核心原理与30个类手写实战+Spring Boot编程思想核心篇pdfSpring 5核心原理与30个类手写实战+Spring Boot编程思想核心篇pdf
Spring Boot编程思想核心篇+Spring 5核心原理与30个类手写实战pdfSpring Boot编程思想核心篇+Spring 5核心原理与30个类手写实战pdf
java电子书]微服务架构设计模式 PDF 电子书 百度云 网盘下载java电子书]微服务架构设计模式 PDF 电子书 百度云 网盘下载

[技术知识] NLog日志框架使用探究-2

[技术知识] NLog日志框架使用探究-2

[复制链接]
我爱萨其马虞co | 显示全部楼层 发表于: 7 天前
查看: 7|回复: 0
目录
            
    前言

在一年前,我写过一篇关于NLog入门文章《NLog日志框架使用探究-1》,文章简单的介绍了Nlog的基本使用以及如何使用Log4View2工具配合统一收集日志查看。本篇文章会记录一些NLog常用的用法。
自定义参数

有时候我们需要根据我们的业务特征自定义一些参数。比如有个唯一的Id。这时候我们可以自定义参数,将Id提取出来,而不是放到日志内容中,这样可以方便检索。
EventProperties Layout Renderer文档中,支持自定义EventPropertie动态的渲染到Layout中。
Nlog已经有一些自定义的参数了,如${counter}、${longdate}、${message:format=message}等。
自定义的参数使用格式为${event-properties:item=String:culture=String:format=String}。
官方示例如下,代码中定义了四种Property
  1. ...Logger logger = LogManager.GetCurrentClassLogger();LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, "", "Pass my custom value");theEvent.Properties["MyValue"] = "My custom string";theEvent.Properties["MyDateTimeValue"] = new DateTime(2015, 08, 30, 11, 26, 50);theEvent.Properties["MyDateTimeValueWithCulture"] = new DateTime(2015, 08, 30, 11, 26, 50);theEvent.Properties["MyDateTimeValueWithCultureAndFormat"] = new DateTime(2015, 08, 30, 11, 26, 50);logger.Log(theEvent);...
复制代码
在配置文件中可以通过${event-properties:item=String:culture=String:format=String}获取到
  1. ${event-properties:item=MyValue} -- renders "My custom string"${event-properties:MyDateTimeValue:format=yyyy-M-dd}"; -- renders "2015-8-30"${event-properties:MyDateTimeValueWithCulture:culture=en-US} -- renders "8/30/2015 11:26:50 AM"${event-properties:MyDateTimeValueWithCultureAndFormat:format=yyyy-M-dd HH:mm:ss:culture=en-US} -- renders "2015-8-30 11:26:50"
复制代码
从上可以看出,若我们需要自定义参数,我们需要创建LogEventInfo对象,并通过Log()方法记录LogEventInfo对象。
调用 Info()等方法内部实际也是创建了LogEventInfo对象,最终还是调用Log()方法。
下面我们可以自己的代码测试一下。
修改上面的Json输出的配置,由于Memo参含有中文,因此需要将encode设置为false,防止被编码为Unicode。以下为Nlog相关源码
  1. protected override void RenderInnerAndTransform(LogEventInfo logEvent, StringBuilder builder, int orgLength){    Inner.RenderAppendBuilder(logEvent, builder);    if (JsonEncode && builder.Length > orgLength)    {        if (RequiresJsonEncode(builder, orgLength))        {            var str = builder.ToString(orgLength, builder.Length - orgLength);            builder.Length = orgLength;            Targets.DefaultJsonSerializer.AppendStringEscape(builder, str, EscapeUnicode);        }    }}private bool RequiresJsonEncode(StringBuilder target, int startPos = 0){    for (int i = startPos; i < target.Length; ++i)    {        if (Targets.DefaultJsonSerializer.RequiresJsonEscape(target[i], EscapeUnicode))        {            return true;        }    }    return false;}
复制代码
在上一篇文章中有同学提问,当encode设置为false时,输出的内容不会有双引号。查阅了下一源码,确实如此。具体为什么这样设计不是很理解,有知道的同学可以说明一下。
  1. public class JsonAttribute{    ...    public bool Encode    {        get => LayoutWrapper.JsonEncode;        set => LayoutWrapper.JsonEncode = value;    }    ...}private bool RenderAppendJsonPropertyValue(JsonAttribute attrib, LogEventInfo logEvent, StringBuilder sb, bool beginJsonMessage){    BeginJsonProperty(sb, attrib.Name, beginJsonMessage);    if (attrib.Encode)    {        // ""{0}":{1}"{2}""        sb.Append(&#39;"&#39;);    }    ...    if (attrib.Encode)    {        sb.Append(&#39;"&#39;);    }    return true;}
复制代码
接下来在nlog.Config的target配置中添加以下配置
  1.                            
复制代码
代码对应的Properites
  1. LogEventInfo theEvent = new LogEventInfo(LogLevel.Debug, "", "自定义动态参数");theEvent.Properties["Id"] = Guid.NewGuid();theEvent.Properties["No"] = "1";theEvent.Properties["Memo"] = "备注";logger.Log(theEvent);
复制代码
输出如下图

需要注意若我们自定义参数,使用json格式写入到文件,则代码中的Properties的Key必须和配置文件的${event-properties:item=key}中的key大小写一致。
日志输出方式

文件

当我们日志需要以文件存放时,通常情况需要根据服务名、模块名等区分日志目录,同样可以通过自定义参数输出。
假设我们需要将日志按服务分目录,同时日志文件名含有我们指定的内容前缀,在每一条日志中需要记录一个唯一的编号。日志配置如下
  1. ...                                                   
复制代码
先看下记录下来的日志,圈出来的都是我们自定义生成的值。


  • ${basedir}是程序的运行目录
  • ${logger:shortName=true}是代码中指定的程序名名称,在代码中可以通过NLog.LogManager.GetLogger("test")指定日志名或NLog.LogManager.GetCurrentClassLogger()指向当前类的全名(包括命名空间)。
  • ${shortdate}是短日期格式,Nlog也内置了${date}获取完整的时间,前面我们说过了可以通过${event-properties:item=String:culture=String:format=String}自定义格式,这里也可以通过${date:format=String}自定义日期格式,比如${date:format=yyyyMMdd}输出的就是如20191201的日期格式。
网络传输

上一章我们提到,日志通过网络发送到Log4View2等工具统一汇总。
  1.             ...
复制代码
Nlog支持tcp或udp协议进行网络传输。

  • 通过xsi:type="Network"指定网络传输
  • 通过address="协议://ip:端口"指定协议和地址。
  • 通过layout="${log4jxmlevent:includeCallSite=true:includeNLogData=true}序列化为XML传输,当然我们也可以传输自定义的格式或Json格式。只要在目标端使用对应的格式解析即可。
下面还是通过Xml序列化传输到Log4View2为例。当我们代码中自定义的字段序列化成Xml发送到对端。我们可以在Log4View2界面上的列右键选择Show Column Chooser项选择哪些字段显示,非常方便。

还支持筛选列,方便我们查找。

数据库

一般情况下日志也不需要实时查看,通常都是排查问题的时候需要看,因此有时候我们可以希望先将日志统一汇总后在做日志分析等工作。Nlog支持将数据插入数据库,比如我将日志入库到Oracle数据库中,使用Oracle.ManagedDataAccess。我们可以通过nuget安装库包Install-Package Oracle.ManagedDataAccess
  1.                                                                      
复制代码

  • dbProvider:首先配置dbProvider。
  • keepConnection:表示是否需要保持连接。
  • optimizeBufferReuse:表示是否是否使用连接池。
  • connectionString:入库的语句。
  • connectionString:连接字符串。
  • commandText:sql语句,sql语句支持参数化。
  • :参数,name为参数名,layout为参数值。
在Log4View2可以将数据源指向日志所在的表。选择数据库接收器。

填写相关配置后,选择表。

选择表的时候需要选择一个Key,但并不是所有Key都是可选的。
从Log4View2源码看,Key需要满足是id结尾时类型是数值或时间类型或者列设置了自增。
  1. this.IsKey = ((this.Name.ToLowerInvariant().EndsWith("id") && DbMessageKey.IsValidKeyType(this.Type)) || column.AutoIncrement);public static bool IsValidKeyType(Type type){    return type == typeof(int) || type == typeof(uint) || type == typeof(long) || type == typeof(ulong) || type == typeof(decimal) || type == typeof(DateTime);}
复制代码

这个key是用于时间筛选的。在日志配置中也可以设置获取指定的日志等级,或者,我们可以指定一个列作为时间筛选条件。
看下Log4View2的源码,在DBReceiver初始化的时候会把我们选择的Key传入赋值给_dbMessageKey
  1. public DbReceiver(IReceiverFactory factory, ReceiverConfig recRow) : base(factory, recRow){    ...    this._columns = new DbColumns(dbReceiverConfig.DbColumns);    this._dbMessageKey = this._columns.Key;    ...}
复制代码
在初始化查询sql的时候就会用到该值
  1. private DbCommand CreateReadQuery(){    ...    DbCommand dbCommand = this._database.CreateCommand();    dbCommand.CommandTimeout = this._commandTimeout;    string parameterName = this._database.GetParameterName(0);    string arg = this._dbMessageKey.IsUnique ? ">" : ">=";    string text = this._database.QuoteName(this._dbMessageKey.Name);    string tableName = this._database.QuoteName(this._tableName);    DbParameter dbParameter = dbCommand.CreateParameter();    dbParameter.ParameterName = parameterName;    dbParameter.DbType = this._dbMessageKey.DbType;    dbParameter.Value = this._dbMessageKey.ParameterValue;    dbCommand.Parameters.Add(dbParameter);    string text2 = string.Format("WHERE ({0} {2} {1})", text, parameterName, arg);    ...    return dbCommand;}
复制代码


科学使用

Log4View2工具首次安装使用有30天的试用期,试用期过了一些功能就会被限制。下一章我会讲解如何是使用反编译工具科(po)学(jie)使用Log4View2。
参考文档


微信扫一扫二维码关注订阅号杰哥技术分享
出处:本文地址:https://www.cnblogs.com/Jack-Blog/p/11972400.html
作者:杰哥很忙
本文使用「CC BY 4.0」创作共享协议。欢迎转载,请在明显位置给出出处及链接。

鲁班 Java架构师VIP课程一期共89G视频教程 luban it教程下载:http://www.77cxw.com/download/78
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|网站地图|java自学教程|www.konglongmei.com

GMT+8, 2019-12-10 10:52 , Processed in 0.140777 second(s), 47 queries .

快速回复 返回顶部 返回列表