트레이스 컨텍스트 전파 (Trace Context Propagation)
분산 애플리케이션의 한 부분에서 다른 부분으로 Trace ID, Span ID, 샘플링 결정 같은 트레이싱 정보를 전달하는 메커니즘이에요. 요청 안의 모든 트레이스(및 추가 텔레메트리)를 서로 연관 지을 수 있게 해주죠. 자동 계측을 활성화하면 Datadog SDK가 트레이스 컨텍스트 전파를 자동으로 처리해요.
출처: 문서
본문
트레이스 컨텍스트 전파는 분산 애플리케이션의 한 부분에서 다른 부분으로 Trace ID, Span ID, 샘플링 결정 같은 트레이싱 정보를 전달하는 메커니즘이에요. 이 덕분에 요청 안의 모든 트레이스(및 추가 텔레메트리)를 서로 연관 지을 수 있어요. 자동 계측이 활성화되면 Datadog SDK가 트레이스 컨텍스트 전파를 자동으로 처리해요.
기본적으로 Datadog SDK는 다음 형식을 사용해 분산 트레이싱 헤더를 추출하고 주입해요.
- Datadog (헤더 추출 시 우선순위가 높아요)
- W3C Trace Context
- Baggage
이 기본 구성은 구버전 Datadog SDK·제품과의 호환성을 최대화하면서, OpenTelemetry 같은 다른 분산 트레이싱 시스템과의 상호 운용도 허용해요.
트레이스 컨텍스트 전파 사용자 지정 (Customize trace context propagation)
다음 경우에는 트레이스 컨텍스트 전파 구성을 변경해야 할 수 있어요.
- 분산 트레이싱 정보를 다른 지원 형식으로 통신하는 경우
- 분산 트레이싱 헤더의 추출이나 주입을 막아야 하는 경우
분산 트레이싱 헤더를 읽고 쓰는 형식을 구성하려면 다음 환경 변수를 사용하세요. 언어별 구성 값은 Language support 섹션을 참고하세요.
DD_TRACE_PROPAGATION_STYLE
추출과 주입에 사용할 트레이스 컨텍스트 전파 형식을 쉼표로 구분한 목록으로 지정해요. 추출 전용 또는 주입 전용 구성으로 재정의될 수 있어요. 기본값: datadog,tracecontext,baggage 참고: 트레이스 컨텍스트 형식이 여러 개면 추출은 지정된 순서대로 진행돼요(예: datadog,tracecontext는 Datadog 헤더를 먼저 확인). 첫 번째 유효한 컨텍스트가 트레이스를 이어가고, 추가 유효한 컨텍스트는 span link가 돼요. baggage가 포함되면 기존 컨텍스트에 baggage로 추가돼요.
OTEL_PROPAGATORS
추출과 주입 모두에 사용할 트레이스 컨텍스트 전파 형식을 지정해요(쉼표로 구분). 우선순위가 가장 낮아서 다른 Datadog 트레이스 컨텍스트 전파 환경 변수가 설정되어 있으면 무시돼요. 참고: 이 구성은 애플리케이션을 OpenTelemetry SDK에서 Datadog SDK로 마이그레이션할 때만 사용하세요. 이 구성과 다른 OpenTelemetry 환경 변수에 대한 자세한 내용은 Datadog SDK와 함께 OpenTelemetry 환경 변수 사용하기를 참고하세요.
DD_TRACE_PROPAGATION_BEHAVIOR_EXTRACT
서비스 수준에서 들어오는 분산 트레이싱 헤더를 어떻게 처리할지 지정해요. 허용 값은 다음과 같아요. continue: 들어오는 분산 트레이싱 헤더가 유효한 트레이스 컨텍스트를 나타내면 SDK가 분산 트레이스를 계속 이어가요. restart: SDK가 항상 새 트레이스를 시작해요. 들어오는 분산 트레이싱 헤더가 유효한 트레이스 컨텍스트를 나타내면, 서비스 진입 스팬에서 해당 트레이스 컨텍스트가 span link로 표현돼요(continue 구성의 부모 스팬 대신). ignore: SDK가 항상 새 트레이스를 시작하고 들어오는 모든 분산 트레이싱 헤더를 무시해요. 기본값: continue
고급 구성 (Advanced configuration)
대부분 서비스는 같은 형식으로 트레이스 컨텍스트 헤더를 주고받아요. 하지만 한 형식으로 헤더를 받고 다른 형식으로 보내야 하는 서비스라면 다음 구성을 사용하세요.
DD_TRACE_PROPAGATION_STYLE_EXTRACT
추출 전용 트레이스 컨텍스트 전파 형식을 쉼표로 구분해 지정해요. 추출 전파자 구성에 가장 높은 우선순위를 가져요.
DD_TRACE_PROPAGATION_STYLE_INJECT
주입 전용 트레이스 컨텍스트 전파 형식을 쉼표로 구분해 지정해요. 주입 전파자 구성에 가장 높은 우선순위를 가져요.
지원 형식 (Supported formats)
Datadog SDK가 지원하는 트레이스 컨텍스트 형식은 다음과 같아요.
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| B3 Single | 언어 의존 값 |
| B3 Multi | b3multi |
| Baggage | baggage* |
| 없음 (None) | none |
* 참고: baggage는 Rust에서는 지원되지 않아요.
언어 지원 (Language support)
Java
지원 형식
Datadog Java SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| B3 Single | b3 single header |
b3single |
|
| B3 Multi | b3multi |
b3 (더 이상 사용되지 않음) |
|
| Baggage | baggage |
| AWS X-Ray | xray |
| 없음 (None) | none |
추가 구성
환경 변수 구성 외에도 System Property 구성으로 전파자를 업데이트할 수 있어요.
-Ddd.trace.propagation.style=datadog,b3multi-Dotel.propagators=datadog,b3multi-Ddd.trace.propagation.style.inject=datadog,b3multi-Ddd.trace.propagation.style.extract=datadog,b3multi
Python
지원 형식
Datadog Python SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
| B3 Single | b3 |
b3 single header (v3.0에서 제거) |
|
| B3 Multi | b3multi |
| 없음 (None) | none |
Ruby
지원 형식
Datadog Ruby SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
| B3 Single | b3 |
| B3 Multi | b3multi |
| 없음 (None) | none |
추가 구성
환경 변수 구성 외에도 코드에서 Datadog.configure를 사용해 전파자를 업데이트할 수 있어요.
Datadog.configure do |c|
# 추출해야 하는 헤더 형식 목록
c.tracing.propagation_extract_style = [ 'tracecontext', 'datadog', 'b3' ]
# 주입해야 하는 헤더 형식 목록
c.tracing.propagation_inject_style = [ 'tracecontext', 'datadog' ]
end
Go
지원 형식
Datadog Go SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
| B3 Single | B3 single header |
| B3 Multi | b3multi |
b3 (더 이상 사용되지 않음) |
|
| 없음 (None) | none |
Node.js
지원 형식
Datadog Node.js SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
| B3 Single | B3 single header |
| B3 Multi | b3multi |
B3 (더 이상 사용되지 않음) |
|
| 없음 (None) | none |
PHP
지원 형식
Datadog PHP SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
| B3 Single | B3 single header |
| B3 Multi | b3multi |
B3 (더 이상 사용되지 않음) |
|
| 없음 (None) | none |
추가 사용 사례
다음 사용 사례는 Datadog PHP SDK에만 해당돼요.
PHP 스크립트 시작 시 분산 트레이싱
새 PHP 스크립트가 시작되면 Datadog SDK가 분산 트레이싱용 Datadog 헤더 존재 여부를 자동으로 확인해요.
x-datadog-trace-id(환경 변수:HTTP_X_DATADOG_TRACE_ID)x-datadog-parent-id(환경 변수:HTTP_X_DATADOG_PARENT_ID)x-datadog-origin(환경 변수:HTTP_X_DATADOG_ORIGIN)x-datadog-tags(환경 변수:HTTP_X_DATADOG_TAGS)
분산 트레이싱 컨텍스트 수동 설정
CLI 스크립트에서 새 트레이스나 기존 트레이스에 트레이싱 정보를 수동으로 설정하려면 DDTrace\set_distributed_tracing_context(string $trace_id, string $parent_id, ?string $origin = null, ?array $tags = null) 함수를 사용하세요.
<?php
function processIncomingQueueMessage($message) {
}
\DDTrace\trace_function(
'processIncomingQueueMessage',
function(\DDTrace\SpanData $span, $args) {
$message = $args[0];
\DDTrace\set_distributed_tracing_context($message->trace_id, $message->parent_id);
}
);
버전 0.87.0 이후에는 원시 헤더를 사용할 수 있다면 DDTrace\consume_distributed_tracing_headers(array|callable $headersOrCallback) 함수를 사용하세요. 참고: 헤더 이름은 소문자여야 해요.
$headers = [
"x-datadog-trace-id" => "1234567890",
"x-datadog-parent-id" => "987654321",
];
\DDTrace\consume_distributed_tracing_headers($headers);
트레이스 컨텍스트를 헤더로 직접 추출하려면 DDTrace\generate_distributed_tracing_headers(?array $inject = null): array 함수를 사용하세요.
$headers = DDTrace\generate_distributed_tracing_headers();
// 헤더를 어딘가 저장하고, 아웃바운드 요청에 주입하세요, ...
// 이 $headers는 다른 프로세스에서 \DDTrace\consume_distributed_tracing_headers로 다시 읽을 수도 있어요.
이 함수의 선택적 인자는 주입 스타일 이름 배열을 받아요. 기본값은 구성된 주입 스타일이에요.
RabbitMQ
PHP SDK는 php-amqplib/php-amqplib 라이브러리(0.87.0+ 버전)의 자동 트레이싱을 지원해요. 하지만 어떤 경우에는 분산 트레이스가 끊길 수 있어요. 예를 들어 기존 트레이스 밖에서 basic_get 메서드로 분산 큐에서 메시지를 읽을 때, basic_get 호출과 그에 해당하는 메시지 처리 주위에 커스텀 트레이스를 추가해야 해요.
// 주변 트레이스 만들기
$newTrace = \DDTrace\start_trace_span();
$newTrace->name = 'basic_get.process';
$newTrace->service = 'amqp';
// basic_get 호출 + 메시지 처리
$msg = $channel->basic_get($queue);
if ($msg) {
$messageProcessing($msg);
}
// 완료되면 스팬을 닫아요
\DDTrace\close_span();
소비·처리 로직 주위에 이 트레이스를 만들면 분산 큐의 관측 가능성이 보장돼요.
C++
지원 형식
Datadog C++ SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
| B3 Multi | b3 |
b3multi |
|
| 없음 (None) | none |
추가 구성
환경 변수 구성 외에도 코드에서 전파자를 업데이트할 수 있어요.
#include <datadog/tracer_config.h>
#include <datadog/propagation_style.h>
namespace dd = datadog::tracing;
int main() {
dd::TracerConfig config;
config.service = "my-service";
// `injection_styles`는 트레이스 컨텍스트를 주입(전송)할 때
// 트레이스 전파가 호환되는 트레이싱 시스템을 나타내요.
// `injection_styles`로 지정된 모든 스타일이 주입에 사용돼요.
// `injection_styles`는 `DD_TRACE_PROPAGATION_STYLE_INJECT`와
// `DD_TRACE_PROPAGATION_STYLE` 환경 변수로 재정의돼요.
config.injection_styles = {dd::PropagationStyle::DATADOG, dd::PropagationStyle::B3};
// `extraction_styles`는 트레이스 컨텍스트를 추출(수신)할 때
// 트레이스 전파가 호환되는 트레이싱 시스템을 나타내요.
// 추출 스타일은 `extraction_styles`에 나타난 순서대로 적용돼요.
// 트레이스 컨텍스트를 생성하거나 오류를 생성하는 첫 번째 스타일이
// 추출 결과를 결정해요.
// `extraction_styles`는 `DD_TRACE_PROPAGATION_STYLE_EXTRACT`와
// `DD_TRACE_PROPAGATION_STYLE` 환경 변수로 재정의돼요.
config.extraction_styles = {dd::PropagationStyle::W3C};
...
}
추가 사용 사례
전파된 컨텍스트 수동 추출
전파 컨텍스트를 추출하려면 커스텀 DictReader 인터페이스를 구현하고 Tracer::extract_span 또는 Tracer::extract_or_create_span을 호출하세요.
HTTP 헤더에서 전파 컨텍스트를 추출하는 예시는 다음과 같아요.
#include <datadog/dict_reader.h>
#include <datadog/optional.h>
#include <datadog/string_view.h>
#include <unordered_map>
namespace dd = datadog::tracing;
class HTTPHeadersReader : public datadog::tracing::DictReader {
std::unordered_map<dd::StringView, dd::StringView> headers_;
public:
HTTPHeadersReader(std::unordered_map<dd::StringView, dd::StringView> headers)
: headers_(std::move(headers)) {}
~HTTPHeadersReader() override = default;
// 지정된 `key`의 값을 반환하거나, `key`에 값이 없으면 `nullopt`를 반환해요.
dd::Optional<dd::StringView> lookup(dd::StringView key) const override {
auto found = headers_.find(key);
if (found == headers_.cend()) return dd::nullopt;
return found->second;
}
// 이 객체의 각 키/값 쌍마다 지정된 `visitor`를 한 번씩 호출해요.
void visit(
const std::function<void(dd::StringView key, dd::StringView value)>& visitor)
const override {
for (const auto& [key, value] : headers_) {
visitor(key, value);
}
};
};
// 사용 예시:
void handle_http_request(const Request& request, datadog::tracing::Tracer& tracer) {
HTTPHeadersReader reader{request.headers};
auto maybe_span = tracer.extract_span(reader);
..
}
분산 트레이싱용 컨텍스트 수동 주입
전파 컨텍스트를 주입하려면 DictWriter 인터페이스를 구현하고 스팬 인스턴스에서 Span::inject를 호출하세요.
#include <datadog/dict_writer.h>
#include <datadog/string_view.h>
#include <string>
#include <unordered_map>
using namespace dd = datadog::tracing;
class HTTPHeaderWriter : public dd::DictWriter {
std::unordered_map<std::string, std::string>& headers_;
public:
explicit HTTPHeaderWriter(std::unordered_map<std::string, std::string>& headers) : headers_(headers) {}
~HTTPHeaderWriter() override = default;
void set(dd::StringView key, dd::StringView value) override {
headers_.emplace(key, value);
}
};
// 사용 예시:
void handle_http_request(const Request& request, dd::Tracer& tracer) {
auto span = tracer.create_span();
HTTPHeaderWriter writer(request.headers);
span.inject(writer);
// `request.headers`에 이제 스팬 전파에 필요한 헤더가 채워져 있어요.
..
}
.NET
지원 형식
Datadog .NET SDK는 다음 트레이스 컨텍스트 형식을 지원해요(더 이상 사용되지 않는 구성 값 포함).
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
| Baggage | baggage |
W3C (더 이상 사용되지 않음) |
|
| B3 Single | B3 single header |
B3SingleHeader (더 이상 사용되지 않음) |
|
| B3 Multi | b3multi |
B3 (더 이상 사용되지 않음) |
|
| 없음 (None) | none |
추가 사용 사례
이전 구성 기본값
- [2.48.0][6] 버전부터 기본 전파 스타일은
datadog, tracecontext예요. 즉 Datadog 헤더를 먼저 사용하고 W3C Trace Context를 그다음에 사용해요. - 2.48.0 이전에는 추출·주입 전파 모두 순서가
tracecontext, Datadog였어요. - [2.22.0][7] 버전 이전에는
Datadog주입 스타일만 활성화되어 있었어요. - [2.42.0][8] 버전부터, 추출기가 여러 개 지정되면
DD_TRACE_PROPAGATION_EXTRACT_FIRST=true구성으로 첫 번째 유효한tracecontext를 감지하자마자 컨텍스트 추출을 즉시 중단할지 지정해요. 기본값은false예요.
메시지 큐와 함께하는 분산 트레이싱
대부분의 경우 헤더 추출·주입은 자동이에요. 하지만 분산 트레이스가 끊길 수 있는 알려진 경우가 있어요. 예를 들어 분산 큐에서 메시지를 읽을 때 일부 라이브러리가 스팬 컨텍스트를 잃을 수 있어요. Kafka 메시지를 소비할 때 DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED를 false로 설정한 경우에도 발생해요. 이런 경우 다음 코드로 커스텀 트레이스를 추가할 수 있어요.
var spanContextExtractor = new SpanContextExtractor();
var parentContext = spanContextExtractor.Extract(headers, (headers, key) => GetHeaderValues(headers, key));
var spanCreationSettings = new SpanCreationSettings() { Parent = parentContext };
using var scope = Tracer.Instance.StartActive("operation", spanCreationSettings);
GetHeaderValues 메서드를 제공하세요. 이 메서드의 구현 방식은 SpanContext를 담는 구조에 따라 달라져요.
예시는 다음과 같아요.
// Confluent.Kafka
IEnumerable<string> GetHeaderValues(Headers headers, string name)
{
if (headers.TryGetLastBytes(name, out var bytes))
{
try
{
return new[] { Encoding.UTF8.GetString(bytes) };
}
catch (Exception)
{
// 무시됨
}
}
return Enumerable.Empty<string>();
}
// RabbitMQ
IEnumerable<string> GetHeaderValues(IDictionary<string, object> headers, string name)
{
if (headers.TryGetValue(name, out object value) && value is byte[] bytes)
{
return new[] { Encoding.UTF8.GetString(bytes) };
}
return Enumerable.Empty<string>();
}
// SQS
public static IEnumerable<string> GetHeaderValues(IDictionary<string, MessageAttributeValue> headers, string name)
{
// SQS에는 메시지 속성 헤더가 최대 10개까지만 있어서,
// Datadog 헤더는 다음 속성을 가진 하나의 헤더로 결합돼요.
// - 키: "_datadog"
// - 값: MessageAttributeValue 객체
// - DataType: "String"
// - StringValue: <키-값 헤더가 담긴 JSON 맵>
if (headers.TryGetValue("_datadog", out var messageAttributeValue)
&& messageAttributeValue.StringValue is string jsonString)
{
var datadogDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonString);
if (datadogDictionary.TryGetValue(name, out string value))
{
return new[] { value };
}
}
return Enumerable.Empty<string>();
}
SpanContextExtractor API로 Kafka 소비자 스팬을 트레이싱할 때는 DD_TRACE_KAFKA_CREATE_CONSUMER_SCOPE_ENABLED를 false로 설정하세요. 이렇게 하면 메시지를 토픽에서 소비한 직후 소비자 스팬이 제대로 닫히고 partition, offset 같은 메타데이터가 올바르게 기록돼요. SpanContextExtractor API로 Kafka 메시지에서 만든 스팬은 프로듀서 스팬의 자식이자 소비자 스팬의 형제예요.
자동 계측되지 않는 라이브러리(예: WCF 클라이언트)라면 트레이스 컨텍스트를 수동으로 전파해야 할 수 있어요. 이때 SpanContextInjection API를 사용할 수 있어요. this가 WCF 클라이언트인 예시는 다음과 같아요.
using (OperationContextScope ocs = new OperationContextScope(this.InnerChannel))
{
var spanContextInjector = new SpanContextInjector();
spanContextInjector.Inject(OperationContext.Current.OutgoingMessageHeaders, SetHeaderValues, Tracer.Instance.ActiveScope?.Span?.Context);
}
void SetHeaderValues(MessageHeaders headers, string name, string value)
{
MessageHeader header = MessageHeader.CreateHeader(name, "datadog", value);
headers.Add(header);
}
Rust
Datadog Rust SDK는 미리 보기(Preview) 상태예요.
Datadog Rust SDK는 OpenTelemetry(OTel) SDK 기반으로 만들어져요.
트레이스 컨텍스트 전파는 OTel SDK가 처리하며, datadog-opentelemetry가 datadog와 tracecontext(W3C) 형식을 모두 지원하도록 구성해요.
지원 형식
| 형식 | 구성 값 |
|---|---|
| Datadog | datadog |
| W3C Trace Context | tracecontext |
구성
DD_TRACE_PROPAGATION_STYLE 환경 변수를 설정해 사용할 전파 형식을 제어할 수 있어요. 쉼표로 구분된 목록을 제공할 수 있어요.
예를 들어:
# W3C와 Datadog를 모두 지원하려면
export DD_TRACE_PROPAGATION_STYLE="tracecontext,datadog"
수동 주입과 추출
Rust에는 자동 계측이 없으므로 원격 호출(예: HTTP 요청)을 할 때나 받을 때 컨텍스트를 수동으로 전파해야 해요.
HeaderExtractor는 들어오는 요청 헤더에서 부모 컨텍스트를 추출해요.HeaderInjector는 현재 컨텍스트를 아웃바운드 요청 헤더에 주입해요.
먼저 Cargo.toml에 opentelemetry-http를 추가하세요.
[dependencies]
# HeaderInjector와 HeaderExtractor를 제공해요
# 이 버전이 다른 opentelemetry 의존성과 일치하는지 확인하세요
opentelemetry-http = "0.31"
# 아래 Hyper 예시에만 필요해요
http-body-util = "0.1"
opentelemetry-http는 나머지 OpenTelemetry 의존성과 같은 크레이트 버전을 사용해서 버전 충돌을 피하세요.
컨텍스트 주입 (클라이언트 측)
HTTP 요청을 만들 때(hyper 1.0 예시) HeaderInjector를 사용해 현재 스팬 컨텍스트를 요청 헤더에 주입하세요.
use opentelemetry::{global, Context};
use opentelemetry_http::HeaderInjector;
use hyper::Request;
use http_body_util::Empty;
use hyper::body::Bytes;
// HYPER 예시
fn build_outbound_request(url: &str) -> http::Result<Request<Empty<Bytes>>> {
let cx = Context::current();
// 요청을 만들고 헤더를 즉시 주입해요
let mut builder = Request::builder().method("GET").uri(url);
global::get_text_map_propagator(|prop| {
prop.inject_context(&cx, &mut HeaderInjector(builder.headers_mut().unwrap()))
});
builder.body(Empty::<Bytes>::new())
}
컨텍스트 추출 (서버 측)
HTTP 요청을 받을 때 HeaderExtractor를 사용해 헤더에서 트레이스 컨텍스트를 추출해요.
Tokio 같은 비동기 런타임을 사용할 때는 추출한 컨텍스트를 future에 연결해서 async 작업 체인을 통해 올바르게 전파되도록 해야 해요.
use opentelemetry::{
global,
trace::{Span, FutureExt, SpanKind, Tracer},
Context,
};
use opentelemetry_http::HeaderExtractor;
use hyper::{Request, Response};
use hyper::body::Incoming;
use http_body_util::Full;
use hyper::body::Bytes;
// hyper 요청에서 컨텍스트를 추출하는 유틸리티 함수
fn extract_context(req: &Request<Incoming>) -> Context {
global::get_text_map_propagator(|propagator| {
propagator.extract(&HeaderExtractor(req.headers()))
})
}
// 실제 요청 처리 로직을 위한 자리 표시자
async fn your_handler_logic() -> Response<Full<Bytes>> {
// ... 로직 ...
Response::new(Full::new(Bytes::from("Hello, World!")))
}
// HYPER 예시
async fn hyper_handler(req: Request<Incoming>) -> Response<Full<Bytes>> {
// 들어오는 헤더에서 부모 컨텍스트를 추출해요
let parent_cx = extract_context(&req);
let tracer = global::tracer("my-server-component");
// 추출한 컨텍스트의 자식으로 서버 스팬을 시작해요
let server_span = tracer
.span_builder("http.server.request")
.with_kind(SpanKind::Server)
.start_with_context(tracer, &parent_cx);
// 새 서버 스팬이 담긴 새 컨텍스트를 만들어요
// 비동기 전파에 매우 중요해요
let cx = parent_cx.with_span(server_span);
// .with_context(cx)를 사용해 새 컨텍스트를 future에 연결해요
// 이렇게 하면 핸들러가 실행되는 동안 스팬이 활성 상태가 돼요
your_handler_logic().with_context(cx).await
}
커스텀 헤더 형식 (Custom header formats)
Datadog 형식
Datadog SDK가 추출이나 주입(또는 둘 다)에 Datadog 형식으로 구성되면, Datadog SDK는 다음 요청 헤더와 상호 작용해요.
x-datadog-trace-id
128비트 trace-id의 하위 64비트를 10진수 형식으로 지정해요.
x-datadog-parent-id
현재 스팬의 64비트 span-id를 10진수 형식으로 지정해요.
x-datadog-origin
Real User Monitoring이나 Synthetic Monitoring처럼 트레이스를 시작한 Datadog 제품을 지정해요. 이 헤더가 있으면 값은 rum, synthetics, synthetics-browser 중 하나여야 해요.
x-datadog-sampling-priority
표현된 스팬에 대해 내려진 샘플링 결정을 10진수 형식의 정수로 지정해요.
x-datadog-tags
128비트 trace-id의 상위 64비트(16진수 형식)를 포함한 추가 Datadog 트레이스 상태 정보를 지정해요.
없음 형식 (None format)
Datadog SDK가 추출이나 주입(또는 둘 다)에 없음(None) 형식으로 구성되면, Datadog SDK는 요청 헤더와 상호 작용하지 않아요. 즉 해당 컨텍스트 전파 작업이 아무것도 하지 않아요.
Baggage
기본적으로 Baggage는 OpenTelemetry의 W3C 호환 헤더를 사용해 분산 요청을 통해 자동으로 전파돼요. Baggage를 비활성화하려면 DD_TRACE_PROPAGATION_STYLE을 datadog,tracecontext로 설정하세요.
Baggage를 스팬 태그로 추가하기
기본적으로 user.id,session.id,account.id baggage 키가 스팬 태그로 추가돼요. 이 구성을 사용자 지정하려면 컨텍스트 전파 구성을 참고하세요. 지정된 baggage 키는 자동으로 스팬 태그 baggage.<key>(예: baggage.user.id)로 추가돼요.
Baggage를 스팬 태그로 지원하는 것은 다음 릴리스에서 도입됐어요.
| 언어 | 최소 SDK 버전 |
|---|---|
| Java | 1.52.0 |
| Python | 3.7.0 |
| Ruby | 2.20.0 |
| Go | 2.2.2 |
| .NET | 3.23.0 |
| Node | 5.54.0 |
| PHP | 1.10.0 |
| C++/Proxy | 1.9.0 (Nginx). 다른 프록시는 미지원. |
| Rust | 미지원 |