Worker background service Serilog problem

Cenk 1,036 Reputation points
2023-04-10T18:37:16.9733333+00:00

Hi, I have a worker background service that works as a Windows service on production. The problem is, it does not log errors on file. Here is the appsettings.json:

"Serilog": {
    "Using": [ "Serilog.Sinks.Email", "PurchaseRazerCodesMultipleRequestService", "Serilog.Sinks.File", "Serilog.Sinks.Console", "Serilog.Sinks.MSSqlServer" ],
    "Override": {
      "Microsoft.AspNetCore": "Warning"
    },
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "{Timestamp:HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
        }
      },
      {
        "Name": "File",
        "Args": {
          "path": "Serilogs\\AppLogs.log",
          "restrictedToMinimumLevel": "Error",
          "buffered": false,
          "rollingInterval": "Day",
          "retainedFileCountLimit": 3
        }
      },
...

Here is the program.cs

public class Program
    {
        public static void Main(string[] args)
        {
            Serilog.Debugging.SelfLog.Enable(Console.WriteLine);

            IHost host = Host.CreateDefaultBuilder(args)
                .UseSerilog()
                .UseWindowsService(options =>
                {
                    options.ServiceName = "Razer Bulk Service";
                })
                .ConfigureServices(services =>
                {
                    services.AddHttpClient();
                    services.AddHostedService<Worker>();
                })
                .Build();
            Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(host.Services.GetRequiredService<IConfiguration>()).CreateLogger();

            host.Run();
        }
    }

Actually logging into the file works on development. Does it due to the path? Here is how I created the Windows service on the production server.

sc.exe create "Razer BULK Is Completed Service" binpath="C:\BulkPurchaseIsComplete\BulkPurchaseIsCompleted.exe"

Thank you.

Developer technologies ASP.NET ASP.NET Core
0 comments No comments
{count} votes

Accepted answer
  1. Chen Li - MSFT 1,231 Reputation points
    2023-04-11T06:06:10.12+00:00

    Hi @Cenk,

    Whether the exe file you use to create the Windows service is the original exe file or the published file. I built a simple example, using the exe after publishing to create a Windows service, the path of the output log file is changed. NuGet Packages used: Microsoft.ApplicationInsights.AspNetCore, Microsoft.ApplicationInsights.WorkerService, Microsoft.Extensions.Hosting, Microsoft.Extensions.Hosting.WindowsServices, Serilog.AspNetCore, Serilog.Extensions.Hosting, Serilog.Sinks.Map.

    Worker.cs:

    
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private readonly TelemetryClient _telemetryClient;
    
        public Worker(ILogger<Worker> logger,
          TelemetryClient telemetryClient,
          IConfiguration configuration)
        {
            _logger = logger;
            _telemetryClient = telemetryClient;
        }
    
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                using (_telemetryClient.StartOperation<RequestTelemetry>("Execute Async"))
                {
                    Log.Information("TestLog-Serilog");
                    _logger.LogInformation("TestLog-Logger");
                }
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
    

    Program.cs:

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Information()
        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
        .MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
        .Enrich.FromLogContext()
        .WriteTo.File("./logs/log-.txt", rollingInterval: RollingInterval.Day)
        .CreateBootstrapLogger();
    
    try
    {
        Environment.CurrentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    
        IHost host = Host.CreateDefaultBuilder(args)
            .UseWindowsService(options =>
            {
                options.ServiceName = "Razer Bulk Service";
            })
            .ConfigureAppConfiguration((hostContext, configBuilder) =>
            {
                configBuilder
                    .SetBasePath(Directory.GetCurrentDirectory())
                    .AddJsonFile("appsettings.json")
                    .AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: true)
                    .AddJsonFile($"appsettings.{Environment.MachineName}.json", true, true)
                    .Build();
            })
            .UseSerilog((context, services, configuration) => configuration
                .ReadFrom.Configuration(context.Configuration)
                .ReadFrom.Services(services)
                .Enrich.FromLogContext())
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
                services.AddApplicationInsightsTelemetryWorkerService();
            })
            .Build();
    
    
        await host.RunAsync();
    }
    catch (Exception ex)
    {
        Log.Fatal(ex, "There was a problem starting the service");
    }
    finally
    {
        Log.Information("Service successfully stopped");
    
        Log.CloseAndFlush();
    }
    

    appsetting.json:

    {
      "Logging": {
        "ApplicationInsights": {
          "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning"
          }
        },
        "LogLevel": {
          "Default": "Information",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      "ApplicationInsights": {
        "InstrumentationKey": "the-appinsights-guid"
      },
      "Serilog": {
        "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Debug" ],
        "MinimumLevel": {
          "Default": "Information",
          "Override": {
            "Microsoft": "Warning",
            "System": "Warning"
          }
        },
        "WriteTo": [
          { "Name": "Console" },
          {
            "Name": "File",
            "Args": {
              "path": ".\\logs\\log-.txt",
              "rollingInterval": "Day"
            }
          }
        ],
        "Enrich": [ "FromLogContext" ]
      }
    }
    

    launchSettings.json:

    "environmentVariables": {
      "DOTNET_ENVIRONMENT": "Production"
    }
    

    Then publish it and use the published exe file to create a Windows service:

    sc.exe create "Razer Bulk Service" binpath="Your Project Path\bin\Release\net6.0\publish\2023041101.exe"
    

    When I run the project, the log file is generated in \bin\Debug\net6.0\logs and successfully outputs the log content: User's image

    User's image

    When I run the Windows service:

    sc.exe start "Razer Bulk Service"
    

    The log file is generated in \bin\Release\net6.0\publish\logs and successfully outputs the log content:User's image

    User's image

    You can check it.


    If the answer is helpful, please click "Accept Answer" and upvote it. Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best Regards,

    Chen Li

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.