Skip to content

Metrics, Logs 및 Traces 필터링

전체 문서 PDF

Telemetry 필터링은 반복적으로 발생하지만 분석에는 거의 사용하지 않는 metric, log, span을 Monithub로 보내기 전에 제외하는 기능입니다. Kubernetes 클러스터 안의 Monithub Collector gateway에서 필터를 적용하므로, 조건에 맞는 데이터는 중앙 Collector와 저장소까지 전송되지 않습니다.

대표적으로 다음 데이터를 줄일 때 사용합니다.

  • 상태 확인용 endpoint에서 반복되는 정상 access log
  • 개발 환경이나 테스트 workload에서 생성되는 불필요한 log
  • 사용하지 않는 runtime metric 전체
  • 하나의 metric 안에서 분석 가치가 낮은 특정 datapoint
  • health check처럼 짧고 반복적인 정상 span

필터는 Monithub Collector gateway가 Kubernetes와 Monithub 식별 속성을 보강한 다음, batch와 exporter를 실행하기 전에 적용됩니다.

애플리케이션 또는 수집 Agent
→ Monithub Collector gateway
→ Kubernetes/Monithub 속성 보강
→ Metrics/Logs/Traces 필터
→ 민감 속성 제거와 batch
→ Monithub backend

사용자는 OpenTelemetry Transformation Language(OTTL)를 직접 작성하지 않습니다. MonithubAgent에 필드, 연산자, 값의 타입을 지정하면 Monithub K8S Operator가 Collector 설정으로 변환합니다.

필터는 제외(drop) 전용 방식입니다. 규칙에 일치하는 데이터만 제외하고, 일치하지 않는 데이터는 그대로 통과시킵니다. 규칙을 설정하지 않거나 rules: []로 두면 모든 데이터가 통과합니다.

다음 조건을 확인합니다.

  • Metrics, Logs 및 Traces 필터링 API가 포함된 Monithub K8S Operator chart를 사용해야 합니다.
  • Monithub K8S Operator는 gateway 모드의 Collector를 사용해야 합니다.
  • 기존 Helm values 파일을 수정할 수 있어야 합니다.
  • CRD schema가 chart 버전과 같아야 합니다.

Helm은 upgrade할 때 crds/ 디렉터리의 기존 CRD를 자동으로 갱신하지 않습니다. 필터링 기능이 포함된 버전으로 처음 업데이트한다면 Monithub K8S Operator를 upgrade하기 전에 CRD부터 적용합니다.

Terminal window
helm show crds oci://registry.monithub.org/monithub/charts/monithub-operator \
--version <CHART_VERSION> | kubectl apply --server-side -f -

기존 monithub-values.yaml에 필요한 데이터 종류별 필터 규칙을 추가합니다. 다음 예제는 Metrics, Logs, Traces를 함께 설정하지만, 사용하지 않을 데이터 종류는 생략해도 됩니다.

telemetry:
metrics:
filtering:
rules:
# go.runtime.* metric 전체를 제외합니다.
- name: drop-go-runtime-metrics
scope: metric
match:
all:
- field: metricName
operator: startsWith
value:
string: go.runtime.
# container.cpu.usage의 idle datapoint만 제외합니다.
- name: drop-idle-container-points
scope: datapoint
match:
all:
- field: metricName
operator: equals
value:
string: container.cpu.usage
- field: datapointAttribute
key: container.state
operator: equals
value:
string: idle
logs:
filtering:
rules:
# WARN 미만이면서 health/ready endpoint에서 발생한 log를 제외합니다.
- name: drop-health-access-logs
match:
all:
- field: severityNumber
operator: lessThan
value:
integer: 13
- field: logAttribute
key: http.route
operator: matches
value:
string: ^/(health|ready)$
# body에 반복적인 probe 문구가 포함된 log를 제외합니다.
- name: drop-probe-body-noise
match:
all:
- field: body
operator: contains
value:
string: probe completed
traces:
spanFiltering:
rules:
# server span 중 health/ready endpoint 호출만 제외합니다.
- name: drop-health-check-spans
match:
all:
- field: spanKind
operator: equals
value:
string: server
- field: spanAttribute
key: http.route
operator: matches
value:
string: ^/(health|ready)$

