manigandham/serilog-sinks-googlecloudlogging

Bug: Service not starting when using Topshelf

cufeo opened this issue · 2 comments

cufeo commented

Hey! Thank you for your awesome library! I have this issue when using Serilog with Topshelf, the console application works as expected but when trying to start it as a service. It gives this error:

Error 1053: The service did not respond to the start or control request in a timely fashion

To Reproduce

Environment

  • .NET 5.0
  • Topshelf 4.3.0
  • Serilog 2.10.0
  • Serilog.Sinks.Console 4.0.0
  • Serilog.Sinks.GoogleCloudLogging 3.5.0
  • Topshelf.Serilog 4.3.0

Dummy Console App

using Serilog;
using Serilog.Sinks.GoogleCloudLogging;
using System;
using System.Timers;
using Topshelf;

namespace App
{
    public class TownCrier
    {
        readonly Timer _timer;
        public TownCrier()
        {
            _timer = new Timer(2000) { AutoReset = true };
            _timer.Elapsed += (sender, eventArgs) => Log.Information("All is well!");
        }
        public void Start() { _timer.Start(); }
        public void Stop() { _timer.Stop(); }
    }

    public class Program
    {
        public static void Main()
        {

            Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "gckey.json");
            var config = new GoogleCloudLoggingSinkOptions { ProjectId = "dummy-project", UseJsonOutput = true, ServiceName = "demolog", LogName = "demolog" };
            // Logging
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.Console()
                .WriteTo.GoogleCloudLogging(config)
                .CreateLogger();

            var rc = HostFactory.Run(x =>                                   //1
            {
                x.UseSerilog();
                x.Service<TownCrier>(s =>                                   //2
                {
                    s.ConstructUsing(name => new TownCrier());                //3
                    s.WhenStarted(tc => tc.Start());                         //4
                    s.WhenStopped(tc => tc.Stop());                          //5
                });
                x.RunAsLocalSystem();                                       //6

                x.SetDescription("Sample Topshelf Host");                   //7
                x.SetDisplayName("Stuff");                                  //8
                x.SetServiceName("Stuff");                                  //9
            });                                                             //10

            var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode());  //11
            Environment.ExitCode = exitCode;
        }
    }
}

Build and run the service

  • In a new .bat file add:
cd /d C:\PathToProject\Bin\Debug\net5.0
ProjectName.exe install
ProjectName.exe start
pause
  • Then run it as an admin
cufeo commented

Solved by adding:

public static void Main()
{
   string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
   Directory.SetCurrentDirectory(path);
   ...
}

hey @cufeo

Glad you got it figured out. I"m assuming the issue was with the Google Cloud JSON credentials file? Instead of setting the current directory, you can set the full path to the JSON as the environment variable (instead of just the name). More info about how the authentication works in the official Google Cloud .NET repo here:
https://github.com/googleapis/google-cloud-dotnet#authentication