ASP.NET Core MVC之Serilog日志处理,你了解多少?

时间:2022-09-01 17:06:21

前言

本节我们来看看ASP.NET Core MVC中比较常用的功能,对于导入和导出目前仍在探索中,项目需要自定义列合并,所以事先探索了如何在ASP.NET Core MVC进行导入、导出,更高级的内容还需等我学习再给出。

EntityFramework Core

在学习ASP.NET Core MVC之前我们来看看在EF Core中如何更新对象指定属性,这个问题之前我们已经探讨过,但是还是存在一点问题,请往下看。

        public void Update(T entity, params Expression<Func<T, object>>[] properties)
{
_context.Entry(entity).State = EntityState.Unchanged;
foreach (var property in properties)
{
var propertyName = ExpressionHelper.GetExpressionText(property);
_context.Entry(entity).Property(propertyName).IsModified = true;
}
}

上述方法可以用来更新对象指定属性,使用lambda来指定需要更新的属性,如下:

        [HttpGet("[action]")]
public IActionResult Index()
{
var blog = new Blog() { Id = , Name = "Jeffcky1" };
_blogRepository.Update(blog, d => d.Name);
_blogRepository.SaveChanges();
}

但是当更新数值类型时会解析不到该属性,如下:

             var blog = new Blog() { Id = , Count =  };
_blogRepository.Update(blog, d => d.Count);
_blogRepository.SaveChanges();

此时得到该属性名称为空字符串

ASP.NET Core MVC之Serilog日志处理,你了解多少?

lambda为何解析不到呢?原来它进行了Convert如下:

ASP.NET Core MVC之Serilog日志处理,你了解多少?

既然是将其转换成了Convert,那么在表达式树中应该用其节点类型,如下:

ASP.NET Core MVC之Serilog日志处理,你了解多少?

此时我们需要判断其节点类型是否已经经过Convert即可,最终代码如下:

        public void Update(T entity, params Expression<Func<T, object>>[] properties)
{ EntityEntry<T> entry = _context.Entry(entity);
entry.State = EntityState.Unchanged;
foreach (var property in properties)
{
string propertyName = "";
Expression bodyExpression = property.Body;
if (bodyExpression.NodeType == ExpressionType.Convert && bodyExpression is UnaryExpression)
{
Expression operand = ((UnaryExpression)property.Body).Operand;
propertyName = ((MemberExpression)operand).Member.Name;
}
else
{
propertyName = ExpressionHelper.GetExpressionText(property);
}
entry.Property(propertyName).IsModified = true;
}
}

此时将能正确解析到数值类型名称,如下:

ASP.NET Core MVC之Serilog日志处理,你了解多少?

为何要封装这一层,只是不想首先查询出对象然后再来进行更新属性,其两步操作合并为一步岂不爽哉。当然我们也可以不通过lambda来实现,直接给出属性集合,然后遍历即可,大概如下:

        public void Update(T entity, params object[] properties)
{
_context.ChangeTracker.TrackGraph(entity, e =>
{
e.Entry.State = EntityState.Unchanged;
if ((e.Entry.Entity as T) != null)
{
foreach (var p in properties)
{
_context.Entry(e.Entry.Entity as T).Property(p.ToString()).IsModified = true;
} }
});
}

Serilog日志输出

目前比较流行的日志框架则是Log4net、NLog,之前也一直用的Log4net,但是在.net core中已经内置了日志框架Serilog,在github上也已加星不少,想必比较强大,既然这样为何不使用内置的呢,免去再用其他日志框架还要配置的麻烦。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

创建默认项目在Startup中已经注入日志,如下:

loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();

当利用dotnet.exe调试时在控制台会显示调试各种信息,要是直接运行那该如何呢?在web中的配置文件web.config中,如下:

 <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
</system.webServer>

我们需要设置 stdoutLogEnabled="true" 来启动调试,此时运行项目你会发现屁都没有,此时我们查看windows日志发现根本无法创建文件夹,想必是没有权限的缘故。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

此时我们需要手动创建logs文件夹,最终运行程序则会自动将所有信息写入到日志文件中,如下:

ASP.NET Core MVC之Serilog日志处理,你了解多少?

是不是这样就完了呢,这样设置则会将所有信息都会写入日志那样岂不是额外做些无用功,看看如下生成的日志。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

