Sentry JavaScript SDK 이벤트 정보 확장 가이드

커스텀 컨텍스트 활용

이벤트에 임의의 데이터를 첨부하여 디버깅 정보를 풍부하게 만들 수 있습니다. 컨텍스트는 이벤트 수명 주기 동안 공유되며, 이슈 상세 페이지에서 확인 가능합니다.

구조화된 컨텍스트

데이터 첨부 시 setContext 메서드를 활용하세요. 컨텍스트는 객체 형태로 전달하며, 고유한 이름을 지정해야 합니다:

Sentry.setContext("player_stats", {
  nickname: "ShadowHunter",
  level: 47,
  combat_style: "ranged"
});

페이로드 크기 제한

전체 애플리케이션 상태나 대용량 바이너리를 컨텍스트에 포함하지 마세요. 413 Payload Too Large 오류가 발생하면 이벤트가 거부됩니다. keepalive: true 설정 시 요청이 무한 대기 상태에 빠질 수 있습니다.

직접 컨텍스트 전달

SDK 5.16.0부터 captureExceptioncaptureMessage 호출 시 컨스트를 직접 제공할 수 있습니다. 기존 스코프 데이터와 병합되며, 콜백 방식으로 명시적으로 초기화할 수도 있습니다.

지원하는 컨텍스트 키: tags, extra, contexts, user, level, fingerprint

// 태그 포함하여 예외 캡처
Sentry.captureException(new Error("서버 응답 실패"), {
  tags: {
    module: "payment_gateway"
  }
});

// 스코프 초기화 후 새로 설정
Sentry.captureException(new Error("완전 초기화"), scope => {
  scope.clear();
  scope.setTag("reset", "true");
  return scope;
});

// Scope 인스턴스로 데이터 전달 (전역 스코프와 병합)
const isolatedScope = new Sentry.Scope();
isolatedScope.setTag("module", "payment_gateway");
Sentry.captureException(new Error("결제 처리 오류"), isolatedScope);

// Scope 인스턴스로 데이터 전달 (전역 설정 무시)
const overrideScope = new Sentry.Scope();
overrideScope.setTag("module", "payment_gateway");
Sentry.captureException(new Error("결제 처리 오류"), () => overrideScope);

컨텍스트 정리

컨텍스트는 현재 스코프에 유지되므로 작업 완료 시 정리해야 합니다. Sentry는 두 가지 스코프 유형을 제공합니다:

  • 전역 스코프: 작업 종료 후에도 유지됨
  • 사용자 정의 스코크: 개발자가 직접 관리
// 전역 설정 변경
Sentry.configureScope(scope => scope.setTag("env", "production"));

// 임시 스코프에서만 적용
Sentry.withScope(function(scope) {
  scope.setUser(currentUser);
  Sentry.captureException(err);
});

// 전역 데이터 제거
Sentry.configureScope(scope => scope.clear());

추가 데이터 (Deprecated)

setExtra를 통한 비구조화 데이터 첨부는 더 이상 권장되지 않습니다. 가능한 한 구조화된 컨텍스트로 마이그레이션하세요.

사용자 식별

사용자 정보는 Sentry 내 고유 식별자 역할을 합니다. 최소 하나의 필드가 필요합니다:

  • id: 내부 사용자 식별자
  • username: 표시용 사용자명
  • email: Gravatar 표시 및 알림 기능 활용
  • ip_address: 인증되지 않은 사용자의 대체 식별자. "{{auto}}" 설정 시 자동 추출
// 사용자 설정
Sentry.setUser({ email: "jane.smith@example.com" });

// 사용자 정보 제거
Sentry.configureScope(scope => scope.setUser(null));

트랜잭션 이름 설정

트랜잭션 이름은 성능 모니터링에서 이벤트 그룹화와 실패 지점 분석에 활용됩니다. 변수 값을 제외한 저카널리티 식별자를 권장합니다:

  • GET /api/v2/products/
  • OrderDetailView
  • billing.tasks.generate_monthly_invoices
Sentry.configureScope(scope => scope.setTransactionName("OrderDetailView"));

