"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > NestJS + Opentelemetry(샘플링)

NestJS + Opentelemetry(샘플링)

2024-08-23에 게시됨
검색:715

Grafana Cloud

이전 포스트에서 Grafana Cloud에 Opentelemetry data를 쏴서 저장하고 보는 것을 했다.

그라파나 클라우드 무료 버전을 사용하면 한달에 로그와 트레이스에 50GB정도를 준다. 유저가 얼마 없어서 Trace가 별로 안쌓이는(혹은 로그를 안찍는)서비스라면 그냥 사용해도 되겠지만, 조금 규모가 있는 상태에서 도입한다면 로그가 너무 많이 쌓여 터질까봐 두렵다.

Sampling

Sampling이란 전체에서 일부를 뽑아 쓰는 것이다. 결과적으로 저장되는 Telemetry 데이터의 수를 감소시키는 작업이다.

Why need Sampling

샘플링은 왜 필요할까?

NestJS   Opentelemetry (Sampling)

위의 그림에서 모든 동그라미(트레이스)를 저장할 필요는 없다. 중요한 트레이스(에러, 혹은 너무 수행시간이 긴)와 전체를 대표하는 일부 표본(OK trace중 일부)만 저장하면 충분하다.

Sampling의 종류

샘플링은 크게 Head Sampling, Tail Sampling으로 나눌 수 있다.

Head Sampling

  • 맨 앞에서 샘플링하는 것을 말한다. 대표적으로 그냥 확률적으로 샘플링 하는 것이 있다. 전체 트레이스에서 10퍼센트만 남기고 나머지는 트레이스 하지 않는 것이다.

Javascript

TraceIdRatioBasedSampler를 기본적으로 제공한다.

import { TraceIdRatioBasedSampler } from '@opentelemetry/sdk-trace-node';

const samplePercentage = 0.1;

const sdk = new NodeSDK({
  // Other SDK configuration parameters go here
  sampler: new TraceIdRatioBasedSampler(samplePercentage),
});

단점

  • 묻고 따지지도 않고 Drop해버리는 거기 때문에 중요한 trace들이 드롭되는 경우가 있다.

Tail Sampling

  • 뒤쪽에서 샘플링 하는 것이다. 이 때는 사용할 수 있는 정보가 많기 때문에 원하는 로직에 따라서 필터링 할 수 있다.

  • 예를 들어, 에러 트레이스는 무조건 샘플링 하는 식이다.

  • 보통, 콜렉터에서 일단 모든 트레이스를 받은 이후에 샘플링을 한다.

단점

  • 구현이 어려울 수 있다. 시스템이 바뀌고 조건이 바뀌면 항상 바껴야하는 존재다.

  • 샘플링하기 위해 Stateful인 상태를 유지하고 있어야해서 수행이 어렵다.

  • Tail Sampler가 vendor-specific 인 경우가 있다.

구현

Tail Sampling을 Custom Span Processor를 구현하여 구현해보자.

SamplingSpanProcessor 구현

sampling-span-processor.ts 파일 생성

import { Context } from "@opentelemetry/api";
import {
  SpanProcessor,
  ReadableSpan,
  Span,
} from "@opentelemetry/sdk-trace-node";

/**
 * Sampling span processor (including all error span and ratio of other spans)
 */
export class SamplingSpanProcessor implements SpanProcessor {
  constructor(
    private _spanProcessor: SpanProcessor,
    private _ratio: number
  ) {}

  /**
   * Forces to export all finished spans
   */
  forceFlush(): Promise {
    return this._spanProcessor.forceFlush();
  }

  onStart(span: Span, parentContext: Context): void {
    this._spanProcessor.onStart(span, parentContext);
  }

  shouldSample(traceId: string): boolean {
    let accumulation = 0;
    for (let idx = 0; idx  {
    return this._spanProcessor.shutdown();
  }
}

status.code가 2 (Error)거나 ratio 확률에 당첨되었을 때만 this._spanProcessor.onEnd(span); 를 호출해서 export한다.

OtelSDK 업데이트

main.ts에서 spanProcessors를 업데이트 해준다.

  spanProcessors: [
    new SamplingSpanProcessor(
      new BatchSpanProcessor(traceExporter),
      samplePercentage
    ),
  ],
릴리스 선언문 이 글은 https://dev.to/siisee11/nestjs-opentelemetry-sampling-2ome?1에서 복제됩니다.1 침해 내용이 있는 경우, [email protected]으로 연락하여 삭제하시기 바랍니다.
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3