首页 > 其他分享 >.Net Core微服务 - Serilog+Seq记录日志

.Net Core微服务 - Serilog+Seq记录日志

时间:2024-03-19 13:55:40浏览次数:47  
标签:Core Seq 1024 Serilog NewLine diagnosticContext 日志 public

Serilog介绍

Serilog 是用于 .NET 应用程序的诊断日志记录库。它易于设置,具有干净的 API,并且可以在所有最新的 .NET 平台上运行。Serilog 通过NuGet分发,项目包括一个Seirlog核心项目Seirlog和很多接收器sinks(超过100个),这些接收是通过插件的方式来实现将日志写入到各种终端、文件、邮件、数据库或日志服务器。

在ASP.NET CORE 中使用Serilog记录日志

在asp.net core 中使用Serilog记录日志、按日志级别异步记录写入日志文件、写入控制台打印、异步写入Seq

 <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
    <PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
    <PackageReference Include="Serilog.Expressions" Version="3.4.1" />
    <PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
    <PackageReference Include="Serilog.Sinks.Seq" Version="5.2.2" />
  </ItemGroup>

Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        try
        {
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "*** Program Stop ***");
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
         Host.CreateDefaultBuilder(args)
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseStartup<Startup>();
             });
}

Startup.cs

   public class Startup
    {
        public IConfiguration Configuration { get; }
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public void ConfigureServices(IServiceCollection services)
        {
            // 使用Serilog记录日志
            services.AddConfigSerilog(configuration: Configuration);

            services.AddControllers();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // 使用Serilog记录请求日志
            app.UseSerilogRequestLogging();

            app.UseRouting();
            app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
        }
    }

ApplicationBuilderExtensions.cs

    /// <summary>
    /// ApplicationBuilder 扩展
    /// </summary>
    public static class ApplicationBuilderExtensions
    {
        /// <summary>
        ///  添加使用Serilog请求日志
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseSerilogRequestLogging(this IApplicationBuilder app)
        {
            //允许body重用
            app.Use(next => context =>
            {
                context.Request.EnableBuffering();
                return next(context);
            });

            // 添加使用Serilog记录请求日志
            app.UseSerilogRequestLogging(options =>
            {
                // 请求日志输出模板
                options.MessageTemplate = "\n[R] {RequestMethod}={_RequestPath} | Status={StatusCode} | Time={Elapsed}ms\n[R] Req={_RequestBody} | Res={_ResponseBody}";

                // 发出调试级别事件而不是默认事件,将请求日志记录到:Debug日志
                options.GetLevel = (httpContext, elapsed, ex) => LogEventLevel.Debug;

                // 将其他属性附加到请求完成事件,将请求属性附加可以在模板中使用
                options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
                {
                    diagnosticContext.Set("_RequestPath", WebUtility.UrlDecode(httpContext.Request.Path + httpContext.Request.QueryString));

                    //请求body
                    var requestContent = "";
                    var method = httpContext.Request.Method.ToLower();
                    if (method == "post" || method == "put")
                    {
                        httpContext.Request.Body.Position = 0;
                        var requestReader = new StreamReader(httpContext.Request.Body);
                        requestContent = requestReader.ReadToEnd();
                    }
                    diagnosticContext.Set("_RequestBody", requestContent);
                    diagnosticContext.Set("_Service",AppDomain.CurrentDomain.FriendlyName);
                };
            });

            return app;
        }
    }

