This is an automated email from the ASF dual-hosted git repository. wankai pushed a commit to branch sw-traceql in repository https://gitbox.apache.org/repos/asf/skywalking.git
commit f0cb3e0adaf7542afc0a938d2bbcb48f2254b9d4 Author: wankai123 <[email protected]> AuthorDate: Fri Mar 27 09:56:56 2026 +0800 update docs --- docs/en/api/traceql-service.md | 151 +++++++++++++++++++-- .../traceql/converter/SkyWalkingOTLPConverter.java | 30 +--- .../traceql/converter/ZipkinOTLPConverter.java | 3 +- .../handler/SkyWalkingTraceQLApiHandler.java | 14 +- 4 files changed, 154 insertions(+), 44 deletions(-) diff --git a/docs/en/api/traceql-service.md b/docs/en/api/traceql-service.md index d0c6a1ee9d..e9d0c8fe0f 100644 --- a/docs/en/api/traceql-service.md +++ b/docs/en/api/traceql-service.md @@ -305,7 +305,7 @@ GET /zipkin/api/search?q={resource.service.name="frontend"}&start=1640000000&end { "key": "span.kind", "value": { - "stringValue": "SERVER" + "stringValue": "SPAN_KIND_SERVER" } } ] @@ -336,7 +336,7 @@ GET /zipkin/api/search?q={resource.service.name="frontend"}&start=1640000000&end { "key": "span.kind", "value": { - "stringValue": "CLIENT" + "stringValue": "SPAN_KIND_CLIENT" } } ] @@ -664,23 +664,152 @@ GET /zipkin/api/v2/traces/f321ebb45ffee8b5 **Response (Protobuf)**: When `Accept: application/protobuf` header is set, the response will be in OpenTelemetry Protobuf format. +## Zipkin Trace Conversion + +When using the Zipkin backend, the following conversions are applied: + +### Span Kind Mapping +Zipkin span kinds are mapped to OTLP span kinds: + +| Zipkin Span Kind | OTLP Span Kind | +|------------------|-------------------------| +| `CLIENT` | `SPAN_KIND_CLIENT` | +| `SERVER` | `SPAN_KIND_SERVER` | +| `PRODUCER` | `SPAN_KIND_PRODUCER` | +| `CONSUMER` | `SPAN_KIND_CONSUMER` | +| (absent) | `SPAN_KIND_UNSPECIFIED` | +| (other) | `SPAN_KIND_INTERNAL` | + +### Status Mapping +Zipkin tags are used to derive the OTLP span status in the following priority order: + +1. If the `otel.status_code` tag is present, it is parsed directly as the OTLP `StatusCode` (e.g. `STATUS_CODE_OK`, `STATUS_CODE_ERROR`). +2. Otherwise, if the `error` tag equals `true` (case-insensitive), the status is set to `STATUS_CODE_ERROR`. +3. If neither tag is present, the status defaults to `STATUS_CODE_UNSET`. + +The `otel.status_description` tag, if present, is used as the status message. + +### Endpoint Mapping +Zipkin endpoint fields are mapped to OTLP span attributes: + +| Zipkin Field | OTLP Attribute | +|------------------------------|---------------------------------| +| `localEndpoint.ipv4` | `net.host.ip` | +| `localEndpoint.ipv6` | `net.host.ip` | +| `localEndpoint.port` | `net.host.port` | +| `remoteEndpoint.serviceName` | `net.peer.name`, `peer.service` | +| `remoteEndpoint.ipv4` | `net.peer.ip` | +| `remoteEndpoint.ipv6` | `net.peer.ip` | +| `remoteEndpoint.port` | `net.peer.port` | + +### Annotations +Zipkin annotations are converted to OTLP span events. Each annotation becomes a `Span.Event` with `timeUnixNano` (converted from microseconds) and `name` set to the annotation value. + +### Instrumentation Scope +All spans within a Zipkin trace carry the instrumentation scope: +``` +name: "zipkin-tracer" +version: "0.1.0" +``` + +## SkyWalking Native Trace Conversion + +When using the SkyWalking native backend, the following conversions are applied: + +### Span Kind Mapping +SkyWalking span types are mapped to OTLP span kinds: + +| SkyWalking Span Type | OTLP Span Kind | +|----------------------|-------------------------| +| `Entry` | `SPAN_KIND_SERVER` | +| `Exit` | `SPAN_KIND_CLIENT` | +| `Local` | `SPAN_KIND_INTERNAL` | +| (absent) | `SPAN_KIND_UNSPECIFIED` | +| (other) | `SPAN_KIND_UNSPECIFIED` | + +### Status Mapping +The SkyWalking `isError` flag is mapped to OTLP span status: + +| SkyWalking `isError` | OTLP Status Code | OTLP Status Message | +|----------------------|-----------------------|---------------------| +| `true` | `STATUS_CODE_ERROR` | `"Error occurred"` | +| `false` | `STATUS_CODE_OK` | (empty) | + +### Span Logs +SkyWalking span logs are converted to OTLP span events. Each `LogEntity` produces one `Span.Event` with: +- `timeUnixNano` converted from the log timestamp (milliseconds → nanoseconds) +- `name` fixed as `"log"` +- `attributes` populated from `log.data` key-value pairs as string attributes + +### SpanAttachedEvents +SkyWalking [SpanAttachedEvents](../concepts-and-designs/event.md) are converted to OTLP span events. +Each `SpanAttachedEvent` produces one OTLP `Span.Event` with: +- `timeUnixNano` from `attachedEvent.startTime` +- `name` from `attachedEvent.event` +- `attributes` populated from both `attachedEvent.tags` (string key-value pairs) and `attachedEvent.summary` (numeric key-value pairs, serialised as strings) + +### Instrumentation Scope +All spans within a SkyWalking native trace carry the instrumentation scope: +``` +name: "skywalking-tracer" +version: "0.1.0" +``` + ## Configuration +### Enabling Backends +TraceQL Service supports two backends that can be independently enabled or disabled: + +| Configuration Field | Env Variable | Default | Description | +|----------------------------|------------------------------------------|---------|-------------------------------------| +| `enableDatasourceZipkin` | `SW_TRACEQL_ENABLE_DATASOURCE_ZIPKIN` | `false` | Enable Zipkin-compatible backend | +| `enableDatasourceSkywalking` | `SW_TRACEQL_ENABLE_DATASOURCE_SKYWALKING` | `false` | Enable SkyWalking native backend | + ### Context Path -TraceQL Service supports custom context paths for different trace backends: +Each backend is served under a separate context path: + +| Configuration Field | Env Variable | Default | Description | +|-------------------------------|-------------------------------------------|---------------|------------------------------------| +| `restContextPathZipkin` | `SW_TRACEQL_REST_CONTEXT_PATH_ZIPKIN` | `/zipkin` | Context path for Zipkin backend | +| `restContextPathSkywalking` | `SW_TRACEQL_REST_CONTEXT_PATH_SKYWALKING` | `/skywalking` | Context path for SkyWalking backend | -- **Zipkin Backend**: `/zipkin` - Queries Zipkin-compatible traces and converts to OTLP format -- **SkyWalking Native**: `/skywalking` - Queries SkyWalking native traces and converts to OTLP format +### Traces List Result Tags +The tags included in the search result spans can be configured. Only listed tags are returned in `Search Traces` responses. +`service.name` and `span.kind` are always included regardless of this setting. -Configuration in `application.yml`: +| Configuration Field | Env Variable | Default | +|----------------------------------|--------------------------------------------------|--------------------------------------------------------------------------------------| +| `zipkinTracesListResultTags` | `SW_TRACEQL_ZIPKIN_TRACES_LIST_RESULT_TAGS` | `http.method,error` | +| `skywalkingTracesListResultTags` | `SW_TRACEQL_SKYWALKING_TRACES_LIST_RESULT_TAGS` | `http.method,http.status_code,rpc.status_code,db.type,db.instance,mq.queue,mq.topic,mq.broker` | + +### Other Settings + +| Configuration Field | Env Variable | Default | Description | +|------------------------|---------------------------------|------------|----------------------------------------------------------------------------------------------------| +| `restHost` | `SW_TRACEQL_REST_HOST` | `0.0.0.0` | Bind host | +| `restPort` | `SW_TRACEQL_REST_PORT` | `3200` | Bind port | +| `restIdleTimeOut` | `SW_TRACEQL_REST_IDLE_TIMEOUT` | `30000` | HTTP idle timeout in milliseconds | +| `restAcceptQueueSize` | `SW_TRACEQL_REST_QUEUE_SIZE` | `0` | HTTP accept queue size (0 = unlimited) | +| `lookback` | `SW_TRACEQL_LOOKBACK` | `86400000` | Default look-back window in milliseconds when no `start` is given, the default end time is current | + +Full example in `application.yml`: ```yaml -tempo-query: - zipkinContextPath: /zipkin - skyWalkingContextPath: /skywalking +traceQL: + selector: ${SW_TRACEQL:default} + default: + restHost: ${SW_TRACEQL_REST_HOST:0.0.0.0} + restPort: ${SW_TRACEQL_REST_PORT:3200} + enableDatasourceZipkin: ${SW_TRACEQL_ENABLE_DATASOURCE_ZIPKIN:true} + enableDatasourceSkywalking: ${SW_TRACEQL_ENABLE_DATASOURCE_SKYWALKING:true} + restContextPathZipkin: ${SW_TRACEQL_REST_CONTEXT_PATH_ZIPKIN:/zipkin} + restContextPathSkywalking: ${SW_TRACEQL_REST_CONTEXT_PATH_SKYWALKING:/skywalking} + restIdleTimeOut: ${SW_TRACEQL_REST_IDLE_TIMEOUT:30000} + restAcceptQueueSize: ${SW_TRACEQL_REST_QUEUE_SIZE:0} + lookback: ${SW_TRACEQL_LOOKBACK:86400000} + zipkinTracesListResultTags: ${SW_TRACEQL_ZIPKIN_TRACES_LIST_RESULT_TAGS:http.method,error} + skywalkingTracesListResultTags: ${SW_TRACEQL_SKYWALKING_TRACES_LIST_RESULT_TAGS:http.method,http.status_code,rpc.status_code,db.type,db.instance,mq.queue,mq.topic,mq.broker} ``` -Both backends convert their respective trace formats to OpenTelemetry Protocol (OTLP) format for TraceQL compatibility. - ## Integration with Grafana ### Add Tempo Data Source diff --git a/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/SkyWalkingOTLPConverter.java b/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/SkyWalkingOTLPConverter.java index 9eae310145..c39c80c638 100644 --- a/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/SkyWalkingOTLPConverter.java +++ b/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/SkyWalkingOTLPConverter.java @@ -49,7 +49,6 @@ import static org.apache.skywalking.oap.query.traceql.handler.TraceQLApiHandler. /** * Converter for transforming SkyWalking trace data to OpenTelemetry Protocol (OTLP) format. - * Handles conversion of SkyWalking spans to both Protobuf and JSON representations. * <p> * Note: This class uses fully qualified names for some classes to avoid naming conflicts: * - org.apache.skywalking.oap.server.core.query.type.Trace (SkyWalking Trace) @@ -109,7 +108,7 @@ public class SkyWalkingOTLPConverter { .build()); // Convert each SkyWalking span to OTLP Span - // Note: SkyWalking traceId alread encode to hex string in query list, + // Note: SkyWalking traceId already encode to hex string in query list, // in order to make it compatible with Grafana Tempo, we keep it as hex string and // can directly convert it to bytes for OTLP traceId for (org.apache.skywalking.oap.server.core.query.type.Span swSpan : serviceSpans) { @@ -249,6 +248,7 @@ public class SkyWalkingOTLPConverter { for (org.apache.skywalking.oap.server.core.query.type.KeyNumericValue summary : attachedEvent.getSummary()) { eventBuilder.addAttributes(KeyValue.newBuilder() .setKey(summary.getKey()) + // convert numeric value to string for AnyValue, make it trans to JOSN format easier .setValue(AnyValue.newBuilder() .setStringValue(String.valueOf(summary.getValue())) .build()) @@ -380,7 +380,7 @@ public class SkyWalkingOTLPConverter { spanAttrMap.put(SERVICE_NAME, swSpan.getServiceCode()); } if (swSpan.getType() != null) { - spanAttrMap.put(SPAN_KIND, convertSpanType(swSpan.getType())); + spanAttrMap.put(SPAN_KIND, convertSpanKind(swSpan.getType()).name()); } for (org.apache.skywalking.oap.server.core.query.type.KeyValue tag : swSpan.getTags()) { spanAttrMap.put(tag.getKey(), tag.getValue()); @@ -402,32 +402,12 @@ public class SkyWalkingOTLPConverter { return span; } - /** - * Convert SkyWalking span type to OTLP span kind string. - */ - private static String convertSpanType(String type) { - if (StringUtil.isEmpty(type)) { - return "INTERNAL"; - } - - switch (type.toUpperCase()) { - case "ENTRY": - return "SERVER"; - case "EXIT": - return "CLIENT"; - case "LOCAL": - return "INTERNAL"; - default: - return "UNSPECIFIED"; - } - } - /** * Convert SkyWalking span type to OTLP span kind. */ private static io.opentelemetry.proto.trace.v1.Span.SpanKind convertSpanKind(String type) { if (StringUtil.isEmpty(type)) { - return io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_INTERNAL; + return io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_UNSPECIFIED; } switch (type.toUpperCase()) { @@ -438,7 +418,7 @@ public class SkyWalkingOTLPConverter { case "LOCAL": return io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_INTERNAL; default: - return io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_UNSPECIFIED; + return io.opentelemetry.proto.trace.v1.Span.SpanKind.SPAN_KIND_INTERNAL; } } diff --git a/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/ZipkinOTLPConverter.java b/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/ZipkinOTLPConverter.java index c26099b7c5..10e09580f0 100644 --- a/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/ZipkinOTLPConverter.java +++ b/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/converter/ZipkinOTLPConverter.java @@ -46,7 +46,6 @@ import static org.apache.skywalking.oap.query.traceql.handler.TraceQLApiHandler. /** * Converter for transforming Zipkin trace data to OpenTelemetry Protocol (OTLP) format. - * Handles conversion of Zipkin spans to both Protobuf and JSON representations. */ public class ZipkinOTLPConverter { @@ -404,7 +403,7 @@ public class ZipkinOTLPConverter { spanAttrMap.put(SERVICE_NAME, zipkinSpan.localServiceName()); } if (zipkinSpan.kind() != null) { - spanAttrMap.put(SPAN_KIND, zipkinSpan.kind().name()); + spanAttrMap.put(SPAN_KIND, convertZipkinKindToOtlp(zipkinSpan.kind()).name()); } if (zipkinSpan.tags() != null) { spanAttrMap.putAll(zipkinSpan.tags()); diff --git a/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/handler/SkyWalkingTraceQLApiHandler.java b/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/handler/SkyWalkingTraceQLApiHandler.java index 58942945fd..47a0216e63 100644 --- a/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/handler/SkyWalkingTraceQLApiHandler.java +++ b/oap-server/server-query-plugin/traceql-plugin/src/main/java/org/apache/skywalking/oap/query/traceql/handler/SkyWalkingTraceQLApiHandler.java @@ -241,14 +241,16 @@ public class SkyWalkingTraceQLApiHandler extends TraceQLApiHandler { Set<String> tagKeys = tagAutoCompleteQueryService.queryTagAutocompleteKeys(TagType.TRACE, duration); TagNamesV2Response response = new TagNamesV2Response(); - TagNamesV2Response.Scope scopeObj = new TagNamesV2Response.Scope(); - scopeObj.setName(SCOPE_SPAN); - scopeObj.setTags(new ArrayList<>(tagKeys)); - + TagNamesV2Response.Scope spanScope = new TagNamesV2Response.Scope(); + spanScope.setName(SCOPE_SPAN); + spanScope.setTags(new ArrayList<>(tagKeys)); + //for Grafana variables, tempo only supports label query in variables setting. + TagNamesV2Response.Scope resourceScope = new TagNamesV2Response.Scope(SCOPE_RESOURCE); + resourceScope.getTags().add(SERVICE); List<TagNamesV2Response.Scope> scopes = new ArrayList<>(); - scopes.add(scopeObj); + scopes.add(spanScope); response.setScopes(scopes); - + response.getScopes().add(resourceScope); return successResponse(response); }
