Skip to content

SDK API 레퍼런스 v0.5.0

@dicolytics/discord.js 패키지의 공개 API 전체를 정리합니다.

createDicolytics

SDK 인스턴스를 생성하고 discord.js 클라이언트에 리스너를 등록합니다. new Dicolytics(client, options).attach()와 동일합니다.

ts
function createDicolytics(
  client: Client,
  options: DicolyticsOptions
): Dicolytics
python
def create_dicolytics(
    bot: discord.Bot,
    **options: DicolyticsOptions
) -> Dicolytics

매개변수

매개변수타입설명
clientClientdiscord.js v14 클라이언트 인스턴스
optionsDicolyticsOptions설정 옵션 참고

반환값

Dicolytics 인스턴스를 반환합니다.

예외

조건동작
apiKey가 비어 있거나 누락TypeError 동기 예외
client에 이미 SDK 인스턴스가 연결됨Error 동기 예외
그 외 옵션 오류기본값으로 대체 (예외 없음)

사용 예시

ts
import { Client, GatewayIntentBits } from 'discord.js';
import { createDicolytics } from '@dicolytics/discord.js';

const client = new Client({
  intents: [GatewayIntentBits.Guilds],
});

const analytics = createDicolytics(client, {
  apiKey: process.env.DICOLYTICS_KEY!,
});

client.login(process.env.DISCORD_TOKEN);
python
import os
import discord
from dicolytics import create_dicolytics

bot = discord.Bot()

analytics = create_dicolytics(bot, api_key=os.environ["DICOLYTICS_KEY"])

bot.run(os.environ["DISCORD_TOKEN"])
ts
const analytics = createDicolytics(client, {
  apiKey: process.env.DICOLYTICS_KEY!,
  endpoint: 'https://analytics.example.com',
  debug: true,
});
python
analytics = create_dicolytics(bot,
    api_key=os.environ["DICOLYTICS_KEY"],
    endpoint="https://analytics.example.com",
    debug=True,
)
ts
const analytics = createDicolytics(client, {
  apiKey: process.env.DICOLYTICS_KEY!,
  clusterId: Number(process.env.CLUSTER_ID),
});
python
analytics = create_dicolytics(bot,
    api_key=os.environ["DICOLYTICS_KEY"],
    cluster_id=int(os.environ["CLUSTER_ID"]),
)

DicolyticsOptions

createDicolytics의 두 번째 인자로 전달하는 설정 객체입니다.

ts
interface DicolyticsOptions {
  apiKey: string;
  endpoint?: string;
  disabledEvents?: readonly string[];
  debug?: boolean;
  snapshotIntervalMs?: number;
  flushIntervalMs?: number;
  requestTimeoutMs?: number;
  clusterId?: number;
  autoCapturePromiseRejections?: boolean;
}
python
# create_dicolytics()의 키워드 인자로 전달
api_key: str                          # 필수
endpoint: str = "https://api.dicolytics.com"
disabled_events: list[str] = []
debug: bool = False
snapshot_interval_ms: int = 60000
flush_interval_ms: int = 5000
request_timeout_ms: int = 10000
cluster_id: int | None = None
auto_capture_exceptions: bool = False
옵션타입기본값최솟값설명
apiKeystring(필수)--프로젝트 API 키 (dk_live_... 형식)
endpointstringhttps://api.dicolytics.com--API 기본 URL
disabledEventsstring[][]--비활성화할 이벤트 타입
debugbooleanfalse--진단 로그 출력
snapshotIntervalMsnumber6000010000스냅샷 주기 (ms)
flushIntervalMsnumber5000250플러시 주기 (ms)
requestTimeoutMsnumber100001000HTTP 타임아웃 (ms)
clusterIdnumber--0 (최대 32767)클러스터 식별자
autoCapturePromiseRejectionsbooleanfalse--미처리 rejection 자동 보고

각 옵션의 상세 설명은 설정 옵션을 참고하세요.


track()