예제의 metric 이름, route, attribute key는 실제 계측 데이터에 맞게 바꿔야 합니다. 먼저 Monithub에서 제외할 데이터 한 건을 열어 정확한 이름, 값, 타입을 확인하세요.

설정을 적용합니다.

Terminal window
helm upgrade monithub-operator oci://registry.monithub.org/monithub/charts/monithub-operator \
-n monithub-system \
--version <CHART_VERSION> \
-f monithub-values.yaml

한 규칙 안의 조건은 모두 만족해야 합니다

Section titled “한 규칙 안의 조건은 모두 만족해야 합니다”

match.all에 조건이 여러 개 있으면 모든 조건이 참일 때만 데이터가 제외됩니다.

다음 규칙은 http.route=/health인 log를 모두 버리는 것이 아닙니다. severity가 WARN 미만이라는 조건까지 함께 만족해야 합니다.

- name: drop-health-access-logs
match:
all:
- field: severityNumber
operator: lessThan
value:
integer: 13
- field: logAttribute
key: http.route
operator: equals
value:
string: /health
log 결과 이유
INFO, /health 제외 두 조건을 모두 만족합니다.
ERROR, /health 통과 severity 조건을 만족하지 않습니다.
INFO, /orders 통과 route 조건을 만족하지 않습니다.

여러 규칙은 하나만 일치해도 제외됩니다

Section titled “여러 규칙은 하나만 일치해도 제외됩니다”

rules 아래의 규칙은 서로 OR 관계입니다. drop-health-access-logs 또는 drop-probe-body-noise 중 하나에만 일치해도 해당 log는 제외됩니다.

타입이 다르면 안전하게 통과합니다

Section titled “타입이 다르면 안전하게 통과합니다”

attribute 값의 실제 타입과 규칙의 value 타입이 다르면 그 조건은 일치하지 않는 것으로 처리합니다. 예를 들어 실제 http.status_code가 integer인데 규칙을 string: "200"으로 작성했다면 해당 데이터는 제외되지 않습니다.

이 동작은 잘못된 타입 지정으로 예상보다 많은 데이터가 사라지는 것을 막기 위한 안전 통과(fail-open) 정책입니다. 필터가 예상대로 적용되지 않으면 먼저 실제 attribute의 이름과 타입을 확인하세요.

하나의 metric에는 attribute 조합이 서로 다른 여러 datapoint가 들어갈 수 있습니다.

container.cpu.usage
├─ container.name=api, state=active
├─ container.name=worker, state=active
└─ container.name=batch, state=idle

metric 이름이나 타입이 일치하면 metric 전체와 그 안의 모든 datapoint를 제거합니다.

- name: drop-runtime-metric
scope: metric
match:
all:
- field: metricName
operator: equals
value:
string: process.runtime.jvm.memory.usage

metric은 유지하면서 조건에 일치하는 datapoint만 제거합니다.

- name: drop-idle-points
scope: datapoint
match:
all:
- field: datapointAttribute
key: state
operator: equals
value:
string: idle

모든 datapoint가 제거되면 값이 없는 빈 metric도 함께 제거됩니다. Metric scope 규칙은 datapoint scope 규칙보다 먼저 평가됩니다.

Trace는 하나의 요청이 여러 서비스를 거치는 전체 흐름이고, span은 그 안의 개별 처리 단계입니다. Trace 필터는 trace 전체가 아니라 조건에 일치하는 개별 span을 제거합니다. OBI/Beyla, OpenTelemetry 자동 계측, 외부 SDK가 gateway로 보낸 span에 같은 규칙이 적용됩니다.

다음 예제는 backend 서비스의 이름이 DB인 span만 제거합니다.

telemetry:
traces:
spanFiltering:
rules:
- name: drop-backend-db-spans
match:
all:
- field: spanName
operator: equals
value:
string: DB
- field: resourceAttribute
key: service.name
operator: equals
value:
string: backend
span 결과 이유
service.name=backend, 이름 DB 제외 두 조건을 모두 만족합니다.
service.name=frontend, 이름 DB 통과 service 조건을 만족하지 않습니다.
service.name=backend, 이름 HTTP GET 통과 span name 조건을 만족하지 않습니다.

