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