使用时间戳记录.NET Core应用程序的文件和控制台日志

13

我对.NET Core还不熟悉,也没有深入研究过依赖注入。但是我了解其概念并知道它是个好东西,也知道我的应用程序需要它。因为在某些时候可能需要增强或切换日志功能。

我启动了一个控制台应用程序,使用了一个类库(.NET Standard 2.0),应该将一些东西记录到控制台和日志文件中。

目前我按照一些指南配置了Microsoft.Extensions.Logging.Console来进行日志记录(暂未设置文件输出)。这个记录器的输出是每个条目写两行,例如:

info: SampleWebConsoleApp.Program[0]
      This is a test of the emergency broadcast system.

我不知道你怎么看,但我对将日志输出分为两行有些不喜欢。 我的大脑无法解析 :-)。 我希望日志一行显示,并在开头带有时间戳。 就我所知,控制台记录器似乎无法更改为单行并具有时间戳。

于是我的旅程开始了。 我发现了像Serilog、NLog或我过去使用的老朋友log4net等工具。

我试着使用Serilog,因为它看起来简单易用,而且它还有一个文件记录器,这正是我所需要的。 所以我开始把旧的控制台记录器替换为Serilog的控制台和文件记录器。 但后来我发现了一些像这样的例子:

static void Main(string[] args)
{
        Log.Logger = new LoggerConfiguration()
          .WriteTo.File("consoleapp.log")
          .CreateLogger();
        ...
}

但这似乎与我对依赖注入的稀缺知识相矛盾,因为我认为它应该像这样配置(假设!):

但这似乎与我对依赖注入的稀缺知识相矛盾,因为我认为它应该像这样配置(假设!):

private static void ConfigureServices(IServiceCollection services)
{
    ...
    services.Configure<UnknownSerilogConfigurationClass>(config => config.FileName = "consoleapp.log");
}

我看到有人提到,Serilog本身就是一个记录器工厂,因此是DI的反模式。

现在我有点困惑不知道该从哪里开始。

支持依赖注入的日志记录框架,我应该为一个相对简单的控制台应用程序使用什么? 必须具备的功能是允许我配置输出,以包括时间戳,并且输出应在一行上。

有什么建议吗?


你也可以使用Log4Net。 - Peter Barbanyaga
2个回答

18

您可以使用NLog。配置很简单。在配置完成后,您只需要注入ILogger<T>,其中T是使用记录器的类类型。

nlog.config文件(不要忘记将其复制到输出目录)

<?xml version="1.0" encoding="utf-8" ?>
<!-- XSD manual extracted from package NLog.Schema: https://www.nuget.org/packages/NLog.Schema-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true" >


  <!-- the targets to write to -->
  <targets>
    <!-- write logs to file -->
    <target xsi:type="File" name="target1" fileName="${basedir}/LogFile.txt"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
    <target xsi:type="Console" name="target2"
            layout="${date}|${level:uppercase=true}|${message} ${exception}|${logger}|${all-event-properties}" />
  </targets>

  <!-- rules to map from logger name to target -->
  <rules>
    <logger name="*" minlevel="Trace" writeTo="target1,target2" />    
  </rules>
</nlog>

.NET Core 2.2 应用程序

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using System;

namespace ConsoleApp1
{
    public class Program
    {
        static void Main(string[] args)
        {
            var serviceProvider = new ServiceCollection()
                .AddSingleton<IFooService, FooService>()
                .AddLogging(builder =>
                {
                    builder.SetMinimumLevel(LogLevel.Trace);
                    builder.AddNLog(new NLogProviderOptions
                    {
                        CaptureMessageTemplates = true,
                        CaptureMessageProperties = true
                    });
                })
                .BuildServiceProvider();

            ILogger<Program> logger = serviceProvider.GetService<ILoggerFactory>()
                                        .CreateLogger<Program>();
            logger.LogInformation("Starting application...");

            var fooService = serviceProvider.GetService<IFooService>();
            fooService.DoWork();

            Console.ReadLine();
        }
    }
}

FooService

using Microsoft.Extensions.Logging;

namespace ConsoleApp1
{
    public interface IFooService
    {
        void DoWork();
    }

    public class FooService : IFooService
    {
        private readonly ILogger _logger;

        public FooService(ILogger<FooService> logger)
        {
            _logger = logger;
        }

        public void DoWork()
        {
            _logger.LogInformation("Doing work.");
        }
    }
}

应用程序输出

2019/03/19 23:03:44.875|INFO|Starting application... |ConsoleApp1.Program|
2019/03/19 23:03:44.920|INFO|Doing work. |ConsoleApp1.FooService|

或者,如果你不想使用NLog或其他任何日志记录提供程序,你可以创建自己的自定义控制台记录器自定义文件记录器

1
我会接受你的答案,因为它看起来符合我所陈述的要求。同时,我深入研究了Serilog,并将其用于我的项目中。 - Patric
@Patric,能否分享一下你用于同时记录到文件和控制台的代码? - MoonKnight

8

使用 Serilog 非常简单。请参阅该库的 入门指南 页面。

安装 NuGet 包:

dotnet add package Serilog.Sinks.File

控制台应用程序示例:

using System;
using Serilog;

namespace SerilogExample
{
    class Program
    {
        static void Main()
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Debug()
                .WriteTo.Console()
                .WriteTo.File("logs\\logfile_yyyyDDmm.txt")
            .CreateLogger();

            Log.Information("Hello, world!");

            try
            {
                Log.Warning("Warning message..");
                Log.Debug("debug message..");
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error message");
            }

            Log.CloseAndFlush();
            Console.ReadKey();
        }
    }
}

输出示例:

2021-01-28 00:09:42.123 -03:00 [INF] Hello, world!
2021-01-28 00:09:43.456 -03:00 [WRN] Debug message
2021-01-28 00:09:44.789 -03:00 [DBG] Debug message
2021-01-28 00:09:45.012 -03:00 [ERR] Error message

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接