内置日志的使用

Logger 是 asp .net core 的内置 service,所以我们就不需要在ConfigureService里面注册了。同时在asp.net core 2.0版本及以后,系统已经在CreateDefaultBuilder方法里默认配置了输出到Console和Debug窗口的Logger。

.ConfigureLogging(delegate(WebHostBuilderContext hostingContext, ILoggingBuilder logging)
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})

所以我们可以Controller里面直接注入ILoggerFactory然后再创建具体的Logger。

private readonly ILogger _logger;
public HomeController(ILoggerFactory logger)
{
_logger = logger.CreateLogger<HomeController>();
}

但是还有更好的方式,Container可以直接提供一个ILogger的实例,这时候呢Logger就会使用T的名字作为日志的类别:

private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}

然后在【Output】窗口中可以看到输出的日志:

LogDemo> info: LogDemo.Controllers.HomeController[0]
LogDemo> Return Index view

Log到Debug窗口或者Console窗口还是比较方便的,但是正式生产环境中这肯定不够用。正式环境应该Log到文件或者数据库等。接下来试下Nlog。

使用Nlog

  1. NuGet添加 NLog.Web.AspNetCore

    <PackageReference Include="Microsoft.AspNetCore.App" />
  2. 添加配置文件

    新建一个文件nlog.config(建议全部小写,linux系统中要注意), 并右键点击其属性,将其“复制到输出目录”设置为“始终复制”。文件内容如下

    <?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"
    autoReload="true"
    internalLogLevel="info"
    internalLogFile="c:\temp\internal-nlog.txt"> <!-- enable asp.net core layout renderers -->
    <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
    </extensions> <!-- the targets to write to -->
    <targets>
    <!-- write logs to file -->
    <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-${shortdate}.log"
    layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" /> <!-- another file log, only own logs. Uses some ASP.NET core renderers -->
    <target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-own-${shortdate}.log"
    layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
    </targets> <!-- rules to map from logger name to target -->
    <rules>
    <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Trace" writeTo="allfile" /> <!--Skip non-critical Microsoft logs and so log only own logs-->
    <logger name="Microsoft.*" maxLevel="Info" final="true" />
    <!-- BlackHole without writeTo -->
    <logger name="*" minlevel="Trace" writeTo="ownFile-web" />
    </rules>
    </nlog>
        <Content Update="nlog.config">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  3. 修改Program.cs文件

    添加引用 NLog.Web 和 Microsoft.Extensions.Logging。

    在 .UseStartup() 后添加一句 .UseNLog()

    如果要禁用默认的输出框日志,可以调用logging.ClearProviders()

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging(logging =>
    {
    logging.ClearProviders();
    logging.SetMinimumLevel(LogLevel.Trace);
    })
    .UseNLog();
  4. 输出到数据库

    除了把日志输出到文件之外,也可以保存到SQL Server, PostgreSQL, MySQL, Elasticsearch等。下面是保存到SQL Server的一个示例配置:

    <?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"
    autoReload="true"
    internalLogLevel="info"
    internalLogFile="d:\temp\logs\internal-nlog.txt"> <!-- enable asp.net core layout renderers -->
    <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
    </extensions> <!-- the targets to write to -->
    <targets>
    <!-- write logs to file -->
    <target xsi:type="File" name="allfile" fileName="d:\temp\logs\all-${shortdate}.log"
    layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" /> <target name="blackhole" xsi:type="Null" /> <target name="database" xsi:type="Database" dbProvider="System.Data.SqlClient">
    <connectionString>
    Server=.;Database=Log;Trusted_Connection=True
    </connectionString>
    <commandText>
    insert into dbo.Log (
    Application, Logged, Level, Message,
    Logger, CallSite, Exception
    ) values (
    @Application, @Logged, @Level, @Message,
    @Logger, @Callsite, @Exception
    );
    </commandText> <parameter name="@application" layout="Application" />
    <parameter name="@logged" layout="${date}" />
    <parameter name="@level" layout="${level}" />
    <parameter name="@message" layout="url: ${aspnet-request-url} | action: ${aspnet-mvc-action} | ${message}" /> <parameter name="@logger" layout="${logger}" />
    <parameter name="@callSite" layout="${callsite:filename=true}" />
    <parameter name="@exception" layout="${exception:tostring}" />
    </target>
    </targets> <!-- rules to map from logger name to target -->
    <rules>
    <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Info" writeTo="allfile" /> <!--Skip non-critical Microsoft logs and so log only own logs-->
    <logger name="Microsoft.*" maxLevel="Info" final="true" />
    <!-- BlackHole without writeTo -->
    <logger name="*" minlevel="Info" writeTo="database" />
    </rules>
    </nlog>
  5. 配置简要说明

    targets:用于配置输出相关内容,比如 type 属性可选项为File、Mail、Console等,用于设置输出目标,layout属性用于设置输出信息的组成元素及格式。

    rules: 其实是一个“路由表”,日志是从上到下匹配的。 logger name="Microsoft." maxlevel="Info" final="true" 一句话的 final="true" 过滤掉了"Microsoft." Info级别以下的日志。

  6. 全局异常中间件

    除了输出日志外,可以写一个中间件来处理全局的异常。

    public class GlobalErrorHandlingMiddleware
    {
    private readonly RequestDelegate next;
    private readonly ILogger<GlobalErrorHandlingMiddleware> _logger; public GlobalErrorHandlingMiddleware(RequestDelegate next, ILogger<GlobalErrorHandlingMiddleware> logger)
    {
    this.next = next;
    this._logger = logger;
    } public async Task Invoke(HttpContext context)
    {
    try
    {
    await next(context);
    }
    catch (Exception ex)
    { var Request = context.Request;
    ///访问路径
    string visit_url = Request.Path;
    ///URL 请求方法
    string method = Request.Method.ToUpper();
    ///URL 请求的参数
    string url_paramters = string.Empty; if (method == "GET") url_paramters = Request.QueryString.Value; if (method == "POST")
    {
    foreach (var item in Request.Form)
    url_paramters = url_paramters + item.Key + "=" + item.Value + "&";
    } ///错识信息
    string err_msg = ex.Message;//ex.StackTrace; ///日志格式内容
    var logs_msg = $"{visit_url}#{method}#{url_paramters}#{err_msg}"; _logger.LogError(logs_msg); var statusCode = context.Response.StatusCode; var msg = $"Status Code: {statusCode}, Message: {ex.Message}"; await HandleExceptionAsync(context, msg);
    }
    } private static Task HandleExceptionAsync(HttpContext context, string msg)
    {
    //var data = new Result { Title = "异常中间件返回", Msg = msg };
    //var result = JsonConvert.SerializeObject(data);
    //context.Response.ContentType = "application/json;charset=utf-8";
    return context.Response.WriteAsync(msg);
    }
    } public static class GlobalErrorHandlingMiddlewareExtensions
    {
    public static IApplicationBuilder UseGlobalErrorHandlingMiddleware(
    this IApplicationBuilder builder)
    {
    return builder.UseMiddleware<GlobalErrorHandlingMiddleware>();
    }
    }

