OpenTelemetry 桥接

编辑

Elastic APM OpenTelemetry 桥接允许使用 OpenTelemetry API 创建 Elastic APM TransactionsSpans。同时也会收集 OpenTelemetry 指标。换句话说,它将对 OpenTelemetry API 的调用转换为 Elastic APM,从而允许重用现有的检测。

虽然可以使用 OpenTelemetry API 手动检测来适配 Elastic APM Java agent,但在 Elastic APM Java agent 的上下文中,无法使用来自 opentelemetry-java-instrumentation 的检测。
但是,您可以使用 opentelemetry-java-instrumentation (又名 OpenTelemetry Java agent)并将数据发送到 APM Server。有关更多详细信息,请参阅OpenTelemetry 集成文档

服务的第一个 span 将转换为 Elastic APM Transaction,后续的 span 将映射到 Elastic APM Span

入门

编辑

开始使用 OpenTelemetry API 桥接的第一步是声明对 API 的依赖

pom.xml.

<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-api</artifactId>
    <version>${version.opentelemetry}</version>
</dependency>

build.gradle.

compile "io.opentelemetry:opentelemetry-api:$openTelemetryVersion"

最低要求的 OpenTelemetry 版本为 1.4.0。

初始化跟踪器

编辑

桥接本身不需要单独的依赖项。Java agent 会钩入 GlobalOpenTelemetry 以返回其自身的 OpenTelemetry 实现,该实现连接到 agent 的内部跟踪器。

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.trace.Tracer;

OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
Tracer tracer = openTelemetry.getTracer("");

要禁用该行为并依赖 GlobalOpenTelemetry 的标准发现机制,您可以将 disable_instrumentations 设置为 opentelemetry

向 span 添加自定义元数据

编辑

如果您喜欢 Elastic APM Java agent 的自动检测创建的 span,但又想添加自定义标签,则可以使用 OpenTelemetry API 来获取当前 span 并调用 setAttribute

Span.current().setAttribute("foo", "bar");

自定义 span 跟踪

编辑

我们不仅利用 setAttribute() API 来添加自定义元数据,还通过下面列出的相应的自定义属性来定制一些特殊的跟踪功能。这些属性不会添加到 span 元数据中。例如

Span.current().setAttribute("co.elastic.discardable", false);
co.elastic.discardable
编辑

默认情况下,span 可能会被丢弃,例如,如果设置了 span_min_duration ( [1.16.0] 在 1.16.0 中添加。 ) 且 span 未超过配置的阈值。使用此属性将其设置为 false,以使 span 不可丢弃。

使 span 不可丢弃也会隐式地使整个活动 span 堆栈不可丢弃。子 span 仍然可以被丢弃。

值类型 默认值

co.elastic.discardable

布尔值

true

创建活动 span 的子 span

编辑

这是一个将自定义 span 添加到 Java agent 的自动检测创建的 span 的示例。

// if there's an active span, it will implicitly be the parent
// in case there's no parent, the custom span will become a Elastic APM transaction
Span custom = tracer.spanBuilder("my custom span").startSpan();
// making your child the current one makes the Java agent aware of this span
// if the agent creates spans in the context of myTracedMethod() (such as outgoing requests),
// they'll be added as a child of your custom span
try (Scope scope = custom.makeCurrent()) {
    myTracedMethod();
} catch (Exception e) {
    custom.recordException(e);
    throw e;
} finally {
    custom.end();
}

要了解有关 OpenTelemetry API 的更多信息,请访问他们的文档

指标

编辑

此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic 将努力解决任何问题,但技术预览中的功能不受官方 GA 功能的支持 SLA 的约束。

Elastic APM Java Agent 支持收集通过 OpenTelemetry 定义的指标。您可以使用OpenTelemetry APIOpenTelemetry SDK,以防您需要更多自定义项。

在这两种情况下,Elastic APM Agent 都将遵守 OpenTelemetry 指标的 disable_metricsmetrics_interval 设置。

您可以使用 custom_metrics_histogram_boundaries 设置来自定义直方图 bucket 边界。或者,您可以在提供自己的 MeterProvider 时使用 OpenTelemetry Views 来按指标定义直方图 bucket。请注意,custom_metrics_histogram_boundaries 仅适用于 API 用法。如果您自带 MeterProvider,因此也自带 OpenTelemetry SDK,则该设置仅适用于 1.32.0 之前的 SDK 版本。

API 用法

编辑

您可以通过 GlobalOpenTelemetry 定义指标并报告指标数据

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;

Meter myMeter = GlobalOpenTelemetry.getMeter("my_meter");
LongCounter counter = meter.counterBuilder("my_counter").build();
counter.add(42);

我们不要求您自己在 GlobalOpenTelemetry 中设置 OpenTelemetry MeterProvider。如果未配置 MeterProvider,Elastic APM Java Agent 将检测到这种情况,并在此情况下自动提供自己的 MeterProvider。如果您提供自己的 MeterProvider(请参阅 使用自定义的 MeterProvider),则 agent 将使用提供的实例。

使用自定义的 MeterProvider

编辑

在某些情况下,仅使用 用于指标的 OpenTelemetry API 可能不够灵活。一些示例用例是

  • 使用 OpenTelemetry Views
  • 除了 Elastic APM 之外,还将指标导出到其他工具(例如 prometheus)

对于这些用例,您可以只设置您的 OpenTelemetry SDK MeterProvider。Elastic APM Agent 将通过检测负责安装一个额外的 MetricExporter,该 MetricExporter 会将指标数据发送到 Elastic APM。这需要使用 OpenTelemetry 版本 1.16.0 或更高版本。

要创建自己的 MeterProvider,您需要将 OpenTelemetry Metric SDK 作为依赖项添加到您的项目中

pom.xml.

<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-sdk-metrics</artifactId>
    <version>${version.opentelemetry}</version>
</dependency>

build.gradle.

compile "io.opentelemetry:opentelemetry-sdk-metrics:$openTelemetryVersion"

之后,您可以创建和使用您自己的 MeterProvider,如下所示

import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.api.metrics.DoubleHistogram;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.prometheus.PrometheusHttpServer;
import io.opentelemetry.sdk.metrics.InstrumentSelector;
import io.opentelemetry.sdk.metrics.View;

//Elastic APM MetricReader will be registered automatically by the agent
SdkMeterProvider meterProvider = SdkMeterProvider.builder()
    .registerMetricReader(PrometheusHttpServer.create())
    .registerView(
        InstrumentSelector.builder().setName("my_histogram").build(),
        View.builder().setAggregation(Aggregation.explicitBucketHistogram(List.of(1.0, 5.0))).build()
    )
    .build();

Meter testMeter = meterProvider.get("my_meter");
DoubleHistogram my_histogram = testMeter.histogramBuilder("my_histogram").build();

my_histogram.record(0.5);

注意事项

编辑

并非支持 OpenTelemetry API 的所有功能。

进程内上下文传播
编辑

添加到当前上下文的条目 Context.current().with(...).makeCurrent() 无法通过 Context.current().get(...) 检索。

Span 引用
编辑

Span 只能有一个父级(SpanBuilder#setParent

Baggage
编辑

Baggage 支持已在版本 1.41.0 中添加。自 1.43.0 起,您可以通过 baggage_to_attach 配置选项将 baggage 自动附加为 span、事务和错误属性。

事件
编辑

事件会被静默丢弃,例如 Span.current().addEvent("my event")

注释
编辑

1.45.0 起开始支持OpenTelemetry 检测注释