前言

最近用Asp.net Core开发程序的时候

因为时间的关系,就没有过多的去关注日志方面的功能

都是直接用系统的ILogger先记录着,然后看日志的时候就先在命令行看日志

在开发阶段没有什么问题,但是到了系统上线后

总不能一直在命令行看日志。总要把日志输出到一个方便查看的地方

开始

直接引用NLog.Web.AspNetCore组件

然后编写nlog.config文件放到程序的根目录

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. autoReload="true"
  5. internalLogLevel="Info"
  6. internalLogFile="${basedir}\..\Log\${date:format=yyyyMM}\WMSAPI-internal.txt">
  7. <extensions>
  8. <add assembly="NLog.Web.AspNetCore"/>
  9. </extensions>
  10. <!-- 定义变量当前应用程序名称 -->
  11. <variable name="AppName" value="WMSAPI" />
  12. <!-- 日志输出目标 -->
  13. <targets>
  14. <!-- 把日志记录到文件(通用) -->
  15. <target xsi:type="File" name="allfile" fileName="${basedir}\..\Log\${date:format=yyyyMM}\${var:AppName}-all-${shortdate}.txt" encoding="UTF-8"
  16. archiveFileName="${basedir}\..\Log\WMSAPI-all-${shortdate}.{#}.txt" archiveAboveSize="10485760"
  17. layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" />
  18. <!-- 把日志输出到文件 (Asp.Net Core) -->
  19. <target xsi:type="File" name="ownFile-web" fileName="${basedir}\..\Log\${date:format=yyyyMM}\${var:AppName}-own-${shortdate}.txt" encoding="UTF-8"
  20. archiveFileName="${basedir}\..\Log\WMSAPI-own-${shortdate}.{#}.txt" archiveAboveSize="10485760"
  21. layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}| body: ${aspnet-request-posted-body}" />
  22. <!--把日志输出到控制台 -->
  23. <target xsi:type="Console" name="lifetimeConsole" layout="${level:truncate=4:tolower=true}: ${logger}[0]${newline} ${message}${exception:format=tostring}" />
  24. <!--把日志输出到数据库 -->
  25. <target xsi:type="Database" name="database" dbProvider="MySqlConnector.MySqlConnection, MySqlConnector">
  26. <connectionString>${configsetting:item=ConnectionStrings.GDbContext}</connectionString>
  27. <install-command ignoreFailures="true">
  28. <text>
  29. <!-- NOTE: call LogManager.Configuration.Install(new InstallationContext()); to execute this query. -->
  30. CREATE TABLE IF NOT EXISTS `Sys_Log${date:format=yyyyMMdd}` (
  31. `Id` bigint NOT NULL AUTO_INCREMENT,
  32. `CreateTime` datetime NOT NULL,
  33. `AppName` varchar(50) NOT NULL,
  34. `Level` varchar(50) NOT NULL,
  35. `Logger` varchar(1024) NULL DEFAULT NULL,
  36. `Msg` text NULL,
  37. `Exception` text NULL,
  38. `UserId` varchar(50) NULL DEFAULT NULL,
  39. `Url` varchar(1024) NULL DEFAULT NULL,
  40. `IP` varchar(255) NULL DEFAULT NULL,
  41. PRIMARY KEY (`Id`) USING BTREE
  42. );
  43. </text>
  44. </install-command>
  45. <commandText>
  46. INSERT INTO `Sys_Log${date:format=yyyyMMdd}`(`CreateTime`, `AppName`, `Level`, `Logger`, `Msg`, `Exception`, `UserId`, `Url`, `IP`) VALUES (@CreateTime, @AppName, @Level, @Logger, @Msg, @Exception, @UserId, @Url, @IP);
  47. </commandText>
  48. <parameter name="@CreateTime" layout="${longdate}" />
  49. <parameter name="@AppName" layout="${var:AppName}" />
  50. <parameter name="@Level" layout="${level}" />
  51. <parameter name="@Logger" layout="${logger}" allowDbNull="true" />
  52. <parameter name="@Msg" layout="${message}" allowDbNull="true" />
  53. <parameter name="@Exception" layout="${exception:format=tostring}" allowDbNull="true" />
  54. <parameter name="@UserId" layout="${aspnet-user-claim:userId}" allowDbNull="true" />
  55. <parameter name="@Url" layout="${aspnet-request-url}" allowDbNull="true" />
  56. <parameter name="@IP" layout="${aspnet-request-ip}" allowDbNull="true" />
  57. </target>
  58. </targets>
  59. <!-- 日志输出规则 -->
  60. <rules>
  61. <!--All logs, including from Microsoft-->
  62. <!--<logger name="*" minlevel="Trace" writeTo="allfile" />-->
  63. <!--Output hosting lifetime messages to console target for faster startup detection -->
  64. <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="lifetimeConsole, ownFile-web, database" final="true" />
  65. <logger name="Microsoft.EntityFrameworkCore.Model.Validation" maxlevel="Error" final="true" />
  66. <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
  67. <logger name="Microsoft.*" maxlevel="Info" final="true" />
  68. <logger name="System.Net.Http.*" maxlevel="Info" final="true" />
  69. <logger name="*" minlevel="Trace" writeTo="ownFile-web, database" />
  70. </rules>
  71. </nlog>