集成ELK

  1. ELK简介

    ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是开源软件。现在新增了一个FileBeat,它是一个轻量级的日志收集处理工具。

    • Logstash: 是动态数据收集管道,能够同时从多个来源采集数据、转换数据、然后将数据存到数据库中。
    • Elastaicsearch: 分布式搜索和分析引擎,提供搜集、分析、存储数据三大功能。。
    • Kibana:数据可视化Web。
    • Beats: 轻量型采集器的平台,从边缘机器向 Logstash 和 Elasticsearch 发送数据。

  2. 环境快速搭建

    这里使用docker-compose一键搭建ELK测试环境:

    1. 请确保已经安装Docker-compose

      docker-compose --version
    2. 下载代码从 The ELK stack powered by Docker and Compose 从并运行:

      git clone https://github.com/deviantony/docker-elk.git
      cd docker-elk
      docker-compose up -d
    3. 浏览器上访问安装服务器的ip:5601 可以打开 kibana 管理后台

      • 5000: Logstash TCP input.
      • 9200: Elasticsearch HTTP
      • 9300: Elasticsearch TCP transport
      • 5601: Kibana
  3. 修改nlog配置文件

    <target xsi:type="Network"
    name="ownLog-tcp"
    keepConnection="false"
    address="tcp://IP:5000"
    layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />

    启动项目测试,进入 kibana 后台配置并添加 index pattern。

  4. 其他写入Elasticsearch的方法

    把日志写入Elasticsearch的方法可以有多种:

    • Logstash:如上面的例子。它的优势是灵活性和诸多插件,它的问题是性能以及资源消耗。
    • Filebeat:轻量级的日志传输工具,可以将将日志直接传输存储到 Elasticsearch,也可经过Logstash或者Kafka/Redis。
    • .Net Core logger provider:如果仅限于 .Net Core的话,可以基于Elasticsearch的 .Net Core SDK封装一个日志提供程序直接写入Elasticsearch。

参考

