This is an automated email from the ASF dual-hosted git repository.
Alanxtl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git
The following commit(s) were added to refs/heads/master by this push:
new 84b35ebdab2 docs(golang-sdk): improve tracing guide and add exporter
run steps (#3230)
84b35ebdab2 is described below
commit 84b35ebdab20a54da2c740aa8428a375ff43b481
Author: taffynb667 <[email protected]>
AuthorDate: Thu Sep 3 15:49:14 2026 +0800
docs(golang-sdk): improve tracing guide and add exporter run steps (#3230)
* 完善 Tracing 文档,补充 stdout exporter 运行方式
* Remove duplicate git clone commands from tracing.md
Removed redundant git clone command from multiple sections.
* Update tracing.md
---
.../golang-sdk/tutorial/observability/tracing.md | 338 ++++++++++++++++++---
.../golang-sdk/tutorial/observability/tracing.md | 337 +++++++++++++++++---
2 files changed, 591 insertions(+), 84 deletions(-)
diff --git
a/content/en/overview/mannual/golang-sdk/tutorial/observability/tracing.md
b/content/en/overview/mannual/golang-sdk/tutorial/observability/tracing.md
index f5ae6a6ee0c..ddf77088436 100644
--- a/content/en/overview/mannual/golang-sdk/tutorial/observability/tracing.md
+++ b/content/en/overview/mannual/golang-sdk/tutorial/observability/tracing.md
@@ -6,49 +6,52 @@ type: docs
weight: 3
---
-Dubbo-go supports end-to-end tracing based on the
[OpenTelemetry](https://opentelemetry.io/) standard, while also supporting
export to different tracing backend systems through the following exporters.
+Dubbo-go supports end-to-end tracing based on the
[OpenTelemetry](https://opentelemetry.io/) standard. When tracing is enabled,
Dubbo-go automatically creates spans during RPC calls and exports them to
different backend systems through the configured exporter.
-- [Stdout
exporter](https://opentelemetry.io/docs/specs/otel/logs/sdk_exporters/stdout/)
-- [Jaeger
exporter](https://opentelemetry.io/docs/languages/js/exporters/#jaeger)
-- [Zipkin
exporter](https://opentelemetry.io/docs/languages/js/exporters/#zipkin)
-- [OTLP-HTTP
exporter](https://opentelemetry.io/docs/languages/js/exporters/#use-otlp-exporter-with-httpjson-or-httpprotobuf)
-- [OTLP-gRPC
exporter](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/)
+The following exporters are supported:
-## Usage
+- `stdout`: Prints spans to the process standard output as JSON; suitable for
local development and debugging.
+- `jaeger`: Exports spans to [Jaeger](https://www.jaegertracing.io/).
+- `zipkin`: Exports spans to [Zipkin](https://zipkin.io/).
+- `otlp-http`: Exports spans to OpenTelemetry Collector or other backends over
OTLP/HTTP.
+- `otlp-grpc`: Exports spans to OpenTelemetry Collector or other backends over
OTLP/gRPC.
+
+Runnable examples for the stdout, jaeger, and otlp-http exporters are
available under
[dubbo-go-samples/otel/tracing](https://github.com/apache/dubbo-go-samples/tree/main/otel/tracing).
The sections below explain how to run each of them.
-Please note that tracing functionality is only enabled when creating the Dubbo
application via `dubbo.NewInstance`, which is the `microservice application
mode` mentioned in our quick start. The `lightweight RPC API` does not
currently support enabling tracing.
+## Usage
-## Example Explanation
-You can view the full example source code
[here](https://github.com/apache/dubbo-go-samples/tree/main/otel/tracing).
+- Tracing is currently supported only when the Dubbo application is created
through `dubbo.NewInstance`, i.e. the microservice application mode described
in the quick start. The lightweight RPC API does not support tracing yet.
+- The blank import `dubbo.apache.org/dubbo-go/v3/imports` must be added to
register the exporter implementations.
+- Tracing is configured with `dubbo.WithTracing(...)`; `trace.WithXXX` options
control the exporter, endpoint, propagator, and sampling policy.
-Enable tracing using `dubbo.WithTracing()`, and you can control tracing
behavior with multiple parameters:
+Here is a minimal configuration:
```go
package main
import (
- "dubbo.apache.org/dubbo-go/v3"
- _ "dubbo.apache.org/dubbo-go/v3/imports"
- "dubbo.apache.org/dubbo-go/v3/otel/trace"
+ "dubbo.apache.org/dubbo-go/v3"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+ "dubbo.apache.org/dubbo-go/v3/otel/trace"
)
func main() {
- instance, err := dubbo.NewInstance(
- dubbo.WithTracing(
- // add tracing options here
- trace.WithEnabled(), // enable tracing feature
- trace.WithStdoutExporter(),
- trace.WithW3cPropagator(),
- trace.WithAlwaysMode(),
- trace.WithRatioMode(), // use ratio mode
- trace.WithRatio(0.5), // sample ratio, only active when using ratio
mode
- ),
- )
+ ins, err := dubbo.NewInstance(
+ dubbo.WithTracing(
+ trace.WithEnabled(), // enable tracing
+ trace.WithStdoutExporter(), // use the stdout exporter
+ trace.WithW3cPropagator(), // use W3C trace context
propagation
+ trace.WithAlwaysMode(), // sample all requests for
local verification
+ ),
+ )
+ if err != nil {
+ panic(err)
+ }
+ _ = ins
}
-
```
-If you do not specify any option parameters in the `dubbo.WithTracing()` call,
the default behavior will be used:
+If no options are passed to `dubbo.WithTracing()`, the default configuration
below is used:
```yaml
# default tracing config
@@ -58,26 +61,277 @@ endpoint: ""
propagator: w3c
sample-mode: ratio
sample-ratio: 0.5
+insecure: false
```
-## TracingOptions Explained
+Note that `enable` defaults to `false`. You must call `trace.WithEnabled()`
(or set `tracing.enable: true` in YAML) to actually turn tracing on.
+
+## Common dubbo.WithTracing options
-- enable: enable tracing or not
- - `trace.WithEnabled()` means enable tracing
-- exporter: tracing exporter backends, support stdout, jaeger, zipkin,
otlp-http, otlp-grpc
+- `enable`: whether tracing is enabled; defaults to `false`.
+ - `trace.WithEnabled()` enables tracing.
+- `exporter`: the span exporter type; supports `stdout`, `jaeger`, `zipkin`,
`otlp-http`, and `otlp-grpc`.
- `trace.WithStdoutExporter()`
- `trace.WithJaegerExporter()`
- `trace.WithZipkinExporter()`
- `trace.WithOtlpHttpExporter()`
- `trace.WithOtlpGrpcExporter()`
-- endpoint: exporter backend endpoint, for example, jaeger exporter's endpoint
is `http://localhost:14268/api/traces`
- - `trace.WithEndpoint(string)`
-- propagator: context propagator type, supports w3c, b3; more details you can
see [here](https://opentelemetry.io/docs/concepts/context-propagation/)
- - `trace.WithW3cPropagator()`
- - `trace.WithB3Propagator()` zipkin exporter defaults to using this
-- sample-mode: sample mode, support ratio, always, never
- - `trace.WithAlwaysMode()`
- - `trace.WithNeverMode()`
- - `trace.WithRatioMode()`
-- sample-ratio: sample ratio, only used when sample-mode is ratio, range
between 0 and 1
- - `trace.WithRatio(float64)`
+ - Alternatively, use `trace.WithExporter("jaeger")` to set the exporter from
a string.
+- `endpoint`: the backend address of the exporter.
+ - For Jaeger/Zipkin it is usually a full HTTP URL, for example Jaeger's
`http://localhost:14268/api/traces`.
+ - For OTLP exporters use `host:port`, for example `127.0.0.1:4318`.
+ - Configure it with `trace.WithEndpoint("...")`.
+- `insecure`: whether a non-TLS connection is allowed; defaults to `false`.
+ - Set `trace.WithInsecure()` when the OTLP HTTP exporter reports over plain
HTTP.
+- `propagator`: the context propagator; supports `w3c` and `b3`.
+ - `trace.WithW3cPropagator()`: W3C Trace Context; recommended by default.
+ - `trace.WithB3Propagator()`: B3 format; usually used together with Zipkin.
+- `sample-mode`: the sampling mode; supports `always`, `never`, and `ratio`.
These modes are mutually exclusive.
+ - `trace.WithAlwaysMode()` samples all requests.
+ - `trace.WithNeverMode()` samples nothing.
+ - `trace.WithRatioMode()` samples by ratio.
+- `sample-ratio`: the sampling ratio, effective only in ratio mode; valid
range is `[0, 1]`.
+ - `trace.WithRatio(0.5)` samples 50% of requests.
+
+> Sample-mode options are applied in order and the last one wins. Do not mix
`WithAlwaysMode` and `WithRatioMode` in the same configuration, or the earlier
option may be overwritten.
+
+## Running the stdout exporter
+
+The stdout exporter requires no external components, which makes it ideal for
verifying that tracing works locally or for inspecting trace data in a
development environment.
+
+### Get the example
+
+```bash
+cd dubbo-go-samples/otel/tracing/stdout
+```
+
+Example layout:
+
+- `go-server/cmd/main.go`: the server, which listens on port 20000 over the
Triple protocol.
+- `go-client/cmd/main.go`: the client, which connects directly to
`127.0.0.1:20000` and calls `Greet` once.
+- The example uses direct connection, so no registry is needed.
+
+### Configure the stdout exporter
+
+Both the server and the client configure the stdout exporter in
`dubbo.NewInstance`:
+
+```go
+dubbo.WithTracing(
+ trace.WithEnabled(), // enable tracing
+ trace.WithStdoutExporter(), // use the stdout exporter
+ trace.WithW3cPropagator(), // W3C trace context propagation
+ trace.WithAlwaysMode(), // sample all requests
+)
+```
+
+`WithAlwaysMode` samples every request so a span is produced each time. With
the default ratio mode (0.5), only about half of the requests are sampled.
+
+### Run and verify
+
+Start the server in the first terminal:
+
+```bash
+go run ./go-server/cmd/main.go
+```
+
+Start the client in the second terminal:
+
+```bash
+go run ./go-client/cmd/main.go
+```
+
+After a successful call, the client prints a log similar to `Greet response:
hello world`. The server console then shows the exporter startup logs and the
span JSON:
+
+```text
+INFO tracing/tracing.go:53 tracing enabled, exporter: stdout
+INFO tracing/tracing.go:54 tracing enabled, sampler: always_on
+```
+
+The span is printed as JSON with the following key fields:
+
+```json
+{
+ "Name": "Greet",
+ "SpanContext": {
+ "TraceID": "dee1fcd3eafbcb73338aa719a9d4d4ad",
+ "SpanID": "23a21f8330154882"
+ },
+ "Parent": {
+ "TraceID": "00000000000000000000000000000000",
+ "SpanID": "0000000000000000",
+ "Remote": true
+ },
+ "StartTime": "2024-01-24T09:31:51.7352636+08:00",
+ "EndTime": "2024-01-24T09:31:51.7352636+08:00",
+ "Attributes": [
+ {
+ "Key": "rpc.system",
+ "Value": { "Type": "STRING", "Value": "apache_dubbo" }
+ },
+ {
+ "Key": "rpc.service",
+ "Value": { "Type": "STRING", "Value": "greet.GreetService" }
+ },
+ {
+ "Key": "rpc.method",
+ "Value": { "Type": "STRING", "Value": "Greet" }
+ }
+ ],
+ "Status": {
+ "Code": "Ok"
+ },
+ "Resource": [
+ {
+ "Key": "service.name",
+ "Value": { "Type": "STRING", "Value": "dubbo_otel_tracing_server" }
+ }
+ ]
+}
+```
+
+Every client invocation produces a similar span on the server. See the [stdout
example
README](https://github.com/apache/dubbo-go-samples/blob/main/otel/tracing/stdout/README.md)
for the complete output.
+
+## Running the Jaeger exporter
+
+### Start Jaeger
+
+The example starts Jaeger all-in-one with Docker:
+
+```bash
+docker run -d --name jaeger \
+ -e COLLECTOR_OTLP_ENABLED=true \
+ -p 16686:16686 \
+ -p 14268:14268 \
+ -p 4317:4317 \
+ -p 4318:4318 \
+ jaegertracing/all-in-one:latest
+```
+
+`16686` is the Jaeger UI port and `14268` is the Jaeger collector HTTP port
used by the example exporter.
+
+### Get and run the example
+
+```bash
+cd dubbo-go-samples/otel/tracing/jaeger
+```
+
+Start the server in the first terminal:
+
+```bash
+go run ./go-server/cmd/main.go
+```
+
+Start the client in the second terminal:
+
+```bash
+go run ./go-client/cmd/main.go
+```
+
+The exporter-related configuration in the example is:
+
+```go
+dubbo.WithTracing(
+ trace.WithEnabled(),
+ trace.WithJaegerExporter(),
+ trace.WithEndpoint("http://localhost:14268/api/traces"),
+ trace.WithW3cPropagator(),
+ trace.WithAlwaysMode(),
+)
+```
+
+If Jaeger runs on another host or uses a different port, update the address in
`WithEndpoint` accordingly.
+
+### View the trace results
+
+Open `http://localhost:16686` in a browser:
+
+1. Select `dubbo_otel_jaeger_server` or `dubbo_otel_jaeger_client` from the
Service dropdown.
+2. Click Find Traces.
+3. Click a trace to inspect the client and server span timeline.
+
+The client example calls `TracerProvider.Shutdown` after the invocation so
pending spans are flushed to Jaeger before the process exits.
+
+## Running the OTLP HTTP exporter
+
+The `otel/tracing/otlp_http_exporter` example covers the dubbo, triple, and
jsonrpc protocols. It starts a mock OTLP receiver (listening on
`127.0.0.1:4318`) inside the server process to verify that spans produced by
the three protocols are exported correctly.
+
+### Get and run the example
+
+```bash
+cd dubbo-go-samples/otel/tracing/otlp_http_exporter
+```
+
+Start the server in the first terminal:
+
+```bash
+go run ./go-server/cmd/main.go
+```
+
+Start the client in the second terminal:
+
+```bash
+go run ./go-client/cmd/main.go
+```
+
+The client calls the server over triple (port 20000), dubbo (port 20001), and
jsonrpc (port 20002). When all six spans (three client spans plus three server
spans) are exported successfully, the server prints:
+
+```text
+server count: 3, client count: 3
+```
+
+The example panics on timeout or on a span-count mismatch.
+
+The exporter-related configuration in the example is:
+
+```go
+dubbo.WithTracing(
+ trace.WithEnabled(),
+ trace.WithOtlpHttpExporter(),
+ trace.WithEndpoint("127.0.0.1:4318"),
+ trace.WithInsecure(), // the mock receiver uses plain HTTP
+ trace.WithW3cPropagator(),
+ trace.WithAlwaysMode(),
+)
+```
+
+In a real environment, point `endpoint` at an OpenTelemetry Collector or an
OTLP-compatible backend, for example `collector.example.com:4318`. Keep
`WithInsecure` when reporting over plain HTTP, and remove it when the backend
uses TLS.
+
+## How to view trace results
+
+- **stdout exporter**: Spans are printed as JSON on the application standard
output. Inspect `TraceID`, `SpanID`, `Parent`, and `Attributes`; `Attributes`
contains Dubbo RPC information such as `rpc.system`, `rpc.service`, and
`rpc.method`.
+- **Jaeger exporter**: Query by service name in the Jaeger UI to see the full
trace timeline.
+- **OTLP HTTP/gRPC exporter**: Spans are sent to a Collector, which forwards
them to backends such as Jaeger, Zipkin, or Grafana Tempo; query the traces in
that backend's UI.
+
+With tracing enabled, the client and server on the call chain share the same
TraceID automatically. When troubleshooting, first use the stdout exporter to
confirm spans are generated, then switch to a remote backend to verify network
and endpoint configuration.
+
+## FAQ
+
+### 1. Tracing is enabled but no spans are visible
+
+Possible causes:
+
+- `trace.WithEnabled()` is missing. `enable` defaults to `false`, so
`dubbo.WithTracing()` alone does not turn tracing on.
+- The blank import `dubbo.apache.org/dubbo-go/v3/imports` is missing, so the
exporter implementation is not registered.
+- The default ratio mode (sampling ratio 0.5) skips some requests. For local
debugging use `trace.WithAlwaysMode()`, or set the ratio to
`trace.WithRatio(1.0)`.
+
+### 2. The Jaeger UI shows no data / the endpoint is wrong
+
+- Verify that the endpoint matches the Jaeger instance. The example uses
`http://localhost:14268/api/traces`.
+- Verify that the Docker port mappings for `16686` (UI) and `14268` (collector
HTTP) are correct.
+- Restart the application after changing the endpoint, and check the
application logs for `failed to create ... exporter` or connection errors.
+- The service name selected in the Jaeger UI must match `dubbo.WithName(...)`,
for example `dubbo_otel_jaeger_server` or `dubbo_otel_jaeger_client`.
+
+### 3. OTLP HTTP export fails
+
+- Set the OTLP HTTP endpoint as `host:port`, for example `127.0.0.1:4318`; do
not prefix it with `http://` and do not append the `/v1/traces` path.
+- Set `trace.WithInsecure()` when the backend uses plain HTTP; otherwise the
exporter establishes an HTTPS connection and TLS/handshake may fail.
+- Start the Collector or backend before starting the Dubbo application.
+
+### 4. Client and server spans are not linked into one trace
+
+- Tracing must be enabled on both the client and the server.
+- Both sides must use the same propagator: either both use
`trace.WithW3cPropagator()` or both use `trace.WithB3Propagator()`. Mixing W3C
on one side and B3 on the other prevents the context from being propagated.
+
+### 5. Very few traces are visible in ratio mode
+
+`sample-ratio` defaults to 0.5, and the sampling decision is propagated along
the call chain. Use `trace.WithAlwaysMode()` while debugging, and switch back
to ratio mode when you need to control cost.
diff --git
a/content/zh-cn/overview/mannual/golang-sdk/tutorial/observability/tracing.md
b/content/zh-cn/overview/mannual/golang-sdk/tutorial/observability/tracing.md
index 8823648cc30..0f0bb0df8e3 100644
---
a/content/zh-cn/overview/mannual/golang-sdk/tutorial/observability/tracing.md
+++
b/content/zh-cn/overview/mannual/golang-sdk/tutorial/observability/tracing.md
@@ -6,49 +6,52 @@ type: docs
weight: 3
---
-Dubbo-go 支持基于 [OpenTelemetry](https://opentelemetry.io/) 标准的全链路追踪埋点,同时支持通过以下
exporter 导出到不同的 tracing 后端系统。
+Dubbo-go 基于 [OpenTelemetry](https://opentelemetry.io/) 标准提供全链路追踪能力。开启 tracing
后,Dubbo-go 会在 RPC 调用过程中自动创建 Span,并通过配置的 exporter 将 Span 导出到不同的后端系统。
-- [Stdout
exporter](https://opentelemetry.io/docs/specs/otel/logs/sdk_exporters/stdout/)
-- [Jaeger
exporter](https://opentelemetry.io/docs/languages/js/exporters/#jaeger)
-- [Zipkin
exporter](https://opentelemetry.io/docs/languages/js/exporters/#zipkin)
-- [OTLP-HTTP
exporter](https://opentelemetry.io/docs/languages/js/exporters/#use-otlp-exporter-with-httpjson-or-httpprotobuf)
-- [OTLP-gRPC
exporter](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/)
+当前支持的 exporter 包括:
-## 使用方式
+- `stdout`:以 JSON 形式把 Span 打印到进程标准输出,适合本地开发与调试。
+- `jaeger`:上报到 [Jaeger](https://www.jaegertracing.io/)。
+- `zipkin`:上报到 [Zipkin](https://zipkin.io/)。
+- `otlp-http`:通过 OTLP/HTTP 上报到 OpenTelemetry Collector 等后端。
+- `otlp-grpc`:通过 OTLP/gRPC 上报到 OpenTelemetry Collector 等后端。
+
+其中 stdout、jaeger、otlp-http 在
[dubbo-go-samples/otel/tracing](https://github.com/apache/dubbo-go-samples/tree/main/otel/tracing)
下有可直接运行的示例,下文分别介绍其运行方式。
-请注意,仅支持通过 `dubbo.NewInstance` 方式创建 dubbo 应用时开启 tracing
功能,也就是我们快速开始中提到的`微服务应用模式`,对于`轻量 RPC API`暂时不支持开启 tracing。
+## 使用方式
-## 示例详解
-可在此查看[完整示例源码](https://github.com/apache/dubbo-go-samples/tree/main/otel/tracing)。
+- 目前仅支持通过 `dubbo.NewInstance` 创建 dubbo 应用(即快速开始中介绍的微服务应用模式)时开启 tracing;轻量 RPC
API 暂不支持。
+- 使用 tracing 前需要导入 `dubbo.apache.org/dubbo-go/v3/imports` 空包,用于注册各 exporter
的实现。
+- 通过 `dubbo.WithTracing(...)` 配置 tracing,内部使用 `trace.WithXXX` 子选项控制
exporter、endpoint、传播器和采样策略。
-使用 `dubbo.WithTracing()` 开启 tracing,可以通过多个参数控制 tracing 行为:
+下面是一段最简配置:
```go
package main
import (
- "dubbo.apache.org/dubbo-go/v3"
- _ "dubbo.apache.org/dubbo-go/v3/imports"
- "dubbo.apache.org/dubbo-go/v3/otel/trace"
+ "dubbo.apache.org/dubbo-go/v3"
+ _ "dubbo.apache.org/dubbo-go/v3/imports"
+ "dubbo.apache.org/dubbo-go/v3/otel/trace"
)
func main() {
- instance, err := dubbo.NewInstance(
- dubbo.WithTracing(
- // add tracing options here
- trace.WithEnabled(), // enable tracing feature
- trace.WithStdoutExporter(),
- trace.WithW3cPropagator(),
- trace.WithAlwaysMode(),
- trace.WithRatioMode(), // use ratio mode
- trace.WithRatio(0.5), // sample ratio, only active when use ratio
mode
- ),
- )
+ ins, err := dubbo.NewInstance(
+ dubbo.WithTracing(
+ trace.WithEnabled(), // 开启 tracing
+ trace.WithStdoutExporter(), // 使用 stdout exporter
+ trace.WithW3cPropagator(), // 使用 W3C trace context 传播
+ trace.WithAlwaysMode(), // 全量采样,便于本地验证
+ ),
+ )
+ if err != nil {
+ panic(err)
+ }
+ _ = ins
}
-
```
-如果你在 `dubbo.WithTracing()` 调用中不指定任何 option 参数,则会使用默认行为:
+`dubbo.WithTracing()` 不传任何参数时,使用默认配置:
```yaml
# default tracing config
@@ -58,27 +61,277 @@ endpoint: ""
propagator: w3c
sample-mode: ratio
sample-ratio: 0.5
+insecure: false
```
-## TracingOptions详解
+注意默认 `enable: false`,必须通过 `trace.WithEnabled()`(或 YAML 配置 `tracing.enable:
true`)真正开启功能。
+
+## dubbo.WithTracing 常用参数
-- enable: enable tracing or not
- - `trace.WithEnabled()` means enable tracing
-- exporter: tracing exporter backends, support stdout, jaeger, zipkin,
otlp-http, otlp-grpc
+- `enable`:是否开启 tracing,默认 `false`。
+ - `trace.WithEnabled()`:开启 tracing。
+- `exporter`:Span exporter 类型,支持
`stdout`、`jaeger`、`zipkin`、`otlp-http`、`otlp-grpc`。
- `trace.WithStdoutExporter()`
- `trace.WithJaegerExporter()`
- `trace.WithZipkinExporter()`
- `trace.WithOtlpHttpExporter()`
- `trace.WithOtlpGrpcExporter()`
-- endpoint: exporter backend endpoint, for example, jaeger exporter's endpoint
is `http://localhost:14268/api/traces`
- - `trace.WithEndpoint(string)`
-- propagator: context propagator type, support w3c, b3, more details you can
see [here](https://opentelemetry.io/docs/concepts/context-propagation/)
- - `trace.WithW3cPropagator()`
- - `trace.WithB3Propagator()` zipkin exporter default use this
-- sample-mode: sample mode, support ratio, always, never
- - `trace.WithAlwaysMode()`
- - `trace.WithNeverMode()`
- - `trace.WithRatioMode()`
-- sample-ratio: sample ratio, only used when sample-mode is ratio, range
between 0 and 1
- - `trace.WithRatio(float64)`
+ - 也可以使用 `trace.WithExporter("jaeger")` 按字符串设置。
+- `endpoint`:exporter 后端地址。
+ - Jaeger/Zipkin 一般为完整 HTTP 地址,例如 Jaeger 为
`http://localhost:14268/api/traces`。
+ - OTLP exporter 一般填写 `host:port`,例如 `127.0.0.1:4318`。
+ - 使用 `trace.WithEndpoint("...")` 配置。
+- `insecure`:是否允许非 TLS 连接,默认 `false`。
+ - OTLP HTTP 使用纯 HTTP 上报时需要设置 `trace.WithInsecure()`。
+- `propagator`:上下文传播器,支持 `w3c` 和 `b3`。
+ - `trace.WithW3cPropagator()`:W3C Trace Context,推荐默认使用。
+ - `trace.WithB3Propagator()`:B3 格式,通常与 Zipkin 搭配使用。
+- `sample-mode`:采样模式,支持 `always`、`never`、`ratio`,三者互斥。
+ - `trace.WithAlwaysMode()`:全量采样。
+ - `trace.WithNeverMode()`:不采样。
+ - `trace.WithRatioMode()`:按比例采样。
+- `sample-ratio`:采样比例,仅在 ratio 模式下生效,取值范围 `[0, 1]`。
+ - `trace.WithRatio(0.5)`:采样 50%。
+
+> 多个 sample-mode 选项按调用顺序覆盖,后设置的最后生效;不要在同一个配置里混用 `WithAlwaysMode` 和
`WithRatioMode`,否则前面的设置可能被覆盖。
+
+## Stdout exporter 运行方式
+
+stdout exporter 不需要启动任何外部组件,适合在本地快速验证 tracing 是否正常工作,或在开发环境直接查看调用链数据。
+
+### 获取示例
+
+```bash
+cd dubbo-go-samples/otel/tracing/stdout
+```
+
+示例目录说明:
+
+- `go-server/cmd/main.go`:服务端,Triple 协议监听 20000 端口。
+- `go-client/cmd/main.go`:客户端,直连 `127.0.0.1:20000` 并调用一次 `Greet`。
+- 示例使用直连方式,运行前不需要启动注册中心。
+
+### 配置 stdout exporter
+
+服务端与客户端均在 `dubbo.NewInstance` 中配置 stdout exporter:
+
+```go
+dubbo.WithTracing(
+ trace.WithEnabled(), // 开启 tracing
+ trace.WithStdoutExporter(), // 使用 stdout exporter
+ trace.WithW3cPropagator(), // W3C trace context 传播
+ trace.WithAlwaysMode(), // 全量采样
+)
+```
+
+这里使用 `WithAlwaysMode` 全量采样,保证每次调用都能产生 Span;如果使用默认的 ratio 模式(0.5),大约只有一半请求会被采样。
+
+### 启动并验证
+
+在第一个终端启动服务端:
+
+```bash
+go run ./go-server/cmd/main.go
+```
+
+在第二个终端启动客户端:
+
+```bash
+go run ./go-client/cmd/main.go
+```
+
+客户端调用成功后,终端会输出类似 `Greet response: hello world` 的日志。随后在服务端控制台可以看到 exporter
启动日志和本次调用的 Span JSON:
+
+```text
+INFO tracing/tracing.go:53 tracing enabled, exporter: stdout
+INFO tracing/tracing.go:54 tracing enabled, sampler: always_on
+```
+
+Span 以 JSON 形式打印,关键字段如下:
+
+```json
+{
+ "Name": "Greet",
+ "SpanContext": {
+ "TraceID": "dee1fcd3eafbcb73338aa719a9d4d4ad",
+ "SpanID": "23a21f8330154882"
+ },
+ "Parent": {
+ "TraceID": "00000000000000000000000000000000",
+ "SpanID": "0000000000000000",
+ "Remote": true
+ },
+ "StartTime": "2024-01-24T09:31:51.7352636+08:00",
+ "EndTime": "2024-01-24T09:31:51.7352636+08:00",
+ "Attributes": [
+ {
+ "Key": "rpc.system",
+ "Value": { "Type": "STRING", "Value": "apache_dubbo" }
+ },
+ {
+ "Key": "rpc.service",
+ "Value": { "Type": "STRING", "Value": "greet.GreetService" }
+ },
+ {
+ "Key": "rpc.method",
+ "Value": { "Type": "STRING", "Value": "Greet" }
+ }
+ ],
+ "Status": {
+ "Code": "Ok"
+ },
+ "Resource": [
+ {
+ "Key": "service.name",
+ "Value": { "Type": "STRING", "Value": "dubbo_otel_tracing_server" }
+ }
+ ]
+}
+```
+
+每次客户端调用都会在服务端输出一段类似的 Span。完整输出示例可参考 [stdout 示例
README](https://github.com/apache/dubbo-go-samples/blob/main/otel/tracing/stdout/README_zh.md)。
+
+## Jaeger exporter 运行方式
+
+### 启动 Jaeger
+
+示例使用 Docker 启动 Jaeger all-in-one:
+
+```bash
+docker run -d --name jaeger \
+ -e COLLECTOR_OTLP_ENABLED=true \
+ -p 16686:16686 \
+ -p 14268:14268 \
+ -p 4317:4317 \
+ -p 4318:4318 \
+ jaegertracing/all-in-one:latest
+```
+
+其中 `16686` 是 Jaeger UI 端口,`14268` 是 Jaeger collector HTTP 端口(示例 exporter
使用该端口上报)。
+
+### 获取并运行示例
+
+```bash
+cd dubbo-go-samples/otel/tracing/jaeger
+```
+
+第一个终端启动服务端:
+
+```bash
+go run ./go-server/cmd/main.go
+```
+
+第二个终端启动客户端:
+
+```bash
+go run ./go-client/cmd/main.go
+```
+
+示例中 exporter 相关配置如下:
+
+```go
+dubbo.WithTracing(
+ trace.WithEnabled(),
+ trace.WithJaegerExporter(),
+ trace.WithEndpoint("http://localhost:14268/api/traces"),
+ trace.WithW3cPropagator(),
+ trace.WithAlwaysMode(),
+)
+```
+
+如果 Jaeger 不在本机或修改了端口,需要同步修改 `WithEndpoint` 中的地址。
+
+### 查看 trace 结果
+
+打开浏览器访问 `http://localhost:16686`:
+
+1. 在 Service 下拉框中选择 `dubbo_otel_jaeger_server` 或 `dubbo_otel_jaeger_client`。
+2. 点击 Find Traces。
+3. 点击某条 trace 即可查看客户端、服务端的 Span 时间线。
+
+客户端示例在调用结束后会调用 `TracerProvider.Shutdown`,确保 Span 在进程退出前被刷新到 Jaeger。
+
+## OTLP HTTP exporter 运行方式
+
+`otel/tracing/otlp_http_exporter` 示例覆盖 dubbo、triple、jsonrpc 三种协议,并在服务端进程内启动一个
mock OTLP receiver(监听 `127.0.0.1:4318`),用于校验三种协议产生的 Span 是否正确上报。
+
+### 获取并运行示例
+
+```bash
+cd dubbo-go-samples/otel/tracing/otlp_http_exporter
+```
+
+第一个终端启动服务端:
+
+```bash
+go run ./go-server/cmd/main.go
+```
+
+第二个终端启动客户端:
+
+```bash
+go run ./go-client/cmd/main.go
+```
+
+客户端会分别通过 triple(20000 端口)、dubbo(20001 端口)和 jsonrpc(20002 端口)调用服务端。如果 6 个
Span(3 个客户端 Span + 3 个服务端 Span)都成功上报,服务端终端会输出:
+
+```text
+server count: 3, client count: 3
+```
+
+如果超时或数量不匹配,示例会直接 panic。
+
+示例中 exporter 相关配置如下:
+
+```go
+dubbo.WithTracing(
+ trace.WithEnabled(),
+ trace.WithOtlpHttpExporter(),
+ trace.WithEndpoint("127.0.0.1:4318"),
+ trace.WithInsecure(), // mock receiver 使用纯 HTTP
+ trace.WithW3cPropagator(),
+ trace.WithAlwaysMode(),
+)
+```
+
+在真实环境中,把 endpoint 改为 OpenTelemetry Collector 或兼容 OTLP 的观测后端即可,例如
`collector.example.com:4318`。纯 HTTP 上报时保留 `WithInsecure`;如果后端启用了 TLS,则去掉该选项。
+
+## 如何查看 trace 结果
+
+- **stdout exporter**:Span 以 JSON 打印在应用标准输出中。关注 `TraceID`、`SpanID`、`Parent` 和
`Attributes`,其中 `Attributes` 会携带 `rpc.system`、`rpc.service`、`rpc.method` 等
Dubbo RPC 信息。
+- **Jaeger exporter**:在 Jaeger UI 中按服务名查询,可看到完整调用链时间线。
+- **OTLP HTTP/gRPC exporter**:Span 上报到 Collector 后,由 Collector 转发到
Jaeger、Zipkin、Grafana Tempo 等后端,在这些后端的 UI 中查询。
+
+开启 tracing 后,调用链上服务端和客户端会自动共享 TraceID。排查时可以先用 stdout exporter 确认 Span
能正常生成,再切换到远程后端验证网络与 endpoint 配置。
+
+## 常见问题
+
+### 1. 开启了 tracing 却看不到 Span
+
+可能原因:
+
+- 忘记调用 `trace.WithEnabled()`。`enable` 默认是 `false`,只传入 `dubbo.WithTracing()`
不会开启功能。
+- 没有导入 `dubbo.apache.org/dubbo-go/v3/imports`,导致 exporter 实现未注册。
+- 使用默认 ratio 模式(采样率 0.5),部分请求没有被采样。本地调试建议改用 `trace.WithAlwaysMode()`,或把采样率调成
`trace.WithRatio(1.0)`。
+
+### 2. Jaeger 页面没有数据 / endpoint 配错
+
+- 确认 endpoint 与 Jaeger 实例一致。示例默认使用 `http://localhost:14268/api/traces`。
+- 确认 Docker 端口映射正常,`16686`(UI)和 `14268`(collector HTTP)都已暴露。
+- 修改 endpoint 后需要重启应用;同时观察应用日志中是否有 `failed to create ... exporter` 或连接失败错误。
+- Jaeger UI 中查询的服务名要与应用 `dubbo.WithName(...)` 配置一致,例如
`dubbo_otel_jaeger_server`、`dubbo_otel_jaeger_client`。
+
+### 3. OTLP HTTP 上报失败
+
+- OTLP HTTP endpoint 填 `host:port`,例如 `127.0.0.1:4318`,不要带 `http://` 前缀,也不要追加
`/v1/traces` 路径。
+- 后端是纯 HTTP 时必须设置 `trace.WithInsecure()`;否则 exporter 会按 HTTPS 建立连接,导致 TLS/握手失败。
+- 先启动 Collector 或后端,再启动 dubbo 应用。
+
+### 4. 客户端与服务端的 Span 没有串联成一条 trace
+
+- 客户端和服务端都需要开启 tracing。
+- 两端 propagator 需要一致:都使用 `trace.WithW3cPropagator()`,或都使用
`trace.WithB3Propagator()`,避免一边用 W3C、另一边用 B3 导致上下文无法传递。
+
+### 5. 使用 ratio 模式时看到的 trace 很少
+`sample-ratio` 默认是 0.5,且采样决策会沿调用链传递。调试阶段建议使用
`trace.WithAlwaysMode()`;需要控制成本时再切回 ratio 模式并调整比例。