실행 시간으로 필터링할 때는 서비스와 span 이름을 함께 지정해 범위를 좁히는 편이 안전합니다. 다음 규칙은 orders-worker 서비스에서 발생한 정상 cache.poll span 중 5ms보다 짧은 것만 제외합니다.

- name: drop-fast-cache-poll-spans
match:
all:
- field: resourceAttribute
key: service.name
operator: equals
value:
string: orders-worker
- field: spanName
operator: equals
value:
string: cache.poll
- field: statusCode
operator: notEquals
value:
string: error
- field: duration
operator: lessThan
value:
duration: 5ms

Span 필터링과 sampling은 다릅니다

Section titled “Span 필터링과 sampling은 다릅니다”
기능 판단 단위 사용하는 때
Head sampling trace ID 비율 수집 시작 지점에서 전체 수집량을 일정 비율로 줄일 때
Span 필터링 개별 span 내용 이름, 상태, 시간, attribute가 특정 조건인 span만 제외할 때
Tail sampling 완성된 trace 오류 또는 고지연 trace 전체를 선택할 때. 현재 필터 기능에는 포함되지 않습니다.

Head sampling은 span이 gateway에 도착하기 전에 실행될 수 있습니다. 필터 규칙에서 오류 span을 제외하지 않았더라도 앞선 수집 단계에서 이미 선택되지 않은 오류 trace를 복구할 수는 없습니다.

일부 단순한 url.path equals 규칙은 지원되는 OBI/Beyla 환경에서 수집 지점에도 자동 적용되어 node와 gateway 사이의 트래픽을 줄일 수 있습니다. 이 최적화가 적용되지 않더라도 gateway Collector가 모든 Trace 규칙을 계속 실행합니다.

scope field 설명 key 필요 여부
metric metricName OpenTelemetry metric 이름 필요 없음
metric metricType gauge, sum, histogram, exponentialHistogram, summary 필요 없음
metric scopeName metric을 만든 instrumentation scope 이름 필요 없음
metric resourceAttribute 서비스, Pod, 환경 등 resource attribute 필요
datapoint metricName datapoint가 속한 metric 이름 필요 없음
datapoint scopeName instrumentation scope 이름 필요 없음
datapoint datapointAttribute datapoint 자체의 attribute 필요
datapoint resourceAttribute datapoint가 속한 resource attribute 필요

metricTypeequalsnotEquals만 지원합니다. 숫자로 된 datapoint 값 자체를 비교하는 기능은 지원하지 않습니다.

field 설명 key 필요 여부
severityNumber OpenTelemetry severity number 필요 없음
severityText INFO, WARN 같은 severity 문자열 필요 없음
body log message body 필요 없음
scopeName log를 만든 instrumentation scope 이름 필요 없음
logAttribute log record에 포함된 attribute 필요
resourceAttribute 서비스, Pod, 환경 등 resource attribute 필요

body는 실제 값이 문자열일 때만 비교합니다. 구조화된 map, 배열, 숫자 body는 문자열 규칙과 일치하지 않으므로 통과합니다.

범위 수준
0 UNSPECIFIED
1~4 TRACE
5~8 DEBUG
9~12 INFO
13~16 WARN
17~20 ERROR
21~24 FATAL

예를 들어 lessThan: 13에 해당하는 설정은 TRACE, DEBUG, INFO를 대상으로 하며 WARN 이상은 통과시킵니다. severityNumber 비교 값은 0부터 24까지만 사용할 수 있습니다.

field 설명 값과 연산자 key 필요 여부
spanName span 이름 string 비교와 pattern 필요 없음
spanKind span 역할 unspecified, internal, server, client, producer, consumerequals, notEquals 필요 없음
statusCode OpenTelemetry span 상태 unset, ok, errorequals, notEquals 필요 없음
duration span 종료 시각과 시작 시각의 차이 양수 duration의 숫자 비교 필요 없음
scopeName instrumentation scope 이름 string 비교와 pattern 필요 없음
spanAttribute span 자체의 attribute typed 비교 필요
resourceAttribute 서비스, Pod, 환경 등 resource attribute typed 비교 필요

