본문 바로가기
IT/FinOps

[Datadog] 불필요한 비용 줄이기 - APM편

by Jany 2026. 2. 21.
반응형

[IT/FinOps] - [Datadog] 불필요한 비용 줄이기 - Log 편

[IT/FinOps] - [Datadog] 불필요한 비용 줄이기 - Host 편

[IT/FinOps] - [Datadog] 불필요한 비용 줄이기 – Container 편

 


 

Datadog 을 사용하는 주 목적이 APM이라고 해도 과언이 아니다. 그러나 비용 부담때문에 사용하기 쉽지 않다.

APM은 막연히 비싼 게 아니다. 어디서 켰는지 모르면 비싸다.

기존과 마찬가지로 비용 체계를 살펴보고 어떻게 줄일 수 있는지 알아보자.

 

APM Host – 언제 과금되는가

https://docs.datadoghq.com/account_management/billing/apm_tracing_profiler/

https://docs.datadoghq.com/ko/account_management/plan_and_usage/cost_details/

APM Host 는 다음 기준으로 과금 된다.

  • Datadog Agent 실행 중
  • apm_config.enabled: true
  • 트레이스 수집 중
  • 1시간 이상 활성 상태

즉, Agent에 APM이 활성화되어 있고 해당 호스트에서 트레이스가 수집되면 APM Host로 카운트된다.

Agent에서 APM enabled=true인데, 트레이스가 하나도 안 들어오면?

APM HOST로 카운트 되지 않는다.

실제 설정 방법을 살펴보면 다음처럼 되어야 한다.
비활성화롤 설정한 경우에는 Infrastucture Host 로만 과금된다.

EC2/VM 환경

# datadog.yaml

# 활성화
apm_config:
  enabled: true
  
# 비활성화
apm_config:
  enabled: false

 

Kubernetes 환경 (Helm)

# values.yaml
# 활성화
datadog:
  apm:
    enabled: true
    
DD_APM_ENABLED=true

# 비활성화
datadog:
  apm:
    enabled: false

DD_APM_ENABLED=false

 

SPAN – 언제 과금되는가

https://docs.datadoghq.com/tracing/

먼저 SPAN에 대해 알아보자

SPAN은 W3C가 정한 Trace 정보로, 표준 http 헤더 및 값의 형식이 정해져있다. 
https://www.w3.org/TR/trace-context/

다시 말해 SPAN은 "작업 하나의 실행 기록" 이다. 
정확히 말하면 분산 트레이싱에서 가장 작은 단위의 실행 구간 이다.

사용자가 하나의 API를 호출한다고 하면,

GET /orders/123

실제로는 이렇게 진행된다.

API Gateway
  → Order Service
    → Payment Service
      → Database

 

여기의 3가지가 모두 SPAN이다.

  • Order Service에서 처리한 시간
  • Payment Service 호출 시간
  • DB 쿼리 시간

구조를 나눠서 살펴보면 다음처럼 나눌수 있다.

Trace (전체 요청)
 ├── Span 1 (API 수신)
 ├── Span 2 (Order Service 처리)
 ├── Span 3 (Payment 호출)
 └── Span 4 (DB Query)
  • Trace = 사용자 요청 하나 전체 흐름
  • Span = 그 안의 개별 작업 단위

Datadog APM은 이 Span들을 수집한다.

그럼 이러한 SPAN에는 어떤 정보들이 있을까?

  • service 이름
  • operation 이름
  • 시작 시간
  • 종료 시간
  • duration
  • status (error 여부)
  • 태그 (env, version 등)
service: order-api
operation: http.request
duration: 125ms
env: prod
status: ok

이게 하나의 SPAN의 예시이다.


그럼 이제 다시 Datadog span구조를 살펴보자.

Span은 다음처럼 만들어진다.

Application
  → Datadog APM 라이브러리
    → Agent
      → Datadog backend
        → Ingested
        → Indexed
  • 수집된 Span 수 (Ingested Spans)
  • 검색 가능하게 저장된 Span 수 (Indexed Spans)

기준으로 과금한다.

즉, 요청이 많아지면, SPAN도 많아지고, 결국 비용이 증가하게 된다.

# 1개 요청에 10개의 SPAN 이 존재
초당 1,000 req = 초당 10,000 SPAN

실제 서비스 구조를 생각해보자.

사용자 요청 1번으로 처리되는 과정은

→ API
→ 인증 서비스
→ 추천 서비스
→ 캐시
→ DB
→ 외부 결제 API

