Logs SDK
Status: Stable, 除非另有说明
OpenTelemetry 用户需要一种方式,让与 OpenTelemetry API 的交互实际产生遥测数据。OpenTelemetry Logging SDK(以下简称 SDK)是 OpenTelemetry API 的一个实现,它为用户提供了这种功能。
所有语言实现的 OpenTelemetry 都必须提供一个 SDK。
LoggerProvider
LoggerProvider 必须提供一种方式,允许指定一个 Resource。如果指定了 Resource,它应该与由 LoggerProvider 中的任何 Logger 生成的所有 LogRecord 相关联。
LoggerProvider 创建
SDK 应允许创建多个独立的 LoggerProviders。
Logger 创建
只能通过 LoggerProvider 创建 Logger 实例(参见 API)。
LoggerProvider 必须实现 Get a Logger API。
用户提供的输入必须用于创建 InstrumentationScope 实例,该实例存储在创建的 Logger 上。
在指定无效 name(null 或空字符串)的情况下,必须返回一个可用的 Logger 作为后备,而不是返回 null 或抛出异常,其 name 应保留原始无效值,并应记录一条报告指定值无效的消息。
Status: Development - LoggerProvider 必须使用配置的 LoggerConfigurator 计算相关的 LoggerConfig,并创建一个行为符合该 LoggerConfig 的 Logger。
配置
配置(例如,LogRecordProcessors 和(Development)LoggerConfigurator)必须由 LoggerProvider 拥有。如果适用,可以在 LoggerProvider 创建时应用配置。
LoggerProvider 可以提供更新配置的方法。如果配置被更新(例如,添加一个 LogRecordProcessor),则更新后的配置也必须应用于所有已返回的 Logger(即,无论 Logger 是在配置更改之前还是之后从 LoggerProvider 获取的,都必须没有区别)。注意:在实现上,这可能意味着 Logger 实例拥有对其 LoggerProvider 的引用,并且仅通过此引用访问配置。
LoggerConfigurator
状态: 开发中
LoggerConfigurator 是一个函数,它为 Logger 计算 LoggerConfig。
该函数必须接受以下参数
logger_scope:Logger的InstrumentationScope。
该函数必须返回相关的 LoggerConfig,或者返回一个信号,指示应使用 默认 LoggerConfig。这个信号可以是 nil、null、空,或者一个默认 LoggerConfig 的实例,具体取决于语言的习惯用法。
该函数在 Logger 首次创建时调用,并在 LoggerProvider 的 LoggerConfigurator 更新时(如果支持更新)为每个已存在的 Logger 调用。因此,它快速返回很重要。
LoggerConfigurator 被建模为一个函数,以最大化灵活性。但是,实现可以提供简写或辅助函数来适应常见的用例
- 通过精确匹配或模式匹配,选择一个或多个 logger。
- 禁用一个或多个特定的 logger。
- 禁用所有 logger,并选择性地启用一个或多个特定的 logger。
- 为特定的 logger 或 logger 模式设置最低严重级别。
- 为特定的 logger 或 logger 模式启用基于 trace 的过滤。
Shutdown
此方法提供了一种方式,让 provider 进行任何必要的清理。
每个 LoggerProvider 实例只能调用一次 Shutdown。调用 Shutdown 后,不允许后续尝试获取 Logger。SDK 应尽可能为这些调用返回一个有效的 no-op Logger。
Shutdown 应提供一种方式,让调用者知道它是否成功、失败或超时。
Shutdown 应在某个超时时间内完成或中止。Shutdown 可以实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者可以决定是否要使 shutdown 超时可配置。
Shutdown 必须通过调用所有已注册的 LogRecordProcessors 的 Shutdown 来实现。
ForceFlush
此方法提供了一种方式,用于通知已注册的 LogRecordProcessors 立即导出所有尚未导出的 ReadableLogRecords。
ForceFlush 应提供一种方式,让调用者知道它是否成功、失败或超时。如果存在错误条件,ForceFlush 应返回某种 **ERROR** 状态;如果没有错误条件,它应返回某种 **NO ERROR** 状态,语言实现可以决定如何模拟 **ERROR** 和 **NO ERROR**。
ForceFlush 应在某个超时时间内完成或中止。ForceFlush 可以实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者可以决定是否要使 flush 超时可配置。
ForceFlush 必须调用所有已注册的 LogRecordProcessors 的 ForceFlush。
Logger
Status: Development - Logger 必须根据 logger creation 期间计算的 LoggerConfig 进行行为。如果 LoggerProvider 支持更新 LoggerConfigurator,则在更新后,Logger 必须更新为符合新的 LoggerConfig 的行为。
LoggerConfig
状态: 开发中
LoggerConfig 定义了 Logger 行为的各种可配置方面。它包含以下参数
disabled: 一个布尔值,指示 logger 是否已启用。如果未明确设置,
disabled参数应默认为false(即,Loggers 默认启用)。如果
Logger被禁用,它必须表现得等同于 No-op Logger。minimum_severity: 一个 SeverityNumber,指示要处理的日志记录的最低严重级别。如果未明确设置,
minimum_severity参数必须默认为0。如果日志记录的 SeverityNumber 已指定(即不为
0)且小于配置的minimum_severity,则该日志记录必须被Logger丢弃。具有未指定严重级别(即0)的日志记录不受此参数影响,因此会绕过最低严重级别过滤。trace_based: 一个布尔值,指示 logger 是否应仅处理与采样 trace 相关的日志记录。如果未明确设置,
trace_based参数必须默认为false。如果
trace_based为true,与未采样 trace 相关的日志记录必须被Logger丢弃。如果日志记录具有有效的SpanId且其TraceFlags表明 trace 未被采样,则认为该日志记录与未采样 trace 相关。与 trace 上下文无关的日志记录不受此参数影响,因此会绕过基于 trace 的过滤。
实现不必确保这些参数的任何更改立即对 Enabled 的调用者可见。但是,更改必须最终可见。
Emit a LogRecord
如果 Observed Timestamp 未指定,实现应将其设置为当前时间。
Status: Development 在处理日志记录之前,实现必须应用 LoggerConfig 定义的过滤规则(在调用 Enabled 之前发出记录的情况下)
Minimum severity: 如果日志记录的 SeverityNumber 已指定(即不为
0)且小于配置的minimum_severity,则该日志记录必须被丢弃。Trace-based: 如果
trace_based为true,并且日志记录具有SpanId并且TraceFlagsSAMPLED 标志未设置,则该日志记录必须被丢弃。
Enabled
当以下任一情况发生时,Enabled 必须返回 false
- 没有注册的
LogRecordProcessors。 - Status: Development -
Logger已禁用(LoggerConfig.disabled为true)。 - Status: Development - 提供的严重级别已指定(即不为
0)且小于LoggerConfig中配置的minimum_severity。 - Status: Development -
LoggerConfig中trace_based为true,并且当前上下文与未采样 trace 相关联。 - 所有已注册的
LogRecordProcessors都实现了Enabled,并且对其中每个的调用都返回false。
否则,应返回 true。为了支持其他优化和功能,可以返回 false。
Additional LogRecord interfaces
在本文档中,我们引用 ReadableLogRecord 和 ReadWriteLogRecord,定义如下。
ReadableLogRecord
接收此作为参数的函数必须能够访问添加到 LogRecord 的所有信息。它还必须能够(隐式地)访问与 LogRecord 相关的 Instrumentation Scope 和 Resource 信息。
trace context fields 必须在 emitted 时从解析的 Context(显式传递的 Context 或当前 Context)填充。
由于收集限制而产生的属性计数必须可供导出器报告,如 转换为非 OTLP 格式 规范中所述。
注意:通常会使用新接口或(不可变)值类型来实现。SDK 也可以使用单一类型来表示 ReadableLogRecord 和 ReadWriteLogRecord。
ReadWriteLogRecord
ReadWriteLogRecord 是 ReadableLogRecord 的超集。
接收此作为参数的函数还必须能够修改添加到 LogRecord 的以下信息
TimestampObservedTimestampSeverityTextSeverityNumberBodyAttributes(添加、修改、删除)TraceIdSpanIdTraceFlagsEventName
SDK 可以提供一个操作来对 ReadWriteLogRecord 进行深度克隆。该操作可供异步处理器(例如 Batching processor)使用,以避免对不需要并发安全性的日志记录的竞争条件。
LogRecord Limits
LogRecord 属性必须符合 属性限制的通用规则。
如果 SDK 实现属性限制,它必须提供一种方式来更改这些限制,通过对 LoggerProvider 的配置,允许用户配置单个限制,如下面的 Java 示例所示。
这些选项可以捆绑在一个类中,该类应命名为 LogRecordLimits。
public interface LogRecordLimits {
public int getAttributeCountLimit();
public int getAttributeValueLengthLimit();
}
Configurable parameters
SDK 的日志中应打印一条消息,告知用户某个属性因达到此类限制而被丢弃。为避免过度日志记录,该消息最多必须每 LogRecord 打印一次(即,不是每个丢弃的属性都打印一次)。
LogRecordProcessor
LogRecordProcessor 是一个允许挂钩 LogRecord 发射的接口。
内置处理器负责将 LogRecords 批处理并转换为可导出表示,并将批次传递给导出器。
LogRecordProcessors 可以直接注册到 SDK LoggerProvider,并按照注册顺序调用。
注册到 LoggerProvider 的每个处理器都是一个由处理器和可选 exporter 组成的管道的一部分。SDK 必须允许每个管道以单独的导出器结束。
SDK 必须允许用户实现和配置自定义处理器,并装饰内置处理器以实现高级场景,例如使用属性进行丰富。
下图显示了 LogRecordProcessor 与 SDK 中其他组件的关系
+-----+------------------------+ +------------------------------+ +-------------------------+
| | | | | | |
| | | | Batching LogRecordProcessor | | LogRecordExporter |
| | +---> Simple LogRecordProcessor +---> (OtlpExporter) |
| | | | | | |
| SDK | Logger.emit(LogRecord) | +------------------------------+ +-------------------------+
| | |
| | |
| | |
| | |
| | |
+-----+------------------------+
有关如何设置高级日志记录处理(例如过滤或分发)的信息,请参阅 Supplementary Guidelines。
LogRecordProcessor operations
OnEmit
当 LogRecord 被 emitted 时会调用 OnEmit。此方法在发出 LogRecord 的线程上同步调用,因此不应阻塞或抛出异常。
参数
logRecord- 发出的LogRecord的 ReadWriteLogRecord。context- 解析的Context(显式传递的Context或当前Context)
Returns: Void
对于直接注册到 SDK LoggerProvider 的 LogRecordProcessor,logRecord 的更改必须在下一个注册的处理器中可见。
LogRecordProcessor 可以在 OnEmit 调用期间自由修改 logRecord。但是,ReadWriteLogRecord 是否并发安全是可选的。因此,对 logRecord 的任何并发修改和读取都可能导致竞争条件。为避免此类竞争条件,建议实现用户使用 logRecord 的克隆来进行任何并发处理,例如在 batching processor 中。
Enabled
Enabled 是 LogRecordProcessor 可能实现的一个操作,以便通过 Logger.Enabled 支持过滤。
参数
- Context 由调用者显式传递或当前 Context
- 与
Logger关联的 Instrumentation Scope - 调用者传递的 Severity Number
- 调用者传递的 Event Name
Returns: Boolean
如果某个 LogRecord(如果创建了)应该被过滤掉,则实现应返回 false。在任何不确定的状态下,例如在等待配置时,它应默认返回 true。
对 Enabled 中参数的任何修改都不得传播到调用者。参数是不可变的或按值传递的。
此操作通常是同步调用的,因此不应阻塞或抛出异常。
负责过滤和支持 Enable 操作的 LogRecordProcessor 实现应确保 OnEmit 独立处理过滤。不能期望 API 用户在调用 Emit a LogRecord 之前调用 Enabled。此外,OnEmit 和 Enabled 中的过滤逻辑可能不同。
包装其他 LogRecordProcessor(可能执行过滤)的 LogRecordProcessor 实现可以实现 Enabled 并委托给被包装处理器(如果可用)的 Enabled。但是,此类处理器的 OnEmit 实现不应调用被包装处理器(如果可用)的 Enabled,因为 OnEmit 负责独立处理过滤。
ShutDown
关闭处理器。在 SDK 关闭时调用。这是处理器进行任何必要清理的机会。
每个 LogRecordProcessor 实例只能调用一次 Shutdown。调用 Shutdown 后,不允许后续调用 OnEmit。SDK 应尽可能优雅地忽略这些调用。
Shutdown 应提供一种方式,让调用者知道它是否成功、失败或超时。
Shutdown 必须包含 ForceFlush 的效果。
Shutdown 应在某个超时时间内完成或中止。Shutdown 可以实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者可以决定是否要使 shutdown 超时可配置。
ForceFlush
这是确保 LogRecordProcessor 在调用 ForceFlush 之前已收到事件的所有与 LogRecord 相关的任务应尽快完成的提示,最好在从该方法返回之前完成。
特别是,如果任何 LogRecordProcessor 具有关联的导出器,它应该尝试使用所有尚未完成调用的 LogRecords 调用导出器的 Export,然后在其上调用 ForceFlush。内置的 LogRecordProcessors 必须这样做。如果指定了超时(见下文),LogRecordProcessor 必须优先考虑遵守超时而不是完成所有调用。它可以跳过或中止它已进行的某些或所有 Export 或 ForceFlush 调用来实现此目标。
ForceFlush 应提供一种方式,让调用者知道它是否成功、失败或超时。
ForceFlush 仅应在绝对必要的情况下调用,例如在使用某些 FaaS 提供商时,这些提供商可能会在调用结束后暂停进程,但在 LogRecordProcessor 导出已发出的 LogRecords 之前。
ForceFlush 应在某个超时时间内完成或中止。ForceFlush 可以实现为阻塞 API 或异步 API,通过回调或事件通知调用者。OpenTelemetry SDK 作者可以决定是否要使 flush 超时可配置。
Built-in processors
标准的 OpenTelemetry SDK 必须实现简单处理器和批处理处理器,如下所述。
其他常见的处理场景应首先考虑在 OpenTelemetry Collector 中进行进程外实现。
Simple processor
这是 LogRecordProcessor 的一个实现,它将完成的日志以及导出友好的 ReadableLogRecord 表示尽快传递给配置的 LogRecordExporter。
处理器必须同步调用 LogRecordExporter 的 Export,以确保它们不会被并发调用。
Configurable parameters
exporter- 推送LogRecords 的导出器。
Batching processor
这是 LogRecordProcessor 的一个实现,它创建 LogRecords 的批次,并将导出友好的 ReadableLogRecord 表示传递给配置的 LogRecordExporter。
处理器必须同步调用 LogRecordExporter 的 Export,以确保它们不会被并发调用。
Configurable parameters
exporter- 推送LogRecords 的导出器。maxQueueSize- 最大队列大小。达到该大小时,日志将被丢弃。默认值为2048。scheduledDelayMillis- 两次连续导出之间的时间间隔(以毫秒为单位)。默认值为1000。exportTimeoutMillis- 导出运行多长时间后将被取消。默认值为30000。maxExportBatchSize- 每次导出的最大批次大小。它必须小于或等于maxQueueSize。默认值为512。
LogRecordExporter
LogRecordExporter 定义了特定协议的导出器必须实现的接口,以便它们可以插入 OpenTelemetry SDK 并支持遥测数据的发送。
该接口的目标是最大程度地减少协议相关遥测导出器的实现负担。协议导出器主要被期望是一个简单的遥测数据编码器和传输器。
每个实现都必须记录 SDK 对导出器的并发特性要求。
LogRecordExporter operations
LogRecordExporter 必须支持以下功能
Export
导出 ReadableLogRecords 的批次。实现此功能的协议导出器通常期望将数据序列化并传输到目的地。
不应与同一导出器实例的其他 Export 调用并发调用 Export。
根据实现,导出结果可能不会在 Export 调用返回的值中返回给 Processor,而是在语言特定方式中用于指示异步任务的完成。这意味着,虽然导出器实例的 Export 不应被并发调用,但这并不意味着导出任务不能并发执行。如何做到这一点超出了本规范的范围。
Export 绝不能无限期阻塞,必须有一个合理的上限,之后调用必须超时并返回错误结果(Failure)。
并发请求和重试逻辑由导出器负责。默认 SDK 的 LogRecordProcessors 不应实现重试逻辑,因为所需的逻辑很可能高度依赖于日志发送到的特定协议和后端。例如,OpenTelemetry Protocol (OTLP) specification 定义了发送并发请求和重试请求的逻辑。
参数
batch- ReadableLogRecords 的批次。批次的具体数据类型是语言特定的,通常是某种列表,例如 Java 中的日志将通常是Collection<LogRecordData>。
Returns: ExportResult
Export 的返回值是实现特定的。在语言习惯用法中,导出器必须向 Processor 发送一个 ExportResult。ExportResult 的值是 Success 或 Failure
Success- 批次已成功导出。对于协议导出器,这通常意味着数据已通过线路发送并传递到目标服务器。Failure- 导出失败。批次必须被丢弃。例如,当批次包含错误数据且无法序列化时,可能会发生这种情况。
例如,在 Java 中,Export 的返回值将是一个 Future,该 Future 完成后返回 ExportResult 对象。而在 Erlang 中,导出器会将带有特定批次的 ExportResult 的消息发送给处理器。
ForceFlush
这是一个提示,用于确保在调用 ForceFlush 之前,导出器已收到的所有 ReadableLogRecords 的导出应尽快完成,最好在从该方法返回之前完成。
ForceFlush 应提供一种方式,让调用者知道它是否成功、失败或超时。
ForceFlush 仅应在绝对必要的情况下调用,例如在使用某些 FaaS 提供商时,这些提供商可能会在调用结束和导出器导出 ReadlableLogRecords 之间暂停进程。
ForceFlush 应在某个超时时间内完成或中止。ForceFlush 可以实现为阻塞 API 或异步 API,通过回调或事件通知调用者。 OpenTelemetry SDK 作者可以决定是否要使 flush 超时可配置。
Shutdown
关闭导出器。在 SDK 关闭时调用。这是导出器执行任何必需清理工作的机会。
对于每个 LogRecordExporter 实例,Shutdown 应仅调用一次。在调用 Shutdown 后,后续对 Export 的调用是不允许的,并且应返回 Failure 结果。
Shutdown 不应无限期阻塞(例如,如果它尝试刷新数据而目标不可用)。 OpenTelemetry SDK 作者可以决定是否要使 shutdown 超时可配置。