ServiceCollectionExtensions.cs

    /// <summary>
    /// ServiceCollection 扩展
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 添加配置Serilog
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration"></param>
        /// <returns></returns>
        public static IServiceCollection AddConfigSerilog(this IServiceCollection services, IConfiguration configuration)
        {
            var seqApiKey = configuration["seq:apiKey"].ToString();
            var seqServerUrl = configuration["seq:serverUrl"].ToString();

            // 创建Serilog记录日志
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .MinimumLevel.Override("System", LogEventLevel.Debug)
                .MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
                .MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Error)
                .MinimumLevel.Override("Microsoft.AspNetCore.Cors.Infrastructure.CorsService", LogEventLevel.Error)
                .MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Error)
                .MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Error)
                // 全部日志写入到Console
                .WriteTo.Async(c => c.Console(
                   theme: AnsiConsoleTheme.Literate,
                    outputTemplate: "[T] {Timestamp:yyyy-MM-dd HH:mm:ss,fff} {MachineName}{NewLine}[L] [{Level}]{NewLine}[C] [{SourceContext}] {Message:lj}{NewLine}{Exception}{NewLine}"))
                // Information日志写入到文件
                .WriteTo.Async(c => c.File(
                    path: "Logs/Information/.txt",
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1L * 1024 * 1024 * 1024,
                    retainedFileCountLimit: 31,
                    outputTemplate: "[T] {Timestamp:yyyy-MM-dd HH:mm:ss,fff} {MachineName}{NewLine}[L] [{Level}]{NewLine}[C] [{SourceContext}] {Message:lj}{NewLine}{Exception}{NewLine}",
                    restrictedToMinimumLevel: LogEventLevel.Information))
                // Debug日志写入到文件
                .WriteTo.Async(c => c.File(
                    path: "Logs/Debug/.txt",
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1L * 1024 * 1024 * 1024,
                    retainedFileCountLimit: 31,
                    outputTemplate: "[T] {Timestamp:yyyy-MM-dd HH:mm:ss,fff} {MachineName}{NewLine}[L] [{Level}]{NewLine}[C] [{SourceContext}] {Message:lj}{NewLine}{Exception}{NewLine}",
                    restrictedToMinimumLevel: LogEventLevel.Debug))
                // Warning日志写入到文件
                .WriteTo.Async(c => c.File(
                    path: "Logs/Warning/.txt",
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1L * 1024 * 1024 * 1024,
                    retainedFileCountLimit: 31,
                    outputTemplate: "[T] {Timestamp:yyyy-MM-dd HH:mm:ss,fff} {MachineName}{NewLine}[L] [{Level}]{NewLine}[C] [{SourceContext}] {Message:lj}{NewLine}{Exception}{NewLine}",
                    restrictedToMinimumLevel: LogEventLevel.Warning))
                // Error日志写入到文件
                .WriteTo.Async(c => c.File(
                    path: "Logs/Error/.txt",
                    rollingInterval: RollingInterval.Day,
                    fileSizeLimitBytes: 1L * 1024 * 1024 * 1024,
                    retainedFileCountLimit: 31,
                    outputTemplate: "[T] {Timestamp:yyyy-MM-dd HH:mm:ss,fff} {MachineName}{NewLine}[L] [{Level}]{NewLine}[C] [{SourceContext}] {Message:lj}{NewLine}{Exception}{NewLine}",
                    restrictedToMinimumLevel: LogEventLevel.Error))
                // 全部日志写入到Seq
                .WriteTo.Async(c => c.Seq(
                    apiKey: seqApiKey,
                    serverUrl: seqServerUrl))
                .Enrich.FromLogContext()
                .Enrich.WithMachineName()
                // 过滤请求:/health心跳
                .Filter.ByExcluding("RequestPath like '/health%'")
                .CreateBootstrapLogger();

            services.AddSerilog();

            return services;
        }
    }

RequestAuditLogFilter.cs

   public class RequestAuditLogFilter : IResultFilter
    {
        private readonly IDiagnosticContext _diagnosticContext;

        public RequestAuditLogFilter(IDiagnosticContext diagnosticContext) { _diagnosticContext = diagnosticContext; }

        public void OnResultExecuted(ResultExecutedContext context)
        {
            var result = context.Result as ObjectResult;
            var resultJson = JsonConvert.SerializeObject(result?.Value);
            _diagnosticContext.Set("_ResponseBody", resultJson);
        }

        public void OnResultExecuting(ResultExecutingContext context) { }
    }

RequestAuditLogAttribute.cs

    public class RequestAuditLogAttribute : TypeFilterAttribute
    {
        public RequestAuditLogAttribute() : base(typeof(RequestAuditLogFilter)) { }
    }

HomeController.cs

   [Route("api/[controller]")]
    [ApiController]
    public class HomeController : ControllerBase
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IDiagnosticContext _diagnosticContext;

        public HomeController(ILogger<HomeController> logger, IDiagnosticContext diagnosticContext)
        {
            _logger = logger;
            _diagnosticContext= diagnosticContext;
        }

        [HttpGet("LogInformation")]
        [RequestAuditLog]
        public string LogInformation()
        {
            return "ok";
        }

        [HttpGet("LogError")]
        [RequestAuditLog]
        public string LogError()
        {
            int a = 10;
            int b = 0;
            int c = a / b;
            return "ok";
        }

        [HttpPost("LogRequest")]
        [RequestAuditLog]
        public List<string> LogRequest([FromBody] List<string> input)
        {
            for (int i = 0; i < 10; i++)
            {
                input.Add(Guid.NewGuid().ToString());
            }
            return input;
        }
    }

