Динамически установить EventID при входе в Event Viewer с помощью Serilog - PullRequest
1 голос
/ 24 января 2020

В настоящее время я настроил свой регистратор для входа в программу просмотра событий следующим образом:

 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);

Но это не отменяет идентификатор события в записи в средстве просмотра событий , Любые идеи о том, как я могу динамически установить этот EventId при регистрации? Мне нужно иметь эту динамику c и не устанавливать одно значение при создании экземпляра регистратора.

Заранее спасибо

Ответы [ 2 ]

1 голос
/ 11 февраля 2020

Я смог решить эту проблему, выполнив следующие шаги:

Добавьте следующее при создании экземпляра регистратора:

.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;
                }

            }
        }
    }
}

Теперь вы можете использовать журнал и передать свой идентификатор события этому:

_logger.LogInformation(LogValuesEnum.MyEnumVal, "My log message");
1 голос
/ 24 января 2020

Если вы проверите исходный код приемника журнала событий , вы увидите, что он использует EventIdHashProvider для генерации уникальных идентификаторов, хэшируя сообщение о событии.

Что вы можно сделать так, чтобы обеспечить реализацию интерфейса 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. Фактически он принимает EventId strcut, который имеет неявное приведение от int.
Но, как вы можете видеть, этот идентификатор никогда не используется в приемнике. EventId используется для простого отслеживания идентификатора события, но я не уверен, использует ли какой-либо из приемников этот идентификатор повторно ... приемник EventLog этого не делает.

...