OpenTelemetry 샘플링 모범 사례¶
전체 트레이스 데이터는 관련 담당자가 비즈니스 문제를 신속하고 정확하게 발견하는 데 큰 도움이 됩니다. 하지만 기업 비즈니스에서 문제가 발생할 확률은 일반적으로 매우 낮으므로, 전체 트레이스 샘플링은 장단점이 있습니다.
장점
- 트레이스 데이터가 완전함
단점
- 리소스 낭비. 데이터가 완전하여 데이터 저장 리소스 비용이 크게 증가하고, 이상 트레이스 데이터 검색 비용이 증가함
전체 트레이스 데이터 수집 기반의 샘플링에서 OpenTelemetry는 두 가지 유형의 샘플러를 지원합니다.
확률 샘플러(probabilisticsamplerprocessor)
테일 샘플러(tailsamplingprocessor)
확률 샘플 프로세서¶
이름에서 알 수 있듯이 확률 샘플러는 일정 확률에 따라 샘플링합니다. 마찬가지로 OpenTelemetry는 두 가지 확률 샘플링을 지원합니다.
sampling.priorityOpenTracing에서 정의한 의미론적 규칙TraceId 해시
sampling.priority 의미론적 규칙이 TraceId 해시보다 우선합니다. 이름에서 알 수 있듯이 TraceId 해시 샘플링은 TraceId로 결정된 해시 값을 기반으로 합니다. TraceId 해시가 작동하려면 특정 계층의 모든 수집기(예: 동일한 로드 밸런서 뒤에 있는)가 동일한 hash_seed를 가져야 합니다. 또한 다른 수집기 계층에서 hash_seed를 다르게 사용하여 추가 샘플링 요구 사항을 지원할 수 있습니다. 구성 사양은 config.go를 참조하세요.
다음 구성 옵션을 수정할 수 있습니다.
hash_seed(기본값 없음): 해시 알고리즘 계산에 사용되는 정수입니다. 특정 계층의 모든 수집기(예: 동일한 로드 밸런서 뒤에 있는)는 동일한 hash_seed를 가져야 합니다.
여러 계층의 수집기를 사용하여 원하는 샘플링 비율을 구현하는 경우(예: 첫 번째 계층 10%, 두 번째 계층 10%, 전체 샘플링 비율 1%(10% x 10%)) 이는 중요합니다.
모든 계층이 동일한 시드를 사용하면 구성된 샘플링 비율과 관계없이 한 계층을 통과한 모든 데이터가 다음 계층도 통과합니다. 계층마다 다른 시드를 사용하면 각 계층의 샘플링 비율이 의도한 대로 작동합니다.
sampling_percentage(기본값 = 0): 트레이스를 샘플링할 백분율입니다. >= 100이면 모든 트레이스를 수집합니다.
확률 샘플러 구성
확률 샘플러 활성화
service:
extensions: [pprof, zpages, health_check]
pipelines:
traces:
receivers: [otlp]
processors: [batch,probabilistic_sampler]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
테일 샘플러¶
테일 샘플 프로세서는 정의된 정책 집합에 따라 트레이스를 샘플링합니다. 현재 이 프로세서는 단일 수집기 인스턴스에서만 작동합니다. 기술적으로 traceId 인식 로드 밸런싱을 사용하여 여러 수집기 인스턴스를 지원할 수 있지만 이 구성은 아직 테스트되지 않았습니다. 구성 사양은 config.go를 참조하세요.
다음 구성 옵션이 필요합니다.
policies(기본값 없음): 샘플링 결정을 내리는 데 사용되는 정책
현재 여러 정책이 지원됩니다. 여기에는 다음이 포함됩니다.
always_sample: 모든 트레이스 샘플링latency: 트레이스 지속 시간 기반 샘플링. 지속 시간은 가장 이른 시작 시간과 가장 늦은 종료 시간을 확인하여 결정되며, 두 시간 사이에 발생한 일은 고려하지 않습니다.numeric_attribute: 숫자 속성 기반 샘플링probabilistic: 일정 비율의 트레이스를 샘플링합니다.status_code: 상태 코드 기반 샘플링 (OK,ERROR또는UNSET). 많은 사람들이 이를 response body JSON의 code(현재 많은 프로젝트에서 이렇게 정의함)로 생각하지만, 실제로는 그렇지 않습니다.string_attribute: 문자열 속성 값 일치 기반 샘플링, 정확한 일치 및 정규식 값 일치 지원rate_limiting: 속도 기반 샘플링and: 여러 정책 기반 샘플링, AND 정책 생성composite: 위 샘플러 조합 기반 샘플링, 각 샘플러는 정렬 및 속도 할당을 가집니다. 속도 할당은 각 정책 순서에 스팬의 일정 비율을 할당합니다. 예를 들어 max_total_spans_per_second를 100으로 설정하면 rate_allocation을 다음과 같이 설정할 수 있습니다.- test-composite-policy-1 = max_total_spans_per_second의 50% = 50 spans_per_second
- test-composite-policy-2 = max_total_spans_per_second의 25% = 25 spans_per_second
- 남은 용량을 채우려면 always_sample을 정책 중 하나로 사용하세요.
다음 구성 옵션도 수정할 수 있습니다.
decision_wait(기본값 = 30초): 트레이스의 첫 번째 스팬부터 샘플링 결정을 내리기까지의 대기 시간num_traces(기본값 = 50000): 메모리에 보관되는 트레이스 수expected_new_traces_per_sec(기본값 = 0): 예상되는 새 트레이스 수(데이터 구조 할당에 도움이 됨)
예제:
processors:
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 10
policies: [
{
name: test-policy-1,
type: always_sample
},
{
name: test-policy-2,
type: latency,
latency: {threshold_ms: 5000}
},
{
name: test-policy-3,
type: numeric_attribute,
numeric_attribute: {key: key1, min_value: 50, max_value: 100}
},
{
name: test-policy-4,
type: probabilistic,
probabilistic: {sampling_percentage: 10}
},
{
name: test-policy-5,
type: status_code,
status_code: {status_codes: [ERROR, UNSET]}
},
{
name: test-policy-6,
type: string_attribute,
string_attribute: {key: key2, values: [value1, value2]}
},
{
name: test-policy-7,
type: string_attribute,
string_attribute: {key: key2, values: [value1, val*], enabled_regex_matching: true, cache_max_size: 10}
},
{
name: test-policy-8,
type: rate_limiting,
rate_limiting: {spans_per_second: 35}
},
{
name: test-policy-9,
type: string_attribute,
string_attribute: {key: http.url, values: [\/health, \/metrics], enabled_regex_matching: true, invert_match: true}
},
{
name: and-policy-1,
type: and,
and: {
and_sub_policy: [
{
name: test-and-policy-1,
type: numeric_attribute,
numeric_attribute: { key: key1, min_value: 50, max_value: 100 }
},
{
name: test-and-policy-2,
type: string_attribute,
string_attribute: { key: key2, values: [ value1, value2 ] }
},
]
}
},
{
name: composite-policy-1,
type: composite,
composite: {
max_total_spans_per_second: 1000,
policy_order: [test-composite-policy-1, test-composite-policy-2, test-composite-policy-3],
composite_sub_policy: [
{
name: test-composite-policy-1,
type: numeric_attribute,
numeric_attribute: {key: key1, min_value: 50, max_value: 100}
},
{
name: test-composite-policy-2,
type: string_attribute,
string_attribute: {key: key2, values: [value1, value2]}
},
{
name: test-composite-policy-3,
type: always_sample
}
],
rate_allocation: [
{
policy: test-composite-policy-1,
percent: 50
},
{
policy: test-composite-policy-2,
percent: 25
}
]
}
},
]
프로세서 사용에 대한 자세한 예제는 tail_sampling_config.yaml을 참조하세요.
확률 샘플 프로세서와 확률 정책을 사용하는 테일 샘플 프로세서 비교¶
확률 샘플 프로세서와 확률 테일 샘플 프로세서 정책은 매우 유사하게 작동합니다. 즉, 구성 가능한 샘플링 백분율을 기반으로 수신된 트레이스를 고정 비율로 샘플링합니다. 하지만 전체 처리 파이프라인에 따라 하나를 선택하는 것이 좋습니다.
경험상 확률 샘플링을 추가하려는 경우...
...아직 테일 샘플 프로세서를 사용하지 않는 경우: 확률 샘플 프로세서를 사용하세요. 확률 샘플 프로세서를 실행하는 것이 테일 샘플 프로세서보다 효율적입니다. 확률 샘플링 정책은 traceId를 기반으로 결정을 내리므로 더 많은 스팬이 도착할 때까지 기다려도 결정에 영향을 미치지 않습니다.
...이미 테일 샘플 프로세서를 사용하고 있는 경우: 확률 샘플링 정책을 추가하세요. 이미 테일 샘플 프로세서 실행 비용을 부담하고 있으므로 확률 정책을 추가하는 것은 무시할 수 있는 수준입니다. 또한 테일 샘플 프로세서에서 이 정책을 사용하면 다른 정책에서 샘플링한 트레이스가 삭제되지 않습니다.
데모¶
이 데모는 주로 OpenTelemetry 데이터를 Guance로 전송하는 방법을 보여줍니다.
사전 준비¶
-
소스 코드 다운로드: https://github.com/lrwh/observable-demo/tree/main/opentelemetry-collector-sampling
-
DataKit이 설치되어 있는지 확인하세요.
| 서비스 이름 | 포트 | 설명 |
|---|---|---|
| otel-collector | otel/opentelemetry-collector-contrib:0.69.0 | |
| springboot_server | 8080:8080 | opentelemetry-agent 버전 1.21.0, 소스 코드 주소: https://github.com/lrwh/observable-demo/tree/main/springboot-server |
- Datakit에서 OpenTelemetry 수집을 활성화합니다.
서비스 시작¶
다음 예제는 주로 테일 샘플링 정책을 테스트 시나리오로 사용합니다.
테일 샘플러 구성
processors:
# 테일 샘플러
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 100
policies:
[
{
name: policy-1,
type: status_code,
status_code: {status_codes: [ERROR]}
},
{
name: policy-2,
type: probabilistic,
probabilistic: {sampling_percentage: 20}
}
]
위 규칙은 OR 관계입니다. policy-1 또는 policy-2 중 하나라도 성립하면 샘플링이 수행됩니다.
테일 샘플러 활성화
service:
extensions: [pprof, zpages, health_check]
pipelines:
traces:
receivers: [otlp]
processors: [batch,tail_sampling]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
probabilistic 사용¶
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 100
policies:
[
{
name: policy-2,
type: probabilistic,
probabilistic: {sampling_percentage: 20}
}
]
- 서비스 API
gateway를 5회 호출하며, 매번 정상적으로 반환됩니다.
curl http://localhost:8080/gateway
- Guance로 이동하여 트레이스 정보를 확인합니다. 샘플링 규칙에 따라 최대 한 번의 트레이스 데이터가 샘플링됩니다.
status_code 사용¶
processors:
# 테일 샘플러
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 100
policies:
[
{
name: policy-1,
type: status_code,
status_code: {status_codes: [ERROR]}
}
]
- 클라이언트 시작 설정
curl http://localhost:8080/setClient?c=true
현재 데모에서는 클라이언트 서비스가 시작되지 않았으므로 이후 gateway 인터페이스 호출 시 예외가 발생합니다.
-
gateway서비스를 5회 호출하면{"msg":"client 调用失败","code":500}이 반환됩니다. -
Guance로 이동하여 트레이스 정보를 확인합니다. 샘플링 규칙에 따라 예외가 발생하면 예외가 모두 수집됩니다.
span_count 사용¶
스팬 수가 2개 이하이면 보고하지 않습니다. 구성은 다음과 같습니다.
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 100
policies:
[
{
name: p2,
type: span_count,
span_count: {min_spans: 3 }
}
]
string_attribute 사용¶
시나리오: GET 요청의 트레이스만 수집
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 100
policies:
[
{
name: policy-string,
type: string_attribute,
string_attribute: {key: http.method, values: [ GET ] }
}
]
string_attribute가 작동하지 않나요?
네, 맞습니다. string_attribute가 항상 100% 작동하는 것은 아닙니다. http.method를 예로 들어 보겠습니다. GET 요청을 매칭한다고 가정할 때, 이 GET 요청이 다시 POST 요청을 호출하는 트레이스인 경우 전체 트레이스에는 GET과 POST가 모두 포함되어 충돌이 발생합니다. GET을 매칭할 수 있으므로 매칭 요구 사항을 충족하므로 트레이스에 POST가 있다고 해서 필터링되지는 않습니다.
and 사용¶
and: and 조건을 충족하는 경우에만 샘플링하여 보고하고, 그 외의 경우는 폐기합니다.
시나리오: GET 요청을 보고하고 샘플링 비율 20%로 샘플링하며, 그 외의 경우는 폐기합니다.
tail_sampling:
decision_wait: 10s
num_traces: 100
expected_new_traces_per_sec: 100
policies:
[
{
name: and-policy-1,
type: and,
and: {
and_sub_policy:
[
{
name: test-and-policy-2,
type: string_attribute,
string_attribute: { key: http.method, values: [ GET ] }
},
{
name: policy-2,
type: probabilistic,
probabilistic: {sampling_percentage: 20}
}
]
}
}
]
샘플링 작성 형식 참고 사항¶
샘플링 형식이 올바르지 않으면 샘플링이 실패할 수 있으므로 각 단어, 기호, 값 뒤에 공백을 추가하는 것이 좋습니다.