Flutter分布式追踪插件opentelemetry_dart的使用

Flutter分布式追踪插件opentelemetry_dart的使用

OpenTelemetry for Dart

OpenTelemetry fork而来以添加JSON报告器。

此项目旨在成为OpenTelemetry项目的Dart实现,并长期目标是开源。

所有贡献和设计应遵循OpenTelemetry规范,以便与所有其他语言保持一致。

开始使用

首先,你需要配置至少一个导出器。导出器决定了你收集到的跨度将如何处理。 当前选项有:

导出器 描述
CollectorExporter 将跨度发送到配置的opentelemetry-collector。
ConsoleExporter 将跨度打印到控制台。

跨度导出器

CollectorExporter

CollectorExporter 需要 opentelemetry-collector 实例的跟踪收集器的Uri。

import 'package:opentelemetry_dart/sdk.dart' as otel_sdk;

final exporter = otel_sdk.CollectorExporter(Uri.parse('https://my-collector.com/v1/traces'));

ConsoleExporter

ConsoleExporter 没有要求,也没有配置选项。

import 'package:opentelemetry_dart/sdk.dart' as otel_sdk;

final exporter = otel_sdk.ConsoleExporter();

跨度处理器

接下来,你需要至少一个跨度处理器。跨度处理器负责收集你创建的跨度并将它们传递给导出器。 当前选项有:

跨度处理器 描述
BatchSpanProcessor 在配置的时间间隔内批量导出跨度。
SimpleSpanProcessor 当跨度关闭时立即执行提供的导出器。

BatchSpanProcessor

BatchSpanProcessors 每个间隔最多收集2048个跨度,并按定时器执行提供的导出器。

选项 描述 默认
maxExportBatchSize 每批最多处理多少个跨度。 512
scheduledDelay 收集跨度后多久处理它们。 5000 毫秒
import 'package:opentelemetry_dart/sdk.dart' as otel_sdk;

final exporter = otel_sdk.ConsoleExporter();
final processor = otel_sdk.BatchSpanProcessor(exporter, scheduledDelay: 10000);

SimpleSpanProcessor

SimpleSpanProcessor 没有配置选项,并在每个跨度关闭时执行导出器。

import 'package:opentelemetry_dart/sdk.dart' as otel_sdk;

final exporter = otel_sdk.ConsoleExporter();
final processor = otel_sdk.SimpleSpanProcessor(exporter);

跟踪提供器

跟踪提供器注册你的跨度处理器,并负责管理任何跟踪器。

选项 描述 默认
processors 注册的跨度处理器列表。 一个带有 ConsoleExporterSimpleSpanProcessor
import 'package:opentelemetry_dart/sdk.dart' as otel_sdk;

final exporter = otel_sdk.CollectorExporter(Uri.parse('https://my-collector.com/v1/traces'));
final processor = otel_sdk.BatchSpanProcessor(exporter);

// 每5秒发送跨度到收集器
final provider = otel_sdk.TracerProvider([processor]);

// 可选地,可以注册多个处理器
final provider = otel_sdk.TracerProvider([
  otel_sdk.BatchSpanProcessor(otel_sdk.CollectorExporter(Uri.parse('https://my-collector.com/v1/traces'))),
  otel_sdk.SimpleSpanProcessor(otel_sdk.ConsoleExporter())
]);

// 注册跟踪提供器作为全局,以便MSDK中间件可以访问它。
otel_sdk.registerGlobalTracerProvider(provider);

final tracer = provider.getTracer('instrumentation-name');
// 或者
final tracer = otel_sdk.globalTracerProvider.getTracer('instrumentation-name');

带浏览器性能功能的跟踪提供器

还提供了一个特定于Web的跟踪提供器。该跟踪提供器利用浏览器的性能API提供了可配置的选项。

import 'package:opentelemetry_dart/sdk.dart' as otel_sdk;
import 'package:opentelemetry_dart/web_sdk.dart' as web_sdk;

final exporter = otel_sdk.CollectorExporter(Uri.parse('https://my-collector.com/v1/traces'));
final processor = otel_sdk.BatchSpanProcessor(exporter);

// 此提供器配置为创建使用浏览器的性能API而不是Dart的DateTime类来确定跨度时间戳的跟踪器。
final provider = web_sdk.WebTracerProvider(
  processors: [processor],
  timeProvider: web_sdk.WebTimeProvider()
);

// 此跟踪器已配置为使用浏览器的性能API来确定其创建的任何跨度的时间戳。
final tracer = provider.getTracer('instrumentation-name');

// 或者,这些跟踪提供器也可以全局注册。
otel_sdk.registerGlobalTracerProvider(provider);
final tracer = otel_sdk.globalTracerProvider.getTracer('instrumentation-name');

重要提示:使用此跟踪提供器生成的跨度时间戳可能不准确,如果执行系统处于休眠状态。更多信息见此处

收集跨度

要开始一个跨度,可以在跟踪器上执行 startSpan 并传入你正在跟踪的内容的名称。完成后,调用跨度上的 end 方法。

final span = tracer.startSpan('doingWork');
...
span.end();

要创建子跨度,必须将父跨度设置为“当前”,并在 withContext 中执行工作。

