日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

通過OpenTelemetry上報(bào)Android應(yīng)用數(shù)據(jù)

通過OpenTelemetry為應(yīng)用埋點(diǎn)并上報(bào)鏈路數(shù)據(jù)至可觀測(cè)鏈路 OpenTelemetry 版后,可觀測(cè)鏈路 OpenTelemetry 版即可開始監(jiān)控應(yīng)用,您可以查看應(yīng)用拓?fù)洹⒄{(diào)用鏈路、異常事務(wù)、慢事務(wù)和SQL分析等一系列監(jiān)控?cái)?shù)據(jù)。本文介紹如何使用OpenTelemetry為Android應(yīng)用埋點(diǎn)并上報(bào)數(shù)據(jù)。

前提條件

獲取接入點(diǎn)信息

新版控制臺(tái)

  1. 登錄可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái),在左側(cè)導(dǎo)航欄單擊接入中心

  2. 開源框架區(qū)域單擊OpenTelemetry卡片。

  3. 在彈出的OpenTelemetry面板中選擇數(shù)據(jù)需要上報(bào)的地域。

    說明

    初次接入的地域?qū)?huì)自動(dòng)進(jìn)行資源初始化。

  4. 選擇連接方式上報(bào)方式,然后復(fù)制接入點(diǎn)信息。

    • 連接方式:若您的服務(wù)部署在阿里云上,且所屬地域與選擇的接入地域一致,推薦使用阿里云內(nèi)網(wǎng)方式,否則選擇公網(wǎng)方式。

    • 上報(bào)方式:根據(jù)客戶端支持的協(xié)議類型選擇HTTP或gRPC協(xié)議上報(bào)數(shù)據(jù)。

    image.png

舊版控制臺(tái)

  1. 登錄可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)

  2. 在左側(cè)導(dǎo)航欄單擊集群配置,然后在右側(cè)頁面單擊接入點(diǎn)信息頁簽。

  3. 在頁面頂部選擇需要接入的地域,然后在集群信息區(qū)域打開顯示Token開關(guān)。

  4. 客戶端采集工具區(qū)域單擊OpenTelemetry

    相關(guān)信息列中,獲取接入點(diǎn)信息。ot舊版中.jpg

    說明

    如果應(yīng)用部署于阿里云生產(chǎn)環(huán)境,則選擇阿里云VPC網(wǎng)絡(luò)接入點(diǎn),否則選擇公網(wǎng)接入點(diǎn)。

示例Demo

本文將通過具體示例介紹如何使用OpenTelemetry上報(bào)Android應(yīng)用程序的鏈路數(shù)據(jù),該方法同樣適用于Java語言和Kotlin語言應(yīng)用。

示例代碼倉庫地址:opentelemetry-android-demo

步驟一:創(chuàng)建并配置應(yīng)用

  1. 創(chuàng)建應(yīng)用。

    1. 在Android Studio中新建應(yīng)用,選擇Basic Views Activity應(yīng)用模板,然后單擊Nextimage..png

    2. 選擇Java語言或者Kotlin語言,SDK支持的最小版本選擇API 24: Android 7.0 (Nougat),然后單擊Finish

  2. 添加依賴項(xiàng)。

    在Module或Project級(jí)別的build.gradle中,添加以下依賴。

    本例中使用的OpenTelemetry Java SDK版本為1.25.0,更多版本請(qǐng)參見Opentelemetry Java Releases。build.gradle完整示例代碼請(qǐng)參見build.gradle

    implementation platform('io.opentelemetry:opentelemetry-bom:1.25.0')
    implementation "io.opentelemetry:opentelemetry-api"
    implementation "io.opentelemetry:opentelemetry-context"
    implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
    implementation 'io.opentelemetry:opentelemetry-exporter-logging'
    implementation 'io.opentelemetry:opentelemetry-extension-kotlin'
    implementation 'io.opentelemetry:opentelemetry-sdk'
    implementation 'io.opentelemetry:opentelemetry-semconv'
  3. 添加網(wǎng)絡(luò)配置。

    1. app/res/xml目錄下創(chuàng)建network_security_config.xml文件并添加以下內(nèi)容。

      <!-- 查看文件完整內(nèi)容: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/res/xml/network_security_config.xml -->
      
      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
        <domain-config cleartextTrafficPermitted="true">
          <!-- 請(qǐng)將下面的域名替換為您在前提條件中獲取的接入點(diǎn),請(qǐng)不要包含"http://"、端口號(hào)和URL路徑 -->
          <domain includeSubdomains="true">tracing-analysis-dc-hz.aliyuncs.com</domain>
        </domain-config>
      </network-security-config>
    2. 修改app/src/main/AndroidManifest.xml文件,添加以下兩行內(nèi)容為應(yīng)用開啟網(wǎng)絡(luò)權(quán)限。

      <!-- 查看文件完整內(nèi)容: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/AndroidManifest.xml -->
      
      <?xml version="1.0" encoding="utf-8"?>
      <manifest ...>
        <!-- 添加下面一行內(nèi)容,以開啟網(wǎng)絡(luò)權(quán)限 -->
        <uses-permission android:name="android.permission.INTERNET" />
      
        <application
          ...
          <!-- 添加下面一行內(nèi)容,對(duì)要上報(bào)數(shù)據(jù)的域名進(jìn)行網(wǎng)絡(luò)配置 -->
          android:networkSecurityConfig="@xml/network_security_config"
          ...>
      
          ...
        </application>
      
      </manifest>

步驟二:OpenTelemetry初始化

  1. 創(chuàng)建OpenTelemetry工具類。

    在MainActivity所在的同級(jí)目錄下創(chuàng)建OpenTelemetryUtil文件并添加以下內(nèi)容。

    • 方法一:通過gRPC上報(bào)Trace數(shù)據(jù)

      /**
       請(qǐng)?jiān)L問以下鏈接獲取完整代碼
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/OpenTelemetryUtil.java
      */
      
      Resource otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  // 請(qǐng)將<your-service-name>替換為您的應(yīng)用名。
              	ResourceAttributes.SERVICE_NAME, "<your-service-name>",
                  // 請(qǐng)將<your-host-name>替換為您的主機(jī)名。
              	ResourceAttributes.HOST_NAME, "<your-host-name>"
              )
          )
      );
      
      SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // 可選,將鏈路數(shù)據(jù)打印到日志/命令行,如不需要請(qǐng)注釋這一行。
          // 請(qǐng)將<gRPC-endpoint>替換為從前提條件中獲取的接入點(diǎn),<gRPC-token>替換為鑒權(quán)Token。
          .addSpanProcessor(BatchSpanProcessor.builder(
              OtlpGrpcSpanExporter.builder()
                   .setEndpoint("<gRPC-endpoint>") // 例如:http://tracing-analysis-dc-hz.aliyuncs.com:8090
                   .addHeader("Authentication", "<gRPC-token>") // 例如:xxxx@xxxx_xxxx@xxxx
                   .build()).build()
          )
          .setResource(otelResource)
          .build();
      
      OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal();
      
      // 獲取tracer,用來創(chuàng)建Span。
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0");
      /**
       請(qǐng)?jiān)L問以下鏈接獲取完整代碼
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt
      */
      
      val otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  ResourceAttributes.SERVICE_NAME, "<your-service-name>", // 請(qǐng)將<your-service-name>替換為您的應(yīng)用名。
                  ResourceAttributes.HOST_NAME, "<your-host-name>"    // 請(qǐng)將<your-host-name>替換為您的主機(jī)名。
              )
          )
      )
      
      /* 使用gRPC協(xié)議上報(bào)鏈路數(shù)據(jù) */
      val sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // 可選,將鏈路數(shù)據(jù)打印到日志/命令行,如不需要請(qǐng)注釋這一行。
      	// 請(qǐng)將<gRPC-endpoint>替換為從前提條件中獲取的接入點(diǎn),<gRPC-token>替換為鑒權(quán)Token。
          .addSpanProcessor(
              BatchSpanProcessor.builder(
                  OtlpGrpcSpanExporter.builder()
                      .setEndpoint("<gRPC-endpoint>") // 例如:http://tracing-analysis-dc-hz.aliyuncs.com:8090
                      .addHeader("Authentication", "<gRPC-token>") // 例如:xxxx@xxxx_xxxx@xxxx
                      .build()
              ).build()
          )
          .setResource(otelResource)
          .build()
      
      val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal()
      
      // 獲取tracer,用來創(chuàng)建Span。
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0")
    • 方法二:通過HTTP上報(bào)Trace數(shù)據(jù)

      /**
       請(qǐng)?jiān)L問以下鏈接獲取完整代碼
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/OpenTelemetryUtil.java
      */
      
      Resource otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  // 請(qǐng)將<your-service-name>替換為您的應(yīng)用名。
                  ResourceAttributes.SERVICE_NAME, "<your-service-name>",
                  // 請(qǐng)將<your-host-name>替換為您的主機(jī)名。
                  ResourceAttributes.HOST_NAME, "<your-host-name>"
              )
          )
      );
      
      SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // 可選,將鏈路數(shù)據(jù)打印到日志/命令行,如不需要請(qǐng)注釋這一行
          // 請(qǐng)將<HTTP-endpoint>替換為從前提條件中獲取的接入點(diǎn)。
          .addSpanProcessor(BatchSpanProcessor.builder(
              OtlpHttpSpanExporter.builder()
                   .setEndpoint("<HTTP-endpoint>") // 例如 http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces
                   .build()).build()
          )
          .setResource(otelResource)
          .build();
      
      OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal();
      
      // 獲取tracer,用來創(chuàng)建Span。
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0");
      /**
       請(qǐng)?jiān)L問以下鏈接獲取完整代碼
       https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt
      */
      
      val otelResource = Resource.getDefault().merge(
          Resource.create(
              Attributes.of(
                  ResourceAttributes.SERVICE_NAME, "<your-service-name>", // 請(qǐng)將<your-service-name>替換為您的應(yīng)用名。
                  ResourceAttributes.HOST_NAME, "<your-host-name>"    // 請(qǐng)將<your-host-name>替換為您的主機(jī)名。
              )
          )
      )
      
      /* 使用HTTP協(xié)議上報(bào)鏈路數(shù)據(jù) */
      val sdkTracerProvider = SdkTracerProvider.builder()
          .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // 可選,將鏈路數(shù)據(jù)打印到日志/命令行,如不需要請(qǐng)注釋這一行。
      	// 請(qǐng)將<HTTP-endpoint>替換為從前提條件中獲取的接入點(diǎn)。
          .addSpanProcessor(BatchSpanProcessor.builder(
              OtlpHttpSpanExporter.builder()
                  .setEndpoint("<HTTP-endpoint>") // 例如:http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces
                  .build()).build()
                           )
          .setResource(otelResource)
          .build();
      
      val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder()
          .setTracerProvider(sdkTracerProvider)
          .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
          .buildAndRegisterGlobal()
      
      // 獲取tracer,用來創(chuàng)建Span。
      tracer = openTelemetry.getTracer("android-tracer", "1.0.0")
  2. 在應(yīng)用程序初始化時(shí)對(duì)OpenTelemetry進(jìn)行初始化。

    在MainActivity的onCreate方法中調(diào)用OpenTelemetryUtil.init()方法。

    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/MainActivity.java
    */
    
    ...
    public class MainActivity extends AppCompatActivity {
    	...
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 請(qǐng)?zhí)砑舆@一行,對(duì)OpenTelemetry進(jìn)行初始化。
            OpenTelemetryUtil.init();
            ...
        }
        ...
    }
    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/MainActivity.kt
    */
    ...
    
    class MainActivity : AppCompatActivity() {
    
        ...
        override fun onCreate(savedInstanceState: Bundle?) {
            WindowCompat.setDecorFitsSystemWindows(window, false)
            super.onCreate(savedInstanceState)
            // 請(qǐng)?zhí)砑舆@一行,OpenTelemetry初始化。
            OpenTelemetryUtil.init()
    
                ...
        }
    }

步驟三:創(chuàng)建Span追蹤鏈路數(shù)據(jù)

  1. 創(chuàng)建Span。

    在FirstFragment文件的按鈕點(diǎn)擊事件監(jiān)聽方法中,創(chuàng)建一個(gè)名為First Fragment Button onClick的Span。

    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    
    public void onClick(View view) {
        // 獲取Tracer
        Tracer tracer = OpenTelemetryUtil.getTracer();
    	// 創(chuàng)建Span
        Span span = tracer.spanBuilder("First Fragment Button onClick").startSpan();
    	try (Scope scope = span.makeCurrent()) {
            // 獲取traceId
            System.out.println(span.getSpanContext().getTraceId());
            ...
        } finally {
            span.end();
        }
    }
    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    
    binding.buttonFirst.setOnClickListener {
        // 獲取Tracer
        val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
        // 創(chuàng)建Span
        val span = tracer.spanBuilder("First Fragment Button onClick").startSpan()
        try {
            span.makeCurrent().use { scope ->
                // 獲取traceId
                println(span.spanContext.traceId)
                // 獲取spanId
                println(span.spanContext.spanId)
                
                findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
            }
        } catch (t: Throwable) {
            span.setStatus(StatusCode.ERROR, "Something wrong in onClick")
            throw t
        } finally {
            span.end()
        }
    }
  2. 為Span設(shè)置屬性和事件(Event)。

    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    
    // 設(shè)置屬性
    span.setAttribute("key", "value");
    
    Attributes eventAttributes = Attributes.of(
        AttributeKey.stringKey("key"), "value",
        AttributeKey.longKey("result"), 0L);
    // 添加事件
    span.addEvent("onClick", eventAttributes);
    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    
    // 設(shè)置屬性
    span.setAttribute("key", "value")
    val eventAttributes =
        Attributes.of(
            AttributeKey.stringKey("key"), "value",
            AttributeKey.longKey("result"), 0L
        )
    
    // 添加事件
    span.addEvent("onClick", eventAttributes)
  3. 為Span設(shè)置狀態(tài)(Status)。

    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    
    ...
    try (Scope scope = span.makeCurrent()) {
        ...
    } catch (Throwable t) {
        // 設(shè)置Span狀態(tài)
        span.setStatus(StatusCode.ERROR, "Something wrong in onClick");
        throw t;
    } finally {
        span.end(); 
    }
    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    
    ...
    try {
        ...
    } catch (t: Throwable) {
        // 為Span設(shè)置狀態(tài)
        span.setStatus(StatusCode.ERROR, "Something wrong in onClick")
        throw t
    } finally {
        span.end()
    }
  4. 創(chuàng)建嵌套的Span。

    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java
    */
    
    public void parentSpan() {
        // 獲取Tracer
        Tracer tracer = OpenTelemetryUtil.getTracer();
        // 創(chuàng)建Span
        Span span = tracer.spanBuilder("Parent Span").startSpan();
        try (Scope scope = span.makeCurrent()) {
            // 獲取traceId
            System.out.println(span.getSpanContext().getTraceId());
            // 獲取spanId
            System.out.println(span.getSpanContext().getSpanId());
            childSpan();
        } finally {
            span.end();
        }
    }
    
    public void childSpan() {
        // 獲取Tracer
        Tracer tracer = OpenTelemetryUtil.getTracer();
        // 創(chuàng)建Span
        Span span = tracer.spanBuilder("Child Span").startSpan();
        try (Scope scope = span.makeCurrent()) {
            // 獲取traceId
            System.out.println(span.getSpanContext().getTraceId());
            // 獲取spanId
            System.out.println(span.getSpanContext().getSpanId());
        } finally {
            span.end();
        }
    }
    /**
     請(qǐng)?jiān)L問以下鏈接獲取完整代碼
     https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt
    */
    
    // 嵌套Span
    fun parentSpan() {
        // 獲取Tracer
        val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
        // 創(chuàng)建Span
        val span = tracer.spanBuilder("Parent Span").startSpan()
        try {
            span.makeCurrent().use { scope ->
                // 獲取traceId
                println(span.spanContext.traceId)
                // 獲取spanId
                println(span.spanContext.spanId)
                childSpan()
            }
        } finally {
            span.end()
        }
    }
    
    // 嵌套Span
    fun childSpan() {
        // 獲取Tracer
        val tracer: Tracer = OpenTelemetryUtil.getTracer()!!
        // 創(chuàng)建Span
        val span = tracer.spanBuilder("Child Span").startSpan()
        try {
            span.makeCurrent().use { scope ->
                // 獲取traceId
                println(span.spanContext.traceId)
                // 獲取spanId
                println(span.spanContext.spanId)
            }
        } finally {
            span.end()
        }
    }

步驟四:運(yùn)行項(xiàng)目查看上報(bào)的鏈路數(shù)據(jù)

  1. 運(yùn)行項(xiàng)目,單擊Demo應(yīng)用頁面中的按鈕。image..png

    通過logcat查看日志,可以看到通過LoggingSpanExporter導(dǎo)出的Span信息。

    image..png

  2. 可觀測(cè)鏈路 OpenTelemetry 版控制臺(tái)應(yīng)用列表頁面選擇目標(biāo)應(yīng)用,查看鏈路數(shù)據(jù)。

    image..png

步驟五:打通客戶端與服務(wù)端應(yīng)用鏈路

  1. 修改Header中的Trace透?jìng)鞲袷健?/p>

    • 不同協(xié)議使用不同的HTTP Header向下游傳遞Trace上下文,如OpenTelemtry默認(rèn)使用W3C Trace Context格式(也支持修改為其他格式),而Zipkin使用B3或B3 Multi格式。關(guān)于透?jìng)鞲袷降母嘈畔ⅲ?qǐng)參見OpenTelemetry指定透?jìng)鱄eader格式

    • 根據(jù)服務(wù)端使用的協(xié)議類型,在客戶端中設(shè)置對(duì)應(yīng)的透?jìng)鞲袷剑╰extPropagators),以實(shí)現(xiàn)Android客戶端應(yīng)用與服務(wù)端應(yīng)用鏈路打通:

      • 如果服務(wù)端使用OpenTelemetry默認(rèn)的W3C Trace Context格式,客戶端無需設(shè)置textPropagators。

      • 如果服務(wù)端使用Zipkin的B3/B3 Multi格式,客戶端的textPropagators需要設(shè)置為B3Propagator。

        // 設(shè)置B3透?jìng)鞲袷健?OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(TextMapPropagator.composite(
                        B3Propagator.injectingMultiHeaders(),
                        B3Propagator.injectingSingleHeader())))
                .buildAndRegisterGlobal();
      • 如果服務(wù)端使用Jaeger協(xié)議,客戶端的textPropagators需設(shè)置為JaegerPropagator。

        // 設(shè)置Jaeger透?jìng)鞲袷健?OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(TextMapPropagator.composite(
                        JaegerPropagator.getInstance())))
                .buildAndRegisterGlobal();
      • 也可以同時(shí)設(shè)置多種Trace透?jìng)鞲袷健?/p>

        // 同時(shí)使用W3C Trace Context、B3、Jaeger三種Trace透?jìng)鞲袷健?// 設(shè)置Jaeger透?jìng)鞲袷健?OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                .setTracerProvider(sdkTracerProvider)
                .setPropagators(ContextPropagators.create(TextMapPropagator.composite(
                        W3CTraceContextPropagator.getInstance(),
                        B3Propagator.injectingMultiHeaders(),
                        B3Propagator.injectingSingleHeader()
                        JaegerPropagator.getInstance())))
                .buildAndRegisterGlobal();
  2. 導(dǎo)入okhttp3和opentelemetry-okhttp。

    opentelemetry-okhttp-3.0是OpenTelemetry提供的針對(duì)OkHttp的自動(dòng)埋點(diǎn)插件,可以自動(dòng)攔截所有通過OkHttp3發(fā)出的網(wǎng)絡(luò)請(qǐng)求并創(chuàng)建調(diào)用鏈。

    • 在build.gradle中添加以下兩個(gè)依賴。

      dependencies {
          ...
          implementation 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0:2.3.0-alpha'
          implementation 'com.squareup.okhttp3:okhttp:4.12.0'
      }
    • 創(chuàng)建OkHttpConfiguration。

      import io.opentelemetry.api.OpenTelemetry;
      import io.opentelemetry.instrumentation.okhttp.v3_0.OkHttpTelemetry;
      import okhttp3.Call;
      import okhttp3.OkHttpClient;
      
      
      public class OkHttpConfiguration {
      
          //Use this Call.Factory implementation for making standard http client calls.
          public Call.Factory createTracedClient(OpenTelemetry openTelemetry) {
              return OkHttpTelemetry.builder(openTelemetry).build().newCallFactory(createClient());
          }
      
          //your configuration of the OkHttpClient goes here:
          private OkHttpClient createClient() {
              return new OkHttpClient.Builder().build();
          }
      }
  3. 使用OkHttp3進(jìn)行網(wǎng)絡(luò)請(qǐng)求,訪問服務(wù)端。

    private void callHttpService() throws IOException {
        Tracer tracer = OpenTelemetryUtil.getTracer();
        // 創(chuàng)建Span
        Span span = tracer.spanBuilder("AsyncRequestZipkinServer").startSpan();
        System.out.println("AsyncRequestZipkinServer TraceID: " + span.getSpanContext().getTraceId());
        System.out.println("AsyncRequestZipkinServer SpanID: " + span.getSpanContext().getSpanId());
        try (Scope scope = span.makeCurrent()) {
            // 執(zhí)行網(wǎng)絡(luò)請(qǐng)求,例如使用 OkHttp
            OkHttpConfiguration configuration = new OkHttpConfiguration();
            Call.Factory tracedClient = configuration.createTracedClient(GlobalOpenTelemetry.get());
    
            Request request = new Request.Builder().url("${服務(wù)端地址}").get().build();
    
            Call call = tracedClient.newCall(request);
            try (Response response = call.execute()) {
                // 處理響應(yīng)
                String responseBody = response.body().string();
                System.out.println(responseBody);
            } catch (IOException e) {
                // 處理錯(cuò)誤
                e.printStackTrace();
            }
        }  finally {
            span.end();
        }
    }

    展開查看在onClick等事件中異步調(diào)用callHttpService方法的完整代碼

    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Looper;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import androidx.annotation.NonNull;
    import androidx.fragment.app.Fragment;
    import androidx.navigation.fragment.NavHostFragment;
    
    import com.example.androidjavademo.databinding.FragmentFirstBinding;
    
    import java.io.IOException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    import io.opentelemetry.api.GlobalOpenTelemetry;
    import io.opentelemetry.api.common.AttributeKey;
    import io.opentelemetry.api.common.Attributes;
    import io.opentelemetry.api.trace.Span;
    import io.opentelemetry.api.trace.StatusCode;
    import io.opentelemetry.api.trace.Tracer;
    import io.opentelemetry.context.Scope;
    import okhttp3.Call;
    import okhttp3.Request;
    import okhttp3.Response;
    
    public class FirstFragment extends Fragment {
    
        private FragmentFirstBinding binding;
    
        @Override
        public View onCreateView(
                LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState
        ) {
    
            binding = FragmentFirstBinding.inflate(inflater, container, false);
            return binding.getRoot();
    
        }
    
        public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
    
            binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    // 獲取Tracer
                    Tracer tracer = OpenTelemetryUtil.getTracer();
                    // 創(chuàng)建Span
                    Span span = tracer.spanBuilder("First Fragment Button onClick").startSpan();
                    try (Scope scope = span.makeCurrent()) {
                        // 獲取traceId
                        System.out.println(span.getSpanContext().getTraceId());
                        // 獲取spanId
                        System.out.println(span.getSpanContext().getSpanId());
                        // 設(shè)置屬性
                        span.setAttribute("key", "value");
    
                        Attributes eventAttributes = Attributes.of(
                                AttributeKey.stringKey("key"), "value",
                                AttributeKey.longKey("result"), 0L);
    
                        // 添加事件
                        span.addEvent("onClick", eventAttributes);
    
                        parentSpan();
    
                        NavHostFragment.findNavController(FirstFragment.this)
                                .navigate(R.id.action_FirstFragment_to_SecondFragment);
                    } catch (Throwable t) {
                        span.setStatus(StatusCode.ERROR, "Something wrong in onClick");
                        throw t;
                    } finally {
                        span.end();
                    }
                }
            });
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
            binding = null;
        }
    
        public void parentSpan() {
    
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            Handler handler = new Handler(Looper.getMainLooper());
    
            // 獲取Tracer
            Tracer tracer = OpenTelemetryUtil.getTracer();
            // 創(chuàng)建Span
            Span span = tracer.spanBuilder("Parent Span").startSpan();
            try (Scope scope = span.makeCurrent()) {
                // 獲取traceId
                System.out.println(span.getSpanContext().getTraceId());
                // 獲取spanId
                System.out.println(span.getSpanContext().getSpanId());
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        // 執(zhí)行網(wǎng)絡(luò)請(qǐng)求
                        try {
                            callHttpService();
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                        // 執(zhí)行完畢,通過handler切回主線程處理結(jié)果
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                // 處理UI更新或其他工作
                                childSpan();
                            }
                        });
                    }
                });
    
                executorService.shutdown();
            } finally {
                span.end();
            }
        }
    
        public void childSpan() {
            // 獲取Tracer
            Tracer tracer = OpenTelemetryUtil.getTracer();
            // 創(chuàng)建Span
            Span span = tracer.spanBuilder("Child Span").startSpan();
            try (Scope scope = span.makeCurrent()) {
                // 獲取traceId
                System.out.println(span.getSpanContext().getTraceId());
                // 獲取spanId
                System.out.println(span.getSpanContext().getSpanId());
            } finally {
                span.end();
            }
        }
    
        private void callHttpService() throws IOException {
            Tracer tracer = OpenTelemetryUtil.getTracer();
            // 創(chuàng)建Span
            Span span = tracer.spanBuilder("AsyncRequestZipkinServer").startSpan();
            System.out.println("AsyncRequestZipkinServer TraceID: " + span.getSpanContext().getTraceId());
            System.out.println("AsyncRequestZipkinServer SpanID: " + span.getSpanContext().getSpanId());
            try (Scope scope = span.makeCurrent()) {
                // 執(zhí)行網(wǎng)絡(luò)請(qǐng)求,例如使用OkHttp
                OkHttpConfiguration configuration = new OkHttpConfiguration();
                Call.Factory tracedClient = configuration.createTracedClient(GlobalOpenTelemetry.get());
    
                Request request = new Request.Builder().url("${服務(wù)端地址}").get().build();
                Call call = tracedClient.newCall(request);
                try (Response response = call.execute()) {
                    // 處理響應(yīng)
                    String responseBody = response.body().string();
                    System.out.println(responseBody);
                } catch (IOException e) {
                    // 處理錯(cuò)誤
                    e.printStackTrace();
                }
            }  finally {
                span.end();
            }
        }
    
    }
  4. 調(diào)用鏈分析頁面查看客戶端與服務(wù)端打通的調(diào)用鏈。

    如下圖所示,AsyncRequestZipkinServer為Android應(yīng)用,zipkin-demo-server為服務(wù)端應(yīng)用。

    image