태그 커스터마이징

태그는 인덱싱 및 검색 가능한 키-값 쌍으로, 필터링과 분포 맵에 활용됩니다. 호스트명, 플랫폼 버전, 언어 설정 등에 적합합니다.

Sentry.setTag("region", "ap-northeast-2");

Sentry가 자동 설정하는 태그는 덮어쓰지 않는 것을 권장합니다.

첨부 파일

이벤트와 함께 로그 파일 등을 첨부하여 크래시 리포트를 강화할 수 있습니다.

첨부 파일 업로드

이벤트 프로세서를 생성하여 multipart form data로 첨부 엔드포인트에 업로드합니다:

function buildAttachmentEndpoint(dsn, eventId) {
  const { host, path, projectId, port, protocol, user } = dsn;
  const portSegment = port ? `:${port}` : '';
  const pathSegment = path ? `/${path}` : '';
  return `${protocol}://${host}${portSegment}${pathSegment}/api/${projectId}/events/${eventId}/attachments/?sentry_key=${user}&sentry_version=7&sentry_client=custom-javascript`;
}

Sentry.addGlobalEventProcessor((event) => {
  try {
    const client = Sentry.getCurrentHub().getClient();
    const uploadUrl = buildAttachmentEndpoint(client.getDsn(), event.event_id);
    
    const payload = new FormData();
    payload.append(
      'system-logs',
      new Blob([JSON.stringify({ entries: ["디버그 시작", "연결 성공"] })], {
        type: 'application/json',
      }),
      'debug_logs.json'
    );
    
    fetch(uploadUrl, {
      method: 'POST',
      body: payload,
    }).catch((err) => {
      console.error('첨부 업로드 실패:', err);
    });
    
    return event;
  } catch (err) {
    console.error('첨부 처리 오류:', err);
  }
});

이벤트당 최대 100MB까지 첨부 가능하며, 30일 보관됩니다.

브레드크럼

이벤트 발생 전 단계를 추적하는 구조화된 로그입니다.

수동 브레드크럼

Sentry.addBreadcrumb({
  category: "checkout",
  message: "결제 수단 선택: " + paymentMethod,
  level: Sentry.Severity.Info,
});

브레드크럼 커스터마이징

Sentry.init({
  beforeBreadcrumb(breadcrumb, hint) {
    return breadcrumb.category === "console.log" ? null : breadcrumb;
  },
});

사용자 피드백

오류 발생 시 사용자로부터 추가 정보를 수집할 수 있습니다.

위젯 통합

<script
  src="https://browser.sentry-cdn.com/6.0.1/bundle.min.js"
  integrity="sha384-z2Rmh4rfoBkdxaENH00ggKo5Bx8b2SJs+MWQrjWx4DbET95Zr2mxV2Vet3CCj4iW"
  crossorigin="anonymous"
></script>

<script>
  Sentry.init({
    dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
    beforeSend(event, hint) {
      if (event.exception) {
        Sentry.showReportDialog({ 
          eventId: event.event_id,
          title: "문제가 발생했습니다",
          subtitle: "개선을 위해 도움을 주세요",
          labelName: "이름",
          labelEmail: "이메일",
          labelComments: "어떤 일이 있었나요?",
          labelSubmit: "보내기"
        });
      }
      return event;
    },
  });
</script>

스코프와 허브

이벤트 전송 시 SDK는 현재 스코프의 정보를 병합합니다.

스코프 설정

Sentry.configureScope(function(scope) {
  scope.setTag("service", "api-gateway");
  scope.setUser({
    id: 42,
    email: "jane.smith@example.com",
  });
});

로컬 스코프

Sentry.withScope(function(scope) {
  scope.setTag("temporary", "true");
  scope.setLevel("warning");
  Sentry.captureException(new Error("일시적 오류"));
});

// 태그가 적용되지 않음
Sentry.captureException(new Error("다른 오류"));

태그: Sentry JavaScript SDK Error Monitoring Performance Monitoring Breadcrumbs

5월 26일 18:31에 게시됨