扩展包安装
<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.AspNetCore" Version="6.1.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
封装
using Masuit.Tools;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Net7.Configuration;
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Elasticsearch;
using Serilog.Sinks.Elasticsearch;
namespace Net7.Core
{
public static class SerilogHostSetup
{
public static void AddSerilogHost(this IHostBuilder builder, IServiceCollection serviceProvider, ConfigurationManager configuration)
{
var options = configuration.GetSection(SerilogOptions.Position).Get<SerilogOptions>();
Log.Logger = new LoggerConfiguration()
.ConfigureFile(options.File)
.ConfigureConsole(options.Console)
.ConfigureElasticsearch(options.Elasticsearch).Result
.CreateLogger();
builder.UseSerilog();
}
public static void UseSerilogSetup(this IApplicationBuilder app)
{
app.UseSerilogRequestLogging();
}
private static LoggerConfiguration ConfigureFile(this LoggerConfiguration logger, SerilogFileOptions options)
{
if (options == null || options.Minlevels == null || !options.Minlevels.Any())
return logger;
var path = "Serilog/" + ".txt";
foreach (var item in options.Minlevels)
{
logger.WriteTo.File(
path: path,
outputTemplate: options.Template,
rollingInterval: RollingInterval.Day,
shared: true,
fileSizeLimitBytes: 10 * 1024 * 1024,
rollOnFileSizeLimit: true,
restrictedToMinimumLevel: Enum.Parse<LogEventLevel>(item)
);
}
return logger;
}
private static LoggerConfiguration ConfigureConsole(this LoggerConfiguration logger, SerilogConsoleOptions options)
{
if (options == null) return logger;
logger.WriteTo.Console(
restrictedToMinimumLevel: Enum.Parse<LogEventLevel>(options.Minlevel),
outputTemplate: options.Template
);
return logger;
}
private static async Task<LoggerConfiguration> ConfigureElasticsearch(this LoggerConfiguration logger, SerilogElasticsearchOptions options)
{
if (options == null || options.Nodes.FirstOrDefault().IsNullOrEmpty()) return logger;
List<Uri> uris = options.Nodes.Select(x => new Uri(x)).ToList();
uris = await PingAndFilterUrisAsync(uris);
if (uris.Count == 0)
{
return logger;
}
logger.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(uris)
{
IndexFormat = options.Indexformat,
NumberOfShards = options.NumberOfShards,
NumberOfReplicas = options.NumberOfReplicas,
CustomFormatter = new ExceptionAsObjectJsonFormatter(renderMessage: true),
EmitEventFailure = EmitEventFailureHandling.RaiseCallback,
FailureCallback = FailureCallback,
AutoRegisterTemplate = true,
AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
ModifyConnectionSettings = conn =>
{
if (options.UserName.IsNullOrEmpty() || options.Password.IsNullOrEmpty())
{
conn.BasicAuthentication(options.UserName, options.Password);
}
return conn;
}
});
return logger;
}
private static void FailureCallback(LogEvent e)
{
Console.WriteLine("日志记录失败,信息:" + e.MessageTemplate);
}
private static async Task<List<Uri>> PingAndFilterUrisAsync(List<Uri> uris)
{
using var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(3) };
var successfulUris = new List<Uri>();
foreach (var item in uris)
{
try
{
string healthCheckUri = $"{item.AbsoluteUri}";
HttpResponseMessage response = await httpClient.GetAsync(healthCheckUri);
if (response.IsSuccessStatusCode)
{
successfulUris.Add(item);
}
}
catch (TaskCanceledException)
{
Console.WriteLine($"请求至 '{item}' 超时。");
}
catch (Exception ex)
{
Console.WriteLine($"请求至 '{item}' 时发生错误:{ex.Message}");
}
}
return successfulUris;
}
}
}
调用
builder.Host.AddSerilogHost(builder.Services, configuration);
app.UseSerilogSetup();
效果