可以看到我们定义了4个输出目标,前2个是文件,一个是控制台,一个是数据库

输出到文件基本定义

fileName:输出的文件名

archiveFileName,archiveAboveSize这两个参数是当文件超过archiveAboveSize大小的时候

就对文件进行分割,然后分割的文件名是用archiveFileName来定义

layout就是日志文件内容,其中以${}闭合的内容就是NLog提供的参数

具体可以参考

https://nlog-project.org/config/?tab=layout-renderers

  1. <target xsi:type="File" name="ownFile-web" fileName="${basedir}\..\Log\${date:format=yyyyMM}\${var:AppName}-own-${shortdate}.txt" encoding="UTF-8"
  2. archiveFileName="${basedir}\..\Log\WMSAPI-own-${shortdate}.{#}.txt" archiveAboveSize="10485760"
  3. layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}| body: ${aspnet-request-posted-body}" />

输出到数据库基本定义

dbProvider:使用数据库组件

connectionString:连接字符串

install-command:安装脚本(用这个来自动创建表)

commandText:日志插入到数据表的脚本

parameter:插入脚本的参数

  1. <target xsi:type="Database" name="database" dbProvider="MySqlConnector.MySqlConnection, MySqlConnector">
  2. <connectionString>${configsetting:item=ConnectionStrings.GDbContext}</connectionString>
  3. <install-command ignoreFailures="true">
  4. <text>
  5. <!-- NOTE: call LogManager.Configuration.Install(new InstallationContext()); to execute this query. -->
  6. CREATE TABLE IF NOT EXISTS `Sys_Log${date:format=yyyyMMdd}` (
  7. `Id` bigint NOT NULL AUTO_INCREMENT,
  8. `CreateTime` datetime NOT NULL,
  9. `AppName` varchar(50) NOT NULL,
  10. `Level` varchar(50) NOT NULL,
  11. `Logger` varchar(1024) NULL DEFAULT NULL,
  12. `Msg` text NULL,
  13. `Exception` text NULL,
  14. `UserId` varchar(50) NULL DEFAULT NULL,
  15. `Url` varchar(1024) NULL DEFAULT NULL,
  16. `IP` varchar(255) NULL DEFAULT NULL,
  17. PRIMARY KEY (`Id`) USING BTREE
  18. );
  19. </text>
  20. </install-command>
  21. <commandText>
  22. INSERT INTO `Sys_Log${date:format=yyyyMMdd}`(`CreateTime`, `AppName`, `Level`, `Logger`, `Msg`, `Exception`, `UserId`, `Url`, `IP`) VALUES (@CreateTime, @AppName, @Level, @Logger, @Msg, @Exception, @UserId, @Url, @IP);
  23. </commandText>
  24. <parameter name="@CreateTime" layout="${longdate}" />
  25. <parameter name="@AppName" layout="${var:AppName}" />
  26. <parameter name="@Level" layout="${level}" />
  27. <parameter name="@Logger" layout="${logger}" allowDbNull="true" />
  28. <parameter name="@Msg" layout="${message}" allowDbNull="true" />
  29. <parameter name="@Exception" layout="${exception:format=tostring}" allowDbNull="true" />
  30. <parameter name="@UserId" layout="${aspnet-user-claim:userId}" allowDbNull="true" />
  31. <parameter name="@Url" layout="${aspnet-request-url}" allowDbNull="true" />
  32. <parameter name="@IP" layout="${aspnet-request-ip}" allowDbNull="true" />
  33. </target>

