通过OpenTelemetry为应用埋点并上报链路数据至可观测链路 OpenTelemetry 版后,可观测链路 OpenTelemetry 版即可开始监控应用,您可以查看应用拓扑、调用链路、异常事务、慢事务和SQL分析等一系列监控数据。本文介绍如何使用OpenTelemetry为Swift应用埋点并上报数据。
前提条件
示例Demo
本文将通过具体示例介绍如何通过OpenTelemetry上报Swift语言编写的macOS命令行应用数据,该方法同样适用于iOS应用。
示例代码仓库地址:opentelemetry-swift-demo
步骤一:创建应用并添加依赖
选择要创建的应用,例如macOS的Command Line Tool。
在XCode中选择
https://github.com/open-telemetry/opentelemetry-swift
,选择1.4.1版本。 ,然后在搜索框中输入说明更多版本信息,请参考opentelemetry-swift releases信息。
选中所需的Package Products。
本文中使用到的Package Products如下:
步骤二:OpenTelemetry初始化
创建用于导出观测数据的组件。
从以下3种方法中选择1种上报Trace数据。
方法一:通过gRPC协议上报Trace数据
请分别将
<gRPC-endpoint>
和<gRPC-port>
替换为从前提条件中获取的接入点信息,例如:host: "http://tracing-analysis-dc-hz.aliyuncs.com", port:8090
。请将
<your-token>
替换为从前提条件中获取的鉴权Token。
let grpcChannel = ClientConnection( configuration: ClientConnection.Configuration.default( target: .hostAndPort("<gRPC-endpoint>", 8090), // 接入点填写示例:tracing-analysis-dc-hz.aliyuncs.com,不需要添加"http://" eventLoopGroup: MultiThreadedEventLoopGroup(numberOfThreads: 1) ) ) let otlpGrpcConfiguration = OtlpConfiguration( timeout: OtlpConfiguration.DefaultTimeoutInterval, headers: [ ("Authentication","xxxxxx") ] ) let otlpGrpcTraceExporter = OtlpTraceExporter(channel: grpcChannel, config: otlpGrpcConfiguration)
方法二:通过HTTP协议上报Trace数据
请将
<HTTP-endpoint>
替换为从前提条件中获取的接入点信息,例如:http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces
。let url = URL(string: "<HTTP-endpoint>") let otlpHttpTraceExporter = OtlpHttpTraceExporter(endpoint: url!)
方法三:在命令行输出Trace数据
let consoleTraceExporter = StdoutExporter(isDebug: true)
获取用于创建Span的Tracer。
请将
<your-service-name>
替换为要上报的应用名,<your-host-name>
替换为主机名。替换
<trace-exporter>
,根据步骤1上报Trace方法不同替换为不同值。方式一:
<trace-exporter>
替换为otlpGrpcTraceExporter
。方式二:
<trace-exporter>
替换为otlpHttpTraceExporter
。方式三:
<trace-exporter>
替换为consoleTraceExporter
。
// 设置应用名与主机名 let resource = Resource(attributes: [ ResourceAttributes.serviceName.rawValue: AttributeValue.string("<your-service-name>"), ResourceAttributes.hostName.rawValue: AttributeValue.string("<your-host-name>") ]) // 配置TracerProvider OpenTelemetry.registerTracerProvider(tracerProvider: TracerProviderBuilder() .add(spanProcessor: BatchSpanProcessor(spanExporter: <trace-exporter>)) // 上报至可观测链路 OpenTelemetry 版 .with(resource: resource) .build()) // 获取tracer,用来创建Span let tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: "instrumentation-library-name", instrumentationVersion: "1.0.0")
步骤三:创建Span追踪链路数据
创建Span,为Span添加属性(Attribute)和事件(Event),并输出当前Span的TraceId。
let span = tracer.spanBuilder(spanName: "first span").startSpan() // 设置属性 span.setAttribute(key: "http.method", value: "GET") span.setAttribute(key: "http.url", value: "www.aliyun.com") let attributes = [ "key": AttributeValue.string("value"), "result": AttributeValue.int(100) ] // your code... // 设置Event span.addEvent(name: "computation complete", attributes: attributes) // 打印TraceId print(span.context.traceId.hexString) // your code... // 结束当前span span.end()
创建嵌套的Span。
let parentSpan = tracer.spanBuilder(spanName: "parent span").startSpan() // your code... let childSpan = tracer.spanBuilder(spanName: "child span").setParent(parentSpan).startSpan() // your code... childSpan.end() // your code... parentSpan.end()
启动应用。
在可观测链路 OpenTelemetry 版控制台的应用列表页面选择目标应用,查看链路数据。
步骤四:打通客户端与服务端应用链路
修改Header中的Trace透传格式。
不同协议使用不同的HTTP Header向下游传递Trace上下文,如OpenTelemtry默认使用W3C Trace Context格式(也支持修改为其他格式),而Zipkin使用B3或B3 Multi格式。关于透传格式的更多信息,请参见OpenTelemetry指定透传Header格式。
根据服务端使用的协议类型,在客户端中设置对应的透传格式(textPropagators和baggagePropagator),以实现iOS客户端应用与服务端应用链路打通:
如果服务端使用OpenTelemetry默认的W3C Trace Context格式,客户端无需设置textPropagators和baggagePropagator。
如果服务端使用Zipkin的B3/B3 Multi格式,客户端的textPropagators需设置为B3Propagator,baggagePropagator设置为ZipkinBaggagePropagator。
// 设置B3透传格式。 OpenTelemetry.registerPropagators(textPropagators: [B3Propagator()], baggagePropagator: ZipkinBaggagePropagator())
如果服务端使用Jaeger协议,客户端的textPropagators需设置为JaegerPropagator,baggagePropagator设置为JaegerBaggagePropagator。
// 设置Jaeger透传格式。 OpenTelemetry.registerPropagators(textPropagators: [JaegerPropagator()], baggagePropagator: JaegerBaggagePropagator())
也可以同时设置多种Trace透传格式。
// 同时使用W3C Trace Context、B3、Jaeger三种Trace透传格式。 OpenTelemetry.registerPropagators(textPropagators: [W3CTraceContextPropagator(), B3Propagator(), JaegerPropagator()], baggagePropagator: W3CBaggagePropagator())
导入URLSessionInstrumentation。
URLSessionInstrumentation是OpenTelemetry提供的针对URLSession的自动埋点插件,可以自动拦截所有通过URLSession发出的网络请求并创建调用链。
import URLSessionInstrumentation ... let networkInstrumentation = URLSessionInstrumentation(configuration: URLSessionInstrumentationConfiguration())
使用URLSession进行网络请求,访问服务端。
let url = URL(string: "<服务端地址>")! let request = URLRequest(url: url) let semaphore = DispatchSemaphore(value: 0) let task = URLSession.shared.dataTask(with: request) { data, _, _ in if let data = data { let string = String(decoding: data, as: UTF8.self) print(string) } semaphore.signal() } task.resume() semaphore.wait()
启动应用,在调用链分析页面查看客户端与服务端打通的调用链。
如下图所示,
HTTP GET
为iOS应用,zipkin-demo-server
为服务端应用。