埋點
什么是埋點
埋點,本質就是在你的應用程序里,在重要位置插入采集代碼,比如:
- 收集請求開始和結束的時間
- 收集數據庫查詢時間
- 收集函數調用鏈路信息
- 收集異常信息
這些埋點數據(Trace、Metrics、Logs)被收集起來后,可以在監控平臺看到系統運行時的真實表現,幫助你做:
- 性能分析
- 故障排查
- 調用鏈路追蹤
簡單說就是:“在合適的地方插追蹤/監控代碼”。
要使用 OpenTelemetry 檢測應用程序,可以前往訪問 OpenTelemetry 存儲庫,選擇適用于的應用程序的語言,然后按照說明進行操作。具體可以參考文檔:https://opentelemetry.opendocs.io/docs/getting-started/dev/
自動埋點
使用自動埋點是一個很好的方式,因為它簡單、容易,不需要進行很多代碼更改。
如果你沒有必要的知識(或時間)來創建適合你應用程序量身的追蹤代碼,那么這種方法就非常合適。
OpenTelemetry 支持自動化埋點的語言:
- .net
- Java
- JavaScript
- PHP
- Python
手動檢測
手動檢測是指為應用程序編寫特定的埋點代碼。這是向應用程序添加可觀測性代碼的過程。這樣做可以更有效地滿足你的需求,因為可以自己添加屬性和事件。這樣做的缺點是需要導入庫并自己完成所有工作。
埋點方式對比
手動埋點(Manual Instrumentation) | 自動埋點(Automatic Instrumentation) | |
---|---|---|
定義 | 程序員自己在代碼里顯式寫下采集邏輯 | 借助 SDK/Agent 自動攔截應用,無需修改業務代碼 |
實現方式 | 引用 OpenTelemetry API,比如創建 Tracer ,手動打 span | 安裝一個 Agent(Java agent、Python instrumentation)自動檢測框架和庫,插入追蹤 |
控制力度 | 非常高,想怎么打點都可以 | 較低,受限于 Agent 支持的范圍 |
開發成本 | 高,需要自己判斷哪里要加埋點 | 低,幾乎開箱即用 |
支持范圍 | 業務邏輯細粒度打點,比如特定函數、算法內部 | 框架級打點,比如 HTTP 請求、數據庫訪問、消息隊列消費 |
性能影響 | 可控,看你打點多少 | 可能稍高,因為 Agent 會 Hook 很多地方 |
典型場景 | 需要追蹤復雜業務邏輯 | 快速上線鏈路追蹤,不想改代碼 |
k8s 應用自動埋點步驟
- 部署 OpenTelemetry Operator:它幫你管理
Instrumentation
和OpenTelemetryCollector
,實現自動注入、自動采集功能。 - 部署 OpenTelemetryCollector:用來接收自動埋點產生的數據,比如 traces。
- 定義 Instrumentation 對象:聲明“我想要給哪些應用自動打點”(比如 Java 的 agent),并指定用哪個
Collector
。 - 給你的 Pod 加上 Annotation:Operator 會根據 Annotation 自動注入 Agent 和 Sidecar。
自動埋點配置詳解
配置示例
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:name: <name>namespace: <namespace>
spec:exporter: # 導出目標配置endpoint: <string> # 指定導出的地址,通常是 OpenTelemetry Collector 的 OTLP 接收端口tls: # 是否使用非加密連接(跳過 TLS)insecure: <bool> # 跳過 TLS 校驗,默認 falseinsecureSkipVerify: <bool>propagators: # 上下文傳播協議,如果是跨服務追蹤,一定要所有服務使用同一傳播協議- tracecontext # W3C Trace Context 標準(推薦)- baggage # W3C Baggage(支持傳遞 key-value)- b3 # B3 single-header(Zipkin 風格)- b3multi # B3 multi-header- jaeger # Jaeger 原生格式sampler: # 采樣器配置type: <sampler_type>argument: <string> resource: # 資源標簽,可選配置attributes:service.name: <string> # 用于區分不同服務service.namespace: <string> # 服務所屬 namespaceservice.version: <string> # 服務版本env: # 全局環境變量- name: OTEL_FOOvalue: "bar"
采樣器配置
采樣器配置如下:
類型 | 含義 | 是否支持 argument |
---|---|---|
always_on | 全部采樣 | 否 |
always_off | 全部不采樣 | 否 |
traceidratio | 指定比例采樣 | 是(如 "0.25" ) |
parentbased_traceidratio | 如果上游有 trace,繼承上游;否則按照比例采樣 | 是 |
parentbased_always_on | 如果上游有 trace,繼承;否則全部采樣 | 否 |
parentbased_always_off | 如果上游有 trace,繼承;否則不采樣 | 否 |
argument
字段通常是小數,表示采樣概率,如 "1"
表示 100%,"0.5"
表示 50%。
其他配置
其他配置可通過環境變量方式注入,具體配置項可參考文檔:
https://opentelemetry.io/docs/languages/sdk-configuration/
部署示例應用
部署 java 應用
這里我們將使用一個名為 Petclinic 的 Java 應用程序,這是一個使用 Maven 或 Gradle 構建的 Spring Boot 應用程序。該應用程序將使用 OpenTelemetry 生成數據。
Petclinic 示例項目地址:https://github.com/spring-projects/spring-petclinic
apiVersion: apps/v1
kind: Deployment
metadata:name: java-demo
spec:selector:matchLabels:app: java-demotemplate:metadata:labels:app: java-demospec:containers:- name: java-demoimage: contrastsecuritydemo/spring-petclinic:1.5.1imagePullPolicy: IfNotPresentresources:limits:memory: "500Mi"cpu: "200m"ports:- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:name: java-demo
spec:selector:app: java-demoports:- port: 8080targetPort: 8080
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:name: java-demo
spec:entryPoints:- webroutes:- match: Host(`java-demo.cuiliangblog.cn`)kind: Ruleservices:- name: java-demoport: 8080
部署完成后通過域名訪問驗證。
部署 python 應用
這里我們將使用一個名為 python-demoapp 的 python 應用程序,這是一個使用 flask 構建的 web 應用程序。該應用程序將使用 OpenTelemetry 生成數據。
項目地址:https://github.com/benc-uk/python-demoapp
apiVersion: apps/v1
kind: Deployment
metadata:name: python-demo
spec:selector:matchLabels:app: python-demotemplate:metadata:labels:app: python-demospec:containers:- name: python-demoimage: ghcr.io/benc-uk/python-demoapp:latestimagePullPolicy: IfNotPresentresources:limits:memory: "500Mi"cpu: "200m"ports:- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:name: python-demo
spec:selector:app: python-demoports:- port: 5000targetPort: 5000
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:name: python-demo
spec:entryPoints:- webroutes:- match: Host(`python-demo.local.com`)kind: Ruleservices:- name: python-demoport: 5000
接下來通過域名訪問應用
應用埋點
java 應用自動埋點
對于 Java 應用,我們可以通過下載 OpenTelemetry 提供的 opentelemetry-javaagent 這個 jar 包來使用 OpenTelemetry 自動檢測應用程序。
opentelemetry-javaagent 地址:https://github.com/open-telemetry/opentelemetry-java-instrumentation
只需要將這個 jar 包添加到應用程序的啟動命令中即可,比如:
java -javaagent:opentelemetry-javaagent.jar -jar target/*.jar
Java 自動檢測使用可附加到任何 Java 8+ 應用程序的 Java 代理 JAR。它動態注入字節碼以從許多流行的庫和框架捕獲遙測數據。它可用于捕獲應用程序或服務“邊緣”的遙測數據,例如入站請求、出站 HTTP 調用、數據庫調用等。通過運行以上命令,我們可以對應用程序進行插樁,并生成鏈路數據,而對我們的應用程序沒有任何修改。
尤其是在 Kubernetes 環境中,我們可以使用 OpenTelemetry Operator 來注入和配置 OpenTelemetry 自動檢測庫,這樣連 javaagent 我們都不需要去手動注入了。
接下來為 Java 應用程序添加一個 Instrumentation 資源。
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation # 聲明資源類型為 Instrumentation(用于語言自動注入)
metadata:name: java-instrumentation # Instrumentation 資源的名稱(可以被 Deployment 等引用)namespace: opentelemetry
spec:propagators: # 指定用于 trace 上下文傳播的方式,支持多種格式- tracecontext # W3C Trace Context(最通用的跨服務追蹤格式)- baggage # 傳播用戶定義的上下文鍵值對- b3 # Zipkin 的 B3 header(用于兼容 Zipkin 環境)sampler: # 定義采樣策略(決定是否收集 trace)type: always_on # 始終采樣所有請求(適合測試或調試環境)java:# image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:latest# 使用的 Java 自動注入 agent 鏡像地址image: harbor.cuiliangblog.cn/otel/autoinstrumentation-java:latestenv:- name: OTEL_EXPORTER_OTLP_ENDPOINTvalue: http://center-collector.opentelemetry.svc:4318
為了啟用自動檢測,我們需要更新部署文件并向其添加注解。這樣我們可以告訴 OpenTelemetry Operator 將 sidecar 和 java-instrumentation 注入到我們的應用程序中。修改 Deployment 配置如下:
apiVersion: apps/v1
kind: Deployment
metadata:name: java-demo
spec:selector:matchLabels:app: java-demotemplate:metadata:labels:app: java-demoannotations:instrumentation.opentelemetry.io/inject-java: "opentelemetry/java-instrumentation" # 填寫 Instrumentation 資源的名稱sidecar.opentelemetry.io/inject: "opentelemetry/sidecar" # 注入一個 sidecar 模式的 OpenTelemetry Collectorspec:containers:- name: java-demoimage: contrastsecuritydemo/spring-petclinic:1.5.1imagePullPolicy: IfNotPresentresources:limits:memory: "500Mi"cpu: "200m"ports:- containerPort: 8080
接下來更新 deployment,然后查看資源信息,java-demo 容器已經變為兩個。
# kubectl get pod
NAME READY STATUS RESTARTS AGE
java-demo-557fff6b7c-x8tjg 2/2 Running 0 3m6s
# kubectl get opentelemetrycollectors -A
NAMESPACE NAME MODE VERSION READY AGE IMAGE MANAGEMENT
default sidecar sidecar 0.123.1 39m managed
opentelemetry simple deployment 0.123.1 1/1 39m ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector:0.123.1 managed
# kubectl get instrumentations -A
NAMESPACE NAME AGE ENDPOINT SAMPLER SAMPLER ARG
opentelemetry java-instrumentation 39m always_on
查看 sidecar日志,已正常啟動并發送 spans 數據
# kubectl logs java-demo-557fff6b7c-x8tjg -c otc-container
2025-04-23T08:56:32.664Z info grpc@v1.71.0/server.go:690 [core] [Server #3]Server created {"grpc_log": true}
2025-04-23T08:56:32.669Z info otlpreceiver@v0.123.0/otlp.go:116 Starting GRPC server {"endpoint": "0.0.0.0:4317"}
2025-04-23T08:56:32.670Z info otlpreceiver@v0.123.0/otlp.go:173 Starting HTTP server {"endpoint": "0.0.0.0:4318"}
2025-04-23T08:56:32.670Z info service@v0.123.0/service.go:287 Everything is ready. Begin running and processing data.
2025-04-23T08:56:32.670Z info grpc@v1.71.0/server.go:886 [core] [Server #3 ListenSocket #4]ListenSocket created {"grpc_log": true}
2025-04-23T08:56:32.686Z info grpc@v1.71.0/clientconn.go:1224 [core] [Channel #1 SubChannel #2]Subchannel Connectivity change to READY {"grpc_log": true}
2025-04-23T08:56:32.686Z info pickfirst/pickfirst.go:184 [pick-first-lb] [pick-first-lb 0xc000ab7530] Received SubConn state update: 0xc0008b6550, {ConnectivityState:READY ConnectionError:<nil> connectedAddress:{Addr:simple-collector.opentelemetry.svc:4317 ServerName:simple-collector.opentelemetry.svc:4317 Attributes:<nil> BalancerAttributes:<nil> Metadata:<nil>}} {"grpc_log": true}
2025-04-23T08:56:32.686Z info grpc@v1.71.0/clientconn.go:563 [core] [Channel #1]Channel Connectivity change to READY {"grpc_log": true}
2025-04-23T08:57:26.022Z info Traces {"resource spans": 1, "spans": 72}
2025-04-23T08:57:36.027Z info Traces {"resource spans": 1, "spans": 4}
查看collector 日志,已經收到 traces 數據
# kubectl logs -n opentelemetry simple-collector-5b5699b46f-qgdw6
2025-04-23T07:28:27.220Z info service@v0.123.0/service.go:197 Setting up own telemetry...
2025-04-23T07:28:27.220Z info builders/builders.go:26 Development component. May change in the future.
2025-04-23T07:28:27.223Z info memorylimiter@v0.123.0/memorylimiter.go:148 Using percentage memory limiter {"total_memory_mib": 7914, "limit_percentage": 75, "spike_limit_percentage": 15}
2025-04-23T07:28:27.223Z info memorylimiter@v0.123.0/memorylimiter.go:74 Memory limiter configured {"limit_mib": 5935, "spike_limit_mib": 1187, "check_interval": 1}
2025-04-23T07:28:27.270Z info service@v0.123.0/service.go:264 Starting otelcol... {"Version": "0.123.1", "NumCPU": 4}
2025-04-23T07:28:27.270Z info extensions/extensions.go:41 Starting extensions...
2025-04-23T07:28:27.271Z info otlpreceiver@v0.123.0/otlp.go:116 Starting GRPC server {"endpoint": "0.0.0.0:4317"}
2025-04-23T07:28:27.271Z info otlpreceiver@v0.123.0/otlp.go:173 Starting HTTP server {"endpoint": "0.0.0.0:4318"}
2025-04-23T07:28:27.272Z info service@v0.123.0/service.go:287 Everything is ready. Begin running and processing data.
2025-04-23T08:57:26.022Z info Traces {"resource spans": 1, "spans": 72}
2025-04-23T08:57:36.027Z info Traces {"resource spans": 1, "spans": 4}
python 應用自動埋點
與 java 應用類似,python 應用同樣也支持自動埋點, OpenTelemetry 提供了 opentelemetry-instrument
CLI 工具,在啟動 Python 應用時通過 sitecustomize
或環境變量注入自動 instrumentation。
我們先創建一個java-instrumentation 資源
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation # 聲明資源類型為 Instrumentation(用于語言自動注入)
metadata:name: python-instrumentation # Instrumentation 資源的名稱(可以被 Deployment 等引用)namespace: opentelemetry
spec:propagators: # 指定用于 trace 上下文傳播的方式,支持多種格式- tracecontext # W3C Trace Context(最通用的跨服務追蹤格式)- baggage # 傳播用戶定義的上下文鍵值對- b3 # Zipkin 的 B3 header(用于兼容 Zipkin 環境)sampler: # 定義采樣策略(決定是否收集 trace)type: always_on # 始終采樣所有請求(適合測試或調試環境)python:image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:latestenv: - name: OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED # 啟用日志的自動檢測value: "true"- name: OTEL_PYTHON_LOG_CORRELATION # 在日志中啟用跟蹤上下文注入value: "true"- name: OTEL_EXPORTER_OTLP_ENDPOINTvalue: http://center-collector.opentelemetry.svc:4318
然后更新 deployment 資源清單,添加注解
apiVersion: apps/v1
kind: Deployment
metadata:name: python-demo
spec:selector:matchLabels:app: python-demotemplate:metadata:labels:app: python-demoannotations:instrumentation.opentelemetry.io/inject-python: "opentelemetry/python-instrumentation" # 填寫 Instrumentation 資源的名稱sidecar.opentelemetry.io/inject: "opentelemetry/sidecar" # 注入一個 sidecar 模式的 OpenTelemetry Collector……
接下來觀察日志既可。
查看更多
崔亮的博客-專注devops自動化運維,傳播優秀it運維技術文章。更多原創運維開發相關文章,歡迎訪問https://www.cuiliangblog.cn