IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    前端 SPA 应用通过 OpenTelemetry 接入“链路追踪” · 看不见我的美 · 是你瞎了眼

    馬腊咯稽发表于 2023-02-06 00:00:00
    love 0
    前端 SPA 应用通过 OpenTelemetry 接入“链路追踪”

    事例代码

    新建 tracing.ts:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    
    import { ZoneContextManager } from '@opentelemetry/context-zone';
    import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
    import { registerInstrumentations } from '@opentelemetry/instrumentation';
    import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
    import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
    import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';
    import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
    import { Resource } from '@opentelemetry/resources';
    import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
    import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
    import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
    import { environment } from 'src/environments/environment';
    // Init
    const resource = Resource.default().merge(
     new Resource({
     // 通过 environment.name 变量来区分不同环境的应用
     [SemanticResourceAttributes.SERVICE_NAME]: `${environment.name}`
     })
    );
    // Tracing
    const provider = new WebTracerProvider({
     resource
    });
    if (!environment.production) {
     // 开发环境使用 ConsoleSpanExporter,便于调试
     const consoleExporter = new ConsoleSpanExporter();
     const consoleProcessor = new SimpleSpanProcessor(consoleExporter);
     provider.addSpanProcessor(consoleProcessor);
    } else {
     // 生产环境使用 OTLPTraceExporter
     const traceUrl = 'https://otelcol.xxx.com/v1/traces';
     const traceExporter = new OTLPTraceExporter({
     url: traceUrl,
     headers: {} // Use xhr Rather Than navigator.sendBeacon
     });
     const traceProcessor = new BatchSpanProcessor(traceExporter, {
     maxExportBatchSize: 10,
     maxQueueSize: 100
     });
     provider.addSpanProcessor(traceProcessor);
    }
    provider.register({
     contextManager: new ZoneContextManager()
    });
    // Register
    const propagateTraceHeaderCorsUrls = /.+/g; // 哪些跨域接口添加“追踪请求头”
    const ignoreUrls = [
     /**
     * 哪些接口不添加“追踪请求头”:
     * 1. 加载静态资源的接口
     * 2. 第三方 SDK 调用的接口
     * 3. 本地 DevServer/HMR 接口
     */
     /^(https:\/\/static-offline-objects.xxx.com|https:\/\/static-objects.xxx.com|https:\/\/qiniu.xxx.com|https:\/\/oss.xxx.com)/g,
     /^(https:\/\/eos-scp-int.sit.xxx-express.com)/g,
     /^(https:\/\/eos-scp.sit.xxx-express.com)/g,
     /^(https:\/\/eos-scp-int.xxx-express.com)/g,
     /^(https:\/\/eos-scp.xxx-express.com)/g,
     /^(https:\/\/s9.cnzz.com\/z_stat.php)/g,
     /^(http:\/\/localhost)/g,
     /^(http:\/\/192.168)/g,
     /^(http:\/\/0.0.0.0)/g
    ];
    registerInstrumentations({
     instrumentations: [
     // 处理页面加载
     new DocumentLoadInstrumentation(),
     // 处理用户交互
     new UserInteractionInstrumentation(),
     // 处理 Fetch
     new FetchInstrumentation({
     clearTimingResources: true,
     propagateTraceHeaderCorsUrls,
     ignoreUrls
     }),
     // 处理 XHR
     new XMLHttpRequestInstrumentation({
     clearTimingResources: true,
     propagateTraceHeaderCorsUrls,
     ignoreUrls
     })
     ],
     tracerProvider: provider
    });
    

    在应用入口(以 Angular 为例,如遇接口报错,尝试更新 NgZone)引入 tracing.ts:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    import { AppModule } from './app/app.module';
    import { environment } from './environments/environment';
    import './tracing';
    
    if (environment.production) {
     enableProdMode();
    }
    
    platformBrowserDynamic()
     .bootstrapModule(AppModule)
     .catch(err => console.error(err));
    

    数据传递流程

    每次从前端发起请求时,OTLP 会在请求头中注入 traceparent/X-B3-(TraceId|ParentSpanId|SpanId|Sampled) 字段(取决于使用的是 W3C 规范 还是 B3 规范 ),用来将前后端链路信息关联起来;同时,客户端会将收集到的链路数据通过 OTLPTraceExporter 提交给追踪服务器;服务端会将收集到的链路数据通过 Java Agent 提交给追踪服务器。

    参考

    • 到底什么是 RUM?生产环境如何选择靠谱的前端监控系统
    • What Can OpenTelemetry Do for Frontend Developers?
    • Adding OpenTelemetry to An Angular Application
    • OpenTelemetry Documentation
    • OpenTelemetry 规范阅读


沪ICP备19023445号-2号
友情链接