111 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Microsoft.AspNetCore.Builder;
 | |
| using Microsoft.Extensions.Configuration;
 | |
| using Microsoft.Extensions.Hosting;
 | |
| using Mirea.Api.Endpoint.Common.Services;
 | |
| using Mirea.Api.Endpoint.Configuration.Model;
 | |
| using Serilog;
 | |
| using Serilog.Context;
 | |
| using Serilog.Events;
 | |
| using Serilog.Filters;
 | |
| using Serilog.Formatting.Compact;
 | |
| using System.Collections.Generic;
 | |
| using System.Diagnostics;
 | |
| using System.IO;
 | |
| 
 | |
| namespace Mirea.Api.Endpoint.Configuration.Core.Startup;
 | |
| 
 | |
| public static class LoggerConfiguration
 | |
| {
 | |
|     public static IHostBuilder AddCustomSerilog(this IHostBuilder hostBuilder)
 | |
|     {
 | |
|         return hostBuilder.UseSerilog((context, _, configuration) =>
 | |
|         {
 | |
|             var generalConfig = context.Configuration.Get<GeneralConfig>()?.LogSettings;
 | |
|             configuration
 | |
|                 .MinimumLevel.Debug()
 | |
|                 .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
 | |
|                 .Enrich.FromLogContext()
 | |
|                 .WriteTo.Console(
 | |
|                     outputTemplate:
 | |
|                     "[{Level:u3}] [{Timestamp:dd.MM.yyyy HH:mm:ss}] {Message:lj}{NewLine}{Exception}");
 | |
| 
 | |
|             if (generalConfig?.EnableLogToFile == true)
 | |
|             {
 | |
|                 generalConfig.LogFilePath = PathBuilder.Combine(generalConfig.LogFilePath ?? string.Empty);
 | |
| 
 | |
|                 if (!string.IsNullOrEmpty(generalConfig.LogFilePath) && Directory.Exists(generalConfig.LogFilePath))
 | |
|                     Directory.CreateDirectory(generalConfig.LogFilePath);
 | |
| 
 | |
|                 configuration.WriteTo.File(
 | |
|                     new CompactJsonFormatter(),
 | |
|                     PathBuilder.Combine(
 | |
|                         generalConfig.LogFilePath!,
 | |
|                         generalConfig.LogFileName + ".json"
 | |
|                     ),
 | |
|                     LogEventLevel.Debug,
 | |
|                     rollingInterval: RollingInterval.Day);
 | |
|             }
 | |
| 
 | |
|             if (!string.IsNullOrEmpty(generalConfig?.OpenTelemetryEndpoint)
 | |
|                 && !string.IsNullOrEmpty(generalConfig.OpenTelemetryServiceName))
 | |
|                 configuration.WriteTo.OpenTelemetry(options =>
 | |
|                 {
 | |
|                     options.Endpoint = generalConfig.OpenTelemetryEndpoint;
 | |
|                     options.Protocol = Serilog.Sinks.OpenTelemetry.OtlpProtocol.Grpc;
 | |
|                     options.ResourceAttributes = new Dictionary<string, object>
 | |
|                     {
 | |
|                         ["service.name"] = generalConfig.OpenTelemetryServiceName,
 | |
|                         ["deployment.environment"] = context.HostingEnvironment.EnvironmentName
 | |
|                     };
 | |
|                 });
 | |
| 
 | |
|             configuration
 | |
|                 .MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Warning)
 | |
|                 .MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Warning)
 | |
|                 .MinimumLevel.Override("Microsoft.AspNetCore.Routing", LogEventLevel.Warning)
 | |
|                 .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Warning)
 | |
|                 .MinimumLevel.Override("Microsoft.AspNetCore.Authorization", LogEventLevel.Warning);
 | |
| 
 | |
|             configuration.Filter.ByExcluding(Matching.WithProperty<string>("SourceContext", sc =>
 | |
|                 sc.Contains("Microsoft.EntityFrameworkCore.Database.Command")));
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     public static IApplicationBuilder UseCustomSerilog(this IApplicationBuilder app)
 | |
|     {
 | |
|         return app.Use(async (context, next) =>
 | |
|         {
 | |
|             var traceId = Activity.Current?.Id ?? context.TraceIdentifier;
 | |
| 
 | |
|             using (LogContext.PushProperty("TraceId", traceId))
 | |
|             using (LogContext.PushProperty("UserAgent", context.Request.Headers.UserAgent.ToString()))
 | |
|             using (LogContext.PushProperty("RemoteIPAddress", context.Connection.RemoteIpAddress?.ToString()))
 | |
|             {
 | |
|                 await next();
 | |
|             }
 | |
|         }).UseSerilogRequestLogging(options =>
 | |
|         {
 | |
|             options.MessageTemplate = "[{RequestMethod}] {RequestPath} [Client {RemoteIPAddress}] [{StatusCode}] in {Elapsed:0.0000} ms";
 | |
| 
 | |
|             options.GetLevel = (httpContext, elapsed, ex) =>
 | |
|             {
 | |
|                 if (httpContext.Request.Path.StartsWithSegments("/health"))
 | |
|                     return LogEventLevel.Verbose;
 | |
| 
 | |
|                 return elapsed >= 2500 || ex != null
 | |
|                     ? LogEventLevel.Warning
 | |
|                     : elapsed >= 1000
 | |
|                         ? LogEventLevel.Information
 | |
|                         : LogEventLevel.Debug;
 | |
|             };
 | |
| 
 | |
|             options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
 | |
|                 {
 | |
|                     diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
 | |
|                     diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
 | |
|                     diagnosticContext.Set("UserAgent", httpContext.Request.Headers.UserAgent);
 | |
|                     diagnosticContext.Set("RemoteIPAddress", httpContext.Connection.RemoteIpAddress?.ToString() ?? string.Empty);
 | |
|                 };
 | |
|         });
 | |
|     }
 | |
| } |