Elastic.Extensions.Logging
编辑Elastic.Extensions.Logging编辑
用于 Microsoft.Extensions.Logging 的 Elastic 日志记录提供程序。
使用 Elastic 通用架构 (ECS) 直接写入 Elasticsearch,并从消息和范围值中进行结构化数据的语义日志记录。结果可以在 Kibana 控制台中查看和查询。
安装编辑
添加对 Elastic.Extensions.Logging
包的引用
<PackageReference Include="Elastic.Extensions.Logging" Version="8.6.0" />
用法编辑
然后,在主机构造期间使用提供的扩展方法将提供程序添加到 loggingBuilder。
using Elastic.Extensions.Logging; // ... .ConfigureLogging((hostContext, loggingBuilder) => { loggingBuilder.AddElasticsearch(); })
默认配置将写入在 https://127.0.0.1:9200/ 上运行的本地 Elasticsearch。
发送一些日志事件后,打开 Kibana(例如 https://127.0.0.1:5601/),并为“dotnet-*”定义一个索引模式,并使用时间过滤器“@timestamp”。
然后,您可以发现索引的日志事件。要添加的一些有用列是 log.level
、log.logger
、event.code
、message
、tags
和 process.thread.id
。
如果您在运行多个应用程序或在多个服务器上运行,您可能希望包含 service.type
、service.version
和 host.hostname
。
其他字段定义如下,所有单独的消息和范围值都作为 labels.*
自定义键值对进行记录,例如 labels.CustomerId
。
基本配置编辑
为了部署,您通常需要使用实际的服务器位置覆盖配置。另一个有用的配置值是环境标签,例如开发/暂存/生产。
{ "Logging": { "Elasticsearch": { "NodeUris": [ "https://elastic-staging.example.com:9200" ], "Tags": [ "Staging" ] } } }
注意: 您不需要任何配置就可以使用本地 Elasticsearch 实例,因为它默认为 https://127.0.0.1:9200/。
配置设置编辑
日志记录提供程序将自动使用别名为 Elasticsearch
的任何日志记录设置进行配置。
使用以下默认设置。
{ "Logging": { "Elasticsearch": { "IncludeHost": true, "IncludeProcess": true, "IncludeScopes": true, "IncludeUser": true, "Index": "dotnet-{0:yyyy.MM.dd}", "IndexOffset": null, "IsEnabled": true, "ListSeparator": ", ", "MapCorrelationValues": true, "Tags": [], "ShipTo": { "NodePoolType": "SingleNode", "NodeUris": [ "https://127.0.0.1:9200" ] } } } }
设置 | 类型 | 描述 |
---|---|---|
IncludeHost |
布尔值 |
默认 |
IncludeProcess |
布尔值 |
默认 |
IncludeScopes |
布尔值 |
默认 |
IncludeUser |
布尔值 |
默认 |
Index |
格式 |
用于使用当前时间戳生成 Elasticsearch |
IndexOffset |
时间跨度 |
覆盖以设置用于生成 |
IsEnabled |
布尔值 |
默认 |
ListSeparator |
字符串 |
用于 |
Tags |
数组 |
要包含在消息中的其他标签。用于指定环境或其他详细信息,例如 |
ShipTo 设置可以具有以下属性,具体取决于连接池的类型。
设置 | 类型 | 描述 |
---|---|---|
ApiKey |
字符串 |
API 密钥,其中连接池类型为云,并通过 API 密钥进行身份验证。 |
CloudId |
字符串 |
云 ID,其中连接池类型为云。 |
NodePoolType |
枚举 |
默认值为 |
NodeUris |
数组 |
要连接到的 Elasticsearch 节点的 URI(s)。默认值为单个节点 |
Password |
字符串 |
密码,其中连接池类型为云,并通过用户名/密码进行身份验证。 |
Username |
字符串 |
用户名,其中连接池类型为云,并通过用户名/密码进行身份验证。 |
如果要从其他部分进行配置,则可以手动配置
.ConfigureLogging((hostContext, loggingBuilder) => { loggingBuilder.AddElasticsearch(options => hostContext.Configuration.Bind("Logging:CustomElasticsearch", options)); })
当然,也可以在代码中进行配置,例如添加环境作为标签。
Elastic Cloud 配置编辑
如果提供了 CloudId
,则 ConnectionPoolType
默认为 Cloud
{ "Logging": { "Elasticsearch": { "ShipTo": { "CloudId": "12345", "ApiKey": "abcdef" } } } }
输出 - Elastic 通用架构 (ECS)编辑
发送到 Elasticsearch 的日志消息遵循 Elastic 通用架构 (ECS)。
示例文档编辑
_source
字段是来自 LoggerProvider 的发送消息,以及 _index
和 _id
(GUID)。
{ "_index": "dotnet-2020.04.12", "_type": "_doc", "_id": "563503a8-9d10-46ff-a09f-c6ccbf124db9", "_version": 1, "_score": null, "_source": { "MessageTemplate": "Unexpected error processing customer {CustomerId}.", "Scopes": [ "IP address 2001:db8:85a3::8a2e:370:7334", "PlainScope" ], "agent": { "version": "1.0.0+bd3ad6", "type": "Elastic.Extensions.Logging.LoggerProvider" }, "ecs": { "version": "1.5.0" }, "error": { "message": "Calculation error", "type": "System.Exception", "stack_trace": "System.Exception: Calculation error\n ---> System.DivideByZeroException: Attempted to divide by zero.\n at HelloElasticsearch.Worker.ExecuteAsync(CancellationToken stoppingToken) in /home/sly/Code/essential-logging/examples/HelloElasticsearch/Worker.cs:line 80\n --- End of inner exception stack trace ---\n at HelloElasticsearch.Worker.ExecuteAsync(CancellationToken stoppingToken) in /home/sly/Code/essential-logging/examples/HelloElasticsearch/Worker.cs:line 84" }, "event": { "code": "5000", "action": "ErrorProcessingCustomer", "severity": 3 }, "host": { "os": { "platform": "Unix", "full": "Linux 4.15.0-91-generic #92-Ubuntu SMP Fri Feb 28 11:09:48 UTC 2020", "version": "4.15.0.91" }, "hostname": "VUB1804", "architecture": "X64" }, "log": { "level": "Error", "logger": "HelloElasticsearch.Worker" }, "process": { "thread": { "id": 10 }, "pid": 25982, "name": "HelloElasticsearch" }, "service": { "type": "HelloElasticsearch", "version": "1.0.0" }, "user": { "id": "[email protected]", "name": "sly", "domain": "VUB1804" }, "@timestamp": "2020-04-13T21:25:22.3352989+10:00", "tags": [ "Development" ], "labels": { "ip": "2001:db8:85a3::8a2e:370:7334", "CustomerId": "12345" }, "message": "Unexpected error processing customer 12345.", "trace": { "id": "c20bde1071f7cf4e9a6f368c824e05f7" }, "transaction": { "id": "92ba5ee64d963746" } }, "fields": { "@timestamp": [ "2020-04-13T11:25:22.335Z" ] }, "sort": [ 1586777122335 ] }
标准字段编辑
字段 | 类型 | 描述 |
---|---|---|
@timestamp |
日期 |
记录消息的 |
message |
字符串 |
格式化的日志消息和参数。 |
tags |
数组 |
来自配置的自定义标签,例如 |
event.action |
字符串 |
记录的 EventId 的名称,例如 |
event.code |
字符串 |
EventId 的数值(作为字符串),例如 |
event.severity |
长整型 |
与日志级别相对应的 syslog 严重程度,2 = 严重错误、3 = 错误、4 = 警告、6 = 信息、7 = 调试和跟踪。(也用于 ConsoleLoggerProvider 的 Systemd 格式) |
log.level |
字符串 |
日志级别: |
log.logger |
字符串 |
日志记录器的类别名称(命名空间和类),例如 |
event.severity
字段是数值,可用于按级别对事件进行排序,例如 Kibana 查询 event.severity <= 4
将获取所有日志级别为 Warning
或更糟的消息。
错误字段编辑
如果日志消息包含异常,则异常详细信息将在错误字段中报告。
字段 | 类型 | 描述 |
---|---|---|
error.message |
字符串 |
任何异常的 |
error.stack_trace |
字符串 |
异常的完整详细信息, |
error.type |
字符串 |
错误消息的类型,例如 |
自定义字段编辑
遵循 ECS 约定,这些使用替代标题大小写来识别它们是非标准字段。
字段 | 类型 | 描述 |
---|---|---|
MessageTemplate |
字符串 |
原始消息模板,例如“处理客户 {CustomerId} 时出现意外错误”。 |
Scopes |
数组 |
字符串格式范围值的数组,按添加顺序排列。 |
标签值编辑
字段 | 类型 | 描述 |
---|---|---|
labels.* |
字符串 |
所有命名参数值和命名范围值的自定义键值对。所有值都是字符串(没有嵌套对象)。 |
标签值可以通过其键访问,例如,如果消息或范围包含参数 CustomerId,则该值将作为 labels.CustomerId
记录,可以在 Kibana 中使用“labels.CustomerId: 12345”进行搜索。
示例
以下将生成两个标签,来自消息的 labels.EndTime
和来自范围的 labels.CustomerId
using (_logger.BeginScope("{CustomerId}", customerId)) { _logger.LogWarning("End of processing reached at {EndTime}.", end); }
标签来自消息(状态)和任何范围值(可以通过配置选项禁用)。在 Microsoft.Extensions.Logging 中,内部 FormattedLogValues 用于 ILogger 的日志级别和范围重载;它实现了 IEnumerable<KeyValuePair<string,object>>
接口,该接口用于提取单个参数值。
ECS 中的 labels
属性不应包含嵌套对象,因此值将转换为关键字字符串。对于大多数对象,这仅仅是调用 ToString(),而某些类型则具有特定格式,例如,在列表上调用字符串通常没有用,因此会记录列表的内容。
标签值格式
类型 | 格式 |
---|---|
字节 |
十六进制,例如“9A” |
字节[] |
带前缀的十六进制,例如“0x12789AF0” |
DateTimeOffset |
ISO 格式,例如“2020-01-02T03:04:05.000000+06:00” |
DateTime |
在大多数情况下,应使用 |
IEnumerable |
用“,” 分隔的值(可配置) |
IDictionary<string, object> |
包含键值对的字符串,例如 |
其他值 |
|
(1) 请参阅 https://docs.microsoft.com/en-us/dotnet/standard/datetime/choosing-between-datetime
代理字段编辑
这些标识正在使用的日志记录提供程序的版本。
字段 | 类型 | 描述 |
---|---|---|
agent.type |
字符串 |
日志记录提供程序程序集的名称, |
agent.version |
字符串 |
记录器程序集的信息版本号,例如 |
ecs.version |
字符串 |
使用的 ECS 标准版本,当前为 |
服务字段编辑
标识正在运行并生成日志的应用程序/服务。
这些值从入口程序集 Assembly.GetEntryAssembly()
中获取,使用 Name
和 AssemblyInformationalVersionAttribute
值(如果信息版本未设置,则回退到程序集 Version
)。
字段 | 类型 | 描述 |
---|---|---|
service.type |
字符串 |
入口程序集的名称,例如 |
service.version |
字符串 |
入口程序集的信息版本号,例如 |
注意: 您应该使用在构建过程中正确设置程序集信息版本的构建流程。例如,如果您有一个使用 Git 的 .NET 项目,您可以安装本地工具 GitVersion.Tool
,并使用它从 Git 分支信息中自动生成语义版本号。
要安装该工具,请执行以下操作
dotnet new tool-manifest dotnet tool install GitVersion.Tool
然后使用该工具创建一个可以在构建流程中使用的语义版本号
dotnet tool restore dotnet gitversion
欢迎使用此存储库中的 build.ps1
脚本作为示例。
跟踪字段编辑
字段 | 类型 | 描述 |
---|---|---|
trace.id |
字符串 |
跨服务跟踪关联标识符。来自 |
transaction.id |
字符串 |
此服务的交易,例如单个请求标识符。如果使用 W3C 格式,则从 |
ASP.NET 将自动在层之间传递关联标识符;从 3.0 开始,它还支持 W3C 跟踪上下文标准 (https://www.w3.org/TR/trace-context/)。
Activity.Current.RootId
的值用作跨服务标识符(在 W3C 格式中,这是跟踪 ID),如果使用 W3C 格式,则使用 Activity.Current.Id
的 Span ID 部分作为交易,否则使用完整值(这与 ASP.NET 的工作方式一致)。
建议打开 W3C 格式,以与其他系统兼容
Activity.DefaultIdFormat = ActivityIdFormat.W3C;
主机字段编辑
可以通过配置禁用。
字段 | 类型 | 描述 |
---|---|---|
host.architecture |
字符串 |
处理器架构,例如 X64。 |
host.hostname |
字符串 |
计算机名称。 |
host.os.full |
字符串 |
操作系统完整描述。 |
host.os.platform |
字符串 |
操作系统平台。 |
host.os.version |
字符串 |
操作系统版本。 |
进程字段编辑
可以通过配置禁用。
字段 | 类型 | 描述 |
---|---|---|
process.name |
字符串 |
当前进程名称。来自 |
process.pid |
长整型 |
当前进程 ID。来自 |
process.thread.id |
长整型 |
当前线程 ID。 |
process.thread.name |
字符串 |
线程名称。来自 |
用户字段编辑
可以通过配置禁用。
字段 | 类型 | 描述 |
---|---|---|
user.domain |
字符串 |
当前域,可以是机器名称或 Windows 域。 |
user.id |
字符串 |
当前用户主体名称(如果已设置)。 |
user.name |
字符串 |
当前用户。 |