Exporters
发送遥测数据到 OpenTelemetry Collector,以确保其正确导出。在生产环境中使用 Collector 是一种最佳实践。要可视化您的遥测数据,请将其导出到后端,例如 Jaeger、Zipkin、Prometheus 或 特定厂商 的后端。
可用导出器
该注册表包含一份 JavaScript 导出器列表。
在导出器中,OpenTelemetry Protocol (OTLP) 导出器是按照 OpenTelemetry 数据模型设计的,可以无损地发出 OTel 数据。此外,许多处理遥测数据的工具都支持 OTLP(例如 Prometheus、Jaeger 和大多数 厂商),为您提供高度的灵活性。要了解更多关于 OTLP 的信息,请参阅 OTLP 规范。
此页面介绍了主要的 OpenTelemetry JavaScript 导出器以及如何设置它们。
OTLP
Collector 设置
如果您已经设置了 OTLP collector 或后端,可以跳过此部分,直接 设置应用程序的 OTLP 导出器依赖项。
要尝试并验证您的 OTLP 导出器,您可以在一个 Docker 容器中运行 collector,该容器将遥测数据直接写入控制台。
在一个空目录下,创建一个名为 collector-config.yaml 的文件,内容如下
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [otlp]
exporters: [debug]
metrics:
receivers: [otlp]
exporters: [debug]
logs:
receivers: [otlp]
exporters: [debug]
现在,在 Docker 容器中运行 collector
docker run -p 4317:4317 -p 4318:4318 --rm -v $(pwd)/collector-config.yaml:/etc/otelcol/config.yaml otel/opentelemetry-collector
此 collector 现在可以通过 OTLP 接受遥测数据。稍后,您可能需要 配置 collector,以便将其遥测数据发送到您的可观察性后端。
依赖项
如果您想将遥测数据发送到 OTLP 端点(例如 OpenTelemetry Collector、 Jaeger 或 Prometheus),您可以在三种不同的协议之间进行选择来传输您的数据
首先,将相应的导出器包安装为项目的依赖项
npm install --save @opentelemetry/exporter-trace-otlp-proto \
@opentelemetry/exporter-metrics-otlp-proto
npm install --save @opentelemetry/exporter-trace-otlp-http \
@opentelemetry/exporter-metrics-otlp-http
npm install --save @opentelemetry/exporter-trace-otlp-grpc \
@opentelemetry/exporter-metrics-otlp-grpc
Node.js 使用方式
接下来,配置导出器以指向 OTLP 端点。例如,您可以更新 入门指南中的 instrumentation.ts 文件(如果您使用 JavaScript,则为 instrumentation.js),如下所示通过 OTLP(http/protobuf)导出 traces 和 metrics:
/*instrumentation.ts*/
import * as opentelemetry from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-proto';
import { PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
const sdk = new opentelemetry.NodeSDK({
traceExporter: new OTLPTraceExporter({
// optional - default url is https://:4318/v1/traces
url: '<your-otlp-endpoint>/v1/traces',
// optional - collection of custom headers to be sent with each request, empty by default
headers: {},
}),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: '<your-otlp-endpoint>/v1/metrics', // url is optional and can be omitted - default is https://:4318/v1/metrics
headers: {}, // an optional object containing custom headers to be sent with each request
}),
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
/*instrumentation.js*/
const opentelemetry = require('@opentelemetry/sdk-node');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const {
OTLPTraceExporter,
} = require('@opentelemetry/exporter-trace-otlp-proto');
const {
OTLPMetricExporter,
} = require('@opentelemetry/exporter-metrics-otlp-proto');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const sdk = new opentelemetry.NodeSDK({
traceExporter: new OTLPTraceExporter({
// optional - default url is https://:4318/v1/traces
url: '<your-otlp-endpoint>/v1/traces',
// optional - collection of custom headers to be sent with each request, empty by default
headers: {},
}),
metricReader: new PeriodicExportingMetricReader({
exporter: new OTLPMetricExporter({
url: '<your-otlp-endpoint>/v1/metrics', // url is optional and can be omitted - default is https://:4318/v1/metrics
headers: {}, // an optional object containing custom headers to be sent with each request
concurrencyLimit: 1, // an optional limit on pending requests
}),
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
浏览器中使用方式
当您在基于浏览器的应用程序中使用 OTLP 导出器时,您需要注意:
下面您将找到使用正确导出器、配置 CSPs 和 CORS 头部以及暴露 Collector 时需要注意的事项的说明。
使用 OTLP 导出器配合 HTTP/JSON 或 HTTP/protobuf
OpenTelemetry Collector Exporter with gRPC 仅适用于 Node.js,因此您只能使用OpenTelemetry Collector Exporter with HTTP/JSON 或 OpenTelemetry Collector Exporter with HTTP/protobuf。
如果您使用的是 OpenTelemetry Collector Exporter with HTTP/JSON,请确保您的导出器的接收端(Collector 或可观测性后端)接受 http/json,并且您正在将数据导出到正确的端点,端口设置为 4318。
配置 CSPs
如果您的网站使用了内容安全策略 (CSPs),请确保您的 OTLP 端点的域包含在内。如果您的 Collector 端点是 https://collector.example.com:4318/v1/traces,请添加以下指令
connect-src collector.example.com:4318/v1/traces
如果您的 CSP 未包含 OTLP 端点,您将看到一条错误消息,表明对您端点的请求违反了 CSP 指令。
配置 CORS 头部
如果您的网站和 Collector 托管在不同的域上,您的浏览器可能会阻止发送到 Collector 的请求。您需要为跨域资源共享 (CORS) 配置特殊的头部。
OpenTelemetry Collector 为基于 http 的接收器提供了一个功能,用于添加必要的头部以允许接收器接受来自 Web 浏览器的 traces。
receivers:
otlp:
protocols:
http:
include_metadata: true
cors:
allowed_origins:
- https://foo.bar.com
- https://*.test.com
allowed_headers:
- Example-Header
max_age: 7200
安全地暴露您的 Collector
要从 Web 应用程序接收遥测数据,您需要允许您的最终用户浏览器将数据发送到您的 Collector。如果您的 Web 应用程序可以从公共互联网访问,您也必须让您的 Collector 对所有人可见。
建议您不要直接暴露您的 Collector,而是将其置于反向代理(NGINX、Apache HTTP Server 等)之后。反向代理可以负责 SSL 卸载、设置正确的 CORS 头部以及许多其他 Web 应用程序特有的功能。
下面您将找到一个适用于流行的 NGINX Web 服务器的配置,供您参考
server {
listen 80 default_server;
server_name _;
location / {
# Take care of preflight requests
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Origin' 'name.of.your.website.example.com' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Accept-Language,Content-Language,Content-Type' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' 'name.of.your.website.example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Accept-Language,Content-Language,Content-Type' always;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://collector:4318;
}
}
控制台
为了调试您的仪器或在开发环境中本地查看值,您可以使用将遥测数据写入控制台(stdout)的导出器。
如果您遵循了入门指南或手动插桩指南,您已经安装了控制台导出器。
ConsoleSpanExporter 包含在@opentelemetry/sdk-trace-node 包中,而 ConsoleMetricExporter 包含在@opentelemetry/sdk-metrics 包中。
Jaeger
后端设置
Jaeger 原生支持 OTLP 来接收跟踪数据。您可以在 Docker 容器中运行 Jaeger,UI 可通过端口 16686 访问,OTLP 可通过端口 4317 和 4318 访问。
docker run --rm \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 9411:9411 \
jaegertracing/all-in-one:latest
用法
然后按照说明设置 OTLP 导出器。
Prometheus
要将您的指标数据发送到 Prometheus,您可以 启用 Prometheus 的 OTLP Receiver 并使用 OTLP 导出器,或者您可以使用 Prometheus 导出器,这是一个 MetricReader,它会启动一个 HTTP 服务器,在请求时收集指标并将其序列化为 Prometheus 文本格式。
后端设置
如果您已经设置了 Prometheus 或与 Prometheus 兼容的后端,可以跳过此部分,并为您的应用程序设置 Prometheus 或 OTLP 导出器依赖项。
您可以按照以下说明,在 Docker 容器中运行 Prometheus,端口 9090 可访问。
创建一个名为 prometheus.yml 的文件,内容如下
scrape_configs:
- job_name: dice-service
scrape_interval: 5s
static_configs:
- targets: [host.docker.internal:9464]
在 Docker 容器中运行 Prometheus,UI 可通过端口 9090 访问。
docker run --rm -v ${PWD}/prometheus.yml:/prometheus/prometheus.yml -p 9090:9090 prom/prometheus --enable-feature=otlp-write-receive
当使用 Prometheus 的 OTLP Receiver 时,请确保在您的应用程序中将指标的 OTLP 端点设置为 https://:9090/api/v1/otlp。
并非所有 Docker 环境都支持 host.docker.internal。在某些情况下,您可能需要将 host.docker.internal 替换为 localhost 或您机器的 IP 地址。
依赖项
将导出器包安装为应用程序的依赖项
npm install --save @opentelemetry/exporter-prometheus
更新您的 OpenTelemetry 配置以使用该导出器并将数据发送到您的 Prometheus 后端
import * as opentelemetry from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
const sdk = new opentelemetry.NodeSDK({
metricReader: new PrometheusExporter({
port: 9464, // optional - default is 9464
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
const opentelemetry = require('@opentelemetry/sdk-node');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
const { PeriodicExportingMetricReader } = require('@opentelemetry/sdk-metrics');
const sdk = new opentelemetry.NodeSDK({
metricReader: new PrometheusExporter({
port: 9464, // optional - default is 9464
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
通过上述配置,您可以访问您的指标,地址为 https://:9464/metrics。Prometheus 或带有 Prometheus receiver 的 OpenTelemetry Collector 可以从此端点抓取指标。
Zipkin
后端设置
如果您已经设置了 Zipkin 或与 Zipkin 兼容的后端,可以跳过此部分,并为您的应用程序设置 Zipkin 导出器依赖项。
您可以通过执行以下命令,在 Docker 容器中运行 Zipkin。
docker run --rm -d -p 9411:9411 --name zipkin openzipkin/zipkin
依赖项
要将您的 trace 数据发送到 Zipkin,您可以使用 ZipkinExporter。
将导出器包安装为应用程序的依赖项
npm install --save @opentelemetry/exporter-zipkin
更新您的 OpenTelemetry 配置以使用该导出器并将数据发送到您的 Zipkin 后端
import * as opentelemetry from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
import { ZipkinExporter } from '@opentelemetry/exporter-zipkin';
const sdk = new opentelemetry.NodeSDK({
traceExporter: new ZipkinExporter({}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
const opentelemetry = require('@opentelemetry/sdk-node');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const { ZipkinExporter } = require('@opentelemetry/exporter-zipkin');
const sdk = new opentelemetry.NodeSDK({
traceExporter: new ZipkinExporter({}),
instrumentations: [getNodeAutoInstrumentations()],
});
自定义导出器
最后,您也可以编写自己的导出器。有关更多信息,请参阅 API 文档中的 SpanExporter 接口。
批量发送 Span 和 Log 记录
OpenTelemetry SDK 提供了一组默认的 Span 和 Log 记录处理器,允许您逐个发送 Span(“简单”)或批量发送。建议使用批量发送,但如果您不想批量发送 Span 或 Log 记录,可以改用简单的处理器,如下所示:
/*instrumentation.ts*/
import * as opentelemetry from '@opentelemetry/sdk-node';
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
const sdk = new NodeSDK({
spanProcessors: [new SimpleSpanProcessor(exporter)],
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
/*instrumentation.js*/
const opentelemetry = require('@opentelemetry/sdk-node');
const {
getNodeAutoInstrumentations,
} = require('@opentelemetry/auto-instrumentations-node');
const sdk = new opentelemetry.NodeSDK({
spanProcessors: [new SimpleSpanProcessor(exporter)],
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();