仪表化
Instrumention 是指您自己向应用程序添加可观察性代码的过程。
如果您正在 instrumenting 应用程序,您需要为您使用的语言使用 OpenTelemetry SDK。然后,您将使用 SDK 初始化 OpenTelemetry,并使用 API instrument 您的代码。这将从您的应用程序和任何也带有 instrumention 的已安装库中发出遥测数据。
如果您正在 instrumenting 库,请仅安装您语言的 OpenTelemetry API 包。您的库不会自行发出遥测数据。只有当它作为使用 OpenTelemetry SDK 的应用程序的一部分时,它才会发出遥测数据。有关 instrumenting 库的更多信息,请参阅 Libraries。
有关 OpenTelemetry API 和 SDK 的更多信息,请参阅 specification。
设置
OpenTelemetry Swift 在默认配置下功能有限。为了获得更实用的功能,需要进行一些配置。
默认注册的 TracerProvider 和 MetricProvider 没有配置导出器。根据您的需求,有几种 导出器 可供选择。下面我们将探讨配置 OTLP 导出器,该导出器可用于将数据发送到 collector。
import GRPC
import OpenTelemetryApi
import OpenTelemetrySdk
import OpenTelemetryProtocolExporter
// initialize the OtlpTraceExporter
let otlpConfiguration = OtlpConfiguration(timeout: OtlpConfiguration.DefaultTimeoutInterval)
let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads:1))
.connect(host: <collector host>, port: <collector port>)
let traceExporter = OtlpTraceExporter(channel: grpcChannel,
config: otlpConfiguration)
// build & register the Tracer Provider using the built otlp trace exporter
OpenTelemetry.registerTracerProvider(tracerProvider: TracerProviderBuilder()
.add(spanProcessor:SimpleSpanProcessor(spanExporter: traceExporter))
.with(resource: Resource())
.build())
OtlpMetricExporter 的模式类似
// otlpConfiguration & grpcChannel can be reused
OpenTelemetry.registerMeterProvider(meterProvider: MeterProviderBuilder()
.with(processor: MetricProcessorSdk())
.with(exporter: OtlpMetricExporter(channel: channel, config: otlpConfiguration))
.with(resource: Resource())
.build())
配置 MeterProvider 和 TracerProvider 后,所有后续初始化的 Instrumentation 都将使用此 OTLP 导出器进行导出。
追踪
获取 Tracer
要进行 tracing,您需要一个 tracer。tracer 通过 tracer provider 获取,并负责创建 spans。OpenTelemetry 管理着我们上面定义的和注册的 tracer provider。tracer 需要一个 instrumentation 名称和一个可选的版本才能创建。
let tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: "instrumentation-library-name", instrumentationVersion: "1.0.0")
创建 Span
Span 代表一个工作单元或操作。Spans 是 Traces 的构建块。要创建 span,请使用与 tracer 关联的 span builder。
let span = tracer.spanBuilder(spanName: "\(name)").startSpan()
...
span.end()
必须调用 end() 来结束 span。
创建嵌套 Span
Span 用于在操作之间建立关系。下面是一个关于我们如何手动构建 Span 之间关系的示例。
在下面,我们有 parent() 调用 child(),以及如何手动链接这些方法的 spans。
func parent() {
let parentSpan = someTracer.spanBuilder(spanName: "parent span").startSpan()
child(span: parentSpan)
parentSpan.end()
}
func child(parentSpan: Span) {
let childSpan = someTracer.spanBuilder(spanName: "child span")
.setParent(parentSpan)
.startSpan()
// do work
childSpan.end()
}
如果使用 activeSpan,则父子关系将自动链接。
func parent() {
let parentSpan = someTracer.spanBuilder(spanName: "parent span")
.setActive(true) // automatically sets context
.startSpan()
child()
parentSpan.end()
}
func child() {
let childSpan = someTracer.spanBuilder(spanName: "child span")
.startSpan() //automatically captures `active span` as parent
// do work
childSpan.end()
}
获取当前 Span
有时,对当前/活动 span 执行某些操作会很有用。以下是从代码中的任意点访问当前 span 的方法。
let currentSpan = OpenTelemetry.instance.contextProvider.activeSpan
Span 属性
Span 也可以用附加属性进行注释。所有 Span 都将自动用附加到 tracer provider 的 Resource 属性进行注释。Opentelemetry-swift SDK 已经在 SDKResourceExtension instrumentation 中提供了常见属性的 instrumentation。在此示例中,网络请求的 span 使用现有的 语义约定 捕获有关该请求的详细信息。
let span = tracer.spanBuilder("/resource/path").startSpan()
span.setAttribute("http.method", "GET");
span.setAttribute("http.url", url.toString());
创建 Span 事件
Span Event 可以被看作是 Span 上的结构化日志消息(或注释),通常用于表示 Span 持续期间内有意义的、单一时间点。
let attributes = [
"key" : AttributeValue.string("value"),
"result" : AttributeValue.int(100)
]
span.addEvent(name: "computation complete", attributes: attributes)
设置 Span 状态
可以在 Span 上设置 Status,通常用于指定 Span 未成功完成 - Error。默认情况下,所有 spans 的状态都是 Unset,这意味着 span 完成时没有错误。Ok 状态保留给您需要明确将 span 标记为成功而不是坚持默认的 Unset(即,“无错误”)的情况。
可以在 span 完成之前的任何时间设置状态。
func myFunction() {
let span = someTracer.spanBuilder(spanName: "my span").startSpan()
defer {
span.end()
}
guard let criticalData = get() else {
span.status = .error(description: "something bad happened")
return
}
// do something
}
在 Span 中记录异常
语义约定为记录异常的事件提供了特殊的标记。
let span = someTracer.spanBuilder(spanName: "my span").startSpan()
do {
try throwingFunction()
} catch {
span.addEvent(name: SemanticAttributes.exception.rawValue,
attributes: [SemanticAttributes.exceptionType.rawValue: AttributeValue.string(String(describing: type(of: error))),
SemanticAttributes.exceptionEscaped.rawValue: AttributeValue.bool(false),
SemanticAttributes.exceptionMessage.rawValue: AttributeValue.string(error.localizedDescription)])
})
span.status = .error(description: error.localizedDescription)
}
span.end()
指标
Metrics API 和 SDK 的文档缺失,您可以 编辑此页面 来帮助提供相关文档。
日志
日志 API 和 SDK 目前正在开发中。
SDK 配置
处理器
OpenTelemetry-swift 提供了不同的 Span Processor。SimpleSpanProcessor 会立即将结束的 spans 转发给导出器,而 BatchSpanProcessor 会将它们批量处理并一起发送。可以使用 MultiSpanProcessor 同时配置多个 Span Processor。例如,您可以创建一个 SimpleSpanProcessor 导出到日志记录器,以及一个 BatchSpanProcessor 导出到 OpenTelemetry Collector。
let otlpConfiguration = OtlpConfiguration(timeout: OtlpConfiguration.DefaultTimeoutInterval)
let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads:1))
.connect(host: <collector host>, port: <collector port>)
let traceExporter = OtlpTraceExporter(channel: grpcChannel
config: otlpConfiguration)
// build & register the Tracer Provider using the built otlp trace exporter
OpenTelemetry.registerTracerProvider(tracerProvider: TracerProviderBuilder()
.add(spanProcessor:BatchSpanProcessor(spanExporter: traceExporter))
.add(spanProcessor:SimpleSpanProcessor(spanExporter: StdoutExporter))
.with(resource: Resource())
.build())
Batch Span Processor 允许使用各种参数进行自定义,包括:
导出器
OpenTelemetry-Swift 提供了以下导出器:
InMemoryExporter:将 span 数据保存在内存中。这对于测试和调试很有用。DatadogExporter:将 OpenTelemetry span 数据转换为 Datadog traces,并将 span Events 转换为 Datadog logs。JaegerExporter:将 OpenTelemetry span 数据转换为 Jaeger 格式并导出到 Jaeger 端点。- Persistence exporter:一个导出器装饰器,为现有的 metrics 和 trace 导出器提供数据持久性。
PrometheusExporter:将 metric 数据转换为 Prometheus 格式并导出到 Prometheus 端点。StdoutExporter:将 span 数据导出到 Stdout。用于调试。ZipkinTraceExporter:将 span 数据转换为 Zipkin 格式并导出到 Zipkin 端点。