등 다양한 처리과정이 있으므로, SPAN이 10~30개도 생길수 있다.

SPAN생성이 되려면 APM 라이브러리가 설치되어있어야 한다.

Python

from ddtrace import patch_all
patch_all()

Node

require('dd-trace').init();

Java

-javaagent:dd-java-agent.jar

이런 설정이 들어가면 Span이 자동생성된다.


Ingested Span 과금

https://docs.datadoghq.com/tracing/trace_pipeline/ingestion_mechanisms/ 

수집된 전체 Span 수 기준.

https://docs.datadoghq.com/ko/tracing/trace_pipeline/ingestion_mechanisms/

제어 방법은 “샘플링”이다.

샘플링은 Agent 에서도 가능하고, 환경 변수로도 가능하다.

Agent 기반 - TPS 기준 제한

apm_config:
  max_traces_per_second: 10

환경변수 기반 - 20% 수집

DD_TRACE_SAMPLE_RATE=0.2

*Tag 기반 샘플링 방법 (Rule 기반)

https://docs.datadoghq.com/ko/tracing/trace_pipeline/ingestion_mechanisms/?tab=java#in-tracing-libraries-user-defined-rules

Java 기준이나 편의상 개행 했다.

# using system property
java \
  -Ddd.trace.sampling.rules='[
    {
      "service": "my-service",
      "resource": "GET /checkout",
      "sample_rate": 1
    },
    {
      "service": "my-service",
      "sample_rate": 0.2
    }
  ]' \
  -javaagent:dd-java-agent.jar \
  -jar my-app.jar

# using environment variables
export DD_TRACE_SAMPLING_RULES='[
  {
    "service": "my-service",
    "resource": "GET /checkout",
    "sample_rate": 1
  },
  {
    "service": "my-service",
    "sample_rate": 0.2
  }
]'

 

Indexed Span 과금

https://docs.datadoghq.com/ko/tracing/trace_pipeline/

검색 가능하도록 저장된 Span.

Retention Filter에 의해 결정된다.

https://docs.datadoghq.com/ko/tracing/trace_pipeline/

 

Indexed SPAN 비용 줄이는 방법은 GUI Retention Filters 에서 가능하다.ㅏ

APM → Trace Retention → Retention Filters

 

https://docs.datadoghq.com/ko/tracing/trace_pipeline/

특정 조건만 indexed 하게 할수 있다.

error:true
service:api AND duration:>500ms

 

Retention Filter는 Indexed만 줄이기 때문에, Ingested는 그대로이다.


TIP. K8S 환경에서 주의사항

Case 1 – Sidecar auto instrumentation

Istio / Envoy / ddtrace auto-injection

→ 생각지도 못한 서비스에서 Span 생성

 

Case 2 – Async worker

  • Celery
  • Kafka consumer
  • Lambda-like job worker

이건 HTTP 요청이 없어도 Span이 생김.

 


APM 비용 구성 요소 정리

총 APM 비용 ≈
(APM Host 비용)
+
(Ingested Span 비용)
+
(Indexed Span 비용)

 

각 항목을 따로 보면

APM Host 비용 =
월 평균 APM Host 수 × APM Host 단가
총 Span 수 =
RPS × 요청당 평균 Span 수 × 초 × 일 × 30

월 Ingested Span =
RPS × AvgSpanPerTrace × 2,592,000초

 

예시로 계산을 만들어보면

  • 1,000 rps
  • 평균 7 span per trace
  • 샘플링 100%
1,500 × 7 = 10,500 span/sec
10,500 × 2,592,000 ≈ 27,216,000,000 span/month

여기에 샘플링20%를 적용하면

272억 × 0.2 = 54억 span

엄청난 숫자의 차이를 확인할 수 있다.

Indexed 는 전체 중 일부만 저장한다.

월 Indexed Span =
월 Ingested Span × Indexed 비율
  • Ingested 50억
  • Indexed 10%

→ 5억 Indexed Span

이라고 했을때, 

Retention Filter를 잘 설계하면 이 비율을 1~5%까지 낮출 수 있다.

Indexed 20% → 5%로 줄이면?
비용 약 75% 절감

상당히 비용이 절감되는 것을 확인할 수 있다.

 

결과적으로 APM 비용은 기술 비용이 아니라 트래픽 비용이다.

트래픽이 늘면 비용이 늘고, 설계가 복잡하면 더 늘어난다.

그래서 APM은 설정이 아니라 정책이다.

반응형

댓글