OTEL的组件介绍

目录

总览

[1. Specification(规范)](#1. Specification(规范))

[2. 语言 API & SDK(应用侧主力)](#2. 语言 API & SDK(应用侧主力))

[2.1 Instrumentation Libraries(插桩库)](#2.1 Instrumentation Libraries(插桩库))

[2.2 Exporters(导出器)](#2.2 Exporters(导出器))

[2.3 Zero-code(零代码插桩)](#2.3 Zero-code(零代码插桩))

[2.4 Resource Detectors](#2.4 Resource Detectors)

[2.5 Propagators(跨服务传播)](#2.5 Propagators(跨服务传播))

[2.6 Samplers(采样器)](#2.6 Samplers(采样器))

[3. Collector(采集/中转侧主力)](#3. Collector(采集/中转侧主力))

[4. 平台周边](#4. 平台周边)

[① Kubernetes Operator](#① Kubernetes Operator)

[② FaaS 资产(函数计算)](#② FaaS 资产(函数计算))

对照:谁负责什么(排障时用)

和「信号」的关系(避免再混)


官方把主体拆成下面几块(见 ​编辑Components)。

总览

规范 Specification

├─ API 怎么打点

├─ SDK 要求 怎么实现、采样、导出

└─ Data 语义约定 + OTLP

语言实现 API & SDK

├─ 插桩库 Instrumentation Libraries

├─ 导出器 Exporters(首选 OTLP)

├─ 零代码插桩 Zero-code

├─ Resource Detectors

├─ Propagators(跨服务传 Context)

└─ Samplers

Collector 接收 → 处理 → 导出(厂商无关代理)

周边

├─ Kubernetes Operator

├─ Helm Charts

└─ FaaS 资产(如 Lambda Layer)


1. Specification(规范)

跨语言的契约,所有实现都要对齐:

部分 作用
API 生成、关联 Traces / Metrics / Logs 的接口
SDK 语言实现必须满足的行为:配置、处理、导出
Data OTLP(怎么编码传输)+ 语义约定(字段叫什么)

规范本身不是进程,但后面所有组件都按它来。

Specification 是 OTel 的契约,不是进程。各语言 SDK、Collector、OpenObserve 能互通,是因为大家都按这份规范实现。当前文档版本大约是 OTel Spec 1.60.0、OTLP 1.11.0、SemConv 1.44.0。入口:docs/specs/otel


(1)规范解决什么问题

没有规范时:Java 一套字段、Go 一套字段、A 厂商一个协议、B 厂商另一个协议。换后端就要改代码。

规范规定三件事:

API 应用 / 库怎么打点(插座形状)

SDK 怎么采样、批处理、导出(插头怎么做)

Data 字段叫什么(语义约定)+ 网上怎么运(OTLP)

对应排障:

规范块 失败时的现象
API 根本没有 span(没调用或库没插桩)
SDK 有调用但没数据:采样、队列、exporter、OTEL_SDK_DISABLED
语义约定 有数据但查不到:字段名不标准
OTLP SDK 有导出日志,后端没有:端口、路径、Content-Type、413、鉴权

(2)规范怎么读(否则会误读)

规范用 RFC 2119:

  • MUST / MUST NOT:不合规实现
  • SHOULD:强烈建议,实现可以有差异
  • MAY:可选

组件生命周期:Draft → Experimental → Stable → Deprecated。

Stable 的 API/OTLP 有长期兼容承诺;Experimental 的语义约定可能改名,生产查询不要绑死实验字段。

规范还规定:环境变量若某语言支持,名字和解析规则必须统一(例如布尔值只有大小写不敏感的 "true" 才是真)。这就是为什么 Java 和 Python 都能认 OTEL_SERVICE_NAME


(3)三块分别管什么

3.1 API:打点接口,默认是空操作

API 给库作者应用 用。设计要点:没装 SDK 时,API 调用必须几乎零开销、不发数据。这样中间件可以先写上 tracer.span(),用户没接 SDK 也不会崩、也不会变慢。

API 主要包括:

  • Context / Propagators / Baggage
  • Tracing:Tracer、Span、SpanContext
  • Metrics:Meter、各种 Instrument
  • Logs:主要是 Bridge API(给日志框架作者,不是让业务直接调)

3.2 SDK:把 API 变成真数据

SDK 是 API 的实现:Resource、Sampler、Batch Processor、Exporter、属性条数限制等。

规范要求:凡是环境变量能配的,代码里必须有等价配置 。所以 OTEL_TRACES_SAMPLER=always_off 和代码里装一个 AlwaysOff sampler 是同一件事。

3.3 Data:语义约定 + OTLP

  • 语义约定:service.namehttp.request.methodhttp.response.status_code 等,保证 Java/Go 打出来能用同一套查询。
  • OTLP:Export 请求怎么编码、4317/4318、成功/部分成功/重试。

(4)操作示例

下面示例用 Python,只为对照规范;换 Java/Go 概念相同。先装:

python 复制代码
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp

示例 1:只有 API、没有 SDK ------ 规范要求的「空操作」

这是理解规范最重要的一个实验。

python 复制代码
# api_only.py
from opentelemetry import trace

tracer = trace.get_tracer("demo")

with tracer.start_as_current_span("checkout") as span:
    span.set_attribute("order.id", "A1001")
    print("span recording?", span.is_recording())
    print("trace_id", format(span.get_span_context().trace_id, "032x"))
python 复制代码
python api_only.py

执行后会看到:is_recording() 为 False,trace_id 全 0。

调用了 API,但没有 TracerProvider(SDK),规范规定这是 No-Op Span:不记录、不导出。

现象:代码「打了点」,产品里什么都没有。 原因在规范的 API/SDK 分离,不是 OpenObserve 坏了。


示例 2:接上 SDK ------ 规范里的 TracerProvider / Resource / Processor / Exporter

python 复制代码
# sdk_console.py
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter

resource = Resource.create({
    "service.name": "checkout-service",          # 语义约定:Resource
    "service.version": "1.0.0",
    "deployment.environment": "dev",
})

provider = TracerProvider(resource=resource)
provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)

tracer = trace.get_tracer("demo", "1.0.0")       # InstrumentationScope

with tracer.start_as_current_span("POST /checkout") as span:
    span.set_attribute("http.request.method", "POST")
    span.set_attribute("http.route", "/checkout")
    span.set_attribute("http.response.status_code", 200)
    span.set_attribute("order.id", "A1001")     # 业务属性,不是 SemConv 强制字段

provider.force_flush()
python 复制代码
python sdk_console.py

终端会打出 SDK 导出的 Span(name、trace_id、属性、Resource)。

对照规范的三层标签:

示例里是谁
Resource service.name=checkout-service
Scope tracer 名 demo
Span POST /checkout 和那些 attribute

force_flush() 对应规范:进程退出前必须把 Batch Processor 队列刷出去,否则数据还在内存里,后端永远没有。


示例 3:用规范规定的环境变量配置 SDK(不改代码)

规范把常用开关做成统一环境变量。把示例 2 的 Resource 改成从环境读也可以,更常见的是 零代码/自动配置 读这些变量。

PowerShell:

bash 复制代码
$env:OTEL_SERVICE_NAME = "checkout-service"
$env:OTEL_RESOURCE_ATTRIBUTES = "service.version=1.0.0,deployment.environment=dev"
$env:OTEL_TRACES_EXPORTER = "console"
$env:OTEL_TRACES_SAMPLER = "always_on"
$env:OTEL_PROPAGATORS = "tracecontext,baggage"
python sdk_console.py

规范里最常用的一批:

变量 规范含义 默认
OTEL_SERVICE_NAME Resource 的 service.name unknown_service
OTEL_RESOURCE_ATTRIBUTES 其它 Resource 键值
OTEL_SDK_DISABLED true 则全信号 No-Op false
OTEL_PROPAGATORS 传播器 tracecontext,baggage
OTEL_TRACES_SAMPLER 采样器 parentbased_always_on
OTEL_TRACES_SAMPLER_ARG 0.1 表示 10% 视采样器
OTEL_TRACES_EXPORTER 默认 otlp otlp
OTEL_EXPORTER_OTLP_ENDPOINT 基址;HTTP 会自动拼 /v1/traces http://localhost:4318
OTEL_EXPORTER_OTLP_PROTOCOL grpc / http/protobuf / http/json 视 SDK
OTEL_BSP_SCHEDULE_DELAY 批量导出间隔 ms 5000
OTEL_BSP_MAX_QUEUE_SIZE 队列满就丢 2048

操作对照:

bash 复制代码
# 规范行为:全部关掉 → 又变回 No-Op,和示例 1 一样
$env:OTEL_SDK_DISABLED = "true"

# 规范行为:一律不采样 → API 仍 recording 为 false(或采了但不导出)
$env:OTEL_TRACES_SAMPLER = "always_off"

# 没设服务名 → 后端常见 unknown_service(规范默认值)
Remove-Item Env:OTEL_SERVICE_NAME

OTEL_SERVICE_NAMEOTEL_RESOURCE_ATTRIBUTES 里同时有 service.name 时,规范规定前者优先。


示例 4:语义约定 ------ 同样的 HTTP,字段必须同名

规范不要求你用 HTTP,但一旦是 HTTP 操作,键名应对齐 SemConv,查询才能跨语言复用。

python 复制代码
from opentelemetry.semconv.trace import SpanAttributes  # 或新包 semconv

span.set_attribute("http.request.method", "GET")
span.set_attribute("http.route", "/product/{id}")
span.set_attribute("http.response.status_code", 500)
span.set_status(Status(StatusCode.ERROR))  # Span Status ≠ HTTP 码,规范里是两套

错误示范(能导出,但换库/换语言就查不着):

python 复制代码
span.set_attribute("httpCode", 500)
span.set_attribute("method", "GET")

操作: 在 OpenObserve 里对规范字段写 http.response.status_code>=500;若你们库还在用旧名 http.status_code,那是 SemConv 版本迁移,不是产品 bug。查 SemConv 当前 HTTP 约定。


示例 5:OTLP(规范 Data 的传输部分)------ 不写 SDK,直接按协议 POST

OTLP/HTTP JSON 默认路径 POST /v1/tracesContent-Type: application/json

规范要求:traceId/spanId 用十六进制,kind 用数字(2 = SERVER),字段 lowerCamelCase。

先自己算一对 ID(32/16 位 hex),再发:

bash 复制代码
$json = @'
{
  "resourceSpans": [{
    "resource": {
      "attributes": [
        { "key": "service.name", "value": { "stringValue": "checkout-service" } }
      ]
    },
    "scopeSpans": [{
      "scope": { "name": "manual-otlp-demo", "version": "1.0.0" },
      "spans": [{
        "traceId": "a0892f3577b34da6a3ce929d0e0e4736",
        "spanId": "f03067aa0ba902b7",
        "name": "POST /checkout",
        "kind": 2,
        "startTimeUnixNano": "1730000000000000000",
        "endTimeUnixNano": "1730000000500000000",
        "status": { "code": 1 },
        "attributes": [
          { "key": "http.request.method", "value": { "stringValue": "POST" } },
          { "key": "http.response.status_code", "value": { "intValue": "200" } }
        ]
      }]
    }]
  }]
}
'@

# 本地 Collector 默认 4318
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:4318/v1/traces" `
  -ContentType "application/json" -Body $json

成功时 HTTP 200,body 里不应带 rejected_spans(Full Success)。

若打 OpenObserve,路径往往是规范路径加组织前缀,body 仍是这份 OTLP:

POST https://<o2>/api/default/v1/traces (鉴权按环境加 Header。)

故意违反规范看现象:

做法 规范后果
traceId 用 base64 400 / 无法解码
"kind": "SPAN_KIND_SERVER" JSON 枚举必须是数字,对端拒收或忽略
dropped_attributes_count 蛇形命名 必须 droppedAttributesCount
gRPC 打到 4318,或 HTTP 打到 4317 连上了也不是同一种 OTLP 运输
只设 OTEL_EXPORTER_OTLP_ENDPOINT=http://host:4318 却用 gRPC 端口和 protocol 必须一致

SDK 版导出(规范环境变量,等价于示例 5):

bash 复制代码
$env:OTEL_SERVICE_NAME = "checkout-service"
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318"

# HTTP 时 SDK 会拼出 http://127.0.0.1:4318/v1/traces
python sdk_otlp.py

sdk_otlp.py 只需把示例 2 的 ConsoleSpanExporter 换成 OTLPSpanExporter()opentelemetry-exporter-otlp)。


示例 6:Context 在规范里的位置

传播 不是 OTLP,但在 API 规范里(Context + Propagators)。默认 OTEL_PROPAGATORS=tracecontext,baggage

python 复制代码
from opentelemetry.propagate import inject, extract
from opentelemetry import context

headers = {}
inject(headers)          # 发送方:写入 traceparent
print(headers)
# 典型:{'traceparent': '00-a0892f35...-f03067aa0ba902b7-01'}

ctx = extract(headers)   # 接收方:读出,后续 span 共用 trace_id
token = context.attach(ctx)
# ... 在此创建的 span,parent 就是对端 span
context.detach(token)

01 是规范/W3C 里的 sampled 标志。OTLP 只负责把已经采了的 Span 运走;采不采是 SDK 规范。


(5)三块如何对应到一次真实请求

业务代码 / 插桩库

│ 调的是 API 规范

SDK(采样、Batch、Resource)

│ 行为由 SDK 规范 + 环境变量规定

OTLP Export (Data 规范)

│ ResourceSpans → ScopeSpans → Span

Collector / OpenObserve

在产品里看到的每一条 Span,都可以反问:

  1. 哪个 API 调用产生的?
  2. SDK 有没有采样、有没有 flush?
  3. 字段是否符合 SemConv?
  4. OTLP 这一跳是 200 全成功,还是 partial / 4xx / 超时丢掉?

规范正文按需查:API/SDK · 环境变量 · OTLP · SemConv


2. 语言 API & SDK(应用侧主力)

各语言一套实现(Java、Go、Python、JS...),让你在进程里造出信号并送出去。SDK 里通常还包括:

子组件 做什么
Instrumentation Libraries 给 HTTP、gRPC、DB、消息队列等自动打点
Exporters 把数据发给 Collector 或后端;生产优先 OTLP
Zero-code 不改业务代码(Java Agent、Operator 注入、eBPF 等)
Resource Detectors 自动填 service.name、主机、K8s Pod 等
Propagators Inject/Extract Context(默认 W3C traceparent
Samplers 头采样等,决定哪些 Trace 真正导出

是什么: 跑在服务进程里的库。API 是打点接口;SDK 是实现(Provider、Processor、Exporter)。

职责: 生成 Span/Metric/Log → 采样 → 批量 → OTLP 发出。没它(也没零代码),进程不会自己产生 OTel 数据。

下面 6 个子组件都属于「语言实现」这一主组件。

2.1 Instrumentation Libraries(插桩库)

给 HTTP、gRPC、DB、消息队列等自动打点,业务少写 span。

经典操作(Python + Flask + requests):

复制代码
pip install flask requests \
  opentelemetry-api opentelemetry-sdk \
  opentelemetry-instrumentation-flask \
  opentelemetry-instrumentation-requests \
  opentelemetry-exporter-otlp

# app.py  ------ 业务代码几乎不写 span
from flask import Flask
import requests

app = Flask(__name__)

@app.get("/checkout")
def checkout():
    requests.get("https://httpbin.org/delay/1")  # 出站 HTTP,由 requests 插桩打 Client span
    return {"ok": True}

# 启动时挂上插桩(或见 2.3 零代码,一行都不改)
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter

trace.set_tracer_provider(TracerProvider(resource=Resource.create({"service.name": "shop-api"})))
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()

app.run(port=5000)

访问 http://127.0.0.1:5000/checkout,控制台应出现:

  • Server span:GET /checkout
  • Client span:对 httpbin 的出站请求

父子靠插桩库做的 Context 传播,不是你手写的。

2.2 Exporters(导出器)

把 SDK 里的数据送给下一跳。生产优先 OTLP;调试用 console。

经典操作: 同一套打点,只换 exporter。

复制代码
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor

# 调试:看本地是否真正生成了 Span
processor = BatchSpanProcessor(ConsoleSpanExporter())

# 生产:发给 Collector(默认会拼 /v1/traces)
processor = BatchSpanProcessor(OTLPSpanExporter(
    endpoint="http://127.0.0.1:4318/v1/traces"
))

或只改环境变量(规范行为,不改代码):

复制代码
$env:OTEL_TRACES_EXPORTER = "otlp"   # 或 console、none
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318"

排障口诀: console 有、OTLP 没有 → 生成没问题,问题在传输/后端;console 也没有 → 还在 SDK/采样/插桩。

2.3 Zero-code(零代码插桩)

不改业务源码:Java -javaagent、Python opentelemetry-instrument、K8s Operator 注入。

经典操作(Python):

复制代码
pip install flask requests opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

# 业务就是普通 flask,不必 import otel
opentelemetry-instrument python app.py

$env:OTEL_SERVICE_NAME = "shop-api"
$env:OTEL_TRACES_EXPORTER = "console"
$env:OTEL_PROPAGATORS = "tracecontext,baggage"
opentelemetry-instrument python app.py

Java 经典等价:

复制代码
java -javaagent:opentelemetry-javaagent.jar \
  -Dotel.service.name=shop-api \
  -Dotel.exporter.otlp.endpoint=http://otel-collector:4318 \
  -jar app.jar

覆盖 HTTP/DB 等框架调用;订单号等业务属性仍要手动补 span。

2.4 Resource Detectors

给每条信号贴「谁在发」:service.name、主机、容器、K8s Pod。没有它,后端常显示 unknown_service

经典操作:

复制代码
$env:OTEL_SERVICE_NAME = "checkout-service"
$env:OTEL_RESOURCE_ATTRIBUTES = "service.version=1.2.0,deployment.environment=dev"

代码等价:

复制代码
from opentelemetry.sdk.resources import Resource, SERVICE_NAME

Resource.create({
    SERVICE_NAME: "checkout-service",
    "service.version": "1.2.0",
    "k8s.pod.name": "checkout-7f8d9",  # 集群里多由 detector / Collector 的 k8sattributes 补
})

Resource 是进程级,不要把 order.id 放这里(那是 Span 属性)。

2.5 Propagators(跨服务传播)

Inject/Extract Context。默认 W3C:traceparent + baggage。断链第一原因在这里,不在 Collector。

经典操作: 两个进程,只靠 HTTP 头串成一条 Trace。

服务 A(客户端):

复制代码
import requests
from opentelemetry.propagate import inject

headers = {}
inject(headers)  # 写入 traceparent
print("发出的头", headers)
requests.get("http://127.0.0.1:5001/product", headers=headers)

服务 B(服务端,Flask 插桩会自动 Extract;手工则):

复制代码
from opentelemetry.propagate import extract
from opentelemetry import context, trace

ctx = extract(dict(request.headers))
token = context.attach(ctx)
try:
    with tracer.start_as_current_span("GET /product"):
        ...
finally:
    context.detach(token)

看打印应类似:traceparent: 00-<32位trace_id>-<16位span_id>-01

B 的 span 必须沿用这个 trace_id,并把对端 span_id 当 parent。

若 A 用 tracecontext、B 只用 b3,就会裂成两条 Trace。

复制代码
$env:OTEL_PROPAGATORS = "tracecontext,baggage"  # 全链路保持一致

2.6 Samplers(采样器)

决定哪些 Trace 真正导出。头采看 trace-flagsalways_off 时日志仍可能有 trace_id,界面没有 Span。

经典操作:

复制代码
# 全采(开发)
$env:OTEL_TRACES_SAMPLER = "always_on"

# 全丢(对照:产品里突然没 Trace)
$env:OTEL_TRACES_SAMPLER = "always_off"

# 生产常用:尊重父采样,根按 10%
$env:OTEL_TRACES_SAMPLER = "parentbased_traceidratio"
$env:OTEL_TRACES_SAMPLER_ARG = "0.1"

默认是 parentbased_always_on:有父且父 sampled 则采,根默认全采。流量一大才改成 ratio。


3. Collector(采集/中转侧主力)

独立进程:接收、处理、再导出。应用不必直连后端。

管道由五类插件组成:Receiver、Processor、Exporter、Connector、Extension。

生产上常见:应用 SDK → Collector → OpenObserve。Collector 是 OTel 的组件;OpenObserve 是后端产品,不是 OTel 组件。

为什么要它: 应用快速卸数据;重试、批处理、脱敏、加 K8s 属性、一扇出多后端,都放在 Collector,而不是每个服务里写。


两种部署:Agent(每机/每 Pod sidecar) + Gateway(集群统一入口)

经典操作 1 ------ 官方 Quick Start(先证明 Collector 活着):

复制代码
docker pull otel/opentelemetry-collector:0.158.0

docker run --rm -p 4317:4317 -p 4318:4318 -p 55679:55679 \
  otel/opentelemetry-collector:0.158.0

另开终端(需 Go):

复制代码
go install github.com/open-telemetry/opentelemetry-collector-contrib/cmd/telemetrygen@latest
telemetrygen traces --otlp-insecure --traces 3

Collector 日志里应出现 Span;浏览器打开 http://localhost:55679/debug/tracez

这只验证 OTLP 收进 Collector,还没到 OpenObserve。

经典操作 2 ------ 接到后端(含 OpenObserve)的最小 config:

otel-config.yaml

复制代码
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 75
    spike_limit_percentage: 15

exporters:
  debug:
    verbosity: basic
  otlphttp:
    endpoint: https://<你的O2>/api/default   # 会再拼 /v1/traces
    headers:
      Authorization: Basic <token>
    tls:
      insecure: false

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [debug, otlphttp]

docker run --rm -p 4317:4317 -p 4318:4318 \
  -v ${PWD}/otel-config.yaml:/etc/otelcol/config.yaml \
  otel/opentelemetry-collector-contrib:0.158.0 \
  --config /etc/otelcol/config.yaml

应用只需:

复制代码
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:4318"
$env:OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf"

排障: debug 有、O2 没有 → exporter 地址/鉴权/路径;debug 也没有 → 应用没打到 4317/4318,或 grpc/http 混用。


4. 平台周边

组件 做什么
Kubernetes Operator 管 Collector 资源、给工作负载注入自动插桩
Helm Charts 在集群里安装 Collector / Operator
FaaS 资产 如 AWS Lambda 自动插桩 Layer、独立 Collector Layer

① Kubernetes Operator

是什么: 集群里的 Operator,管两件事:

  1. OpenTelemetryCollector CR:帮你跑 Collector
  2. Instrumentation CR + Pod 注解:往工作负载注入零代码 Agent

经典操作:

bash 复制代码
# 需先有 cert-manager
kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/latest/download/opentelemetry-operator.yaml

Collector(Operator 会建 Service demo-collector):

bash 复制代码
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
  name: demo
spec:
  config:
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    processors:
      memory_limiter:
        check_interval: 1s
        limit_percentage: 75
        spike_limit_percentage: 15
    exporters:
      debug: {}
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [memory_limiter]
          exporters: [debug]

注入策略:

bash 复制代码
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: demo-instrumentation
spec:
  exporter:
    endpoint: http://demo-collector:4318
  propagators: [tracecontext, baggage]
  sampler:
    type: parentbased_traceidratio
    argument: "1"

业务 Deployment 只加注解(Java 示例):

复制代码
spec:
  template:
    metadata:
      annotations:
        instrumentation.opentelemetry.io/inject-java: "true"

其它语言:inject-python / inject-nodejs / inject-dotnet / inject-go

滚动发布后,Pod 里会被注入 Agent,流量会出 HTTP/DB span,代码可以零改动。


② FaaS 资产(函数计算)

是什么: 针对 Lambda 等短生命周期环境的现成 Layer:自动插桩 Layer,以及可选的 Collector Layer(函数里不便常驻进程时,用 Layer 做导出)。

和普通 SDK 的差别: 冷启动、执行完进程被冻/杀,必须在返回前 flush;传播要穿过网关事件(API Gateway header → Lambda)。

经典操作(AWS Lambda 自动插桩思路):

  1. 给函数挂上官方 OTel Lambda Layer(按语言选)。
  2. 配置例如:
bash 复制代码
AWS_LAMBDA_EXEC_WRAPPER = /opt/otel-handler
OTEL_SERVICE_NAME = order-fn
OTEL_EXPORTER_OTLP_ENDPOINT = http://localhost:4318
  1. 需要在函数旁收数据时,再挂 Collector Layer,把 OTLP 转到 OpenObserve。
  2. 手工插桩时,handler 结束前调用 force_flush(),否则 Span 还在 Batch 队列里函数就结束了。

细则:FaaS · Lambda Auto-Instrumentation


对照:谁负责什么(排障时用)

现象 先查哪个组件
完全没 span SDK / 零代码没挂上,或 OTEL_SDK_DISABLED
有 HTTP span,没有订单号 插桩库正常;缺手动业务 span
console 有、后端没有 Exporter / Collector 地址、协议、鉴权
两个服务两条 Trace Propagator 不一致或网关剥了 traceparent
日志有 ID、界面无 Trace Sampler always_off / 比例采样
服务名 unknown_service Resource / OTEL_SERVICE_NAME
应用正常、集群里部分 Pod 没数据 Operator 注解没打上或 Instrumentation CR 的 endpoint 错
Lambda 偶发丢 Trace 没 flush,不是 OTLP「丢包」那么简单

和「信号」的关系(避免再混)

每个信号(Trace / Metric / Log)在规范里都对应:API → SDK → OTLP → Collector。

Baggage 只有 API/SDK,没有 OTLP 和 Collector------它沿请求传播,不「导出到后端」。

相关推荐
c_zyer2 个月前
一站式可观测新选择:OpenObserve 深度对标 ELK / Grafana+Prometheus / Netdata,附Docker一键部署实战
elk·grafana·prometheus·netdata·openobserve
不懂的浪漫3 个月前
OpenTelemetry 和 SkyWalking Agent 怎么选?一次讲清 OTel、SkyWalking Agent 的相同点与区别
wpf·skywalking·链路追踪·opentelemetry·otel
洒满阳光的午后4 个月前
我做了一个“能理解业务语义”的可观测性 MCP Server:统一接入 Prometheus、OpenObserve 和 SkyWalking
人工智能·ai·prometheus·skywalking·openobserve·mcp
田猿笔记1 年前
OpenObserve API Usage Guide for Log Management
openobserve
不会飞的小龙人2 年前
Docker安装Quickwit搜索引擎
搜索引擎·docker·日志存储·链路跟踪·otel·portainer容器管理·quickwit
SRETalk2 年前
OpenTelemetry 101:面向 IT 领导者和爱好者的非技术指南
可观测性·opentelemetry·otel
不会飞的小龙人2 年前
遥测数据采集工具Grafana Alloy
spring boot·grafana·日志采集·链路跟踪·alloy·otel
gitxuzan_2 年前
云原生链路观测平台 openobserve + fluent-bit,日志收集
云原生·openobserve·fluent-bit