光说不练假把式,来,我们来实现一个,让你见识见识Serilog的强大。先定义一个自定义输出格式的Option并创建输出日志文件夹。

    public class JeffckyLogOptions
{
public string LogPath { get; set; } = @"C:\Jeffcky_StudyEFCore\logs"; public string PathFormat { get; set; } public static void EnsurePreConditions(JeffckyLogOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
} if (string.IsNullOrWhiteSpace(options.LogPath))
{
throw new ArgumentException("系统日志文件存储路径未配置", nameof(options.LogPath));
} if (string.IsNullOrWhiteSpace(options.PathFormat))
{
throw new ArgumentException("系统日志文件名称未配置", nameof(options.PathFormat));
} if (!Directory.Exists(options.LogPath))
{
Directory.CreateDirectory(options.LogPath);
}
}
}

内置实现日志的接口.net core已经给出,所以我们需要获取内置日志接口服务并实现自定义扩展方法。

app.ApplicationServices.GetService(typeof(ILoggerFactory));

此时上述app来源于 IApplicationBuilder 此时我们则只需要实现该接口的自定义扩展方法。我们开始下载Serilog程序包

ASP.NET Core MVC之Serilog日志处理,你了解多少?

此时我们需要对日志通过 LoggerConfiguration 类进行初始化配置。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

接下来则是将日志写到文件中我们可以自定义格式,此时再下载如下程序包。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

