Sentry(v20.12.1) 기반 K8S 클라우드 네이티브 환경에서 JavaScript 성능 모니터링을 위한 트랜잭션 샘플링 전략

트랜잭션 데이터 양 제어 방법

Sentry로 전송되는 트랜잭션의 양은 두 가지 주요 방식으로 조절할 수 있습니다. 이는 성능 데이터 수집의 효율성과 비용 간 균형을 맞추는 데 핵심적인 역할을 합니다.

정적 샘플링 비율 (Uniform Sample Rate)

애플리케이션 내 어디서든 발생하는 모든 트랜잭션에 대해 동일한 확률로 샘플링하고자 할 경우, tracesSampleRate 설정을 사용하는 것이 적합합니다. 이 값은 0.0(모두 무시)부터 1.0(모두 수집) 사이의 실수로 지정되며, 해당 비율만큼 트랜잭션이 무작위로 선택되어 전송됩니다.

예를 들어, 20%의 트랜잭션만 기록하려면 다음과 같이 초기화 코드를 구성합니다:

Sentry.init({
  dsn: "__YOUR_DSN__",
  tracesSampleRate: 0.2 // 약 20%의 트랜잭션을 전송
});

이 설정은 상속 규칙에 따라 자식 스팬에도 자동으로 적용되며, 별도의 동적 로직 없이 일관된 샘플링을 유지할 수 있습니다.

동적 샘플링 함수 (Dynamic Sampling Function)

다양한 유형의 트랜잭션에 대해 서로 다른 샘플링 전략을 적용하거나 특정 요청을 완전히 필터링해야 하는 경우, tracesSampler 콜백 함수를 정의하면 됩니다. 이 함수는 각 트랜잭션 생성 시점에 호출되며, 샘플링 컨텍스트 정보를 기반으로 실시간으로 결정을 내릴 수 있습니다.

Sentry.init({
  dsn: "__YOUR_DSN__",
  tracesSampler: (context) => {
    const { transactionContext, parentSampled } = context;

    // 부모 트랜잭션의 결정을 항상 따름 (부분 추적 방지)
    if (parentSampled !== undefined) {
      return parentSampled;
    }

    // 특정 작업 유형에 대해 높은 샘플링 비율 적용
    if (transactionContext.op === "pageload") {
      return 0.8;
    }

    // 검색 요청처럼 빈번하게 발생하는 작업은 낮은 비율로 제한
    if (transactionContext.name.includes("search")) {
      return 0.05;
    }

    // 특정 조건에서는 아예 수집하지 않음
    if (transactionContext.name.includes("/health")) {
      return 0;
    }

    // 기본값: 10%
    return 0.1;
  }
});

샘플링 컨텍스트 정보

tracesSampler 함수에 전달되는 samplingContext 객체는 다음 정보를 포함합니다:

  • transactionContext: 트랜잭션 이름, 작업 타입(op), 사용자 정의 태그 등
  • parentSampled: 상위 트랜잭션의 샘플링 여부 (존재할 경우)
  • location: 브라우저의 현재 URL 정보
  • 사용자 정의 데이터: startTransaction 호출 시 추가 가능

사용자 정의 샘플링 데이터 전달

민감한 정보나 전송하기에는 너무 큰 데이터를 샘플링 판단 근거로 사용하고 싶지만, 트랜잭션 레코드 자체에는 포함시키고 싶지 않은 경우, 두 번째 인자로 별도의 컨텍스트를 전달할 수 있습니다:

Sentry.startTransaction(
  {
    name: "User Profile Search",
    op: "search",
    tags: { cohort: "beta-testers" }
  },
  {
    userId: "user_7890",
    previousResultsCount: 150
  }
);

이 데이터는 샘플링 함수 내에서 접근 가능하지만, 최종 이벤트에는 저장되지 않아 보안과 전송 비용 측면에서 유리합니다.

상속 메커니즘 (Inheritance)

트랜잭션의 샘플링 결정은 하위 span 및 분산 시스템 내 연계된 서비스로 전파됩니다. 이를 통해 추적이 부분적으로 끊기는 것을 방지하고, 전체 요청 흐름을 일관되게 관찰할 수 있습니다. 부모의 결정을 명시적으로 따르도록 설정하면 다음과 같습니다:

tracesSampler: (ctx) => {
  if (ctx.parentSampled !== null) {
    return ctx.parentSampled; // 상위 결정을 그대로 계승
  }
  return 0.1;
}

강제 샘플링 결정

특정 트랜잭션에 대해 반드시 수집하거나 건너뛰도록 강제 설정할 수도 있습니다. 이 경우 tracesSampleRate 또는 tracesSampler의 영향을 받지 않습니다:

const transaction = Sentry.startTransaction({
  name: "Critical Payment Flow",
  sampled: true // 무조건 전송
});

우선순위 규칙 (Precedence)

여러 샘플링 설정이 동시에 적용될 수 있는 경우, 다음 우선순위에 따라 최종 결정이 이루어집니다:

  1. 강제 설정: startTransaction에서 sampled가 지정된 경우 가장 높은 우선순위
  2. 동적 함수: tracesSampler가 존재하면 그 반환값이 적용됨
  3. 상속 결정: tracesSampler 미정의 시, 부모 트랜잭션의 결정을 따름
  4. 정적 비율: 그 외의 경우 tracesSampleRate 기반으로 무작위 샘플링

태그: Sentry kubernetes JavaScript Performance Monitoring Tracing

5월 25일 22:14에 게시됨