nreco / logging

Generic file logger for .NET Core (FileLoggerProvider) with minimal dependencies
MIT License
284 stars 56 forks source link

Logger can't write log outside the function that logger created #27

Closed darknessWONG closed 2 years ago

darknessWONG commented 3 years ago

Hi, Thanks for your logging module, but I have got some issues when using it.

Logger can only work in the function that be created. Here is my code: Program.cs

using Microsoft.Extensions.Logging;
using Backend.Common.Log;

namespace Backend
{
    class Program
    {
        static void Main(string[] args)
        {
            LogUilts.LoggerOutput<Program>(LogLevel.Error, "Log that in Main"); // This doesn't work
        }
    }
}

Backend.Common.Log.LogUtils:

using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;

namespace Backend.Common.Log
{
    class LogUilts
    {
        private static  ILogger logger;

        static LogUilts()
        {
            loggers = new();
        }

        public static void LoggerOutput<T>(LogLevel logLevel, string message)
        {
            string className = typeof(T).Name;
            if(!loggers.ContainsKey(className))
            {
                var tmpLogger = CreateLogger<T>();
                logger .Log(LogLevel.Information, "Log out of function that logger created");  // This doesn't work
                tmpLogger .Log(LogLevel.Information, "Log out of function that logger craeted"); // This doesn't work
            }
        }

        private static ILogger CreateLogger<T>()
        {
            using var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder
                .AddConsole();
            });

            var timeStamp = DateTime.Now.ToString("yyyyMMddHmmss");
            string name = typeof(T).Name;
            loggerFactory.AddProvider(new NReco.Logging.File.FileLoggerProvider($"./logs/{name}_{timeStamp}.log", true)
            {
                FormatLogEntry = (msg) => {
                    var sb = new System.Text.StringBuilder();
                    System.IO.StringWriter sw = new System.IO.StringWriter(sb);
                    var jsonWriter = new Newtonsoft.Json.JsonTextWriter(sw);
                    jsonWriter.WriteStartArray();
                    jsonWriter.WriteValue(DateTime.Now.ToString("o"));
                    jsonWriter.WriteValue(msg.LogLevel.ToString());
                    jsonWriter.WriteValue(msg.LogName);
                    jsonWriter.WriteValue(msg.EventId.Id);
                    jsonWriter.WriteValue(msg.Message);
                    jsonWriter.WriteValue(msg.Exception?.ToString());
                    jsonWriter.WriteEndArray();
                    string result = sb.ToString();
                    return result;
                }
            });

            logger = loggerFactory.CreateLogger<T>();
            logger.Log(LogLevel.Information, "Log in function that logger crated");    // This is work
            return logger;
        }

    }
}

But all of these can output to console. Here is the output in console:

info: Backend.Program[0]
      Log in function that logger crated
info: Backend.Program[0]
      Log out of function that logger created
info: Backend.Program[0]
      Log out of function that logger craeted
fail: Backend.Program[0]
      Log that in Main

And this is the output in file:

["2021-08-25T12:28:16.7199510+09:00","Information","Backend.Program",0,"Log in function that logger crated",null]
Ciel1996 commented 2 years ago

Hi I might be a bit late, but I got into using this library just today and found, that the reason why your logger might not log outside it's creating method is the line:

using var loggerFactory = LoggerFactory.Create(builder =>

in my application I had to get rid of the using, in order to get it to work. I know that this is bad practice and should be avoided as much as possible, but in my case I'm using the logger in a small application to temporarily monitor some network I/O.

But I really don't get why invoking Dispose on the factory should cause the logger to break. It obviously works perfectly when logging to console. To me this looks almost, as if the logger or part of the logger gets disposed as soon as the factory is disposed.

So my code looks similar to this: var loggerFactory = LoggerFactory.Create(builder =>

Please keep in mind, that in this case you should assign LoggerFactory to a variable which will be disposed later.

Hopefully this might help someone who stumbles across this issue in the future. :)

darknessWONG commented 2 years ago

oh, thank you to replay me! I tried the way you suggested, It's works.

Thank you very much!