【问题标题】:Proper way to print class names in log entries在日志条目中打印类名的正确方法
【发布时间】:2018-03-07 00:06:57
【问题描述】:

我想我想出了相当数量的 Serilog 可以在我的应用程序中使用。但是,我想用classnames 等“丰富”日志(将来的HTTP 方法)。在 Autofac 中注册了Logger 对象的全局实例并在其他类中调用它,但写入日志文件的行被截断或覆盖。请帮助提出正确的打印类名的方法。这是我的代码,

ZLogger.cs(剥离验证、try/catch 等)

public class ZLogger
{
    public Serilog.ILogger Logger
    {
        get
        {
            Serilog.ILogger logger = null;
            if (logger == null)
            {
                logger = new LoggerConfiguration()
                .Destructure.ByTransforming<MySqlConnectionInfo>(
                    conn => new {
                        DatabaseName = conn.DatabaseName,
                        Hostname = conn.Hostname,
                        IPAddress = conn.HostIPAddress,
                        Username = conn.Username,
                        Password = "**********"
                    })
                .MinimumLevel.Verbose()
                .WriteTo.Console(
                    outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} | [{SourceContext}] | [{Level:u4}] | {Message:lj}{NewLine}{Exception}",
                    restrictedToMinimumLevel: LogEventLevel.Verbose,
                    theme: SystemConsoleTheme.Colored)
                .WriteTo.File(
                    "../logs/logFile.log",
                    outputTemplate: "{UserInfo} | {Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} | [{SourceContext}] | [{Level:u4}] | {Message:lj}{NewLine}{Exception}",
                .Enrich.FromLogContext()
                .Enrich.With(new UserInfoEnricher())
                .CreateLogger();
            }
            return logger;
        }
    }

    public ILogger GetCurrentClassLogger<T>()
    {
        return Logger.ForContext<T>();
    }
}

ReadConfig.cs(剥离验证、try/catch 等)

public class ReadConfig
{
    public ILogger Logger;

    public ReadConfig(ZLogger logger)
    {
        Logger = logger.GetCurrentClassLogger<ReadConfig>();
    }

    public T GetConfig<T>(string configFileName)
    {
        T config = default(T);

        var rootDir = Directory.GetParent(Environment.CurrentDirectory);
        var configFile = Directory.GetFiles(rootDir.FullName, configFileName);

        Logger.Information("Reading information from - \"{file}\"", configFile);
        var jsonContent = File.ReadAllText(configFile[0], Encoding.UTF8);
        config = JsonConvert.DeserializeObject<T>(jsonContent);
        Logger.Information("Parsed Config: {@config}", config);

        return config;
    }
}

IoCBuilder.cs(Autofac Builder)

public class IoCBuilder : Module
{
    ILogger Logger;

    protected override void Load(ContainerBuilder builder)
    {
        MySqlConnectionInfo mySqlConnection = null;
        var zlogger = new ZLogger();
        Logger = zlogger.GetCurrentClassLogger<IoCBuilder>();
        Logger.Debug("Registering dependancies ...");

        Logger.Debug("Reading Global Config ...");
        var readConfig = new ReadConfig(zlogger);
        var globalConfig = readConfig.GetConfig<GlobalConfig>("globalconfig.json");

        if (globalConfig.Environment == RunEnvironment.Production)
        {
            Logger.Debug("SQL Connection Information for {env}", globalConfig.Environment);
            mySqlConnection = globalConfig.MySqlConnectionInfo.FirstOrDefault(conn => conn.Name == "prod-master");
            Logger.Debug("Selected {@sqlconn}", mySqlConnection);
        }
        else
        {
            mySqlConnection = globalConfig.MySqlConnectionInfo.FirstOrDefault(conn => conn.Name == "dev-master");
            Logger.Debug("Selected {@sqlconn}", mySqlConnection);
        }

        // Registrations
        builder.RegisterInstance(zlogger).As<ZLogger>().SingleInstance();
        builder.RegisterInstance(mySqlConnection).As<MySqlConnectionInfo>();
    }
}

这是日志, 控制台

