通过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为服务端应用。 

