manigandham / serilog-sinks-googlecloudlogging

Serilog sink that writes events to Google Cloud Logging
MIT License
41 stars 25 forks source link

Bug: Service not starting when using Topshelf #52

Closed cufeo closed 3 years ago

cufeo commented 3 years ago

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

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

cufeo commented 3 years ago

Solved by adding:

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

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