簡體   English   中英

使用 Serilog 登錄事件查看器時動態設置 EventID

[英]Dynamically set EventID when logging to Event Viewer using Serilog

目前,我已經將我的記錄器設置為像這樣記錄到事件查看器:

 Log.Logger = new LoggerConfiguration()
               .MinimumLevel.Information()
               .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
               .Enrich.FromLogContext()
               .WriteTo.EventLog("MySource", "EventViewerArea")
               .CreateLogger();

當我登錄時,我使用以下命令:

_logger.LogWarning(logText);

看起來我可以將 EventId 傳遞給 LogWarning 方法,所以我想在運行 LogWarning/LogInformation 方法時設置它:

_logger.LogWarning(9876, logText);

但這不會覆蓋事件查看器條目中的事件 ID。 關於如何在記錄時動態設置此 EventId 的任何想法? 在實例化記錄器時,我需要有這個動態而不是設置為一個值。

提前致謝

我能夠通過以下步驟解決此問題:

在實例化記錄器時添加以下內容:

.WriteTo.EventLog("SourceInEventViewer", 
    "AreaInEventViewer", 
    formatProvider: new EventLogFormatProvider(),
    eventIdProvider: new EventIdProvider(),
    manageEventSource: true,
    restrictedToMinimumLevel: LogEventLevel.Information)

將以下類添加到項目中

using Newtonsoft.Json.Linq;
using Serilog.Events;
using Serilog.Sinks.EventLog;
using System;
using System.Linq;

namespace IndependentFile.Extensions
{
    public class LoggerSetupExtensions
    {
        public class EventLogFormatProvider : IFormatProvider, ICustomFormatter
        {
            public object GetFormat(Type formatType)
            {
                return formatType == typeof(ICustomFormatter) ? this : null;
            }

            public string Format(string format, object arg, IFormatProvider formatProvider)
            {
                return arg.ToString();
            }
        }       

        public class EventIdProvider : IEventIdProvider
        {
            public ushort ComputeEventId(LogEvent logEvent)
            {
                var eventTypeProp = logEvent.Properties.FirstOrDefault(prop => prop.Key == "EventId");

                if (eventTypeProp.Value == null)
                {
                    return (ushort)LogValuesEnum.Unknown;
                }
                try
                {
                    var val = eventTypeProp.Value;
                    string eventType = eventTypeProp.Value.ToString();

                    //this is not the right way to parse the logEventPropertyValue
                    var parseEventType = JObject.Parse(eventType);

                    var eventIdInt = parseEventType["Id"].ToString();

                    if (eventType == null) return (int)LogValuesEnum.Unknown;

                    var tryParseEventId = Enum.TryParse<LogValuesEnum>(eventIdInt, ignoreCase: true, out var res);
                    if (tryParseEventId)
                    {
                        return (ushort)res;
                    }

                    return (ushort)LogValuesEnum.Unknown;
                }
                catch(Exception exc)
                {
                    return (ushort)LogValuesEnum.Unknown;
                }

            }
        }
    }
}

現在您可以使用日志並將您的事件 ID 傳遞給它:

_logger.LogInformation(LogValuesEnum.MyEnumVal, "My log message");

如果您檢查事件日志接收器的源代碼,您會發現它使用EventIdHashProvider通過對事件消息進行哈希處理來生成唯一 ID。

您可以做的是在配置接收器時提供IEventIdProvider接口的實現,如下所示(添加了eventIdProvider: new CustomEventIdProvider() ):

Log.Logger = new LoggerConfiguration()
               .MinimumLevel.Information()
               .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
               .Enrich.FromLogContext()
               .WriteTo.EventLog("MySource", "EventViewerArea", eventIdProvider: new CustomEventIdProvider())
               .CreateLogger();

.LogWarnning()來自Microsoft.Extensions.Logging 它實際上接受從 int 隱式轉換的EventId strcut。
但是正如您所看到的,這個 id 從未在接收器中使用過。 EventId 用於輕松跟蹤事件的身份,但我不確定是否有任何接收器正在重用此 ID ... EventLog接收器沒有。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM