App监控关联前后端Trace

ARMS用户体验监控支持以用户会话作为切入点,追踪用户与应用交互过程中的错误、缓慢、异常问题,通过与ARMS应用监控联动,实现端到端分析,帮助您打通问题分析链路。本文介绍移动端监控如何实现端到端Trace打通。

前提条件

  • 确保您的移动端应用(包含Android、iOS)已接入RUM新版SDK。具体操作,请参见接入移动应用

    说明

    Android SDK版本号≥0.2.0 ,iOS SDK版本号≥0.2.0。

  • 确保您的后端应用,已接入ARMS应用监控或可观测链路 OpenTelemetry 版。具体操作,请参见接入指南

  • 确保您的后端应用,有提供Web服务(HTTP),用于解析Header,关联Trace上下文。

支持的Trace协议类型

  • Skywalking:v3版本(Skywalking 8.*)

  • OpenTelemetry(w3c)

接入操作

添加自身服务域名并开启Trace透传

  1. 登录ARMS控制台
  2. 在左侧导航栏选择用户体验监控 > 应用列表,并在顶部菜单栏选择目标地域。

  3. 单击目标应用名称,然后单击应用设置

  4. 请求管理区域配置自身服务域名。

    重要

    请勿将第三方服务域名添加为自身服务,否则Trace打通可能不会生效。

    添加自身服务域名,打开链路打通开关,并选择后端服务对应的透传协议。

    说明

    后端应用需要先接入ARMS链路追踪,具体操作,请参见接入指南

    image

    透传格式名称

    格式

    sw8(Skywalking v3)

    sw8: {sample}-{trace-id}-{segment-id}-{0}-{service}-{instance}-{endpoint}-{peer}

    tracecontext

    traceparent : {version}-{trace-id}-{parent-id}-{trace-flags}

    tracestate: rum={version}&{appType}&{pid}&{sessionId}

  5. 单击确认,系统将会自动推送Trace打通配置到移动端。

    重要
    • 端侧配置的生效,可能会有分钟级延迟,具体取决于用户侧行为,SDK默认在App冷启动时会拉取一次配置,切至后台超过30s后再次打开时,也会重新拉取。

    • 需要注意,虽然移动端不存在WebCORS策略限制,但各协议透传的Request Header需要服务端网关支持透传,否则后端服务无法接受Header,也就无法实现RUMTrace打通。

验证是否配置成功

此处以SkyWalking V3版本透传协议为例验证Trace是否配置成功。

Android

可通过Android Studio内置的App Inspection工具查看网络请求的Request Headers中是否携带了sw8协议信息判断是否接入成功。image

iOS

可通过Xcode Profile工具(在Xcode工具栏选择Product > Profile > Network)查看网络请求的Request Headers中是否携带了sw8协议信息判断是否接入成功。

image

配置后端应用Trace串联

为了打通完整Trace链路,还需要对后端应用进行配置,目前支持的后端应用类型以及接入方式如下:

Java应用

使用ARMS应用监控探针接入

ARMS应用监控探针默认集成了对OpenTelemetry协议的支持,因此无需额外配置,即可实现与RUM Trace关联,但需要确保以下两点:

  • 支持的ARMS应用监控探针版本:2.x、3.x、4.x,为了获得更好的使用体验,推荐升级到4.x版本。

  • 支持的Web容器和框架:支持Tomcat、Jetty、WebLogic、Undertow等主流Web容器,以及SpringBoot、SpringMVC等框架。支持的完整组件和框架请参见ARMS应用监控支持的Java组件和框架

ARMS应用监控探针接入操作请参见开始监控Java应用

使用OpenTelemetry接入

通过OpenTelemetry接入ARMS(可观测链路 OpenTelemetry 版),目前分为两种方式:自动埋点和手动埋点。

  • 自动埋点场景下,由于OpenTelemetry已经支持了绝大多数主流框架,因此,无需额外配置,即可实现与RUM Trace的串联。

    说明

    OpenTelemetry支持的Java框架,请参见通过OpenTelemetry上报Java应用数据

  • 手动埋点场景下,需要通过OpenTelemetry SDK提供的扩展机制,实现与RUM Trace的串联,即从前端请求头(traceparent、tracesate)中,解析出Trace上下文,以下是Springboot场景代码示例:

    1. 引入OpenTelemetry的依赖项。

      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-api</artifactId>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-sdk-trace</artifactId>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-extension-annotations</artifactId>
        <version>1.18.0</version>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-exporter-otlp</artifactId>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-sdk</artifactId>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-semconv</artifactId>
        <version>1.30.1-alpha</version>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
        <version>1.34.1</version>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry</groupId>
        <artifactId>opentelemetry-extension-incubator</artifactId>
        <version>1.35.0-alpha</version>
      </dependency>
    2. OpenTelemetry初始化时,添加W3C Propagator。

      Resource resource = Resource.getDefault()
              .merge(Resource.create(Attributes.of(
                      ResourceAttributes.SERVICE_NAME, "otel-demo",
                      ResourceAttributes.HOST_NAME, "xxxx"
      )));
      
      SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
              .addSpanProcessor(BatchSpanProcessor.builder(OtlpHttpSpanExporter.builder()
                      .setEndpoint("Your Endpoint")
                      .addHeader("Authentication", "Your Token")
                      .build()).build())
              .setResource(resource)
              .build();
      
      openTelemetry = OpenTelemetrySdk.builder()
              .setTracerProvider(sdkTracerProvider)
              // 这里添加W3C Propagator
              .setPropagators(ContextPropagators.create(
                      TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()))
               ).buildAndRegisterGlobal();
      // 这里需要使用扩展的Tracer
      tracer = ExtendedTracer.create(openTelemetry.getTracer("com.example.tracer", "1.0.0"));
    3. 在业务接口中,添加headers参数,并从请求头中解析Trace上下文,设置parent。

      // Controller中添加请求header参数,用于解析Trace上下文
      @RequestMapping("/test")
      public String test(@RequestHeader Map<String, String> headers) {
          Span span = OpenTelemetrySupport.getTracer()
                  .spanBuilder("/test")
                  // 从headers中解析parent span
                  .setParentFrom(OpenTelemetrySupport.getContextPropagators(), headers)
                  .setSpanKind(SpanKind.SERVER)
                  .startSpan();
          try (Scope scope = span.makeCurrent()) {
              // do something
          } catch (Throwable t) {
              span.setStatus(StatusCode.ERROR, "handle parent span error");
          } finally {
              span.end();
          }
          return "success";
      }

使用SkyWalking接入

完整接入方式请参见Java Agent插件

SkyWalking目前仅提供了Java Agent接入方式,您只需要按照上述文档接入,即可实现RUM与后端Trace串联。

RUM侧配置的协议匹配要求:sw8(v3版本)对应SkyWalking 8.x版本探针。

Go应用

通过OpenTelemetry接入

完整接入方式请参见通过OpenTelemetry上报Go应用数据

按照文档接入,然后在HTTP请求Handler中,通过request context生成Span,即可实现与RUM Trace串联。

// 初始化tracer
tracer := otel.Tracer(common.TraceInstrumentationName)
// 通过request context生成span
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    ctx := req.Context()
    span := trace.SpanFromContext(ctx)
    // do something
    w.Write([]byte("Hello World"))
})

使用SkyWalking接入

完整接入方式请参见通过SkyWalking上报Go应用数据

按照文档接入,推荐采用skywalking-go接入方式,该方式支持了主流的Web服务框架,如gin、go-restful、http、go-kratos v2、go-micro、go-resty等,无需修改代码即可实现与RUM Trace串联。

如果您希望手动从HTTP请求头中解析出Trace上下文,也可参考以下代码实现:

//Extract context from HTTP request header `sw8`
span, ctx, err := tracer.CreateEntrySpan(r.Context(), "/api/test", func(key string) (string, error) {
		return r.Header.Get(key), nil
})

Python应用

通过OpenTelemetry接入

完整接入方式请参见通过OpenTelemetry上报Python应用数据

按照文档接入,然后从HTTP请求头中解析Span上下文,实现与RUM Trace串联,代码示例如下:

// 初始化tracer
trace.set_tracer_provider(TracerProvider())
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))

tracer = trace.get_tracer(__name__)

@app.route('/test')
def test():
    headers = dict(request.headers)

    // 从headers中解析trace context
    carrier ={'traceparent': headers['Traceparent'], 'tracestate': headers['Tracestate']}
    ctx = TraceContextTextMapPropagator().extract(carrier=carrier)

    with tracer.start_span("test", context=ctx):
        // do something
        return "success"

使用SkyWalking接入

完整接入方式请参见通过SkyWalking上报Python应用数据

按照文档接入,然后从HTTP请求头中解析Span上下文,实现与RUM Trace串联,代码示例如下:

from skywalking import config, agent
from skywalking.trace.context import SpanContext, get_context
from skywalking.trace.carrier import CarrierItem

# 配置 SkyWalking,根据需要调整相关参数
config.init(agent_collector_backend_services='<endpoint>',
            agent_authentication='<auth-token>')

agent.start()

# 示例 HTTP 请求处理函数,需要传入 HTTP 请求的 headers
def handle_request(headers):
    # 从请求头 headers 中提取追踪信息
    carrier_items = []
    for item in SpanContext.make_carrier():
        carrier_header = headers.get(item.key.lower())
        if carrier_header:
            carrier_items.append(CarrierItem(item.key, carrier_header))

    carrier = SpanContext.make_carrier(carrier_items)

    # 从 Carrier 中提取追踪上下文
    context = get_context().extract(carrier)
    
    # 创建一个新 Span 来处理请求
    with get_context().new_entry_span(op='operation_name') as span:
        # 在这里处理请求,并在结束时自动提交 Span
        ...

# 模拟接收到的 HTTP 请求 header 包含 sw8
incoming_headers = {
    'sw8': '1-My40LjU=-MTY1MTcwNDI5OTk5OA==-xxxx-xx-x-x==',  # 示例值,实际根据请求填写
    # 其他 header...
}

# 调用函数处理请求
handle_request(incoming_headers)

查看端到端完整Trace数据

完成前后端Trace打通后,您可以在ARMS用户体验控制台查看前端请求对应的调用链。

image

单击查看调用链,可以看到请求的完整调用链路,以及应用拓扑。此时,可以结合RUM侧的请求明细数据,与后端Trace数据,分析错慢请求问题。

image

最上面的Span即代表RUM入口Span,根据端侧接入类型,分为以下几种:

  • Web & H5场景:应用名:rum-browser,Span名称前缀:"browser.request:"

  • 小程序场景:应用名:rum-miniapp,Span名称前缀:"miniapp.request: "

  • 移动端Android场景:应用名:rum-android,Span名称前缀:"android.request: "

  • 移动端iOS场景:应用名:rum-ios,Span名称前缀:"ios.request: "

同时,也可以通过拓扑图,直观地看到整个请求的上下游服务拓扑。

image