2012-07-06 99 views
2

我正在使用NLog和記錄事件到SQL服務器。其中一個記錄的字段是日誌級別,它被記錄爲一個字符串,'Info','Warn'等。我也想將這個級別記錄爲一個整數值,以便在查看日誌事件時提供更好的排序一個GUI。Nlog枚舉整數

是否有可能將枚舉轉換爲整數以插入數據庫而無需編寫自定義佈局渲染器?

配置行記錄的電平到一個數據庫作爲字符串是

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

在理想情況下可能存在於整數轉換,等等;

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

非常喜歡有一個format=tostring轉換器。

+0

這幾天簡單地使用EF連接到數據庫和運行查詢,我不知道你爲什麼使用傳統的日誌記錄方式。 – 2012-07-06 08:45:32

+1

因爲這是我推出賽義德的方式。 – 2012-07-06 11:21:37

+0

我也使用log4net爲正常日誌(文件,事件查看器,控制檯 ),但在數據庫日誌的情況下,我發現使用EF更容易,在特殊情況下不需要重新添加處理程序的代碼,並且沒有限制它,通常數據庫日誌是至關重要的,他們需要一些額外的信息。 – 2012-07-06 11:27:24

回答

1

這是我爲此編寫的自定義LayoutRenderer。我寫的反對NLOG 1.0,所以它可能不是完全堅持NLOG 2.0約定LayoutRenderer(例如,我認爲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; 
    } 

    } 
} 
+0

最後,我在持有日誌記錄的表上插入並更新觸發器。根據日誌級別字符串,它會更新LevelOrdinal整數字段。將邏輯掩埋在觸發器中並不理想,但可能的日誌級別足夠靜態以使其可接受。 – 2012-07-11 10:38:00

3

另一種選擇是將字符串轉換爲在一個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> 
+0

最好的選擇,你不能/不想部署額外的程序集 – fra 2015-01-27 08:01:17

1

試試這個佈局渲染器。這是非常簡單的)

public class NlogLevelToIntLayoutRenderer : LayoutRenderer 
{ 
    protected override void Append(StringBuilder builder, LogEventInfo logEvent) 
    { 
     builder.Append(logEvent.Level.Ordinal); 
    } 
}