Файл журнала не создается при вызове UseWindowsService

#c# #serilog #asp.net-core-5.0

Вопрос:

Я следовал инструкциям Serilog, чтобы добавить очень простой файл журнала в свое приложение.

Я могу воспроизвести его, выполнив следующее:

  • Создал новый ASP.NET Core Web Api с помощью Visual Studio с параметрами по умолчанию: .NET 5, без аутентификации, настроен для HTTPS, включает поддержку OpenAPI
  • Установил Serilog.AspNetCore пакет
  • Установил Microsoft.Extensions.Hosting.WindowsServices пакет (чтобы я мог вызвать метод UseWindowsService() расширения)
  • Отредактировал свой Program.cs класс следующим образом:
 public class Program
{
    public static void Main(string[] args)
    {
        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .WriteTo.File("logs.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();

        try
        {
            Log.Information("Starting Web Host");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host terminated unexpectedly");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .UseSerilog()
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
 
  • Удалил раздел ведения журнала из приложения.настройки:
 {
  "AllowedHosts": "*"
}
 

До сих пор, когда я запускаю веб-api из Visual Studio или проводника Windows, все работает отлично: файл logs.txt создается, как ожидалось, и веб-api работает.

Но затем, когда я создаю службу Windows для запуска приложения:

 sc.exe create TestService binPath="pathtoWebApplication1.exe"
 

Несмотря на то, что веб-api работает хорошо, файл журнала не создан.

Вот некоторые из вещей, которые я пробовал:

  • Изменил пользователя, запускающего службу с моей собственной учетной записью => без изменений
  • Удален вызов UseWindowsService() => веб-api не запускается
  • Использовал другого поставщика (NLog) => такое же поведение: файл журнала не создан
  • Переключил вызовы между UseWindowsService() и UseSerilog() => без изменений
  • Вызывается UseWindowsService() и UseSerilog() (в обоих порядках) после ConfigureWebHostDefaults() => без изменений

Что я сделал не так? Может быть, вся run as a windows service эта часть-не лучший способ запустить мой веб-api как службу?

Ответ №1:

Первое правило устранения неполадок Serilog состоит в том, чтобы включить SelfLog и посмотреть, какие сообщения об ошибках выдаются приемником Serilog.


Скорее всего, это проблема с разрешениями (т. Е. у учетной записи нет разрешения на запись в папку, в которую вы пытаетесь выполнить запись).

.WriteTo.File("logs.txt", ...) запись в текущий рабочий каталог, а в случае служб Windows обычно означает %WINDIR%System32 , что я уверен, что это не то место, где вы хотите хранить свои журналы в любом случае.

Таким образом, вам необходимо более четко указать путь, по которому вы хотите записывать свои журналы, и убедиться, что он указывает на папку, к которой учетная запись, используемая для запуска службы, будет иметь доступ для записи.

Общим шаблоном является определение пути в файле конфигурации (например appSettings.json ) и его извлечение.

Если вы хотите записать в ту же папку, где находятся двоичные файлы службы Windows, в настоящее время надежным способом является использование Process.GetCurrentProcess().MainModule?.FileName (1). Например:

 var startupPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName);
var logFilePath = Path.Combine(startupPath, "logs.txt");

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .WriteTo.File(logFilePath, rollingInterval: RollingInterval.Day)
    .CreateLogger();
 

(1) В будущей версии .NET вы сможете использовать Environment.ProcessPath или Environment.ApplicationDirectory

Комментарии:

1. Я думал UseWindowsService() , что изменил корневой каталог ( docs.microsoft.com/en-us/aspnet/core/host-and-deploy/… ) но, похоже, это не так …