Net8将Serilog日志推送ES,附视频
这是一个Serilog的实践Demo,包括了区别记录存放,AOP 日志记录,EF 执行记录,并且将日志推送到Elastic Search。
说在前面的话
自从AI出来之后,学习的曲线瞬间变缓了,学习的路径也有了很大的变化。
与本人来说以前大多数都先知晓理论再找相关的框架官网或博客,然后去实践Demo,再加入到代码中,也就是理论-》实践-》应用-》技能
。
而现在,可以在稍微知晓概念之后,直接找AI要Demo先跑起来,应用到代码中去,然后反向结合代码去问AI每一步实现的逻辑与理论,再消化成自己技能,也就是 概念-》应用-》理论知识-》技能
。
故此次尝试不同的写文思路,从拿到源代码的读者角度,开始思考与实践。
依照惯例,源代码在文末,需要自取~
环境准备
- Docker Desktop
- VS2022 SDK .NET8
- Elastic Search 8.0+ Kibana(Docker)
- SqlServer (Docker 或者本地 SqlServer)
- Chat Gpt (可选)
效果一览
实现要求
- 分别记录EF、非EF日志,存放至不同的路径
- 其中非EF日志以AOP的思想,记录执行方法的前后信息,API接口调用详情与返回结果,
- 把所有的消息推送至elastic search。
实现效果
Docker中启动 ES 和 SqlServer
再 F5 启动项目
- EF 日志存储在 Logs/EFSql 文件夹下
- 非EF日志存储在 Logs/AuditLogs 文件夹下
所有的日志推送至Elastic Search
从Program 初见端倪
OK,相信你现在已经把代码拉下来了,如果没有想生啃代码,不用跳过此节。
.net 8 与 .net 6 可以使用顶级语句,相对于.net 5 及以前的版本,去掉了Startup作为web的配置程序,也就是上手各大项目的入口, 这里直接看Program 来探究Demo 如何配置Web,来一窥端倪吧!
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Autofac.Extras.DynamicProxy;
using Microsoft.EntityFrameworkCore;
using SampleDemo.Yzh.Net.Logger;
using SampleDemo.Yzh.Net.Repository;
using SampleDemo.Yzh.Net.Service;
using SampleDemo.Yzh.Net.Core;
using Serilog;
using ILogger = Serilog.ILogger;
var builder = WebApplication.CreateBuilder(args);
// Config
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
// Serilog
builder.Host.AddCustomLog();
// EF
builder.Services.AddDbContextPool<TestContext>
(o => o.UseSqlServer(builder.Configuration.GetConnectionString("NicoLocaldbStr"))
#if DEBUG
.EnableSensitiveDataLogging()
#endif
.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddSerilog())
));
// Http Info
builder.Services.AddHttpContextAccessor();
// Auto Fac
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
// 注册AopDemo拦截器为单例模式
containerBuilder.RegisterType<AopDemo>().SingleInstance();
// InterceptedBy指定拦截器
containerBuilder.RegisterType<ValuesService>().As<IValuesService>().EnableInterfaceInterceptors().InterceptedBy(typeof(AopDemo));
// 或者在IValuesService 加标签 [Intercept(typeof(AopDemo))]
//containerBuilder.RegisterType<ValuesService>().As<IValuesService>().EnableInterfaceInterceptors();
//向 Autofac 容器注册 Log.Logger 这个已经存在的日志记录器实例 ,指定这个实例作为 ILogger 接口的实现 ,此ILogger为 Serilog的ILogger
//当应用程序中的组件通过依赖注入请求 ILogger 接口的实例时,它们会接收到 Log.Logger 这个单例对象
containerBuilder.RegisterInstance(Log.Logger).As<ILogger>();
});
builder.Services.AddControllers();
var app = builder.Build();
// Middleware
app.UseMiddleware<ResponseLoggingMiddleware>(); //返回客户端响应的日志记录
app.UseAuthorization();
app.MapControllers();
app.Run();
这里我直接把Program.cs 51 行代码全部拉出来,由此来看大致做了些什么。
using 中可以看到 引用了Autofac以及他的扩展包, 引入了 Serilog,并且指定了ILogger为 Serilog.ILogger,作用暂且按下不表
builder.Services.AddSingleton(new AppSettings(builder.Configuration)) 这里将配置以单例的形式封装在AppSettings类中,后续取配置直接从AppSettings类中取即可
builder.Host.AddCustomLog(); 这里用一个扩展方法,将Serilog的注入写入AddCustomLog()方法中,后续这将是该Demo核心方法,重点看
builder.Services.AddDbContextPool<TestContext>
(o => o.UseSqlServer(builder.Configuration.GetConnectionString("NicoLocaldbStr"))
#if DEBUG
.EnableSensitiveDataLogging()
#endif
.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddSerilog())
));
上述代码,以DbContext池化的方式注入EF,并且在Debug模式下开启敏感日志,配置Serilog作为日志的记录工具
builder.Services.AddHttpContextAccessor(); 添加访问Http请求的信息,用于后续Reponse中间件开发提供HTTP信息
builder.Host.UseServiceProviderFactory 以及 builder.Host.ConfigureContainer 配置Auto Fac,注释详解
app.UseMiddleware< ResponseLoggingMiddleware >(); ResponseLoggingMiddleware中间件返回客户端响应的日志记录
再看Serilog拓展
从上文可知,使用了 AddCustomLog() 这样的一个扩展方法,注入了Serilog,OK! ,Ctrl + F12 进入一探究竟
public static class CustomLogger
{
public static IHostBuilder AddCustomLog(this IHostBuilder builder)
{
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(AppSettings.Configuration)
.Enrich.FromLogContext()
// 输出到控制台
.WriteToConsole()
// 输出到文件
.WriteToFile()
// 输出到Es
.WriteToElasticsearch()
.CreateLogger();
builder.UseSerilog();
return builder;
}
}
.ReadFrom.Configuration(AppSettings.Configuration):指示 Serilog 从应用程序的配置文件(如 appsettings.json)中读取配置信息。这里假设有一个 AppSettings 类,它持有应用程序的配置信息。
.Enrich.FromLogContext(): 添加从日志上下文中丰富日志事件的能力,例如,可以自动地将关联的 HTTP 请求信息添加到日志中。
.WriteToConsole(): 配置 Serilog 将日志输出到控制台。
.WriteToFile(): 配置 Serilog 将日志输出到文件。
.WriteToElasticsearch(): 配置 Serilog 将日志输出到 Elasticsearch。这对于在 Elasticsearch 中集中管理和分析日志非常有用。
WriteToConsole与WriteToFile 也是拓展方法,那就继续Ctrl + F12 继续下去咯
public static class LoggerConfigurationExtensions
{
/// <summary>
/// 输出在控制台
/// </summary>
/// <param name="loggerConfiguration"></param>
/// <returns></returns>
public static LoggerConfiguration WriteToConsole(this LoggerConfiguration loggerConfiguration)
{
// 输出普通日志
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterRemoveSqlLog().WriteTo.Console());
// 输出SQL
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterSqlLog().WriteTo.Console());
return loggerConfiguration;
}
/// <summary>
/// 写入文件
/// </summary>
/// <param name="loggerConfiguration"></param>
/// <returns></returns>
public static LoggerConfiguration WriteToFile(this LoggerConfiguration loggerConfiguration)
{
// SQL语句写入
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterSqlLog()
.WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.EFSql, @"EFSql.txt"), rollingInterval: RollingInterval.Day,
outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));
// 非SQL写入
loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
lg.FilterRemoveSqlLog()
.WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.AuditLogs, @"AuditLog.txt"), rollingInterval: RollingInterval.Hour,
outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));
return loggerConfiguration;
}
/// <summary>
/// 推送至 ES
/// </summary>
/// <param name="loggerConfiguration"></param>
/// <returns></returns>
public static LoggerConfiguration WriteToElasticsearch(this LoggerConfiguration loggerConfiguration)
{
var esUri = AppSettings.GetValue("ElasticConfiguration:Uri");
loggerConfiguration = loggerConfiguration.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(
new Uri(esUri))
{
AutoRegisterTemplate = true,
IndexFormat = "nico-api-log-{0:yyyy.MM.dd}",
ModifyConnectionSettings = con => con.ServerCertificateValidationCallback((sender, certificate, chain, sslPolicyErrors) => true)
.BasicAuthentication(
AppSettings.GetValue("ElasticConfiguration:Es_UserName"),
AppSettings.GetValue("ElasticConfiguration:Es_Pwd"))
});
return loggerConfiguration;
}
/// <summary>
/// 过滤出 SQL语句的日志
/// </summary>
/// <param name="lc"></param>
/// <returns></returns>
public static LoggerConfiguration FilterSqlLog(this LoggerConfiguration lc)
{
return lc.Filter.ByIncludingOnly(e =>
e.Properties.ContainsKey("SourceContext") &&
e.Properties["SourceContext"].ToString().Contains("Microsoft.EntityFrameworkCore.Database.Command"));
}
/// <summary>
/// 过滤非 SQL语句的日志
/// </summary>
/// <param name="lc"></param>
/// <returns></returns>
public static LoggerConfiguration FilterRemoveSqlLog(this LoggerConfiguration lc)
{
return lc.Filter.ByExcluding(e =>
e.Properties.ContainsKey("SourceContext") &&
e.Properties["SourceContext"].ToString().Contains("Microsoft.EntityFrameworkCore.Database.Command"));
}
}
注释非常详尽,不再赘述,这里需要解释核心的问题,如何区别的SQL与非SQL的?
日志上下文 (SourceContext):Serilog 允许通过日志事件的属性来进行过滤。在这个例子中,使用了 SourceContext 属性,这是一个常用于标识日志来源的属性。对于由 Entity Framework Core 生成的日志,SourceContext 通常会包含值 "Microsoft.EntityFrameworkCore.Database.Command",这表示日志条目是由 EF Core 在执行数据库命令时产生的。
过滤器 (Filter.ByIncludingOnly):这个方法允许配置日志系统仅包含符合特定条件的日志条目。在这里,条件是日志事件的属性中必须包含 SourceContext,并且其值包含 "Microsoft.EntityFrameworkCore.Database.Command"。这样,只有 EF Core 产生的数据库命令日志会被包括进来。
如果此节看懂了,下面实践绝对难不倒读者。
部署ES
本人在部署ES的时候遇到了很多坑,看到一些大佬的博客也是一笔带过,这里用Docker desktop 一步一步全部覆盖到位,跟着文章步骤走,绝对搞得定。
启动elasticsearch 、 kibana
首先先贴上 ES官方文档启动教程 https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html
下载elasticsearch 、 kibana 镜像,本文截至24年7月30日,使用最新的ES版本8.14.3
docker创建网络
docker network create elastic-net
docker中启动ES,并且记住登录的密码,加入集群的Token
docker run --name es01 --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -t elasticsearch:8.14.3
启动之后,会在终端显示密码,还有加入集群的Token,待会在启动kibana时要用,如果不小心关掉了,可以在docker desktop中,找到es的容器日志找到。
到这里ES启动完成,接下来启动Kibana
docker中启动kibana,加入集群
docker run --name kib01 --net elastic -p 5601:5601 kibana:8.14.3
http://0.0.0.0/5601 可能进不去(改了host文件的原因),用 http://localhost/5601即可
将token传入 ,静待部署完成, 就进入了登录界面
账号默认为 elastic 密码(小写) 则为一开始保存的 密码,这里为 _*5O7P+5FKSV7nC_EDEE 记得改为你自己的 ,成功登录之后就进入后台页面
ES后台创建数据集 (DataView)
创建 Data view , 此时需要重点注意 , Index pattern这里需要填对应索引的名称,匹配成功才能在Discover中看到日志
至此 ES 搭建完成,现在要去将 Log 推送到 ES平台来
启动!!!
上文中已经将ES部署好了,现在需要将项目跑起来,将日志推送到ES平台中去。
修改项目配置
数据库使用的是SQL Server , 需要修改为你自己的SQL 链接字符串即可。
"ConnectionStrings": {
// SQL Server
"NicoLocaldbStr": "Data Source=localhost;Initial Catalog=nicolocaldb;User ID=sa;Password=MyStrongPwd!2#;Trust Server Certificate=True"
}
这里需要加张表
-- SQL Server
CREATE TABLE TestEFTable (
Id INT PRIMARY KEY IDENTITY(1,1), -- Id 列为主键并设置为自增
Name NVARCHAR(255) NULL, -- Name 列,允许 NULL,使用 NVARCHAR 类型来支持 Unicode 字符
LastModifiedAt DATETIMEOFFSET NULL, -- LastModifiedAt 列,允许 NULL,使用 DATETIMEOFFSET 类型
LastModifiedBy INT NOT NULL -- LastModifiedBy 列,不允许 NULL
);
"ElasticConfiguration": {
"Uri": "https://localhost:9200", // ES 地址
"Es_UserName": "elastic", // 账号
"Es_Pwd": "_*5O7P+5FKSV7nC_EDEE" // 密码
}
ES 的配置同样修改为自己的配置。
原神启动!(bushi
F5启动! (以下是操作视频)
https://www.bilibili.com/video/BV1w3vUeWE4n/
总结
稍微总结一下,
- Demo集成了Elasticsearch,Serilog,拦截器,autofac,EF。
- 区分EF 与非EF日志的记录与存放
- 记录完整的操作视频,包教包会!
源代码仓库 [GitHub] https://github.com/OrzCoCo-Y/LogSampleDemo
[Gitee] https://gitee.com/yi_zihao/LogSampleDemo
参考资料
【ChatGPT】
【严架的Maomi 框架】https://maomi.whuanle.cn 借鉴了其中HTTP日志记录,取代了自己写中间件
【老八的哲学开源框架】https://github.com/anjoy8/Blog.Core 借鉴了其中服务注册
Net8将Serilog日志推送ES,附视频的更多相关文章
- asp.net core使用serilog将日志推送到腾讯云日志服务
为什么是serilog? Serilog是 .NET 中最著名的结构化日志类库. 基于日志事件log events,而不是日志消息log message. 你可以将日志事件格式化为控制台的可读文本或者 ...
- iOS原生推送(APNS)进阶iOS10推送图片、视频、音乐
代码地址如下:http://www.demodashi.com/demo/13208.html 前言 我们首先要在AppDelegate里面进行iOS的适配,可以参考这篇文章 iOS原生推送(APNS ...
- Android 4.3发布 新增4大改变25日推送升级[附Android 4.3 工厂镜像]
北京时间7月25日,谷歌举行发布会,正式发布了全新的Nexus 7平板电脑以及Android 4.3系统. 其中Android 4.3系统隶属于4.X果冻豆(Jelly Bean)系列,是目前最新的操 ...
- html5 websocket 实时日志推送
http://blog.csdn.net/neutrojan/article/details/46119645
- 使用SignalR从服务端主动推送警报日志到各种终端(桌面、移动、网页)
微信公众号:Dotnet9,网站:Dotnet9,问题或建议:请网站留言, 如果对您有所帮助:欢迎赞赏. 使用SignalR从服务端主动推送警报日志到各种终端(桌面.移动.网页) 阅读导航 本文背景 ...
- Kindle 推送教程:教你用电子邮箱推送电子书(Kindle伴侣)
Kindle 推送是什么意思?如何通过电子邮件附件推送?或许刚刚接触 Kindle 的朋友对这个概念不是很清楚,其实所谓 Kindle 推送是指亚马逊提供的一个"Kindle 个人文档服务& ...
- Kindle 推送教程:教你用电子邮箱推送电子书
Kindle 推送是什么意思?如何通过电子邮件附件推送?或许刚刚接触 Kindle 的朋友对这个概念不是很清楚,其实所谓 Kindle 推送是指亚马逊提供的一个"Kindle 个人文档服务& ...
- [转]Kindle 推送教程:教你用电子邮箱推送电子书
Kindle 推送是什么意思?如何通过电子邮件附件推送?或许刚刚接触 Kindle 的朋友对这个概念不是很清楚,其实所谓 Kindle 推送是指亚马逊提供的一个“Kindle 个人文档服务”,我们只需 ...
- C# 实现IP视频监控(摄像头)画面推送(简单的不能再简单的DEMO)
最近继续在家休息,在完成上一个Python抓取某音乐网站爬虫后,琢磨着实现一个基于HTTP推送的 IP视频监控,比如外出的时候,在家里 开启一个监控端(摄像头+服务端),可以看到实时画面,如果再加上自 ...
- APP消息推送功能
1.APP内部最好设计-我的消息-的功能,以便用户查看推送消息历史记录,通过角标.已读.未读等设计吸引用户读取消息.(画下来这都是重点) 2.建议提供推送设置功能,允许用户设置推送消息是否显示于通知栏 ...
随机推荐
- linux系统下,安装mysql教程
1.查看mysql是否安装 首先我们需要查看软件是否已经安装,或者说查看安装的软件包名称.如查找是否安装mysql rpm -qa | grep mysql 2.卸载查到的软件 rpm -e --no ...
- INFINI Labs 产品更新 | Console 数据迁移支持 Percentiles 均匀分区
INFINI Labs 产品又更新啦~,包括 Console v1.14.0,Gateway 1.21.0.其中 Console 数据迁移支持 Percentiles 均匀分区,修复已知 Bug 等. ...
- C#.NET 简单使用log4net
1.nuget 中安装log4net 2.添加一个配置文件"log4net2.config",内容如下: <?xml version="1.0" enco ...
- 项目管理--PMBOK 读书笔记(11)【项目风险管理】
1.风险分解结构(RBS): RBS 有两个含义,一个是资源分解结构(Resource),一个是风险分解结构(Risk). 1)技术风险 2)管理风险 3)商业风险 4)外部风险 2.核对单 核对 ...
- vue使用wx-open-launch-weapp
vue使用wx-open-launch-weapp 官方文档 <template> <div style="width: 100%; height: 100%;" ...
- echarts 各种特效图
饼图标签展示数值 配置项: option = { title: { text: '项目时间分布', left: 'center' }, tooltip: { trigger: 'item', form ...
- 【题解】CatOJ C0458C 滑动窗口定期重构
标题 trick 的名字我也不知道是什么,就这样吧. 首先有显然的 dp 式子:\(f(i)=\min \{f(j) \times \max\{a_{j+1},\dots,a_i\}\}\).考虑怎么 ...
- Jenkins构建项目遇到的问题总结
4.2.1 在Windows下,Jenkins运行python项目 https://www.jianshu.com/p/f6edbaaa8a0d 4.2.2 配置不同类型的项目的操作步骤 http ...
- kong网关部署
软件版本: Postgresql:9.6 (不使用最新版,是因为 konga 不支持) Kong:3.4.2 konga:0.14.7 (UI管理界面) ### Postgresql部署 ## doc ...
- 2019徐州区域赛 ACEFM 题解 & pollard-rho & miller-rabin & 求出每个子树的重心 板子
A. Cat 题目大意:你需要在 [L , R] 选取连续的一段,使得这一段的异或和小于给定的数 S. 请求出最长的长度. 做法:我们可以发现 \[(2k) \oplus (2k+1) = 1, (2 ...