refactor logging

This commit is contained in:
meysamhadeli 2022-09-10 21:31:15 +04:30
parent 0151c7b2c9
commit 4583b5eca7
11 changed files with 129 additions and 66 deletions

View File

@ -1,21 +1,12 @@
<Project> <Project>
<ItemGroup> <ItemGroup>
<PackageReference Include="Meziantou.Analyzer" Version="1.0.688" Condition="$(MSBuildProjectExtension) == '.csproj'" PrivateAssets="all">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference <PackageReference
Include="StyleCop.Analyzers" Include="StyleCop.Analyzers"
Version="1.2.0-beta.354" Version="1.2.0-beta.354"
PrivateAssets="all" PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'" Condition="$(MSBuildProjectExtension) == '.csproj'"
/> />
<PackageReference
Include="SonarAnalyzer.CSharp"
Version="8.29.0.36737"
PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'"
/>
<PackageReference <PackageReference
Include="Roslynator.Analyzers" Include="Roslynator.Analyzers"
@ -47,18 +38,20 @@
PrivateAssets="all" PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'" Condition="$(MSBuildProjectExtension) == '.csproj'"
/> />
<PackageReference
Include="SerilogAnalyzer"
Version="0.15.0"
PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'"
/>
</ItemGroup> <PackageReference
Include="Meziantou.Analyzer"
Version="1.0.723"
PrivateAssets="all"
Condition="$(MSBuildProjectExtension) == '.csproj'"
/>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -26,7 +26,7 @@ public static class Extensions
var healthChecksBuilder = services.AddHealthChecks() var healthChecksBuilder = services.AddHealthChecks()
.AddSqlServer(sqlOptions.DefaultConnection) .AddSqlServer(sqlOptions.DefaultConnection)
.AddRabbitMQ(rabbitConnectionString: $"amqp://{rabbitMqOptions.UserName}:{rabbitMqOptions.Password}@{rabbitMqOptions.HostName}") .AddRabbitMQ(rabbitConnectionString: $"amqp://{rabbitMqOptions.UserName}:{rabbitMqOptions.Password}@{rabbitMqOptions.HostName}")
.AddElasticsearch(logOptions.ElasticUri); .AddElasticsearch(logOptions.Elastic.ElasticServiceUrl);
if (mongoOptions.ConnectionString is not null) if (mongoOptions.ConnectionString is not null)
healthChecksBuilder.AddMongoDb(mongoOptions.ConnectionString); healthChecksBuilder.AddMongoDb(mongoOptions.ConnectionString);

View File

@ -0,0 +1,8 @@
namespace BuildingBlocks.Logging;
public class ElasticOptions
{
public bool Enable { get; set; }
public string ElasticServiceUrl { get; set; }
public string ElasticSearchIndex { get; set; }
}

View File

@ -1,47 +1,67 @@
using System.Reflection; using System.Text;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog; using Serilog;
using Serilog.Enrichers.Span;
using Serilog.Events; using Serilog.Events;
using Serilog.Exceptions; using Serilog.Exceptions;
using Serilog.Sinks.Elasticsearch; using Serilog.Sinks.Elasticsearch;
using Serilog.Sinks.SpectreConsole; using Serilog.Sinks.SpectreConsole;
namespace BuildingBlocks.Logging; namespace BuildingBlocks.Logging
public static class Extensions
{ {
public static class Extensions
{
public static WebApplicationBuilder AddCustomSerilog(this WebApplicationBuilder builder) public static WebApplicationBuilder AddCustomSerilog(this WebApplicationBuilder builder)
{ {
builder.Host.UseSerilog((context, loggerConfiguration) => builder.Host.UseSerilog((context, services, loggerConfiguration) =>
{ {
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var loggOptions = context.Configuration.GetSection(nameof(LogOptions)).Get<LogOptions>(); var logOptions = context.Configuration.GetSection(nameof(LogOptions)).Get<LogOptions>();
var appOptions = context.Configuration.GetSection(nameof(AppOptions)).Get<AppOptions>(); var appOptions = context.Configuration.GetSection(nameof(AppOptions)).Get<AppOptions>();
var logLevel = Enum.TryParse<LogEventLevel>(loggOptions.Level, true, out var level)
var logLevel = Enum.TryParse<LogEventLevel>(logOptions.Level, true, out var level)
? level ? level
: LogEventLevel.Information; : LogEventLevel.Information;
loggerConfiguration loggerConfiguration
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(loggOptions.ElasticUri)) .MinimumLevel.Is(logLevel)
.WriteTo.SpectreConsole(logOptions.LogTemplate, logLevel)
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
// Only show ef-core information in error level
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Error)
// Filter out ASP.NET Core infrastructure logs that are Information and below
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
.Enrich.WithExceptionDetails()
.Enrich.FromLogContext()
.ReadFrom.Configuration(context.Configuration);
if (logOptions.Elastic.Enable)
{
loggerConfiguration.WriteTo.Elasticsearch(
new ElasticsearchSinkOptions(new Uri(logOptions.Elastic.ElasticServiceUrl))
{ {
AutoRegisterTemplate = true, AutoRegisterTemplate = true,
IndexFormat = IndexFormat =
$"{appOptions.Name}-{environment?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM}" $"{appOptions.Name}-{environment?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM}"
}) });
.WriteTo.SpectreConsole(loggOptions.LogTemplate, logLevel) }
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Error)
.Enrich.WithSpan() if (logOptions.File.Enable)
.Enrich.WithExceptionDetails() {
.Enrich.FromLogContext() var path = string.IsNullOrWhiteSpace(logOptions.File.Path) ? "logs/.txt" : logOptions.File.Path;
.ReadFrom.Configuration(context.Configuration); if (!Enum.TryParse<RollingInterval>(logOptions.File.Interval, true, out var interval))
{
interval = RollingInterval.Day;
}
loggerConfiguration.WriteTo.File(path, rollingInterval: interval, encoding: Encoding.UTF8,
outputTemplate: logOptions.LogTemplate);
}
}); });
return builder; return builder;
} }
}
} }

