zoukankan      html  css  js  c++  java
  • .NET .Core 选择日志框架

    先来介绍.NET中三种最受欢迎​​的日志记录框架:log4net,NLog和Serilog。

    一、Log4net

    1、Log4net概述

      Log4Net有四种主要的组件,分别是Logger(记录器),Repository(库),Appender(附着器)以及 Layout(布局)

    • Logger记录器

      Logger是应用程序需要交互的主要组件,它用来产生日志消息。产生的日志消息并不直接显示,还要预先经过Layout的格式化处理后才会输出。Logger提供了多种方式来记录一个日志消息,你可以在你的应用程序里创建多个Logger,每个实例化的Logger对象都被log4net框架作为命名实体(named entity)来维护,这意味着为了重用Logger对象,可以将Logger对象当做参数使用。Log4net框架定义了一个ILog接口,所有的logger类都必须实现这个接口。如果你想实现一个自定义的logger,你必须首先实现这个接口。Log4Net框架定义了一个叫做LogManager的类,用来管理所有的logger对象。它有一个GetLogger()静态方法,用我们提供的名字参数来检索已经存在的Logger对象。如果框架里不存在该Logger对象,它也会为我们创建一个Logger对象。 

    • Repository库

      Repository主要用于负责日志对象组织结构的维护。

    • Appender(附着器)

      Appender决定日志输出的媒介。主要包括以下几种:

      • AnsiColorTerminalAppender:在ANSI 窗口终端写下高亮度的日志事件。
      • AspNetTraceAppender:能用asp.net中Trace的方式查看记录的日志。
      • BufferingForwardingAppender:在输出到子Appenders之前先缓存日志事件。
      • ConsoleAppender:将日志输出到控制台。
      • EventLogAppender:将日志写到Windows Event Log. 
      • FileAppender:将日志写到文件中。
      • LocalSyslogAppender:将日志写到local syslog service (仅用于UNIX环境下). 
      • MemoryAppender:将日志存到内存缓冲区。
      • NetSendAppender:将日志输出到Windows Messenger service.这些日志信息将在用户终端的对话框中显示。
      • RemoteSyslogAppender:通过UDP网络协议将日志写到Remote syslog service。
      • RemotingAppender:通过.NET Remoting将日志写到远程接收端。
      • RollingFileAppender:将日志以回滚文件的形式写到文件中。(实例代码中使用的是此类型)
      • SmtpAppender:将日志写到邮件中。
      • TraceAppender:将日志写到.NET trace 系统。
      • UdpAppender:将日志connectionless UDP datagrams的形式送到远程宿主或以UdpClient的形式广播。   
    • root

      Appender和root经常搭配使用,root用来对设置输出的方式进行指定。
    <root>
        <!--批定DEBUG输出的文件形式记录日志-->
        <level value="DEBUG"/>
        <appender-ref ref="Log4Net_ERROR" />
      
      <!--批定INFO输出的文件形式记录日志-->
        <level value="INFO"/>
        <appender-ref ref="Log4Net_INFO" />
    </root>
    • Appender Filters过滤器

      Appender的过滤器(Appender Filters) 可以按照不同的标准过滤日志事件。在log4net.Filter的名字空间下已经有几个预定义的过滤器。使用这些过滤器,你可以按照日志级别范围过滤日志事件,或者按照某个特殊的字符串进行过滤。过滤器通常有以下几种:

      • DenyAllFilter 阻止所有的日志事件被记录
      • LevelMatchFilter 只有指定等级的日志事件才被记录
      • LevelRangeFilter 日志等级在指定范围内的事件才被记录
      • LoggerMatchFilter 与Logger名称匹配,才记录
      • PropertyFilter 消息匹配指定的属性值时才被记录
      • StringMathFilter 消息匹配指定的字符串才被记录
    • Layout布局

      Layout 组件用于向用户显示最后经过格式化的输出信息。输出信息可以以多种格式显示,主要依赖于我们采用的Layout组件类型。可以是线性的或一个XML文件。Layout组件和一个Appender组件一起工作。API帮助手册中有关于不同Layout组件的列表。一个Appender对象,只能对应一个Layout对象。要实现你自己的Layout类,你需要从log4net.Layout.LayoutSkeleton类继承,它实现了ILayout接口。一个Appender只能有一个Layout。最常用的Layout应该是经典格式的PatternLayout,其次是SimpleLayout,RawTimeStampLayout和ExceptionLayout。然后还有IRawLayout,XMLLayout等几个使用较少。Layout可以自己实现,需要从log4net.Layout.LayoutSkeleton类继承,来输出一些特殊需要的格式,在后面扩展时就重新实现了一个Layout。

        • SimpleLayout简单输出格式,只输出日志级别与消息内容。
        • RawTimeStampLayout 用来格式化时间,在向数据库输出时会用到。样式如“yyyy-MM-dd HH:mm:ss“
        • ExceptionLayout需要给Logger的方法传入Exception对象作为参数才起作用,否则就什么也不输出。输出的时候会包含Message和Trace。
        • PatterLayout使用最多的一个Layout,能输出的信息很多
    • 配置文件说明

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <!--添加自定义节点:log4net  type:解析类名,程序集名(log4net.dll)-->
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
      </configSections>
    
      <log4net>
        <!--定义输出到文件中-->
        <appender name="Log4Net_INFO" type="log4net.Appender.RollingFileAppender">
          <!--定义文件存放位置-->
          <file value="C:/log4net/"/>
          <!--是否追加到文件,默认为true,通常无需设置-->
          <appendToFile value="true"/>
          <RollingStyle value="Date"/>
          <!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
          <DatePattern value="INFO_yyyyMMdd".log"" />
          <!--日志文件名是否为静态-->
          <StaticLogFileName value="false"/>
          <!--多线程时采用最小锁定-->
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <!--布局(向用户显示最后经过格式化的输出信息)-->
          <layout type="log4net.Layout.PatternLayout">
            <!--
               %m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息 
               %n(new line):换行 
               %d(datetime):输出当前语句运行的时刻 
               %r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数 
               %t(thread id):当前语句所在的线程ID 
               %p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等 
               %c(class):当前日志对象的名称,例如:
               %L:输出语句所在的行号 
               %F:输出语句所在的文件名 
               %-数字:表示该项的最小长度,如果不够,则用空格填充
              -->
            <Header value="[Header]
    "/>
            <Footer value="[Footer]
    "/>
            <!--正文-->
            <ConversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline"  />
          </layout>
        </appender>
    
        <appender name="Log4Net_ERROR" type="log4net.Appender.RollingFileAppender">
          <file value="C:/log4net/"/>
          <appendToFile value="true"/>
          <RollingStyle value="Date"/>
          <DatePattern value="ERROR_yyyyMMdd".log"" />
          <StaticLogFileName value="false"/>
          <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
          <layout type="log4net.Layout.PatternLayout">
            <Header value="[Header]
    "/>
            <Footer value="[Footer]
    "/>
            <!--正文-->
            <ConversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline"  />
          </layout>
        </appender>
    
        <root>
          <level value="DEBUG"/>
          <appender-ref ref="Log4Net_ERROR" />
    
          <level value="INFO"/>
          <appender-ref ref="Log4Net_INFO" />
        </root>
    
      </log4net>
    
    </configuration>

    2、自定义Logger示例

    定义一个类库Log4netManager,通过nuget引用log4net组件,类库结构如下:

    ELogLevel.cs代码如下:

    namespace Log4netManager
    {
        public enum ELogLevel
        {
            /// <summary>
            /// 错误信息
            /// </summary>
            Error=1,
            /// <summary>
            /// 跟踪信息
            /// </summary>
            Trace=2,
            /// <summary>
            /// 调试信息
            /// </summary>
            Debug=3,
            /// <summary>
            /// 记录信息
            /// </summary>
            Info=4
        }
    }
    

    ILog.cs代码如下:

    using System;
    
    namespace Log4netManager
    {
        public interface ILog:IDisposable
        {
            void LogWithTime(string msg, ELogLevel logLevel = ELogLevel.Error);
            bool Enabled { get; set; }
        }
    }

    FileLogger.cs代码如下:

    using System;
    using System.Diagnostics;
    using System.IO;
    
    namespace Log4netManager
    {
        public class FileLogger : ILog
        {
            private string _configLevel = null;
            private bool _enabled = true;
            private log4net.ILog _log = null;
            public FileLogger()
            {
                this._configLevel = GetAppSettingValue("LogLevel");
                string logName = GetAppSettingValue("LogName");
                string configPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "log4net.xml");
                log4net.Config.XmlConfigurator.Configure(new FileInfo(configPath));
                this._log = log4net.LogManager.GetLogger(logName);
            }
    
            public static string GetAppSettingValue(string key)
            {
                string value = null;
                foreach (string item in System.Configuration.ConfigurationManager.AppSettings)
                {
                    if (item.Equals(key, System.StringComparison.CurrentCultureIgnoreCase))
                    {
                        value = System.Configuration.ConfigurationManager.AppSettings[key];
                        break;
                    }
                }
                return value;
            }
    
            #region ILog成员
            public void LogWithTime(string msg, ELogLevel logLevel)
            {
                if (string.IsNullOrWhiteSpace(msg) || !this._enabled)
                {
                    return;
                }
    #if DEBUG
                Trace.TraceInformation(msg);
    #endif
                if (string.IsNullOrWhiteSpace(this._configLevel))
                {
                    this._configLevel = ((int)ELogLevel.Error).ToString();
                }
                int configLevel = Convert.ToInt32(this._configLevel);
                if ((int)logLevel < configLevel)
                {
                    try
                    {
                        switch (logLevel)
                        {
                            case ELogLevel.Error:
                                this._log.Error(msg);
                                break;
                            case ELogLevel.Trace:
                                this._log.Warn(msg);
                                break;
                            case ELogLevel.Debug:
                                this._log.Debug(msg);
                                break;
                            case ELogLevel.Info:
                                this._log.Info(msg);
                                break;
                            default:
                                break;
                        }
                    }
                    catch
                    {
                    }
                }
            }
            public bool Enabled
            {
                get { return this._enabled; }
                set { this._enabled = value; }
            }
            #endregion
    
            #region IDisposable
            public void Dispose()
            { }
            #endregion 
        }
    }

    OK,接下来使用下我们自定义的Logger,先建立一个控制台项目,引入刚刚自定义的Log4netManager类库,结构如下:

    App.config代码:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
        </startup>
      <appSettings>
        <add key="LogName" value="TestConsole"/>
        <add key="LogLevel" value="4"/>
      </appSettings>
    </configuration>

    log4net.xml如下:

    <?xml version="1.0" encoding="utf-8" ?>
    <log4net debug="true">
      <appender name="FlatFile" type="log4net.Appender.RollingFileAppender,log4net">
        <param name="File" value="logs/website.log" />
        <param name="Encoding" value="utf-8" />
        <param name="AppendToFile" value="true" />
        <param name="RollingStyle" value="Date" />
        <param name="ImmediateFlush" value="true" />
        <param name="MaximumFileSize" value="50MB"/>
        <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
        <param name="DatePattern" value="-yyyy.MM.dd'.log'" />
        <param name="StaticLogFileName" value="true" />
        <layout type="log4net.Layout.PatternLayout,log4net">
          <param name="ConversionPattern" value="%-5level [%logger] - %message [%date] %newline" />
        </layout>
      </appender> 
      <root>
        <priority value="DEBUG" />
        <appender-ref ref="FlatFile" />
      </root>  
    </log4net>

    Program.cs如下:

    using Log4netManager;
    
    namespace log4netConsole
    {
        class Program
        {
            static void Main(string[] args)
            {
                ILog _fileLogger = new FileLogger();
                _fileLogger.LogWithTime("日志测试",ELogLevel.Debug);
                System.Console.WriteLine("日志所在的位置 "+System.AppDomain.CurrentDomain.BaseDirectory);
                System.Console.ReadKey();
            }
        }
    }

    效果如下:

    3、Netcore中使用log4net

    新建一个netcore mvc项目,通过nuget引入包Microsoft.Extensions.Logging.Log4Net.AspNetCore,项目结构如下:

    Program.cs代码如下:

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    
    namespace NetCoreLog
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureLogging((context, loggingbuilder) =>
                    {
                        loggingbuilder.AddFilter("System", LogLevel.Warning); //过滤掉系统默认的一些日志
                        loggingbuilder.AddFilter("Microsoft", LogLevel.Warning);//过滤掉系统默认的一些日志                    
                        loggingbuilder.AddLog4Net();
                    })
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });
        }
    }

    log4net.config如下:

    <?xml version="1.0" encoding="utf-8"?>
    <log4net>
        <appender name="RollingAppender" type="log4net.Appender.RollingFileAppender">
            <!--指定日志文件保存的目录-->
            <file value="loglog.txt"/>
            <!--追加日志内容-->
            <appendToFile value="true"/>
            <!--可以为:Once|Size|Date|Composite-->
            <!--Compoosite为Size和Date的组合-->
            <rollingStyle value="Composite"/>
            <!--设置为true,当前最新日志文件名永远为file字节中的名字-->
            <staticLogFileName value="false"/>
            <!--当备份文件时,备份文件的名称及后缀名-->
            <datePattern value="yyyyMMdd.TXT"/>
            <!--日志最大个数-->
            <!--rollingStyle节点为Size时,只能有value个日志-->
            <!--rollingStyle节点为Composie时,每天有value个日志-->
            <maxSizeRollBackups value="20"/>
            <!--可用的单位:KB|MB|GB-->
            <maximumFileSize value="5MB"/>
            <filter type="log4net.Filter.LevelRangeFilter">
                <param name="LevelMin" value="ALL"/>
                <param name="LevelMax" value="FATAL"/>
            </filter>
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline"/>
            </layout>
        </appender>
        <root>
            <priority value="ALL"/>
            <level value="ALL"/>
            <appender-ref ref="RollingAppender"/>
        </root>
    </log4net>

    HomeController.cs代码如下:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using NetCoreLog.Models;
    using System.Diagnostics;
    
    namespace NetCoreLog.Controllers
    {
        public class HomeController : Controller
        {
            //ILoggerFactory和ILogger都是系统内置的接口,两个都可以写日志,使用其中之一即可
            private readonly ILogger<HomeController> _logger;
            private readonly ILoggerFactory _factory;
            public HomeController(ILogger<HomeController> logger, ILoggerFactory factory)
            {
                this._logger = logger;
                this._factory = factory;
            }
    
            public IActionResult Index()
            {
                this._factory.CreateLogger<HomeController>().LogError("记录错误信息!!!");
                this._logger.LogError("记录错误信息!");
                return View();
            }
    
            public IActionResult Privacy()
            {
                return View();
            }
    
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
            public IActionResult Error()
            {
                return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
            }
        }
    }

    效果如下:

    二、NLog

    1、NLog概述

    NLog是一个基于.NET平台编写的类库,我们可以使用NLog在应用程序中添加极为完善的跟踪调试代码。NLog是一个简单灵活的.NET日志记录类库。通过使用NLog,我们可以在任何一种.NET语言中输出带有上下文的(contextual information)调试诊断信息,根据喜好配置其表现样式之后发送到一个或多个输出目标(target)中。NLog遵从BSD license,即允许商业应用且完全开放源代码。任何人都可以免费使用并对其进行测试,然后通过邮件列表反馈问题以及建议。 

    • NLog和Log4net的区别

      NLog的API非常类似于log4net,且配置方式非常简单。NLog使用路由表(routing table)进行配置,但log4net却使用层次性的appender配置,这样就让NLog的配置文件非常容易阅读,并便于今后维护。

    • NLog配置介绍

    <?xml version="1.0" encoding="utf-8" ?>
    <!-- 默认命名空间 -->
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd">
      <!-- 这个命名空间里面的元素或者属性就必须要以xsi:这种方式来写,比如schemaLocation就是他的一个属性,所以写成xsi:schemaLocation。
      而默认命名空间不带类似xsi这种;其实xml标签名称有个专业叫法叫做QName,而如果没有前面的xsi:这种一般叫做NCName -->
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      <!--表示把定义这个命名空间的schema文件给引用进来,好让开发类型工具能够解析和验证你的xml文件是否符合语法规范
      简单来说 上面是用来验证你XML格式是否正确的。-->
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      <!--一旦启动程序,这时候NLog.config文件被读取后,知道程序再启动都不会再读取配置文件了。假如我们不想停掉程序,比如说服务器哪能说停就停哈。这就用上这个配置了,这个配置功能是,一旦你对配置文件修改,程序将会重新读取配置文件,也就是自动再配置。-->
      autoReload="true"
      <!--NLog日志系统抛出异常-->
      throwExceptions="false"
      <!--日志级别 -->
      internalLogLevel="Debug"
      <!--NLog内部日志文件位置 -->
      internalLogFile="c:	emp
    log-internal.log">
      <!--variable定义配置文件中用到的变量-->
    <variable name="myvar" value="myvalue"/>
      <!--定义日志的目标/输出-->
      <targets> </targets>
      <!--定义日志的路由规则-->
      <rules> </rules>
    </nlog>

    2、NetCore中使用NLog

    新建一个netcore  mvc项目,通过nuget引入包NLog.Config和NLog.Web.AspNetCore。在引入NLog.Config包的时候,在项目根目录自动生成一个NLog.config,将该文件属性改为始终复制。项目结构如下:

    修改下NLog.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
          autoReload="true"
          throwExceptions="false"
          internalLogLevel="Off" internalLogFile="c:	emp
    log-internal.log">
    
        <!-- optional, add some variables
      https://github.com/nlog/NLog/wiki/Configuration-file#variables
      -->
        <variable name="myvar" value="myvalue"/>
    
        <!--
      See https://github.com/nlog/nlog/wiki/Configuration-file
      for information on customizing logging rules and outputs.
       -->
        <targets>
    
            <!--
        add your targets here
        See https://github.com/nlog/NLog/wiki/Targets for possible targets.
        See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
        -->
    
            <!--
        Write events to a file with the date in the filename.
         -->
            <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
                    layout="${longdate} ${uppercase:${level}} ${message}" />
    
        </targets>
    
        <rules>
            <!-- add your logging rules here -->
    
            <!--
        Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
        -->
            <logger name="*" minlevel="Debug" writeTo="f" />
    
        </rules>
    </nlog>

    Program.cs代码如下:

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Logging;
    using NLog.Web;
    
    namespace NetCoreNlog
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    })
                    //using NLog.Web;
                    .ConfigureLogging(logging =>
                    {
                        logging.ClearProviders();
                    }).UseNLog();
        }
    }

    HomeController.cs代码如下:

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Logging;
    using NetCoreNlog.Models;
    using System.Diagnostics;
    
    namespace NetCoreNlog.Controllers
    {
        public class HomeController : Controller
        {
            private readonly ILogger<HomeController> _logger;
    
            public HomeController(ILogger<HomeController> logger)
            {
                _logger = logger;
            }
    
            public IActionResult Index()
            {
                _logger.LogInformation("这里是日志记录");
                return View();
            }
    
            public IActionResult Privacy()
            {
                return View();
            }
    
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
            public IActionResult Error()
            {
                return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
            }
        }
    }

    效果如下:

    三、Serilog

    1、Serilog概述

    该系列的最新日志记录框架Serilog于2013年发布。Serilog与其他框架之间的最大区别在于,该框架旨在进行结构化的现成日志记录。

    2、Serilog示例

    这次无需任何XML配置!Serilog的配置使用流畅的界面,使其非常美观和干净。

    using Serilog;
    using System;
    namespace LoggingDemo.Serilog
    {
        class Program
        {
            static void Main(string[] args)
            {
                Log.Logger = new LoggerConfiguration()
                    .MinimumLevel.Debug()
                    .WriteTo.Console()
                    .WriteTo.File("logfile.log", rollingInterval: RollingInterval.Day)
                    .CreateLogger();
                Log.Debug("Starting up");
                Log.Debug("Shutting down");
                Console.ReadLine();
            }
        }
    }
    The logging output from Serilog looks like:
    

    输出结果如下:

    2018-08-18 14:37:21.463 -06:00 [DBG] Starting up
    2018-08-18 14:37:21.560 -06:00 [DBG] Shutting down

    四、.NET .Core 使用Serilog

    最佳日志记录框架:Serilog。该API更现代,更易于设置,维护更好,并且默认情况下进行结构化日志记录。添加浓缩器的功能能够拦截和修改消息,这非常有用。

    1、在控制台项目中使用

    前提:引入Serilog.AspNetCore包

    新建一个Serilog帮助类SerilogHelper,定义两种方法,一个是将日志输出到console,一个是将日志输出到文件

    using Serilog;
    using System;
    using System.IO;
    
    namespace SerilogTest
    {
        public static class SerilogHelper
        {
            /// <summary>
            /// 输出到Console
            /// </summary>
            public static void WriteToConsole()
            {
                //日志的输出模板
                string Logformat = @"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3} {SourceContext:l}] {Message:lj}{NewLine}{Exception}";
                //类似创建一个管道
                Log.Logger = new LoggerConfiguration()
                    //设置最低等级
                    .MinimumLevel.Debug()
                    //将事件发送到控制台并展示
                    .WriteTo.Console(outputTemplate: Logformat)
                    .CreateLogger();
    
                //这里因为设置了最低等级为Debug,所以比Debug低的Verbose不会展示在控制台
                Log.Verbose("Verbose级别的日志消息");
                Log.Information("计算开始");
    
                try
                {
                    int a = 0;
                    int b = 5;
                    Log.Debug("计算两者相除");
                    Console.WriteLine(b / a);
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "计算出现意外的错误");
                }
                Log.Information("计算结束");
            }
    
            public static void WriteToFile()
            {
                var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "log.txt");
                //日志的输出模板
                string Logformat = @"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3} {SourceContext:l}] {Message:lj}{NewLine}{Exception}";
                Log.Logger = new LoggerConfiguration()
                  .MinimumLevel.Debug()
                  //该行代码表示输出到console
                  .WriteTo.Console(outputTemplate: Logformat)
                  //第一个参数是文件路径,第二个参数是输出模板的选择,第三个参数是表示程序隔多长时间新创造一个日志文件
                  .WriteTo.File(path, outputTemplate: Logformat, rollingInterval: RollingInterval.Day)
                  .CreateLogger();
    
                //这里因为设置了最低等级为Debug,所以比Debug低的Verbose不会展示在控制台
                Log.Verbose("Verbose级别的日志消息");
                Log.Information("计算开始");
    
                try
                {
                    int a = 0;
                    int b = 5;
                    Log.Debug("计算两者相除");
                    Console.WriteLine(b / a);
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "计算出现意外的错误");
                }
                Log.Information("计算结束");
            }
        }
    }

    在Program调用方法

    复制代码
    namespace SerilogTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                //SerilogHelper.WriteToConsole();
                SerilogHelper.WriteToFile();
            }        
        }
    }
    复制代码

    2、在web中使用Serilog

    前提:引入Serilog.AspNetCore包

    配置appsettings.json

    {
      "log": { //日志配置
        "minlevel": "Verbose", //定义详见Serilog.Events.LogEventLevel
        "console": {
          "enabled": true
        },
        "debug": {
          "enabled": true
        },
        "file": {
          "enabled": true
        },
        "elasticsearch": {
          "enabled": false,
          "nodes": [ "http://localhost:9200/" ],
          "indexformat": "colder"
        },
        "overrides": [ //重写日志输出级别
          {
            "source": "Microsoft.AspNetCore",
            "minlevel": "Warning"
          },
          {
            "source": "Microsoft.EntityFrameworkCore",
            "minlevel": "Information"
          },
          {
            "source": "Microsoft.EntityFrameworkCore.Infrastructure",
            "minlevel": "Warning"
          }
        ]
      },
      "AllowedHosts": "*"
    }

    新建一个对应appsettings.json的model

    复制代码
    using System.Collections.Generic;
    
    namespace SerilogWebTest
    {
        public class LogConfig
        {
            public string minlevel { get; set; }
            public Option console { get; set; } = new Option();
            public Option debug { get; set; } = new Option();
            public Option file { get; set; } = new Option();
            public Option elasticsearch { get; set; } = new Option();
            public List<OverrideConfig> overrides { get; set; } = new List<OverrideConfig>();
        }
    
        public class Option
        {
            public bool enabled { get; set; }
            public List<string> nodes { get; set; } = new List<string>();
            public string indexformat { get; set; }
        }
    
        public class OverrideConfig
        {
            public string source { get; set; }
            public string minlevel { get; set; }
        }
    }
    复制代码

    定义IHostBuilder扩展类,配置Serilog

    using Serilog.Events;
    using Serilog.Sinks.Elasticsearch;
    using System;
    using System.IO;
    using Microsoft.Extensions.Configuration;
    using System.Linq;
    using Microsoft.Extensions.Hosting;
    using Serilog;
    
    namespace SerilogWebTest
    {
        public static partial class Extention
        {
            /// <summary>
            /// 将枚举类型的文本转为枚举类型
            /// </summary>
            /// <typeparam name="TEnum">枚举类型</typeparam>
            /// <param name="enumText">枚举文本</param>
            /// <returns></returns>
            public static TEnum ToEnum<TEnum>(this string enumText) where TEnum : struct
            {
                Enum.TryParse(enumText, out TEnum value);
                return value;
            }
            public static IHostBuilder UseLog(this IHostBuilder hostBuilder)
            {
                var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs", "log.txt");
                return hostBuilder.UseSerilog((hostingContext, serilogConfig) =>
                {
                    var envConfig = hostingContext.Configuration;
                    LogConfig logConfig = new LogConfig();
                    envConfig.GetSection("log").Bind(logConfig);
                    logConfig.overrides.ForEach(aOverride =>
                    {
                        serilogConfig.MinimumLevel.Override(aOverride.source, aOverride.minlevel.ToEnum<LogEventLevel>());
                    });
    
                    serilogConfig.MinimumLevel.Is(logConfig.minlevel.ToEnum<LogEventLevel>());
                    if (logConfig.console.enabled)
                        serilogConfig.WriteTo.Console();
                    if (logConfig.debug.enabled)
                        serilogConfig.WriteTo.Debug();
                    if (logConfig.file.enabled)
                    {
                        string template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3} {SourceContext:l}] {Message:lj}{NewLine}{Exception}";
                        serilogConfig.WriteTo.File(
                            path,
                            outputTemplate: template,
                            rollingInterval: RollingInterval.Day,
                            shared: true,
                            fileSizeLimitBytes: 10 * 1024 * 1024,
                            rollOnFileSizeLimit: true
                            );
                    }
                    if (logConfig.elasticsearch.enabled)
                    {
                        var uris = logConfig.elasticsearch.nodes.Select(x => new Uri(x)).ToList();
    
                        serilogConfig.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(uris)
                        {
                            IndexFormat = logConfig.elasticsearch.indexformat,
                            AutoRegisterTemplate = true,
                            AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7
                        });
                    }
                });
            }
        }
    
        
    }

    扩展类中除了允许将日志输出到console、文件,还允许输出到elasticsearch,如果要输出到elasticsearch,需要引入包

     在Program中注入日志服务

    复制代码
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.Extensions.Hosting;
    
    namespace SerilogWebTest
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                CreateHostBuilder(args).Build().Run();
            }
    
            public static IHostBuilder CreateHostBuilder(string[] args) =>
                Host.CreateDefaultBuilder(args)
                    .UseLog()//注入服务
                    .ConfigureWebHostDefaults(webBuilder =>
                    {
                        webBuilder.UseStartup<Startup>();
                    });  
        }
    }
    复制代码 
  • 相关阅读:
    unexpected inconsistency;run fsck manually esxi断电后虚拟机启动故障
    centos 安装mysql 5.7
    centos 7 卸载mysql
    centos7 在线安装mysql5.6,客户端远程连接mysql
    ubuntu 14.04配置ip和dns
    centos7 上搭建mqtt服务
    windows eclipse IDE打开当前类所在文件路径
    git 在非空文件夹clone新项目
    eclipse中java build path下 allow output folders for source folders 无法勾选,该如何解决 eclipse中java build path下 allow output folders for source folders 无法勾选,
    Eclipse Kepler中配置JadClipse
  • 原文地址:https://www.cnblogs.com/qtiger/p/14452974.html
Copyright © 2011-2022 走看看