可以看到我们这里通过install-command编写的建表SQL脚本

表名是Sys_Log${date:format=yyyyMMdd},这样我们创建出来的表名就是Sys_Log20211103(根据日间格式化)

但是NLog不会自动帮我们运行这个建表脚本,要我们在代码里调用

LogManager.Configuration.Install(new InstallationContext());

这个方法,他才会运行install-command里面的脚本。

因为我们是按天来进行分表的,那就相当于我每天要运行一次

LogManager.Configuration.Install(new InstallationContext());

所以我就写了一个定时的HostedService。来每天自动运行NLog的Install方法

  1. public class LogHostedService : IHostedService, IAsyncDisposable
  2. {
  3. private Timer RunTimer { get; set; }
  4. public Task StartAsync(CancellationToken cancellationToken)
  5. {
  6. LogManager.Configuration.Install(new NLog.Config.InstallationContext());//启动后执行一次
  7. this.RunTimer = new Timer(LogInstall, null, DateTime.Now.AddDays(1).Date - DateTime.Now, TimeSpan.FromDays(1));
  8. return Task.CompletedTask;
  9. }
  10. public void LogInstall(object state)
  11. {
  12. LogManager.Configuration.Install(new NLog.Config.InstallationContext());//每天0点执行一次
  13. }
  14. public Task StopAsync(CancellationToken cancellationToken)
  15. {
  16. this.RunTimer?.Change(Timeout.Infinite, 0);
  17. return Task.CompletedTask;
  18. }
  19. public ValueTask DisposeAsync()
  20. {
  21. return this.RunTimer.DisposeAsync();
  22. }
  23. }

这样就会在系统启动时和每天的0点的时候,创建当天的日志表

然后我们的插入语句INSERT INTO Sys_Log${date:format=yyyyMMdd}

就会自动插入到每天的日志表里面

代码启用NLog

我们在Program.cs文件里使用UseNLog()启用NLog组件

  1. public static IHostBuilder CreateHostBuilder(string[] args) =>
  2. Host.CreateDefaultBuilder(args)
  3. .ConfigureWebHostDefaults(webBuilder =>
  4. {
  5. webBuilder.UseStartup<Startup>();
  6. })
  7. .UseNLog();

然后在Startup.cs里启用HostedService来定时创建每天的日志表

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddHostedService<LogHostedService>();//每天自动创建日志表
  4. }

成果