里面有个 RollingFile 方法来自定输出日志模板,自此我们就有了如下代码:

          var serilog = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.RollingFile(Path.Combine(options.LogPath, options.PathFormat),
outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {Message}{NewLine}{Exception}");

我们获取.net core内置的日志接口服务。

 ILoggerFactory loggerFactory = (ILoggerFactory)app.ApplicationServices.GetService(typeof(ILoggerFactory));

同时设置我们输出日志的路径选项。

JeffckyLogOptions.EnsurePreConditions(options);

接下来将Serilog创建的日志添加到内置日志服务中,如下:

 loggerFactory.AddSerilog(serilog.CreateLogger());

当然上述AddSerilog方法时扩展方法,此时我们仍需要添加如下扩展程序包:

ASP.NET Core MVC之Serilog日志处理,你了解多少?

最后还差一步则是日志的生命周期,灰常重要,为什么说灰常重要,我们要确保当程序关闭时或者系统出问题时所有在内存缓冲区的日志都将输送到日志文件夹中,如下:

            // Ensure any buffered events are sent at shutdown
IApplicationLifetime appLifetime = (IApplicationLifetime)app.ApplicationServices.GetService(typeof(IApplicationLifetime));
if (appLifetime != null)
{
appLifetime.ApplicationStopped.Register(Log.CloseAndFlush);
}

一气呵成,最终我们在Startup的如下方法中进行调用即可:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{...}

利用Serilog添加自定日志格式输出,进行如下调用:

            app.UseJeffckySelfDefineLog(new JeffckyLogOptions()
{
LogPath = Configuration[nameof(JeffckyLogOptions.LogPath)],
PathFormat = "Jeffcky_StudyEFCore_{Date}.log"
});

当然还有其他强大功能,比如Serilog中可以获取到上下文,这样的话我们就可以过滤对于那个应用程序使用对应的日志输出级别以及其他,如下:

                serilog = serilog.Filter.ByIncludingOnly((e) =>
{
var context = e.Properties["SourceContext"].ToString(); return (context.StartsWith("\"Your Applicion Name") ||
e.Level == LogEventLevel.Warning ||
e.Level == LogEventLevel.Error ||
e.Level == LogEventLevel.Fatal);
});

说一千到一万,出现结果才是真理,我们一起来看看。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

看看日志输出信息,你会看到干净的日志输出。

ASP.NET Core MVC之Serilog日志处理,你了解多少?

总结

本节我们详细讲解了.net core中新生代日志框架-Serilog,别抱着Log4net不放了,Serilog你值得拥有,跟着老大一直学习中,涨涨见识!因为项目中会用到批量导入和导出,所以在研究导出、导入,下节可能会讲到导入、导出在ASP.NET Core MVC中,也有可能会讲SQL Server中的最后几节关于死锁的内容,不管怎样都是在积累知识,你说呢,敬请期待!

ASP.NET Core MVC之Serilog日志处理,你了解多少?的更多相关文章

  1. asp&period;net core MVC 全局过滤器之ExceptionFilter异常过滤器&lpar;一&rpar;

    本系类将会讲解asp.net core MVC中的内置全局过滤器的使用,将分为以下章节 asp.net core MVC 过滤器之ExceptionFilter异常过滤器(一) asp.net cor ...

  2. asp&period;net core MVC 过滤器之ActionFilter过滤器&lpar;二&rpar;

    本系类将会讲解asp.net core MVC中的内置全局过滤器的使用,将分为以下章节 asp.net core MVC 过滤器之ExceptionFilter过滤器(一) asp.net core ...

  3. ASP&period;NET Core MVC&plus;EF Core从开发到部署

    笔记本电脑装了双系统(Windows 10和Ubuntu16.04)快半年了,平时有时间就喜欢切换到Ubuntu系统下耍耍Linux,熟悉熟悉Linux命令.Shell脚本以及Linux下的各种应用的 ...

  4. Asp&period;Net Core MVC框架内置过滤器

    第一部分.MVC框架内置过滤器 下图展示了Asp.Net Core MVC框架默认实现的过滤器的执行顺序: Authorization Filters:身份验证过滤器,处在整个过滤器通道的最顶层.对应 ...

  5. ASP&period;NET Core MVC内置服务的使用

    ASP.NET Core中的依赖注入可以说是无处不在,其通过创建一个ServiceCollection对象并将服务注册信息以ServiceDescriptor对象的形式添加在其中,其次针对Servic ...

  6. ASP&period;NET Core MVC 2&period;x 全面教程&lowbar;ASP&period;NET Core MVC 02&period; Web Host 的默认配置

    视频地址: https://www.bilibili.com/video/av38392956/?p=2 语雀 https://www.yuque.com/yuejiangliu/dotnet/ixt ...

  7. 从零开始实现ASP&period;NET Core MVC的插件式开发&lpar;六&rpar; - 如何加载插件引用

    标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/1171 ...

  8. asp&period;net core MVC 过滤器之ExceptionFilter过滤器&lpar;一&rpar;

    简介 异常过滤器,顾名思义,就是当程序发生异常时所使用的过滤器.用于在系统出现未捕获异常时的处理. 实现一个自定义异常过滤器 自定义一个异常过滤器需要实现IExceptionFilter接口 publ ...

  9. 如何在 ASP&period;Net Core 中使用 Serilog

    记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...

随机推荐

  1. C&num; 图片压缩

    /// <summary>        /// 图片压缩方法        /// </summary>        /// <param name="sF ...

  2. ios7中的多任务

    转自:http://onevcat.com/2013/08/ios7-background-multitask/ WWDC 2013 Session笔记 - iOS7中的多任务 iOS7的后台多任务特 ...

  3. Java算法-堆排序

    package org.rut.util.algorithm.support; import org.rut.util.algorithm.SortUtil; public class HeapSor ...

  4. LinuxC语言读取文件,分割字符串,存入链表,放入另一个文件

    //file_op.c #include <string.h> #include <stdio.h> #include <stdlib.h> struct info ...

  5. eclipse 插件未安装成功定位

    以gef未安装成功为例 在eclipse根目录下: eclipse –clean –console –noExit 右击窗口标题栏,属性,勾中快速编辑模式,这样可以在命令行窗口点击右键将剪贴板上的内容 ...

  6. CentOS&colon;安装桌面GNOME图形化界面

    u盘安装dvd版的CentOS7后,没有桌面,浏览器也是黑框版的:如果需要桌面的话,下面三条命令即可:但是安装桌面后,系统会没有之前纯净: 1 安装Gnome包: sudo yum groupinst ...

  7. 快速入门Http协议

    本节主要讲解http协议相关的内容,作为后期讲述的一个预备知识.深入了解Http协议,对你今后的JavaSE,JavaEE学习都大有裨益,本节难度不是很大,却很重要. 早期的Http协议是1.0版本的 ...

  8. Ceph神坑系列

    1. 在使用librbd的过程中,发现一个如果ceph集群异常librbd函数不返回的问题,对librbd的源码进行跟踪,发现了rados接口中的rados_mon_op_timeout(how ma ...

  9. 如何在BIOS中设置RAID?

    随着价格的下降和相应主板的支持,目前SATA硬盘已经逐渐成为主流.但由于受芯片组和操作系统的影响,不少用户对SATA硬盘的使用及安装系统掌握不足,今天小编就给大家介绍一下SATA硬盘的日常应用技巧,希 ...

  10. 【NOIP模拟赛】总结

    题目描述 输入 第一行是5个正整数,n,m,k,S,T,分别代表无向图点数,边数,蝙蝠的数量,二小姐所在起点的编号,目标点的编号. 第二行是k个正整数,分别代表大小姐每个蝙蝠所在的起点的编号.接下来有 ...