ASP.NET Core 中的日志记录的更多相关文章

  1. (14)ASP.NET Core 中的日志记录

    1.前言 ASP.NET Core支持适用于各种内置和第三方日志记录提供应用程序的日志记录API.本文介绍了如何将日志记录API与内置提供应用程序一起使用. 2.添加日志提供程序 日志记录提供应用程序 ...

  2. ASP.NET Core 异常处理与日志记录

    1. ASP.NET Core 异常处理与日志记录 1.1. 异常处理 1.1.1. 异常产生的原因及处理 1.1.2. ASP.NET Core中启动开发人员异常页面 1.2. 日志记录 1.2.1 ...

  3. 玩转ASP.NET Core中的日志组件

    简介 日志组件,作为程序员使用频率最高的组件,给程序员开发调试程序提供了必要的信息.ASP.NET Core中内置了一个通用日志接口ILogger,并实现了多种内置的日志提供器,例如 Console ...

  4. asp.net core 系列 13 日志

    一.概述 ASP.NET Core 支持适用于各种内置和第三方日志记录, 供程序的日志记录 API,本文介绍了如何将日志记录 API 与内置提供程序一起使用.对于第三方日志记录提供程序使用,文章最后有 ...

  5. asp.net core 集成 log4net 日志框架

    asp.net core 集成 log4net 日志框架 Intro 在 asp.net core 中有些日志我们可能想输出到数据库或文件或elasticsearch等,如果不自己去实现一个 Logg ...

  6. Asp.Net Core中利用Seq组件展示结构化日志功能

    在一次.Net Core小项目的开发中,掌握的不够深入,对日志记录并没有好好利用,以至于一出现异常问题,都得跑动服务器上查看,那时一度怀疑自己肯定没学好,不然这一块日志不可能需要自己扒服务器日志来查看 ...

  7. ASP.NET Core 1.0 开发记录

    官方资料: https://github.com/dotnet/core https://docs.microsoft.com/en-us/aspnet/core https://docs.micro ...

  8. 谈谈ASP.NET Core中的ResponseCaching

    前言 前面的博客谈的大多数都是针对数据的缓存,今天我们来换换口味.来谈谈在ASP.NET Core中的ResponseCaching,与ResponseCaching关联密切的也就是常说的HTTP缓存 ...

  9. 在 .NET Core 中使用 DiagnosticSource 记录跟踪信息

    前言 最新一直在忙着项目上的事情,很久没有写博客了,在这里对关注我的粉丝们说声抱歉,后面我可能更多的分享我们在微服务落地的过程中的一些经验.那么今天给大家讲一下在 .NET Core 2 中引入的全新 ...

随机推荐

  1. Ansible基本命令

    Ansible安装完成之后就自带很多命令,其中较常用的有7个: ansible ansible-doc ansible-galaxy ansible-init ansible-playbook ans ...

  2. codis服务部署前的操作及初始化

    1.检查服务器ipv6模块是否打开,如果打开需要禁用ipv6,防止codis-dashbord连接zookeeper失败. 因为不确定codis-dashbord服务连接zookeeper使用ipv4 ...

  3. python 几种方法实现随机生成8位同时包含数字、大写字符、小写字符密码的小程序

    python 实现随机生成包8位包含大写字母.小写字母和数字的密码的程序.要求:1用户输入多少次就生成多少条密码,2要求密码必须同时包含大写字母.小写字母和数字,长度8位,不能重复代码如下: impo ...

  4. php CI框架log写入

    1.首先,打开application下的config.php文件,将log配置打开如下 /* |---------------------------------------------------- ...

  5. js中的基本类型与引用类型学习

    一.基本数据类型 ECMAScript 有 5 种原始类型(primitive type),即 Undefined.Null.Boolean.Number 和 String,也称为基本数据类型,ES6 ...

  6. Cordova - CordovaError: Promise rejected with non-error: 'ios-deploy was not found

    错误信息: CordovaError: Promise rejected with non-error: 'ios-deploy was not found. Please download, bui ...

  7. Aizu 2249Road Construction 单源最短路变形《挑战程序设计竞赛》模板题

    King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...

  8. execvp php-fpm reload使用的函数

    php重启 本质上是调用 execvp("/usr/local/php/sbin/php-fpm"); execvp就是用一个新的进程把自己替换掉,一个进程一旦调用exec类函数, ...

  9. 【OpenCV3】threshold()函数详解

    threshold()函数源码 double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxva ...

  10. JavaScript 函数的4种调用方法

    JavaScript 函数有 4 种调用方式. 每种方式的不同方式在于 this 的初始化. 作为一个函数调用 function myFunction(a, b) { return a * b; } ...