在日志条目中打印类名的正确方法

时间:2018-03-06 02:45:43

标签: c# logging serilog

想想我在我的应用程序中找到了相当数量的Serilog。但是,我想"充实"具有classnames等的日志(将来的HTTP方法)。在Autofac中注册了Logger对象的全局实例,并在其他类中调用它,但写入日志文件的行被截断或覆盖。请帮助建议一个正确的打印类名的方法。这是我的代码,

ZLogger.cs (剥离验证,试用/捕获等)

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 (剥离验证,尝试/捕获等)

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和第3行。 4在日志文件中,它们不是有序的。认为logger.GetCurrentClassLogger<T>()是罪魁祸首,因为它在每个类中都是new'd,从而创建了一个新的记录器,这可能会在写入日志文件时导致竞争条件。

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

(很抱歉这篇长篇文章,认为尽可能多地包含详细信息会很有用!)

1 个答案:

答案 0 :(得分:0)

我很傻:D。不得不在logger类的Logger属性之外声明Zlogger.cs为私有字段,问题已解决!!

工作代码:

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:)