statusCode: unset은 성공을 뜻하지 않습니다. 오류 span을 보존하려는 규칙이라면 실제 계측 라이브러리가 status를 어떻게 기록하는지 먼저 확인하세요.

operator 의미 사용할 수 있는 값
exists attribute가 존재함 value를 작성하지 않음
notExists attribute가 존재하지 않음 value를 작성하지 않음
equals 값이 같음 string, integer, double, boolean
notEquals 값이 다름 string, integer, double, boolean
contains 문자열에 일부 문자가 포함됨 string
startsWith 문자열이 지정한 값으로 시작함 string
endsWith 문자열이 지정한 값으로 끝남 string
matches 정규식에 일치함 string
greaterThan 지정한 숫자나 시간보다 큼 integer, double, duration
greaterThanOrEqual 지정한 숫자나 시간보다 크거나 같음 integer, double, duration
lessThan 지정한 숫자나 시간보다 작음 integer, double, duration
lessThanOrEqual 지정한 숫자나 시간보다 작거나 같음 integer, double, duration

existsnotExistslogAttribute, datapointAttribute, spanAttribute, resourceAttribute처럼 attribute를 확인하는 필드에서만 사용할 수 있습니다.

Duration 비교는 Trace의 duration 필드에서만 사용할 수 있으며 equalsnotEquals는 지원하지 않습니다.

matches에는 RE2 호환 정규식을 사용합니다. 잘못된 정규식은 적용 전에 거부됩니다. 복잡하고 넓은 정규식보다 정확한 prefix나 equals를 우선하면 의도하지 않은 데이터 제외를 줄일 수 있습니다.

value에는 비교 대상에 맞는 타입을 정확히 하나만 작성합니다. 기본 타입은 string, integer, double, boolean이며, Trace의 duration 필드에는 duration을 사용합니다.

value:
string: production
value:
integer: 13
value:
double: 0.5
value:
boolean: true
value:
duration: 250ms

attribute의 타입과 비교 값의 타입은 같아야 합니다. 특히 integer: 1double: 1.0은 서로 다른 타입으로 평가됩니다.

Duration은 5ms, 250ms, 2s, 1m처럼 Kubernetes duration 형식으로 작성하며 0보다 커야 합니다.

항목 제한
Metrics 규칙 최대 20개
Logs 규칙 최대 20개
Traces 규칙 최대 20개
한 규칙의 match.all 조건 1개 이상, 최대 10개
규칙 이름 최대 63자, 소문자 영문·숫자·하이픈 사용
attribute key 최대 256자
string 값 최대 512자
정규식 최대 256자, RE2 문법
Trace duration 0보다 큰 값

규칙 이름은 같은 데이터 종류 안에서 중복될 수 없습니다. 다음처럼 짧고 목적이 드러나는 이름을 사용합니다.

drop-health-access-logs
drop-health-check-spans
drop-idle-container-points
drop-runtime-metrics

Helm upgrade 후 Monithub K8S Operator와 Collector rollout을 확인합니다.

Terminal window
kubectl -n monithub-system rollout status deploy/monithub-operator
kubectl -n monithub-system rollout status deploy/monithub-collector

필터 상태를 확인합니다.

Terminal window
kubectl -n monithub-system get monithubagent monithub -o yaml

정상적으로 적용되면 다음 값을 확인할 수 있습니다.

status:
spanFiltering:
desiredMode: dropMatching
appliedMode: dropMatching
configuredRuleCount: 1
appliedRuleCount: 1
desiredRevisionHash: <REVISION_HASH>
appliedRevisionHash: <REVISION_HASH>
metricFiltering:
desiredMode: dropMatching
appliedMode: dropMatching
configuredRuleCount: 2
appliedRuleCount: 2
desiredRevisionHash: <REVISION_HASH>
appliedRevisionHash: <REVISION_HASH>
logFiltering:
desiredMode: dropMatching
appliedMode: dropMatching
configuredRuleCount: 2
appliedRuleCount: 2
desiredRevisionHash: <REVISION_HASH>
appliedRevisionHash: <REVISION_HASH>

주요 condition은 다음과 같이 읽습니다.