View File

@ -0,0 +1,8 @@
namespace BuildingBlocks.Logging;
public class FileOptions
{
public bool Enable { get; set; }
public string Path { get; set; }
public string Interval { get; set; }
}

View File

@ -0,0 +1,10 @@
namespace BuildingBlocks.Logging
{
public class LogOptions
{
public string Level { get; set; }
public ElasticOptions Elastic { get; set; }
public FileOptions File { get; set; }
public string LogTemplate { get; set; }
}
}

View File

@ -1,8 +0,0 @@
namespace BuildingBlocks.Logging;
public class LogOptions
{
public string Level { get; set; }
public string LogTemplate { get; set; }
public string ElasticUri { get; set; }
}

View File

@ -3,9 +3,17 @@
"Name": "Booking-Service" "Name": "Booking-Service"
}, },
"LogOptions": { "LogOptions": {
"Level": "Information", "Level": "information",
"LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}",
"ElasticUri": "http://localhost:9200" "Elastic": {
"Enable": true,
"ElasticServiceUrl": "http://localhost:9200"
},
"File": {
"enable": false,
"path": "logs/logs.txt",
"interval": "day"
}
}, },
"Jwt": { "Jwt": {
"Authority": "https://localhost:5005", "Authority": "https://localhost:5005",

View File

@ -3,9 +3,17 @@
"Name": "Flight-Service" "Name": "Flight-Service"
}, },
"LogOptions": { "LogOptions": {
"Level": "Information", "Level": "information",
"LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}",
"ElasticUri": "http://localhost:9200" "Elastic": {
"Enable": true,
"ElasticServiceUrl": "http://localhost:9200"
},
"File": {
"enable": false,
"path": "logs/logs.txt",
"interval": "day"
}
}, },
"ConnectionStrings": { "ConnectionStrings": {
"DefaultConnection": "Server=.\\sqlexpress;Database=FlightDB;Trusted_Connection=True;MultipleActiveResultSets=true" "DefaultConnection": "Server=.\\sqlexpress;Database=FlightDB;Trusted_Connection=True;MultipleActiveResultSets=true"

View File

@ -12,9 +12,17 @@
"Password": "guest" "Password": "guest"
}, },
"LogOptions": { "LogOptions": {
"Level": "Information", "Level": "information",
"LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}",
"ElasticUri": "http://localhost:9200" "Elastic": {
"Enable": true,
"ElasticServiceUrl": "http://localhost:9200"
},
"File": {
"enable": false,
"path": "logs/logs.txt",
"interval": "day"
}
}, },
"PersistMessageOptions": { "PersistMessageOptions": {
"Interval": 30, "Interval": 30,

View File

@ -20,9 +20,17 @@
"Password": "guest" "Password": "guest"
}, },
"LogOptions": { "LogOptions": {
"Level": "Information", "Level": "information",
"LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}",
"ElasticUri": "http://localhost:9200" "Elastic": {
"Enable": true,
"ElasticServiceUrl": "http://localhost:9200"
},
"File": {
"enable": false,
"path": "logs/logs.txt",
"interval": "day"
}
}, },
"PersistMessageOptions": { "PersistMessageOptions": {
"Interval": 30, "Interval": 30,