c# – 使用自定义参数记录log4net数据库

前端之家收集整理的这篇文章主要介绍了c# – 使用自定义参数记录log4net数据库前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用AdoNetAppender进行数据库日志记录.我想要做的是在每个日志语句上记录用户身份.但是,我不想使用标准的log4net%identity参数有两个原因:

> log4net警告它非常慢,因为它必须查找上下文标识.
>在某些服务组件中,标准标识是服务帐户,但我们已经在变量中捕获了用户标识,我想使用它.

我见过一些代码,其中一些人使用log4net.ThreadContext来添加其他属性,但我知道由于线程交错这是“不安全”(并且它也是性能消耗).

我的方法是扩展AdoNetAppenderParameter类:

  1. public class UserAdoNetAppenderParameter : AdoNetAppenderParameter
  2. {
  3.  
  4. public UserAdoNetAppenderParameter()
  5. {
  6. DbType = DbType.String;
  7. PatternLayout layout = new PatternLayout();
  8. Layout2RawLayoutAdapter converter = new Layout2RawLayoutAdapter(layout);
  9. Layout = converter;
  10. ParameterName = "@username";
  11. Size = 255;
  12. }
  13.  
  14.  
  15. public override void Prepare(IDbCommand command)
  16. {
  17. command.Parameters.Add(this);
  18. }
  19.  
  20.  
  21. public override void FormatValue(IDbCommand command,LoggingEvent loggingEvent)
  22. {
  23. string[] data = loggingEvent.RenderedMessage.Split('~');
  24. string username = data[0];
  25. command.Parameters["@username"] = username;
  26. }
  27.  
  28. }

然后以编程方式将其添加到当前的appender,如下所示:

  1. ILog myLog = LogManager.GetLogger("ConnectionService");
  2. IAppender[] appenders = myLog.Logger.Repository.GetAppenders();
  3. AdoNetAppender appender = (AdoNetAppender)appenders[0];
  4.  
  5. appender.AddParameter(new UserAdoNetAppenderParameter());
  6.  
  7. myLog.InfoFormat("{0}~{1}~{2}~{3}",userName,"ClassName","Class Method","Message");

这里的目的是使用消息的标准格式并解析字符串的第一部分,该部分应该始终是用户名.然后,自定义appender参数的FormatValue()方法应仅使用该字符串的那一部分,以便可以将其写入日志数据库中的单独字段.

我的问题是没有日志语句写入数据库.奇怪的是,在调试时,只有在我停止服务时才会触发FormatValue()方法中的断点.

我已经搜索了大量与此有关的东西,但还没有找到任何答案.
有没有人设法做到这一点,或者我是在错误的轨道上.
附:我也试过扩展AdoNetAppender,但它不能让你访问设置参数值.

解决方法

我还需要记录结构化数据,并喜欢使用这样的日志记录界面:
  1. log.Debug( new {
  2. SomeProperty: "some value",OtherProperty: 123
  3. })

所以我也编写了自定义AdoNetAppenderParameter类来完成这项工作:

  1. public class CustomAdoNetAppenderParameter : AdoNetAppenderParameter
  2. {
  3. public override void FormatValue(IDbCommand command,LoggingEvent loggingEvent)
  4. {
  5. // Try to get property value
  6. object propertyValue = null;
  7. var propertyName = ParameterName.Replace("@","");
  8.  
  9. var messageObject = loggingEvent.MessageObject;
  10. if (messageObject != null)
  11. {
  12. var property = messageObject.GetType().GetProperty(propertyName);
  13. if (property != null)
  14. {
  15. propertyValue = property.GetValue(messageObject,null);
  16. }
  17. }
  18.  
  19. // Insert property value (or db null) into parameter
  20. var dataParameter = (IDbDataParameter)command.Parameters[ParameterName];
  21. dataParameter.Value = propertyValue ?? DBNull.Value;
  22. }
  23. }

现在log4net配置可用于记录给定对象的任何属性

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <log4net>
  3. <appender name="MyAdoNetAppender" type="log4net.Appender.AdoNetAppender">
  4. <connectionType value="System.Data.sqlClient.sqlConnection,System.Data,Version=1.0.3300.0,Culture=neutral,PublicKeyToken=b77a5c561934e089" />
  5. <connectionString value="... your connection string ..." />
  6. <commandText value="INSERT INTO mylog ([level],[someProperty]) VALUES (@log_level,@SomeProperty)" />
  7.  
  8. <parameter>
  9. <parameterName value="@log_level" />
  10. <dbType value="String" />
  11. <size value="50" />
  12. <layout type="log4net.Layout.PatternLayout">
  13. <conversionPattern value="%level" />
  14. </layout>
  15. </parameter>
  16.  
  17. <parameter type="yourNamespace.CustomAdoNetAppenderParameter,yourAssemblyName">
  18. <parameterName value="@SomeProperty" />
  19. <dbType value="String" />
  20. <size value="255" />
  21. </parameter>
  22. </appender>
  23.  
  24. <root>
  25. <level value="DEBUG" />
  26. <appender-ref ref="MyAdoNetAppender" />
  27. </root>
  28. </log4net>

猜你在找的C#相关文章