condition/reason 의미
SpanFilteringApplied=True, RulesApplied Traces 규칙이 적용됐습니다.
MetricFilteringApplied=True, RulesApplied Metrics 규칙이 적용됐습니다.
LogFilteringApplied=True, RulesApplied Logs 규칙이 적용됐습니다.
PassAll 해당 데이터 종류에 규칙이 없어 모두 통과합니다.
RulesAppliedWithWarnings 규칙은 적용됐지만 범위가 넓거나 수집 지점 최적화가 제한될 수 있습니다. 경고 내용을 확인합니다.
RolloutPending 새 Collector revision이 준비되는 중입니다.
InvalidSpanFilterPolicy Traces 규칙의 필드, 연산자 또는 값이 잘못됐습니다.
InvalidMetricFilterPolicy Metrics 규칙의 필드, 연산자 또는 값이 잘못됐습니다.
InvalidLogFilterPolicy Logs 규칙의 필드, 연산자 또는 값이 잘못됐습니다.
CollectorConfigRejected 새 Collector revision이 실행되지 않아 거부됐습니다.
RolledBackToLastKnownGood 이전에 정상 동작하던 Collector revision으로 복구됐습니다.

desiredRevisionHashappliedRevisionHash가 같고 적용 condition이 True이면 현재 values의 규칙이 실행 중입니다.

Trace, Metrics, Logs 설정은 하나의 Collector revision으로 함께 적용됩니다. 어느 한 데이터 종류의 규칙이 잘못되면 새 revision 전체를 적용하지 않으며, 기존에 정상 동작하던 설정을 유지합니다.

운영 환경에 넓은 규칙을 바로 적용하지 말고 다음 순서로 검증합니다.

  1. 개발 또는 staging 클러스터에서 metric 이름, log route, span 이름처럼 범위가 좁은 대상 하나로 규칙을 만듭니다.
  2. 조건에 일치해 사라져야 하는 제외 대상 데이터를 발생시킵니다.
  3. 조건 하나가 다른 비교용 데이터도 함께 발생시킵니다.
  4. 사용한 데이터 종류의 SpanFilteringApplied, MetricFilteringApplied, LogFilteringApplied condition이 True인지 확인합니다.
  5. Monithub의 최근 시간 범위에서 제외 대상은 없고 비교용 데이터는 남아 있는지 확인합니다.
  6. 충분한 시간 동안 대시보드, 알림, 인시던트 분석에 필요한 데이터가 유지되는지 확인한 뒤 범위를 넓힙니다.

필터를 적용하기 전에 사용량이 높은 metric, log, span을 먼저 파악하면 비용 절감 효과와 데이터 손실 위험을 함께 판단하기 쉽습니다.

필터링을 중단하려면 각 데이터 종류의 규칙을 빈 배열로 바꾸고 Helm upgrade를 다시 실행합니다.

telemetry:
traces:
spanFiltering:
rules: []
metrics:
filtering:
rules: []
logs:
filtering:
rules: []

모두 통과시키는 새 Collector revision이 Ready가 되면 이후에 들어오는 데이터부터 다시 저장됩니다. 필터가 활성화된 동안 이미 제외된 데이터는 복구되지 않습니다.