2018-03-05 21:33:08.331 | [Core.IoCBuilder] | [DBUG] | Registering dependancies ...
2018-03-05 21:33:08.470 | [Core.IoCBuilder] | [DBUG] | Reading Global Config ...
2018-03-05 21:33:10.530 | [Core.Config.ReadConfig] | [INFO] | Reading information from - "globalconfig.json"
2018-03-05 21:33:11.095 | [Core.Config.ReadConfig] | [INFO] | Parsed Config: {"Environment": "Production", "RedisConnectionInfo": [{"Name": "metadata", "Hostname": "localhost", "Port": 6379, "DbNumber": 0, "$type": "RedisConnectionInfo"}, {...}
2018-03-05 21:33:11.109 | [Core.IoCBuilder] | [DBUG] | SQL Connection Information for Production
2018-03-05 21:33:11.113 | [Core.IoCBuilder] | [DBUG] | Selected {"DatabaseName": "***", "Hostname": "***", "IPAddress": "**", "Username": "**", "Password": "**********"}
2018-03-05 21:33:11.168 | [test.Program] | [WARN] | 0 - Hello Serilog
2018-03-05 21:33:11.168 | [test.Program] | [WARN] | 1 - Hello Serilog
2018-03-05 21:33:11.168 | [test.Program] | [WARN] | 2 - Hello Serilog
2018-03-05 21:33:11.168 | [test.Program] | [WARN] | 3 - Hello Serilog
2018-03-05 21:33:11.169 | [test.Program] | [WARN] | 4 - Hello Serilog

日志文件

2018-03-05 21:33:08.331 -05:00 | [Core.IoCBuilder] | [DBUG] | Registering dependancies ...
2018-03-05 21:33:08.470 -05:00 | [Core.IoCBuilder] | [DBUG] | Reading Global Config ...
2018-03-05 21:33:11.109 -05:00 | [Core.IoCBuilder] | [DBUG] | SQL Connection Information for "Production"
2018-03-05 21:33:11.113 -05:00 | [Core.IoCBuilder] | [DBUG] | Selected {"DatabaseName": "***", "Hostname": "***", "IPAddress": "**", "Username": "**", "Password": "**********"}
":"localhost","Port":6379,"DbNumber":0,"$type":"RedisConnectionInfo"},{...}
2018-03-05 21:33:11.168 -05:00 | [test.Program] | [WARN] | 0 - Hello Serilog
2018-03-05 21:33:11.168 -05:00 | [test.Program] | [WARN] | 1 - Hello Serilog
2018-03-05 21:33:11.168 -05:00 | [test.Program] | [WARN] | 2 - Hello Serilog
2018-03-05 21:33:11.168 -05:00 | [test.Program] | [WARN] | 3 - Hello Serilog
2018-03-05 21:33:11.169 -05:00 | [test.Program] | [WARN] | 4 - Hello Serilog

请注意日志文件中的第 3 行和第 4 行,它们不是按顺序排列的。认为logger.GetCurrentClassLogger&lt;T&gt;() 是罪魁祸首,因为这是new'd 在每个类中都出现了,因此创建了一个新的记录器,这可能会在写入日志文件时导致竞争条件。

有谁知道如何正确实现这一点?非常感谢任何帮助!

(抱歉,这篇文章太长了,我认为包含尽可能多的细节会很有用!)

【问题讨论】:

    标签: c# logging serilog


    【解决方案1】:

    这对我来说很愚蠢:D。必须在Zlogger.cs 类中将logger 声明为Logger 属性之外的私有字段,问题就解决了!!

    工作代码:

    public class ZLogger
    {
    
      Serilog.ILogger logger = null; // >>>>>> Had to move this out of Property get method <<<<<
    
      public Serilog.ILogger Logger
      {
          get
          {
    
              if (logger == null)
              {
                  logger = new LoggerConfiguration()
                  .Destructure.ByTransforming<MySqlConnectionInfo>(
                    ....
    

    谢谢@nblumhardt :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-10
      • 2019-06-18
      • 2014-11-17
      • 2017-11-14
      相关资源
      最近更新 更多