经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » ASP.net » 查看文章
开源高性能结构化日志模块NanoLog
来源:cnblogs  作者:白菜园  时间:2024/6/12 16:21:41  对本文有异议

最近在写数据库程序,需要一个高性能的结构化日志记录组件,简单研究了一下Microsoft.Extensions.Logging和Serilog,还是决定重造一个轮子。

一、使用方法

直接参考以下示例代码:

  1. NanoLogger.Start();
  2. DateTime? nullable = null;
  3. const bool boolValue = true;
  4. const char charValue = 'C';
  5. const int intValue1 = 12345;
  6. const int intValue2 = 0xABCDEF;
  7. const string stringValue = "你好世界";
  8. var point = new Point { X = 123, Y = 456 };
  9. var person = new Person { Name = "Rick", Birthday = new DateTime(1977, 3, 1), Phone = "13861838709" };
  10. var log = new NanoLogger();
  11. log.Trace("Trace message");
  12. log.Trace($"Trace {DateTime.Now}, {intValue1}, 0x{intValue2:X}");
  13. log.Debug($"Debug {DateTime.Now:yyyy-MM-dd hh:mm:ss}, 你好世界!");
  14. log.Info($"Info {point}, {person}, {charValue}");
  15. log.Warn($"这是警告: {boolValue}");
  16. log.Error($"发生异常: {nullable}, Msg={stringValue}");
  17. NanoLogger.Stop();

执行后控制台输出如下图(记录的结构化值会高亮显示):

二、性能测试

以下测试仅用一个日期类型参数: nanoLogger.Info($"Hello World {now}");

Method Mean Error StdDev Ratio Lock Contentions Allocated Alloc Ratio
NanoLog 154.6 ns 0.91 ns 3.48 ns 0.04 - - 0.00
MsLog 3,922.2 ns 49.13 ns 202.60 ns 1.00 0.0004 264 B 1.00
MsLogCodeGen 4,079.3 ns 52.49 ns 218.77 ns 1.04 0.0010 208 B 0.79
  • NanoLog 本组件控制台输出
  • MsLog Microsoft.Extensions.Logging控制台输出
  • MsLogCodeGen 使用[LoggerMessageAttribute]代码生成方式

三、实现原理

  1. +-----Logger Threads-----+ +-----Background Thread----+
  2. | | | |
  3. | logger.Info(xxx) | | ConsoleLogger.Log() |
  4. | | +-----Log Queue---+ | |
  5. | logger.Debug(xxx) | ==> |-Log-|-Log-|-...-| ==> | FileLogger.Log() |
  6. | | +-----------------+ | |
  7. | logger.Warn(xxx) | | OtherLogger.Log() |
  8. | | | |
  9. +------------------------+ +--------------------------+
  • 日志记录时先判断对应的日志级别是否启用,不启用直接忽略。这里使用C# 6的InterpolatedStringHandlerAttribute自定义实现LogMessageBuilder,一方面避免值类型的装箱,另一方面可以记录结构化信息(名称、类型、值、格式化);

  • 启用则将日志消息、对应的属性类型及属性值序列化后写入LogMessage内。这里的序列化非常简单,仅相当于一个内存复制(参考下图)。LogMessage是一个结构体,如果序列化后的数据小于阀值则直接存储在内置的缓冲块内(没有Heap内存分配的问题),否则从ArrayPool内租用一个缓冲块存储超出部分;

  1. +--------------------LogMessage 缓冲块-----------------------+
  2. |-TokenType-|---Value---|-TokenType-|--------Value------|---|
  3. | Literal | 5,"Hello" | Int | "name",12345,"X2" | |
  4. +-----------------------------------------------------------+
  • 序列化后的事件信息(LogEvent)及消息数据(LogMessage)直接加入一个多生产者-单消费者的消息队列,至此前端日志记录过程结束,不阻塞后续代码执行;

  • 后台线程循环从队列取出待处理日志,由配置的ILogger实现处理。例如ConsoleLogger格式化后输出至控制台;FileLogger将数据写入文件存储。

四、日志搜索

结构化日志当然得支持结构化搜索,参考控制台工程NanoLog.File.Viewer使用Roslyn解析字符串表达式编译后过滤日志记录(参考下图):

  • 表达式中e.XXX对应LogEvent的相关属性条件;
  • 表达式中e["xxx"]["yyy"]对应LogMessage结构化记录的值条件。

五、本文小结

最后GitHub地址:https://github.com/enjoycode/NanoLog.git, 作者个人能力实在有限Bug在所难免,如有问题请邮件联系或Github Issue,欢迎感兴趣的小伙伴们加入共同完善,当然更欢迎赞助项目或给作者介绍工作(目前找工作中)。

原文链接:https://www.cnblogs.com/BaiCai/p/18241681

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号