증상 원인 후보 확인과 조치
unknown field "filtering" 또는 "spanFiltering" CRD가 이전 버전임 chart의 CRD를 먼저 server-side apply한 뒤 Helm upgrade를 다시 실행합니다.
InvalidSpanFilterPolicy Trace field, duration, span kind 또는 status 값 오류 Traces 지원 필드 표와 Monithub K8S Operator의 condition을 확인합니다.
InvalidMetricFilterPolicy scope에 맞지 않는 field, 잘못된 타입 또는 연산자 Metrics 지원 필드 표와 실제 attribute 타입을 확인합니다.
InvalidLogFilterPolicy severity 범위, 정규식, key/value 계약 오류 Monithub K8S Operator의 condition과 log를 확인하고 규칙을 좁혀 다시 적용합니다.
RolloutPending이 오래 지속됨 Collector Pod가 Ready가 되지 않음 Collector Pod event, image pull, resource 부족 상태를 확인합니다.
RolledBackToLastKnownGood 새 설정 또는 custom Collector image가 실행되지 않음 현재 규칙과 Collector image의 filter processor 지원 여부를 확인합니다.
적용 상태는 정상인데 데이터가 계속 보임 기존 저장 데이터, 다른 수집 경로, field/key/type 불일치 최근 시간 범위로 조회하고 실제 telemetry의 attribute 이름과 타입을 확인합니다.
예상보다 많은 데이터가 사라짐 조건이 너무 넓음 규칙을 빈 배열로 되돌린 뒤 정확한 metric 이름, service 또는 route 조건을 추가합니다.
Trace가 중간에서 끊겨 보임 부모 span만 필터링됨 부모·자식 관계를 확인하고 전체 호출 구간에 공통으로 존재하는 좁은 조건을 사용합니다.
RulesAppliedWithWarnings가 표시됨 넓은 Trace 규칙 또는 제한적인 수집 지점 최적화 경고 메시지를 확인합니다. 규칙은 gateway에 적용되므로 데이터 결과를 검증한 뒤 필요하면 범위를 좁힙니다.
문자열 조건이 숫자 attribute에 적용되지 않음 타입 불일치로 fail-open됨 실제 타입에 맞춰 integer, double, boolean 중 하나를 사용합니다.

진단할 때는 다음 로그와 리소스를 순서대로 확인합니다.

Terminal window
kubectl -n monithub-system describe monithubagent monithub
kubectl -n monithub-system logs deploy/monithub-operator --tail=200
kubectl -n monithub-system logs deploy/monithub-collector --tail=200
kubectl -n monithub-system describe deploy/monithub-collector

기존에 저장된 데이터도 삭제되나요?

Section titled “기존에 저장된 데이터도 삭제되나요?”

아니요. 필터는 적용 이후 gateway에 들어오는 데이터에만 작동합니다. 이미 Monithub에 저장된 데이터는 삭제하지 않습니다.

특정 데이터만 통과시키는 keep 규칙을 만들 수 있나요?

Section titled “특정 데이터만 통과시키는 keep 규칙을 만들 수 있나요?”

현재는 제외 규칙만 지원합니다. 허용 목록(allowlist)이 필요하다면 여러 개의 넓은 notEquals 규칙을 조합하기보다 수집 범위를 먼저 조정하거나 Monithub 지원팀과 정책을 검토하세요.

필터를 바꾸면 Collector가 재시작되나요?

Section titled “필터를 바꾸면 Collector가 재시작되나요?”

네. Monithub K8S Operator는 전체 Collector 설정의 새 revision을 만들고 순차적으로 교체합니다. 새 revision이 Ready가 된 경우에만 적용 완료로 기록하며, 실패하면 이전 정상 revision으로 되돌립니다.

Trace 규칙에 일치하면 trace 전체가 제외되나요?

Section titled “Trace 규칙에 일치하면 trace 전체가 제외되나요?”

아니요. 조건에 일치하는 개별 span만 제외됩니다. 부모 span이나 호출 관계의 한쪽만 제외하면 trace와 Service Map이 끊겨 보일 수 있으므로, 적용 전에 부모·자식 관계를 함께 확인하세요.

Span 필터링이 sampling을 대신하나요?

Section titled “Span 필터링이 sampling을 대신하나요?”

아니요. Sampling은 trace 전체의 수집량을 비율이나 완성된 결과로 결정하고, span 필터링은 gateway에 도착한 개별 span의 이름, 속성, 상태, 시간을 기준으로 제외합니다. 두 기능은 목적과 판단 시점이 다릅니다.

실제 제외 건수를 MonithubAgent 상태에서 볼 수 있나요?

Section titled “실제 제외 건수를 MonithubAgent 상태에서 볼 수 있나요?”

현재 MonithubAgent status는 적용된 규칙 수와 revision을 보여주지만 누적 제외 건수는 제공하지 않습니다. Collector 내부 metrics를 별도로 수집하는 환경에서는 otelcol_processor_filter_spans.filtered, otelcol_processor_filter_datapoints.filtered, otelcol_processor_filter_logs.filtered를 사용할 수 있습니다.