使用NLog把日志写入数据库并按天自动分表的更多相关文章

  1. Laravel 上传excel,读取并写入数据库 (实现自动建表、存记录值

    <?php namespace App\Http\Controllers; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminat ...

  2. logback日志写入数据库(mysql)配置

    如题  建议将日志级别设置为ERROR.这样可以避免存储过多的数据到数据中. 1  logback 配置文件(如下) <?xml version="1.0" encoding ...

  3. mySql---logback日志写入数据库(mysql)配置

    如题  建议将日志级别设置为ERROR.这样可以避免存储过多的数据到数据中. 1  logback 配置文件(如下) <?xml version="1.0" encoding ...

  4. 怎样借助log4j把日志写入数据库中

            log4j是一个优秀的开源日志记录项目.我们不仅能够对输出的日志的格式自定义,还能够自定义日志输出的目的地,比方:屏幕.文本文件,数据 库,甚至能通过socket输出.本节使用MySQ ...

  5. 支持MySql的数据库自动分表工具DBShardTools发布

    支持MySql的数据库自动分表工具DBShardTools发布 前段时间参与了公司的一个项目,这个项目的特点是数据量.访问量都比较大,考虑使用数据库水平分表策略,Google了大半天,竟然没有找到分表 ...

  6. MySQL 高可用:mysql+mycat实现数据库分片(分库分表)

    本文引用于http://blog.csdn.net/kk185800961/article/details/51147029 MySQL 高可用:mysql+mycat实现数据库分片(分库分表) 什么 ...

  7. 使用log4j将日志写入数据库并发送邮件

    参考: 快速了解Log4J 1.log4j的初始配置 参考该问的配置即可完整的实现写入数据库及发送邮件的功能 a.写入数据库需要配置相应的jar包,数据库类型不同,请使用指定的数据库配置,该文仅限于o ...

  8. 使用log4j让日志写入数据库

    之前做的一个项目有这么个要求,在日志管理系统里,需要将某些日志信息存储到数据库里,供用户.管理员查看分析.因此我就花了点时间搞了一下这一功能,各位请看. 摘要:我们知道log4j能提供强大的可配置的记 ...

  9. log4j日志写入数据库

    # log4j写入数据库 ### 前言-----------------------------log4j是写入日志到控制台和文件很常见,但是写入到数据库不多见.做性能测试写入到数据库,统计方便些. ...

随机推荐

  1. 优雅地创建未定义类PHP对象

    在PHP中,如果没有事先准备好类,需要创建一个未定义类的对象,我们可以采用下面三种方式: new stdClass() new class{} (object)[] 首先是stdClass,这个类是一 ...

  2. html 随笔-水平控件不对齐的解决办法

    分别在左右两个控件的css代码中加上 vertical-align:top. 便可对齐:(推荐使用,因为这样可以避免脱标流). 来源: https://www.jianshu.com/p/f00d51 ...

  3. 记一次 .NET 某上市工业智造 CPU+内存+挂死 三高分析

    一:背景 1. 讲故事 上个月有位朋友加wx告知他的程序有挂死现象,询问如何进一步分析,截图如下: 看这位朋友还是有一定的分析基础,可能玩的少,缺乏一定的分析经验,当我简单分析之后,我发现这个dump ...

  4. web带宽估算方法

    每个连接约占用10Kb的带宽,以3万总用户数和10%的在线率计算,并按照10%的冗余率,服务器总带宽=每秒总连接数*10Kbps /(1-冗余率)/1024. 带宽占用(Mbps)=30000*10% ...

  5. P3343-[ZJOI2015]地震后的幻想乡【dp,数学期望】

    正题 题目链接:https://www.luogu.com.cn/problem/P3343 题目大意 给出\(n\)个点的一张无向图,每条边被修复的时间是\([0,1]\)的一个随机实数,求这张图联 ...

  6. 【C++ Primer Plus】编程练习答案——第11章 (待更新)

    最近开学,事情较多,过两天更新...

  7. Vue插槽slot理解与初体验 ~

    一.插槽的理解 1.官网介绍 Vue 实现了一套内容分发的 API,将 <slot> 元素作为承载分发内容的出口. 2.为什么使用插槽 Vue 中有一个重要的概念-组件,可以在开发中将子组 ...

  8. Java类加载器概述

    Java类加载器概述 Java 中的类加载器大致可以分成两类,一类是系统提供的,另外一类则是由Java 应用开发人员编写的. 系统提供的类加载器 引导类加载器 它用来加载 Java 的核心库,是用原生 ...

  9. ES6箭头函数(箭头函数和普通函数的区别)

    箭头函数 一个参数 // 只有一个参数 // f : 函数名称 // v : 函数参数 // v+v : 函数内容 let f=v=> v+v console.log(f(10)) //20 两 ...

  10. Serverless:这真的是未来吗?(二)

    原文 | https://www.pulumi.com/blog/is_serverless_the_future_part_2/ 作者 | Lee Briggs & Piers Karsen ...