Search code examples
c#windows-servicesevent-logerror-logging.net-9.0

LoggerMessage and Event Log IDs


Using .NET 9, I have created a Windows Service following Microsoft tutorial. As per this tutorial, my code looks like:

public sealed class WindowsBackgroundService (
        MyService _myService,
        ILogger<WindowsBackgroundService> _logger) 
    : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        try
        {
            await _my.OnStart(stoppingToken);
            while (!stoppingToken.IsCancellationRequested)
                await _my.DoWorkAsync(stoppingToken).ConfigureAwait(false);
        }

etc. I register the service using sc.exe create from an elevated command prompt, which seems to correctly create the Event Source for my application, so that the Event Log recognizes where log messages come from.

In appsettings.json I have the following configuration:

"Logging": {
    "LogLevel": {
        "Default": "Information",
        "Microsoft.Hosting.Lifetime": "Information"
    },
    "EventLog": {
        "SourceName": "My Service Name",
        "LogName": "Application",
        "LogLevel": {
            "Default": "Warning",
            "Microsoft": "Information",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    }
},

Now, if I put _logger.LogWarning("foo"); in my code, then Event Viewer shows me the message foo with Event ID 0. No problem.

However, if I use the recommended LoggerMessage framework, e.g. :

internal static partial class LogMessage
{
    [LoggerMessage(Level = LogLevel.Warning, Message = "Bar")]
    public static partial void Bar(ILogger logger);

with invocation:

    LogMessage.Bar(_logger);

then the message bar shows up in Event Viewer but with some seemingly random 5-digit Event ID, along with a bunch of preamble warning text The description for Event ID 40829 from source My Service Name cannot be found. and so on.

Where is LoggerMessage getting these IDs, and is it possible to either:

  • register those IDs with the Event Log somehow, so that the warning text doesn't show up, or
  • make LoggerMessage send all messages with ID 0 when talking to the Event Log.

Solution

  • Default value for EventId in LoggerMessageAttribute is -1:

    public int EventId { get; set; } = -1;
    

    Which seems to be handled by the framework correspondingly. Try setting the EventId explicitly:

    internal static partial class LogMessage
    {
        [LoggerMessage(EventId = 0, Level = LogLevel.Warning, Message = "Bar")]
        public static partial void Bar(ILogger logger);
        // ...
    }