커스텀 이벤트를 기록합니다.

ts
analytics.track(name: string, props?: Record<string, unknown>): void
python
analytics.track(name: str, props: dict[str, Any] | None = None) -> None

매개변수

매개변수타입설명
namestring이벤트 이름 (최대 256바이트 UTF-8, 앞뒤 공백 자동 제거)
propsRecord<string, unknown> / dict속성 (최대 50키, 키당 100자, 전체 8 KiB)

사용 예시

ts
// 이름만
analytics.track('daily_reward_claimed');

// 이름 + 속성
analytics.track('purchase', {
  sku: 'premium_role',
  amount: 1500,
  currency: 'KRW',
  guildId: interaction.guildId,
});

// 다양한 속성 타입
analytics.track('level_up', {
  userId: member.id,
  newLevel: 42,
  isVIP: true,
  achievedAt: new Date(),  // ISO-8601 문자열로 변환됨
});
python
# 이름만
analytics.track("daily_reward_claimed")

# 이름 + 속성
analytics.track("purchase", {
    "sku": "premium_role",
    "amount": 1500,
    "currency": "KRW",
    "guild_id": str(interaction.guild_id),
})

# 다양한 속성 타입
analytics.track("level_up", {
    "user_id": str(member.id),
    "new_level": 42,
    "is_vip": True,
    "achieved_at": datetime.now().isoformat(),
})

절대 throw하지 않음

track()은 어떤 상황에서도 예외를 던지지 않습니다. SDK 내부 오류는 무시되며, 봇 동작에 영향을 주지 않습니다.

자세한 사용법과 예시는 커스텀 이벤트를 참고하세요.


captureError()

오류를 명시적으로 보고합니다. error 타입 이벤트로 전송됩니다.

ts
analytics.captureError(
  error: unknown,
  context?: Record<string, unknown>
): void
python
analytics.capture_error(
    exc: BaseException,
    context: dict[str, Any] | None = None,
) -> None

매개변수

매개변수타입설명
error / excunknown / BaseException오류 객체. Error 인스턴스가 아니어도 처리됩니다.
contextRecord<string, unknown> / dict추가 컨텍스트 (선택)

context에 사용 가능한 특수 키

타입설명
guildIdstring서버 ID (envelope의 guild_id에 설정됨)
channelIdstring채널 ID (envelope의 channel_id에 설정됨)
userIdstring사용자 ID (envelope의 user_id에 설정됨)

위 키 외의 나머지 context 항목들은 이벤트 data 내부에 포함됩니다.

오류 필드 제한

필드최대 크기
name200자
message2 KiB
stack8 KiB

사용 예시

ts
try {
  await riskyOperation();
} catch (err) {
  analytics.captureError(err, {
    userId: interaction.user.id,
    guildId: interaction.guildId,
    operation: 'risky_operation',
    additionalInfo: 'some context',
  });
}
python
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",
        "additional_info": "some context",
    })

절대 throw하지 않음

captureError()는 어떤 상황에서도 예외를 던지지 않습니다. 오류 보고가 실패해도 봇 동작에 영향을 주지 않습니다.

Error가 아닌 값 처리

입력 타입처리 방식
Error 인스턴스name, message, stack 추출
stringmessage로 사용, name"Error"
그 외String(value)message로 사용

flush()

대기 중인 모든 이벤트를 즉시 서버로 전송합니다.

ts
analytics.flush(): Promise<void>
python
await analytics.flush() -> None

동작

  1. 이벤트 큐의 모든 대기 이벤트를 배치로 묶어 전송합니다.
  2. 전송이 완료될 때까지 기다립니다.
  3. 실패해도 절대 reject하지 않습니다.

사용 시점

일반적으로 호출할 필요 없습니다. SDK가 자동으로 플러시합니다.

  • 50개 이벤트 대기 시 즉시 플러시
  • 5초마다 타이머 기반 플러시 (flushIntervalMs 옵션으로 변경 가능)

수동 플러시가 유용한 경우:

ts
// 중요한 이벤트 즉시 전송
analytics.track('critical_purchase', { amount: 99900 });
await analytics.flush();

// 테스트 환경에서 전송 강제
analytics.track('test_event');
await analytics.flush();
python
# 중요한 이벤트 즉시 전송
analytics.track("critical_purchase", {"amount": 99900})
await analytics.flush()

# 테스트 환경에서 전송 강제
analytics.track("test_event")
await analytics.flush()

shutdown()

리스너와 타이머를 모두 해제하고 마지막 플러시를 수행합니다.

ts
analytics.shutdown(): Promise<void>
python
await analytics.shutdown() -> None

동작

단계설명
1모든 discord.js 이벤트 리스너 제거
2내부 타이머(setInterval) 해제
3대기 이벤트 최종 플러시 (최대 3초 대기)

여러 번 호출해도 안전합니다. 절대 reject하지 않습니다.

자동 종료 처리

SDK는 다음 시그널에 자동으로 종료 플러시를 수행합니다.

시그널동작
SIGINT최대 3초간 플러시 후 시그널 재전달
SIGTERM최대 3초간 플러시 후 시그널 재전달
beforeExit최대 3초간 플러시

참고

직접 shutdown()을 호출하는 것도 가능하지만, 프로세스 종료 시 SDK가 자동으로 마지막 이벤트를 전송합니다.

타이머 unref

SDK의 모든 내부 타이머는 unref()로 설정됩니다. 즉, SDK 타이머만으로는 Node.js 프로세스가 유지되지 않습니다. 다른 활성 작업이 없으면 프로세스가 정상 종료됩니다.


전달 의미론

SDK의 이벤트 전달 동작을 요약합니다. 자세한 내용은 전송과 재시도를 참고하세요.

항목동작
이벤트 IDUUIDv7 (RFC 9562). 재시도 시 동일 ID 재사용 → 서버 측 중복 제거
엔벨로프POST {endpoint}/v1/events -- 배치당 최대 500개 / 1 MiB
플러시50개 대기 또는 5초마다. 동시 요청 1개 (순서 보장)
재시도5xx/네트워크 오류 시 지수 백오프 (최대 5회). 400은 드롭. 401은 전송 비활성화
429Retry-After 준수 (기본 300초). heartbeat/guild_snapshot은 계속 전송
버퍼최대 5,000개 (초과 시 오래된 이벤트부터 삭제)
종료SIGINT/SIGTERM 시 최대 3초간 플러시 후 시그널 재전달
타이머모든 타이머 unref() -- SDK가 프로세스를 유지하지 않음

내보내기 (exports)

@dicolytics/discord.js 패키지에서 내보내는 전체 목록입니다.

ts
// 클래스 & 팩토리
export { Dicolytics, createDicolytics };

// 타입
export type {
  DicolyticsOptions,
  AnalyticsEvent,
  EventEnvelope,
  IngestAcceptedResponse,
  SdkInfo,
  DisableableEvent,
  EventType,
};

// 상수
export { EVENT_TYPES, SDK_NAME, SDK_VERSION };

EVENT_TYPES

모든 이벤트 타입 문자열을 담은 상수 객체입니다. disabledEvents 옵션에 사용할 수 있습니다.

ts
import { createDicolytics, EVENT_TYPES } from '@dicolytics/discord.js';

const analytics = createDicolytics(client, {
  apiKey: '...',
  disabledEvents: [
    EVENT_TYPES.eventTypingStart,     // 'event_typing_start'
    EVENT_TYPES.eventPresenceUpdate,  // 'event_presence_update'
  ],
});
python
from dicolytics import create_dicolytics

analytics = create_dicolytics(bot,
    api_key="...",
    disabled_events=[
        "event_typing_start",
        "event_presence_update",
    ],
)

전체 EVENT_TYPES 목록은 이벤트 레퍼런스를 참고하세요.

관련 문서

Dicolytics — Discord bot analytics