final checkoutSpan = tracer.startSpan('checkout');
withContext(setSpan(Context.current, checkoutSpan), () {
  final ringUpSpan = tracer.startSpan('ringUp');
  ...
  ringUpSpan.end();
  final receiveSpan = tracer.startSpan('receiveCash');
  ...
  receiveSpan.end();
  final returnSpan = tracer.startSpan('returnChange');
  ...
  returnSpan.end();
});
checkoutSpan.end();

为了避免在其他函数中传递跨度作为参数,你可以使用 Context.current.span 获取当前跨度。

doWork() {
  Span parentSpan = Context.current.span;

  Context.current.withSpan(parentSpan).execute(() {
    Span span = tracer.startSpan('doWork');
    ...
    span.end();
  });
}

开发

为了生成protobuf定义,你必须安装并使protoc在你的路径中可用。

https://github.com/protocolbuffers/protobuf/releases

更多关于Flutter分布式追踪插件opentelemetry_dart的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter分布式追踪插件opentelemetry_dart的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在 Flutter 中使用 OpenTelemetry Dart SDK 进行分布式追踪可以帮助你监控和调试应用程序的性能,特别是在微服务架构中。OpenTelemetry 是一个开源的观测框架,支持多种编程语言,包括 Dart。

以下是如何在 Flutter 项目中集成和使用 opentelemetry_dart 插件的步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 opentelemetry_dart 和相关依赖:

dependencies:
  flutter:
    sdk: flutter
  opentelemetry_dart: ^0.8.0
  opentelemetry_dart_console: ^0.8.0  # 用于在控制台输出追踪信息

然后运行 flutter pub get 来安装依赖。

2. 初始化 OpenTelemetry

在你的 Flutter 应用程序的入口点(通常是 main.dart)中初始化 OpenTelemetry:

import 'package:opentelemetry_dart/opentelemetry_dart.dart';
import 'package:opentelemetry_dart_console/opentelemetry_dart_console.dart';

void main() {
  // 创建并配置 TracerProvider
  final tracerProvider = TracerProvider(
    resource: Resource(attributes: {
      'service.name': 'flutter_app',
    }),
  );

  // 创建一个 ConsoleExporter,用于在控制台输出追踪信息
  final consoleExporter = ConsoleExporter();

  // 创建一个 SimpleSpanProcessor,并将 ConsoleExporter 附加到 TracerProvider
  tracerProvider.addSpanProcessor(SimpleSpanProcessor(consoleExporter));

  // 设置全局的 TracerProvider
  OpenTelemetry().setTracerProvider(tracerProvider);

  // 启动 Flutter 应用
  runApp(MyApp());
}

3. 创建和记录 Span

在需要追踪的代码中,你可以使用 Tracer 来创建和记录 Span。例如,在某个方法中:

import 'package:opentelemetry_dart/opentelemetry_dart.dart';

void myFunction() {
  final tracer = OpenTelemetry().getTracer('my_tracer');

  // 创建一个新的 Span
  final span = tracer.startSpan('my_span');

  // 设置一些属性
  span.setAttribute('my_attribute', 'value');

  // 模拟一些工作
  for (var i = 0; i < 3; i++) {
    print('Working...');
  }

  // 结束 Span
  span.end();
}

4. 使用 Baggage 和 Context Propagation

在分布式系统中,你可能需要跨服务传递上下文信息。OpenTelemetry 提供了 BaggageContextPropagation 来实现这一点。

import 'package:opentelemetry_dart/opentelemetry_dart.dart';

void propagateContext() {
  final tracer = OpenTelemetry().getTracer('my_tracer');

  // 创建一个新的 Span
  final span = tracer.startSpan('propagate_context_span');

  // 设置一些 Baggage
  final baggage = Baggage.fromCurrentContext().toBuilder()
    .put('my_baggage_key', 'my_baggage_value')
    .build();

  // 将 Baggage 附加到当前 Context
  final context = Context.current.withBaggage(baggage);

  // 在另一个函数中使用 Context
  Context.run(context, () {
    myFunction();
  });

  // 结束 Span
  span.end();
}

5. 导出追踪数据

除了在控制台输出追踪信息,你还可以将追踪数据导出到后端系统,如 Jaeger、Zipkin 或 OpenTelemetry Collector。你需要使用相应的 SpanExporter,例如 JaegerExporterZipkinExporter

import 'package:opentelemetry_dart/opentelemetry_dart.dart';
import 'package:opentelemetry_dart_jaeger/opentelemetry_dart_jaeger.dart';

void exportToJaeger() {
  final tracerProvider = TracerProvider(
    resource: Resource(attributes: {
      'service.name': 'flutter_app',
    }),
  );

  // 创建一个 JaegerExporter
  final jaegerExporter = JaegerExporter(Uri.parse('http://localhost:14268/api/traces'));

  // 创建一个 BatchSpanProcessor,并将 JaegerExporter 附加到 TracerProvider
  tracerProvider.addSpanProcessor(BatchSpanProcessor(jaegerExporter));

  // 设置全局的 TracerProvider
  OpenTelemetry().setTracerProvider(tracerProvider);
}
回到顶部