Yoko.Tool.Serilog
0.1.5
dotnet add package Yoko.Tool.Serilog --version 0.1.5
NuGet\Install-Package Yoko.Tool.Serilog -Version 0.1.5
<PackageReference Include="Yoko.Tool.Serilog" Version="0.1.5" />
paket add Yoko.Tool.Serilog --version 0.1.5
#r "nuget: Yoko.Tool.Serilog, 0.1.5"
// Install Yoko.Tool.Serilog as a Cake Addin #addin nuget:?package=Yoko.Tool.Serilog&version=0.1.5 // Install Yoko.Tool.Serilog as a Cake Tool #tool nuget:?package=Yoko.Tool.Serilog&version=0.1.5
📚 使用示例
Program.cs
try
{
var builder = WebApplication.CreateBuilder(args);
// 注册配置文件
builder.Services.AddConfiguration<AppSettings>(builder.Configuration, "AppSettings");
//初始化日志服务
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Default", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.MinimumLevel.Override("Quartz", LogEventLevel.Warning)
.MinimumLevel.Override("TouchSocket", LogEventLevel.Warning)
.MinimumLevel.Override("FastEndpoints", LogEventLevel.Warning)
.Enrich.FromLogContext()
.Enrich.WithTraceContextHeader() // 提取追踪上下文
.WriteTo.Http(requestUri: AppSettings.LogCenter //接口地址
, queueLimitBytes: null
, textFormatter: new LogFormatter() // ============================>使用日志格式化器
)
.WriteTo.File(
outputTemplate: "{Message:lj}{NewLine}", // 直接定义输出模板
//formatter: new LogFormatter(true), // ============================> 使用日志格式化器
path: $"{AppDomain.CurrentDomain.BaseDirectory}/Logs/DC-.log",
rollingInterval: RollingInterval.Day,//日志按天保存
rollOnFileSizeLimit: true,//限制单个文件的最大长度
fileSizeLimitBytes: 10485760,//单个文件最大10M
encoding: System.Text.Encoding.UTF8,//文件字符编码
retainedFileCountLimit: 200,//将被保留的日志文件的最大数量,包括当前日志文件。对于无限保留,传递null。默认值为31。
shared: true//允许多个进程共享日志文件。默认值为false
)
.CreateLogger(); //立即配置 Serilog
builder.Services.AddSerilog(); // 使用 Serilog
var app = builder.Build();
app.MapGet("/ok", () => "服务运行正常!").WithTags("健康检查");
Log.Information("服务启动成功");
app.Run();
}
catch (Exception e)
{
Log.Fatal("服务意外终止!{msg}", e.Message);
}
finally
{
Log.CloseAndFlush();
}
📚 使用组件
📒 获取请求中的追踪id
可以从 HTTP 请求头部的 “traceparent” 字段中提取追踪上下文,并将其添加到 Serilog 的日志事件中。
它遵循 W3C Trace Context 规范
按W3C Trace Context 规范, “traceparent” 头部的值应遵循 00-{traceId}-{spanId}-{traceFlags}
的格式
其中:
traceId
是一个 32 个十六进制数字的字符串,表示追踪操作的唯一标识符。spanId
是一个 16 个十六进制数字的字符串,表示单个操作的唯一标识符 (例如,一个 HTTP 请求)。traceFlags
是一个 2 个十六进制数字的字符串,表示追踪选项。目前,唯一定义的选项是 “01”,表示记录追踪数据
示例值:
00-83efd447300bf4dfa660e807869e78f0-3f977cb3083d2ac6-01
📖使用方法
首先,你需要在你的 Serilog 配置中使用 WithTraceContextHeader
方法:
Log.Logger = new LoggerConfiguration()
.Enrich.WithTraceContextHeader()
// 其他配置...
.CreateLogger();
默认情况下,这个插件会从 “traceparent” 头部提取追踪上下文。
如果你的应用程序使用了不同的头部名称,你可以将其作为参数传递给 WithTraceContextHeader
方法:
Log.Logger = new LoggerConfiguration()
.Enrich.WithTraceContextHeader("your-header-name")
// 其他配置...
.CreateLogger();
然后,你就可以像平常一样使用 Serilog 来记录日志。
每个日志事件都会包含两个额外的属性:TraceId
和 SpanId
。
这些属性的值来自 “traceparent” 头部。
📖 推荐
使用 Flurl.Http 库来传递追踪上下文信息
扩展 Flurl 请求来添加追踪上下文,创建一个扩展方法来为 Flurl 请求注入追踪上下文信息。这个方法会提取当前的 Activity
信息,并将其添加到 HTTP 头部中。
using Flurl.Http;
using System.Diagnostics;
public static class FlurlRequestExtensions
{
public static IFlurlRequest WithTracingContext(this string url)
{
var request = new FlurlRequest(url);
var activity = Activity.Current;
if (activity != null)
{
var traceParent = $"00-{activity.TraceId}-{activity.SpanId}-01";
request.WithHeader("traceparent", traceParent);
}
return request;
}
}
http请求示例
var response = await "http://localhost:6689/api"
.WithTracingContext() // 使用扩展方法注入追踪上下文
.GetAsync();
📖 使用常规的HttpClient请求
需要注意的是,在使用HttpClient的时候,要注册名为 “TracingClient” 的 HttpClient
using Microsoft.AspNetCore.Mvc;
using System.Net.Http;
using Microsoft.Extensions.Logging;
namespace YourNamespace.Controllers
{
[ApiController]
[Route("[controller]")]
public class YourController : ControllerBase
{
private readonly ILogger<YourController> _logger;
private readonly HttpClient _client;
public YourController(ILogger<YourController> logger, IHttpClientFactory clientFactory)
{
_logger = logger;
// ============================> 注意这里
_client = clientFactory.CreateClient("TracingClient");
}
[HttpGet("get")]
public async Task<IActionResult> GetAsync()
{
var response = await _client.GetAsync("http://example.com/api/values");
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
return Ok(content);
}
else
{
return StatusCode((int)response.StatusCode, response.ReasonPhrase);
}
}
}
}
📒 日志格式化器
插件还包含一些自定义的日志格式化器,它可以输出两种不同的日志格式:
- JSON格式:new LogFormatter();
- 文件格式:new LogFormatter(isFileLog: true,version: AppVersion.Current);
- isFileLog: true 输出实体文件
- version:版本号,不填则默认1.0.0
📖使用方法
首先,创建一个 LogFormatter
实例。你可以选择是否使用文件日志格式:
formatter : new LogFormatter(isFileLog: true,version: AppVersion.Current); // 使用实体文件日志格式
formatter : new LogFormatter(); // 使用JSON日志格式
然后,你可以在你的日志配置中使用这个格式化器:
.WriteTo.Http(
textFormatter: new LogFormatter() // ==================> 使用JSON格式化器
)
//============================================================
.WriteTo.File(
formatter: new LogFormatter(true), //==================> 使用文件格式化器
)
📖特性
- 两种日志格式:这个格式化器可以输出JSON格式的日志,也可以输出文件格式的日志。
- 灵活的配置:你可以在创建格式化器的时候选择使用哪种日志格式。
- 包含版本信息:日志中包含了程序集的版本信息。
📖格式说明
🔎 JSON日志格式
JSON日志格式是一种结构化的日志格式,它使用JSON(JavaScript Object Notation)数据交换格式来表示日志事件。这种格式的优点是易于机器处理和查询,特别是在大数据和日志分析环境中。
以下是一个JSON日志格式的示例:
{
"TimeStamp": "2024-04-29 10:35:34.576",
"Level": "Information",
"Message": "服务启动成功",
"TrackingId": "1234567890",
"Path": "/api/start",
"Source": "MyApp",
"Version": "1.0.0"
}
🔎 文件日志格式
文件日志格式是一种非结构化的日志格式,它将日志事件表示为简单的文本消息。这种格式的优点是易于人类阅读和理解,特别是在进行故障排查和调试时。
以下是一个文件日志格式的示例:
[2024-04-29 10:35:34.576] [Information] [1234567890] [/api/start] 服务启动成功
在这个示例中,每个方括号内的字段分别代表时间戳、日志级别、跟踪ID和请求路径,最后是日志消息本身。
📒 自定义日志格式化器
自定义一个格式化器,然后继承 ITextFormatter 实现对应的方法即可
示例:自带的类型判断的格式化器
public class DcLogFormatter : ITextFormatter
{
public void Format(LogEvent logEvent, TextWriter output)
{
var type = 0;
if (logEvent.Properties.TryGetValue("type", out var typeValue) && typeValue is ScalarValue scalarTypeValue)
{
type = scalarTypeValue.Value.ToInt32();
}
if (type == 1)
{
var json = logEvent.RenderMessage();
output.Write(json);
}
}
}
internal static class StringExtensions
{
internal static int ToInt32(this object s)
{
if (s == null)
{
return 0;
}
return int.TryParse(s.ToString(), out int result) ? result : 0;
}
}
使用示例:
using (LogContext.PushProperty("type", 1))
{
Log.Information(new
{
CreateTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
TimeStamp = model.Tstamp.ToString("yyyy-MM-dd HH:mm:ss.fff"),
State = state
}.ToJson());
}
更新日志
【新增】日志格式化器版本号参数
【新增】可选是否使用日志格式化器
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Serilog.AspNetCore (>= 8.0.1)
- Serilog.Sinks.Console (>= 6.0.0)
- Serilog.Sinks.File (>= 6.0.0)
- Serilog.Sinks.Http (>= 9.0.0)
-
net7.0
- Serilog.AspNetCore (>= 8.0.1)
- Serilog.Sinks.Console (>= 6.0.0)
- Serilog.Sinks.File (>= 6.0.0)
- Serilog.Sinks.Http (>= 9.0.0)
-
net8.0
- Serilog.AspNetCore (>= 8.0.1)
- Serilog.Sinks.Console (>= 6.0.0)
- Serilog.Sinks.File (>= 6.0.0)
- Serilog.Sinks.Http (>= 9.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.