image
image

标签:Core,Seq,1024,Serilog,NewLine,diagnosticContext,日志,public
From: https://www.cnblogs.com/heyangyi/p/18082599

相关文章

  • 不通过 Host 将 Serilog 转换成 ILogger
    安装SerilogpublicstaticclassLoggerExtension{publicstaticILogger<T>CreateLogger<T>(){varlogPath="log.txt";conststringoutputTemplate="[{Timestamp:yyyy-MM-ddHH:mm:ss}{Level:u3}]{Message:......
  • EFcore 连接mysql的一些坑。
    好久不耍mysql了,EFcore连接的时候遇到了点问题,特此记录下来,防止以后又忘了。 第一个问题相当的奇葩,居然告诉我缺.NETcore2.0,,,无语,估计是依赖项里面引用了2.0,于是乎老老实实去官网下载安装。地址如下:https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/sdk-2.0......
  • netcore接入elk
    一、elk的安装教程参考链接:https://www.8kiz.cn/archives/2623.html 二、netcore接入elk1、NLog接入NLog日志输出到logstash里,使用方式①配置logstash,添加tcp端口输入input{tcp{port=>5044type=>"service1-log"}}②重启logstashsudosystemc......
  • Sitecore ListManagaer Operation
    privatevoidListManagerOperate(){//获取服务IClientApiServiceclientApiService=ServiceLocator.ServiceProvider.GetRequiredService<IClientApiService>();//EXMmanagerrootidstringmanagerRoot=Settings.GetSetting(Global.ExmRoot,......
  • CorelDRAW2024中文免费专业平面设计软件,让创意无限飞翔!
    CorelDRAW2024是一款功能强大的专业平面设计软件,它提供了丰富的绘图工具和特效,使用户能够轻松创建各种类型的设计,如图标、海报、宣传册等。无论是从事平面设计、插画、品牌设计还是其他创意领域,CorelDRAW2024都能满足你的需求,帮助你释放无限的创意潜力,让你的设计脱颖而出。......
  • Sitecore 通过 AutomatedMessage 发送邮件
    lasted:https://doc.sitecore.com/xp/en/users/exm/103/email-experience-manager/the-email-campaign-builder.htmlpublicstaticvoidSendEXMEmail(){ //发送人的名称 vartoUserName="Abigail"; //发送人的邮件 vartoEmail="abigail@gmail.com"; ......
  • 为什么ASP.NET Core的路由处理器可以使用一个任意类型的Delegate
    毫不夸张地说,路由是ASP.NETCore最为核心的部分。路由的本质就是注册一系列终结点(Endpoint),每个终结点可以视为“路由模式”和“请求处理器”的组合,它们分别用来“选择”和“处理”请求。请求处理器通过RequestDelegate来表示,但是当我们在进行路由编程的时候,却可以使用任意类型的De......
  • Asp.net Core关于自定义ControllerFeatureProvider的记录
    最近看公司的项目,发现公司对于自定义发现控制器搞了个方法,然后研究了一下,发现神奇现象基本原理可以查看 深入解析ASP.NETCoreMVC的模块化设计[上篇]-Artech-博客园(cnblogs.com) 大佬的博客这个是控制器的部分代码 publicclassApplicationServiceControl......
  • 安装"DESeq2", "edgeR", "limma", "clusterProfiler"几个R包
    安装"DESeq2","edgeR","limma","clusterProfiler"bioPackages=c("DESeq2","edgeR","limma","clusterProfiler")#设置镜像local({r<-getOption("repos");r["......
  • C#使用LINQ和EF Core
    在实际应用中,您可以使用LINQ查询EFCore来执行各种数据库操作。通过LINQ,您可以轻松地过滤、排序、分组和连接数据。要使用LINQ查询EFCore中的数据,您可以按照以下步骤进行操作:首先,确保您已经安装了EntityFrameworkCore包。然后,在您的C#项目中,创建一个继承自Db......