我正在使用NLog并将事件记录到SQL服务器。其中一个记录的字段是日志级别,它记录为字符串,“信息”,“警告”等。我还想将级别记录为整数值,以便在查看日志事件时提供更好的排序。一个GUI。
是否可以将枚举转换为整数以便在不编写自定义布局渲染器的情况下插入数据库?
将级别作为字符串记录到数据库中的配置行是
<parameter name="@Level" layout="${level}"/>
理想情况下,可能会转换为整数,例如;
<parameter name="@LevelId" layout="${level:format=tointeger}"/>
就像有format=tostring
转换器一样。
答案 0 :(得分:3)
另一种选择是将字符串转换为insert语句中的Integer,如下所示:
<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>
答案 1 :(得分:1)
这是我为此目的而编写的自定义LayoutRenderer。我是用NLog 1.0编写的,所以它可能不完全符合LayoutRenderer的NLog 2.0约定(例如我认为不再使用GetEstimatedBufferSize):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NLog;
using NLog.LayoutRenderers;
namespace NLog.Extensions
{
[LayoutRenderer("LogLevelOrdinal")]
class LogLevelOrdinalLayoutRenderer : LayoutRenderer
{
IDictionary<LogLevel, int> ordinals;
public override void Initialize()
{
base.Initialize();
ordinals = GetLogLevels()
.OrderBy(level => level)
.Select((level, index) => new { Level = level, Ordinal = index })
.ToDictionary( x => x.Level, x => x.Ordinal);
}
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
int level = 0;
if (!ordinals.TryGetValue(logEvent.Level, out level)) level = 99;
builder.Append(level);
}
protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
{
return 1;
}
//
// LogLevel is a static class with a static member for each of the different log levels.
// The LogLevel ordinal is not exposed publically (i.e. an ordinal indicating the relative
// "importance" of a LogLevel value).
// The implementation of LogLevel.GetHashCode actually does return the ordinal, but it doesn't
// seem right to rely on that implementation detail.
// In the end, this LayoutRenderer is really just to allow for producing a numeric value to represent
// a particular log level value's "position" relative to the other lob levels. As such,
// We can just get all of the known log level values, order them (they are sortable), and assign our
// own ordinal based on the position of the log level value in the resulting sorted list.
//
// This helper function exposes the known log level values as IEnumerable<LogLevel> so that we can
// easily use LINQ to build a dictionary to map LogLevel to ordinal.
//
internal IEnumerable<LogLevel> GetLogLevels()
{
yield return LogLevel.Trace;
yield return LogLevel.Debug;
yield return LogLevel.Info;
yield return LogLevel.Warn;
yield return LogLevel.Error;
yield return LogLevel.Fatal;
}
}
}
答案 2 :(得分:1)
尝试使用此布局渲染器。这很简单)
public class NlogLevelToIntLayoutRenderer : LayoutRenderer
{
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
builder.Append(logEvent.Level.Ordinal);
}
}