Enums Nlog枚举到整数

Enums Nlog枚举到整数,enums,nlog,Enums,Nlog,我正在使用NLog并将事件记录到SQL server。记录的字段之一是日志级别,它记录为字符串“Info”、“Warn”等。我还希望将级别记录为整数值,以便在GUI中查看日志事件时提供更好的排序 是否可以将枚举转换为整数以插入数据库,而无需编写自定义布局渲染器 将级别作为字符串记录到数据库中的配置行是 <parameter name="@Level" layout="${level}"/> 理想情况下,可能会转换为整数,如 <parameter name="@LevelI

我正在使用NLog并将事件记录到SQL server。记录的字段之一是日志级别,它记录为字符串“Info”、“Warn”等。我还希望将级别记录为整数值,以便在GUI中查看日志事件时提供更好的排序

是否可以将枚举转换为整数以插入数据库,而无需编写自定义布局渲染器

将级别作为字符串记录到数据库中的配置行是

<parameter name="@Level" layout="${level}"/>

理想情况下,可能会转换为整数,如

<parameter name="@LevelId" layout="${level:format=tointeger}"/>


很像是有一个
format=tostring
转换器。

这里有一个自定义的LayoutRenderer,我就是为了这个目的而写的。我是针对NLog 1.0编写的,因此它可能不会完全遵守针对LayoutRenderer的NLog 2.0约定(例如,我认为GetEstimatedBufferSize不再使用):

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用NLog;
使用NLog.LAYUTRENDERS;
名称空间NLog.Extensions
{
[LayoutRenderer(“LogLevelOrdinal”)]
类LoglevelOrdinallYoutRenderer:LayoutRenderer
{
词典序数;
公共覆盖无效初始化()
{
base.Initialize();
序号=GetLogLevels()
.OrderBy(级别=>level)
.Select((级别,索引)=>new{level=level,Ordinal=index})
.ToDictionary(x=>x.Level,x=>x.Ordinal);
}
受保护的覆盖无效附加(StringBuilder生成器,LogEventInfo logEvent)
{
智力水平=0;
如果(!ordinals.TryGetValue(logEvent.Level,out Level))级别=99;
builder.Append(级别);
}
受保护的覆盖int GetEstimatedBufferSize(LogEventInfo logEvent)
{
返回1;
}
//
//LogLevel是一个静态类,每个不同的日志级别都有一个静态成员。
//LogLevel序号不公开(即,表示相对
//日志级别值的“重要性”)。
//LogLevel.GetHashCode的实现实际上返回序号,但它不返回序号
//依赖于实现细节似乎是正确的。
//最后,这个LayoutRenderer实际上只允许生成一个数值来表示
//特定日志级别值相对于其他lob级别的“位置”。因此,
//我们只需获取所有已知的日志级别值,对它们进行排序(它们是可排序的),然后分配
//根据日志级别值在结果排序列表中的位置拥有序号。
//
//这个helper函数将已知的日志级别值公开为IEnumerable,以便
//轻松使用LINQ构建字典以将日志级别映射到序号。
//
内部IEnumerable GetLogLevels()
{
收益率返回对数水平;
产生返回LogLevel.Debug;
收益率返回LogLevel.Info;
产量返回对数水平。警告;
收益率返回LogLevel.Error;
收益率返回对数水平。致命;
}
}
}

另一个选项是在insert语句中将字符串转换为整数,如下所示:

<target name="database" xsi:type="Database" connectionStringName="MyConnectionStringName" useTransactions="true">
  <commandText>
    <![CDATA[
    INSERT INTO [dbo].LogEvent
      (Time,
       LogLevel,
       Title,
       Message,
       ExceptionDetails)
    VALUES
      (@Time,
       CASE @Level
       WHEN 'Trace' THEN 0
       WHEN 'Debug' THEN 1
       WHEN 'Info' THEN 2
       WHEN 'Warn' THEN 3
       WHEN 'Error' THEN 4
       WHEN 'Fatal' THEN 5
       ELSE NULL
       END,
       @Title,
       @Message,
       @ExceptionDetails)
    ]]>
  </commandText>
  <parameter name="@Time" layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}" />
  <parameter name="@Level" layout="${level}" />
  <parameter name="@Title" layout="${ndc}" />
  <parameter name="@Message" layout="${message}" />
  <parameter name="@ExceptionDetails" layout="${exception:format=tostring}" />
</target>

尝试此布局渲染器。(非常简单)


现在使用EF连接到DB并运行查询很简单,我不知道你为什么使用传统的日志记录方式。因为这正是我使用Saeed的方式。我也使用log4net处理普通日志(文件、eventviewer、控制台),但对于数据库日志,我发现使用EF更容易,在特殊情况下,添加处理程序不需要繁重的代码,也没有限制,通常DB日志非常重要,它们需要一些额外的信息。最后,我在保存日志记录的表上使用了insert和update触发器。它根据日志级别字符串更新LevelOrdinal整数字段。将逻辑隐藏在触发器中并不理想,但可能的日志级别是静态的,足以使其可接受。在不能/不想部署其他程序集的情况下,这是一个很好的选择
<target name="database" xsi:type="Database" connectionStringName="MyConnectionStringName" useTransactions="true">
  <commandText>
    <![CDATA[
    INSERT INTO [dbo].LogEvent
      (Time,
       LogLevel,
       Title,
       Message,
       ExceptionDetails)
    VALUES
      (@Time,
       CASE @Level
       WHEN 'Trace' THEN 0
       WHEN 'Debug' THEN 1
       WHEN 'Info' THEN 2
       WHEN 'Warn' THEN 3
       WHEN 'Error' THEN 4
       WHEN 'Fatal' THEN 5
       ELSE NULL
       END,
       @Title,
       @Message,
       @ExceptionDetails)
    ]]>
  </commandText>
  <parameter name="@Time" layout="${date:format=yyyy-MM-dd HH\:mm\:ss.fff}" />
  <parameter name="@Level" layout="${level}" />
  <parameter name="@Title" layout="${ndc}" />
  <parameter name="@Message" layout="${message}" />
  <parameter name="@ExceptionDetails" layout="${exception:format=tostring}" />
</target>
public class NlogLevelToIntLayoutRenderer : LayoutRenderer
{
    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        builder.Append(logEvent.Level.Ordinal);
    }
}