커스텀 이벤트
자동 수집 외에 비즈니스 로직에 맞는 이벤트를 직접 기록하고, 대시보드에서 분석할 수 있습니다.
track()
커스텀 이벤트를 기록합니다. 이름과 선택적 속성(props)을 전달합니다.
const analytics = createDicolytics(client, { apiKey: '...' });
// 이름만 전달
analytics.track('daily_reward_claimed');
// 이름 + 속성
analytics.track('purchase', {
sku: 'premium_role',
amount: 1500,
currency: 'KRW',
});analytics = create_dicolytics(bot, api_key="...")
# 이름만 전달
analytics.track("daily_reward_claimed")
# 이름 + 속성
analytics.track("purchase", {
"sku": "premium_role",
"amount": 1500,
"currency": "KRW",
})참고
- 이벤트 이름: 최대 256바이트 (UTF-8), 앞뒤 공백은 자동 제거됩니다.
- 속성 키 개수: 최대 50개
- 속성 키 길이: 키당 최대 100자
- 속성 전체 크기: JSON 직렬화 후 최대 8 KiB
- 속성 값은 JSON 직렬화 가능한 타입이어야 합니다 (함수, Symbol 등은 무시됨).
이름 규칙
이름은 자유 형식이지만, snake_case를 권장합니다. 대시보드에서 필터링하기 편리합니다.
// 좋은 예시
analytics.track('guild_config_updated');
analytics.track('ticket_opened');
analytics.track('level_up');
// 피해야 할 예시
analytics.track('Guild Config Updated'); // 공백 포함
analytics.track('ticketOpened'); // 일관성 부족# 좋은 예시
analytics.track("guild_config_updated")
analytics.track("ticket_opened")
analytics.track("level_up")
# 피해야 할 예시
analytics.track("Guild Config Updated") # 공백 포함
analytics.track("ticketOpened") # 일관성 부족다양한 활용 예시
analytics.track('purchase', {
sku: 'premium_role',
amount: 1500,
currency: 'KRW',
guildId: interaction.guildId,
});analytics.track('level_up', {
userId: member.id,
guildId: member.guild.id,
newLevel: 42,
xpTotal: 128500,
});analytics.track('vote_received', {
platform: 'top.gg',
userId: voter.id,
isWeekend: true,
});analytics.track('guild_config_updated', {
guildId: interaction.guildId,
setting: 'welcome_channel',
changedBy: interaction.user.id,
});속성(props) 활용
속성은 임의의 키-값 쌍입니다. 대시보드의 탐색(Explore) 기능에서 props.* 필드로 필터링하거나 집계할 수 있습니다.
analytics.track('ticket_opened', {
category: 'billing',
priority: 'high',
guildId: interaction.guildId,
});analytics.track("ticket_opened", {
"category": "billing",
"priority": "high",
"guild_id": interaction.guild_id,
})참고
문자열, 숫자, 불리언을 권장합니다. 객체나 배열도 JSON으로 직렬화되어 저장되지만, 대시보드에서 필터링이 어려울 수 있습니다. 중첩 객체보다는 평탄한(flat) 구조가 좋습니다.
직렬화 규칙
SDK는 속성을 전송 전에 자동으로 정리합니다.
| 입력 타입 | 처리 방식 |
|---|---|
string, number, boolean | 그대로 전송 |
Date | ISO-8601 문자열로 변환 |
BigInt | 문자열로 변환 |
Map | [key, value] 배열로 변환 |
Set | 값 배열로 변환 |
Error | { name, message }로 변환 |
function, Symbol, undefined | 제거 |
| 순환 참조 | 자동 제거 |
문자열 속성은 개당 최대 4 KiB, 이벤트 data 전체는 최대 16 KiB로 제한됩니다. 초과 시 뒤쪽 키부터 잘립니다.
captureError()
오류를 명시적으로 보고합니다. error 타입 이벤트로 전송됩니다.
try {
await riskyOperation();
} catch (err) {
analytics.captureError(err, {
userId: interaction.user.id,
guildId: interaction.guildId,
operation: 'risky_operation',
});
}try:
await risky_operation()
except Exception as exc:
analytics.capture_error(exc, {
"user_id": interaction.user.id,
"guild_id": interaction.guild_id,
"operation": "risky_operation",
})오류 필드는 name (최대 200자), message (최대 2 KiB), stack (최대 8 KiB)으로 자동 제한됩니다. Error 인스턴스가 아닌 값도 처리됩니다 (문자열이면 message로, 그 외에는 String()으로 변환).
절대 throw하지 않음
captureError()는 어떤 상황에서도 예외를 던지지 않습니다. 오류 보고가 실패해도 봇 동작에 영향을 주지 않습니다.
flush()
대기 중인 모든 이벤트를 즉시 서버로 전송합니다.
await analytics.flush();await analytics.flush()일반적으로 호출할 필요 없습니다. SDK가 5초마다 또는 50개 이벤트 대기 시 자동으로 플러시합니다.
참고
수동 플러시가 유용한 경우:
- 중요한 이벤트를 즉시 확인하고 싶을 때
- 테스트 환경에서 전송을 강제할 때
shutdown()
리스너와 타이머를 모두 해제하고 마지막 플러시를 수행합니다.
await analytics.shutdown();await analytics.shutdown()| 단계 | 동작 |
|---|---|
| 1 | 모든 discord.js 이벤트 리스너 제거 |
| 2 | 내부 타이머(setInterval) 해제 |
| 3 | 대기 이벤트 최종 플러시 (최대 3초) |
참고
SDK는 SIGINT, SIGTERM, beforeExit 시그널에 자동으로 종료 플러시를 수행합니다. 직접 shutdown()을 호출할 수도 있지만, 대부분의 경우 자동 처리로 충분합니다.
대시보드에서 확인
커스텀 이벤트는 대시보드에서 여러 방식으로 확인할 수 있습니다.
보고서에서 보기
사이드바의 활동 > 커스텀 이벤트 보고서에서 확인합니다.
- 이벤트 이름별 건수 추이 차트
- 이름을 클릭하면 해당 이벤트의 상세 추이와 속성 분포
- 기간 선택기로 분석 범위를 지정할 수 있습니다
탐색(Explore)에서 분석
탐색에서 더 자유로운 분석이 가능합니다.
- 필터에서
event_type = custom설정 - 차원에
custom_event_name선택 props.*필드로 속성별 필터링 가능
예시: event_type = custom AND props.category = billing
→ billing 카테고리 커스텀 이벤트만 조회비활성화 불가
disabledEvents 옵션으로 자동 수집 이벤트를 끌 수 있지만, custom 이벤트 타입은 비활성화할 수 없습니다. 커스텀 이벤트를 전송하지 않으려면 단순히 track()을 호출하지 않으면 됩니다.
관련 문서
- SDK API 레퍼런스 --
track(),captureError()시그니처 상세 - 수집 체계 -- 이벤트 전송 흐름과 버퍼 구조
- 전송과 재시도 -- HTTP 배치 구조와 재시도 정책