로깅 및 추적 이벤트
로깅 및 추적 이벤트
1) 목적과 프레임
통나무와 산책로는 관찰 가능성의 기초입니다.
통나무는 "무슨 일이 있었는지" 와 "어떤 맥락에서" 응답합니다.
트랙은 분산 쿼리 경로에서 "천천히/왜 잘못" 에 응답합니다.
- 기본적으로 구조화 (JSON); 우선 추적: 핫 경로의 각 로그는 'trace _ id '/' span _ id' 로 바인딩됩니다.
- 소음 최소, 신호 최대: 레벨, 샘플링, 카디널리티.
- 보안 및 개인 정보 보호: 마스킹, 편집, 액세스 제어.
- 로그 및 이벤트의 수정 된 다이어그램.
2) 이벤트 분류
목적지 별 별도의 스트림 및 색인:1. 기술 로그 (런타임, 오류, 네트워크 타임 아웃, 배상).
2. 비즈니스 이벤트 (등록, 예금, 요율, 인출, KYC 단계) - "돈" 경로를 따라 제품 분석 및 사고에 적합합니다.
3. 감사 (구성, 액세스, 플래그, 한계: 무엇을 변경했을 때) 는 변경할 수없는 저널입니다.
4. 보안 (인증, 권한 상승, 제재/PEP 플래그).
5. 인프라 (K8 이벤트, 자동 스케일링, HPA/VPA, 노드/디스크/네트워크).
각 스트림마다 - 보존, 색인 및 액세스에 대한 별도의 규칙.
3) 구조 로그 (JSON 표준)
json
{
"ts": "2025-11-03T14:28:15.123Z",
"level": "ERROR",
"service": "payments-api",
"env": "prod",
"region": "eu-central-1",
"trace_id": "8a4f0c2e9b1f42d7",
"span_id": "c7d1f3a4b8b6e912",
"parent_span_id": "a1b2c3d4e5f60789",
"logger": "withdraw.handler",
"event": "psp_decline",
"msg": "PSP declined transaction",
"http": { "method": "POST", "route": "/withdraw", "status": 502, "latency_ms": 842 },
"user": { "tenant_id": "t_9f2", "user_key": "hash_0a7c", "vip_tier": 3 },
"payment": { "psp": "acme", "amount": 120.50, "currency": "EUR", "idempotency_key": "u123:wd:7845" },
"safe": true, // пройдена проверка на секреты
"version": "1.14.2", // версия сервиса (SemVer)
"build": "sha-1f2a3b4",
"kubernetes": { "pod": "payments-7cbdf", "node": "ip-10-0-2-41" }
}
요구 사항: 도메인 별 플랫 체계 + 첨부 파일, 필요한 필드 ('ts, 레벨, 서비스, env, trace _ id, msg'), 숫자 값 (문자열이 아닌 숫자).
4) 레벨, 카디널리티 및 범위
레벨: 'DEBUG' (판매 아님), 'INFO' (비즈니스 사실), 'WARN' (이상), 'ERROR' (오류), 'FATAL' (충돌).
카디널리티: 임의의 키/동적 레이블을 피하십시오. "id-in-key" 가 없습니다.
샘플링 로그: 속도 제한 반복 메시지; 'DEBUG' 는 범위와 시간에 맞춰 활성화됩니다 (기능 플래그).
Idempotency: 소비자의 중복 이벤트를 억제하기위한 로그 'idempotency _ key'.
5) 개인 정보 보호 및 보안
에이전트의 마스크 PII/비밀 (Fluent Bit/Vector): 키 마스킹 카드 ('이메일', '카드', '토큰', '인증').
해시 'user _ key' 는 필요한 컨텍스트 (국가, KYC 레벨, VIP 계층) 만 보유합니다.
별도의 저장 장치: 따뜻한 (온라인 검색) 및 차가운 (PII가없는 보관소/제거 된 컨텍스트 포함).
감사-추가 전용, WORM 스토리지, 최소 권한 원칙에 따라 액세스 할 수 있습니다.
6) 추적: 표준 및 상황
W3C Trace 컨텍스트: 'traceparent '/' tracestate' 헤더 및 보안 키 용 수하물 (예: '테넌트 _ id', '지역').
링크 메트릭 및 추적: Exemplars-' trace _ id '를 히스토그램의 샘플링 지점으로 전달합니다 (RCA 가속).
샘플링: 문제 쿼리의 경우 기본 샘플링 1-5% + 동적 "오류/느린 p95" 최대 100%.
링크: 비동기 큐/사가의 경우 링크는 '부모' 뿐만 아니라 '링크' 를 통과합니다.
7) 수집 및 라우팅
에이전트: 로그를위한 Fluent Bit/Vector; OTLP OpenTelemetry Collector로 내보냅니다.
수집기: 중앙 게이트웨이 (배치/변환/필터/라우팅).
App → (OTLP logs/traces/metrics) → OTel Collector
→ logs: redact → route(security audit tech biz) → hot index / cold archive
→ traces: tail_sampling(errors p95>threshold) → APM backend
→ metrics: Prometheus exporter (for SLO/alerts)
OTel 수집기 (조각):
yaml processors:
batch: {}
attributes:
actions:
- key: env value: prod action: insert filter/logs:
logs:
include:
match_type: strict resource_attributes:
- key: service.name value: payments-api exporters:
otlp/traces: { endpoint: "apm:4317", tls: { insecure: true } }
loki: { endpoint: "http://loki:3100/loki/api/v1/push" }
prometheus: {}
service:
pipelines:
logs: { receivers: [otlp], processors: [attributes,batch], exporters: [loki] }
traces: { receivers: [otlp], processors: [batch], exporters: [otlp/traces] }
metrics: { receivers: [otlp], processors: [batch], exporters: [prometheus] }
8) 계측: SDK 예
8. 1 노드. js (피노 + 오텔)
js import pino from "pino";
import { context, trace } from "@opentelemetry/api";
const logger = pino({ level: process.env.LOG_LEVEL "info" });
function log(info) {
const span = trace.getSpan(context.active());
const base = span? { trace_id: span.spanContext().traceId, span_id: span.spanContext().spanId }: {};
logger.info({...base,...info });
}
// пример log({ event: "deposit.created", amount: 50, currency: "EUR", user: { user_key: "hash_0a7c" } });
8. 2 자바 (SLF4J + OTel)
java
MDC.put("trace_id", Span.current().getSpanContext().getTraceId());
MDC.put("span_id", Span.current().getSpanContext().getSpanId());
log.info("psp_response status={} latency_ms={}", status, latency);
8. 3 파이썬 (structlog + OTel)
python import structlog from opentelemetry import trace log = structlog.get_logger()
def log_json(event, kwargs):
span = trace.get_current_span()
ctx = {}
if span and span.get_span_context().is_valid:
ctx = {"trace_id": span.get_span_context().trace_id, "span_id": span.get_span_context().span_id}
log.msg(event=event, ctx, kwargs)
8. 4 NGINX → 헤더 추적
nginx proxy_set_header traceparent $http_traceparent;
proxy_set_header tracestate $http_tracestate;
9) 경보 및 자동 작업 신호로 로그
잘못된 패턴 ('psp _ ducking', 'frag _ flag') 이 집계되어 SLO와 관련이 있습니다.
패턴 속도에 대한 경고: "5xx by/relar> 0. 10m 당 5%, "" 사기 _ 플래그 스파이크> 기본의 + 200% ".
자동 작업: 로그가 'introwals _ manual _ mode = 참' 인 경우 플래그 플랫폼을 통한 킬 스위치를 사용할 수 있습니다.
rate(count_over_time({service="payments-api", level="ERROR", event="psp_decline"}[5m])) > 5
10) 유지, 색인, 저장
핫: 7-14 일 (운영 조사).
따뜻한 날씨: 30-90 일 (추세, RCA).
감기: 180-365 + (아카이브, 감사) -전체 텍스트 검색없이 압축, 저렴한 클래스.
인덱싱: 고정 키 ('서비스, env, 레벨, 이벤트, trace _ id, 사용자). 테넌트 _ id '), "모든 연속" 색인에 대한 금지.
이벤트 크기 제한 (예: 자르기/하단): "추가 저장 공간은 MTTR의 적" 입니다.
11) 감사 및 불변성
서명/해시, 서버 시간, '누가/무엇을/언제/왜', 티켓에 대한 링크가있는 별도의 스트림으로 감사 이벤트를 작성하십시오.
"DE에 보너스 플래그를 100% 포함시킨 사람은 누구입니까?" -답변은 1-2 요청에 있어야합니다.
json
{
"ts": "2025-11-03T14:00:00.000Z",
"actor": "alice@company",
"action": "feature_flag.update",
"target": "bonus.enable_vip",
"old": {"rollout": 10},
"new": {"rollout": 100},
"reason": "campaign_2311",
"ticket": "OPS-3481",
"trace_id": "cf12ab.."
}
12) 비즈니스 이벤트 및 데이터 모델
비즈니스 이벤트는 "로그의 텍스트" 가 아니라 계약입니다
'이벤트 _ 유형', '이벤트 _ id', 'arsed _ at', '배우', '주제', '금액', '통화', '상태', 'demempotency _ key'.
dempotent 소비자와 함께 전송 및 "적어도 한 번" 사용하십시오.
13) Kubernetes 및 파이프 라인 로그
버퍼 투 디스크가있는 Sidecar/DaemonSet 에이전트 (네트워크 중단 중).
라우팅을위한 패드의 주석 ('로그. 유형 ',' 유지. 계층 ').
K8 컨트롤러의 로그를 개별적으로 수집하십시오 (클러스터 색인).
ini
[FILTER]
Name modify
Match
Remove authorization, password, card_number
14) 반 패턴
'trace _ id' 가없는 "필요에 따라" 문자열 로그.
로그의 PII/비밀, 페이로드 전체가 덤프됩니다.
수백만 개의 고유 키 → "폭발" 색인.
연중 무휴 판매중인 DEBUG.
감사, 보안 및 기술자를 하나의 지수로 혼합합니다.
보존 정책과 백업 복구 테스트가 없습니다.
15) 구현 점검표 (0-45 일)
0-10 일
게이트웨이/클라이언트에서 W3C 추적 컨텍스트 사용, 헤더 전달
응용 프로그램 로그를 JSON에 번역하고 'trace _ id '/' span _ id' 를 추가하십시오.
거부 PII/비밀 (에이전트에 마스킹) 은 필드 목록을 승인합니다.
11-25 일
별도의 스트림: 기술/비즈/감사/보안/인프라, 설정 유지 및 ACL.
OTel 수집기, 테일 샘플링 오류/느린 쿼리 사용.
대시 보드 "경로 별 로그 속도/오류" + 추적 점프 (표시).
26-45 일
이벤트 패턴 경고 및 SLO와의 상관 관계.
콜드 로그에 대한 보관/복원 (DR 테스트).
CI의 로그 다이어그램 라인터, 비즈니스 이벤트 계약.
16) 성숙도 지표
'Trace _ id' 요청 범위는 95% 이상입니다.
JSON 로그의 비율은 99% 이상입니다.
"추적 점프" 를 통해 발견 된 사건은 <15 분 (p50) 으로 해결되었습니다.
로그의 0 PII 케이스 (누출 스캐너).
모든 흐름에 대해 보존이 관찰됩니다 (감사를 자동으로 증명합니다).
17) 앱: 미니 스니펫
W3C traceparent 생성 (의사)
txt traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
PromQL-많은 로그와 SLO (예)
high_error_logs = rate(log_events_total{service="payments-api",level="ERROR"}[5m])
5xx_rate = sum(rate(http_requests_total{service="payments-api",status=~"5.."}[5m])) / sum(rate(http_requests_total{service="payments-api"}[5m]))
alert if high_error_logs > 10 and 5xx_rate > 0.005
OpenAPI - 상관 헤더
yaml components:
parameters:
Traceparent:
name: traceparent in: header required: false schema: { type: string }
18) 결론
강력한 로깅 및 추적 회로는 구조적 JSON 로그, 단일 'trace _ id', 보안 PII 처리, 스트림에 대한 라우팅 및 보존, SLO, 경고 및 롤백과의 긴밀한 연결과 같은 계약 + 분야입니다. "텍스트 덤프" 에서 이벤트 계약 및 트랙으로 전환하면 생산 사고의 진단이 빠르고 예측 가능하며 검증 가능해집니다.