Search code examples
c#serilog

How to use one logfile with Serilog in multiple classes


internal static class Program
{
    /// <summary>
    ///  The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        // To customize application configuration such as set high DPI settings or default font,
        // see https://aka.ms/applicationconfiguration.
        ApplicationConfiguration.Initialize();
        Application.Run(new Form1());

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .WriteTo.File("logs/ConverterLog.txt", rollingInterval: RollingInterval.Day)
            .CreateLogger();
        Log.Information("Program Startup");
    }
}

I am trying to implement Serilog into my Windows Forms application but I can't figure out how to log over multiple classes to write into the same file. When I use Log.Information for example in the class SqlRead, it does not get added to logfile which is configured in the class Program.

class SqlRead
{
    public void Password(string sqlConnectionString, List<SqlInformation> sqlInformationList)
    {
        string sqlQuerySelect = "SELECT Login, Password FROM Users Order by Login";
        using var sqlConn = new SqlConnection(sqlConnectionString);
        using var sqlCmdSelect = new SqlCommand(sqlQuerySelect, sqlConn);
        try
        {
            sqlConn.Open();
            using SqlDataReader sqlReader = sqlCmdSelect.ExecuteReader();
            while (sqlReader.Read())
            {
                sqlInformationList.Add(new SqlInformation() { Username = sqlReader[0].ToString(), Password = sqlReader[1].ToString() });
            }
            sqlReader.Close();
            Log.Information("SQL data successfully read");
        }
        catch (SqlException e)
        {
            MessageBox.Show(e.Message);
            Log.Error(e.Message);
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

Solution

  • Your original code (with comments from me):

    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            ApplicationConfiguration.Initialize();
            Application.Run(new Form1()); // <-- This will block until you exit.
    
            // Only then (AFTER the main window closes) the Logger will be 
            // actually configured ...
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.File("logs/ConverterLog.txt", rollingInterval: RollingInterval.Day)
                .CreateLogger();
            // ... and this line will be logged.
            Log.Information("Program Startup");
            // As you see: No other class has even a chance to log anything.
        }
    }
    

    What I think should work:

    internal static class Program
    {
        [STAThread]
        static void Main()
        {
            // Configure Logging _first_.
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.File("logs/ConverterLog.txt", rollingInterval: RollingInterval.Day)
                .CreateLogger();
            
            try
            {
                Log.Information("Program Startup");
    
                ApplicationConfiguration.Initialize();
                Application.Run(new Form1()); // <-- This will block until you exit.
          
                Log.Information("Program Exit");
            }
            finally
            {
                Log.CloseAndFlush();
            }
        }
    }
    

    Remove any CloseAndFlush() calls in all other classes.