Skip to content

Conversation

@pan93412
Copy link
Contributor

@pan93412 pan93412 commented Jan 25, 2026

現在的 tracing 資訊少到完全不夠用來 debug,所以請 Claude Code 搭配人類 review 補了一大堆上去。

建議使用結構化 diff 工具來 review,GitHub 的 diff 不能正確判讀 try-block 的情況:

# 需要先安裝 difftastic: https://difftastic.wilfred.me.uk
git -c diff.external=difft show --ext-diff
CleanShot 2026-01-26 at 00 10 59@2x

Tracing Attributes Reference (V2)

本文件記錄後端所有 OpenTelemetry spans 及其 attributes 的完整清單。

目錄


認證相關 (Auth)

auth.send_magic_link

檔案: lib/auth.ts

登入魔法連結發送流程。

Attributes:

  • auth.email.masked (string): 遮罩後的 email (格式: XX***@domain.com)
  • auth.token.length (number): token 長度
  • auth.method (string): 固定值 "magic_link"
  • auth.ip.masked (string, conditional): 遮罩後的 IP 地址 (前 8 碼 + ***)
    • 條件: 當請求中有 IP 資訊時
  • auth.locale (string): 語系 (zh-Hant, en, zh-Hans)
  • magic_link_attempt.id (string, conditional): 嘗試記錄 ID
    • 條件: 成功建立嘗試記錄後

Events:

  • auth.rate_limit.check_start: 開始檢查速率限制
  • auth.rate_limit.throttled: 達到速率限制
    • reason: 限制原因 (recent_attempt_30s, failed_attempts_limit, daily_login_limit, ip_daily_limit)
    • count (conditional): 失敗次數或每日登入次數
  • auth.rate_limit.attempt_recorded: 記錄嘗試
  • auth.rate_limit.transaction_conflict: 交易衝突
  • auth.url_parse_error: URL 解析錯誤
  • auth.email.send_start: 開始發送 email
  • auth.email.send_complete: Email 發送完成

route.public.auth.get_permissions

檔案: routes/public/auth.ts

取得使用者權限資訊。

Attributes:

  • auth.authenticated (boolean): 是否已認證
  • auth.user.id (string, conditional): 使用者 ID
    • 條件: 當使用者已登入時
  • auth.user.role (string, conditional): 使用者角色
    • 條件: 當使用者已登入且找到使用者時
  • auth.permissions.count (number, conditional): 權限數量
    • 條件: 當使用者已登入時

Events:

  • auth.permissions.no_session: 無 session
  • auth.permissions.user_not_found: 找不到使用者

邀請碼相關 (Invitation Codes)

route.invitation_codes.verify

檔案: routes/public/invitationCodes.ts

驗證邀請碼是否有效。

Attributes:

  • invitation_code.masked (string): 遮罩的邀請碼 (格式: XX****XX)
  • ticket.id (string): 票券 ID
  • event.id (string, conditional): 活動 ID
    • 條件: 找到票券後
  • invitation_code.id (string, conditional): 邀請碼 ID
    • 條件: 找到邀請碼後
  • invitation_code.usage_count (number, conditional): 已使用次數
    • 條件: 找到邀請碼後
  • invitation_code.usage_limit (number, conditional): 使用上限 (-1 表示無限制)
    • 條件: 找到邀請碼後
  • available_tickets.count (number): 可用票券數量

Events:

  • validation.failed: 驗證失敗
    • error.reason: missing_required_fields
  • ticket.lookup: 查詢票券
  • validation.result: 驗證結果
    • result: invalid_ticket, code_not_found, expired, not_yet_valid, usage_limit_exceeded, valid
    • valid_until (conditional): 過期時間
    • valid_from (conditional): 生效時間
  • tickets.lookup: 查詢票券列表

route.invitation_codes.get_info

檔案: routes/public/invitationCodes.ts

取得邀請碼詳細資訊。

Attributes:

  • invitation_code.masked (string): 遮罩的邀請碼
  • ticket.id (string): 票券 ID
  • invitation_code.id (string, conditional): 邀請碼 ID
    • 條件: 找到邀請碼後
  • invitation_code.usage_count (number, conditional): 已使用次數
    • 條件: 找到邀請碼後
  • invitation_code.usage_limit (number, conditional): 使用上限
    • 條件: 找到邀請碼後

Events:

  • invitation_code.lookup: 查詢邀請碼
  • invitation_code.not_found: 找不到邀請碼
  • validation.result: 驗證結果
    • result: expired, not_yet_valid, usage_limit_exceeded, valid

route.admin.invitation_codes.create

檔案: routes/admin/invitationCodes.ts

建立新邀請碼 (Admin)。

Attributes:

  • invitation_code.code.masked (string): 遮罩的邀請碼
  • invitation_code.ticket_id (string): 票券 ID
  • invitation_code.id (string, conditional): 建立後的邀請碼 ID
    • 條件: 成功建立後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 成功建立後
  • event.id (string, conditional): 活動 ID
    • 條件: 取得票券資訊後

Events:

  • invitation_code.checking_existing: 檢查是否已存在
  • invitation_code.already_exists: 邀請碼已存在
  • invitation_code.creating: 建立邀請碼
  • invitation_code.created: 建立成功

route.admin.invitation_codes.get

檔案: routes/admin/invitationCodes.ts

取得邀請碼詳細資訊 (Admin)。

Attributes:

  • invitation_code.id (string): 邀請碼 ID
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到邀請碼後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到邀請碼且有關聯活動時
  • invitation_code.code.masked (string, conditional): 遮罩的邀請碼
    • 條件: 找到邀請碼後
  • invitation_code.used_count (number, conditional): 已使用次數
    • 條件: 找到邀請碼後

Events:

  • invitation_code.fetching: 取得邀請碼
  • invitation_code.not_found: 找不到邀請碼

route.admin.invitation_codes.update

檔案: routes/admin/invitationCodes.ts

更新邀請碼 (Admin)。

Attributes:

  • invitation_code.id (string): 邀請碼 ID
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到邀請碼後
  • invitation_code.existing.used_count (number, conditional): 現有使用次數
    • 條件: 找到邀請碼後

Events:

  • invitation_code.fetching_existing: 取得現有邀請碼
  • invitation_code.not_found: 找不到邀請碼
  • invitation_code.checking_code_conflict: 檢查邀請碼衝突
  • invitation_code.code_conflict: 邀請碼衝突
  • invitation_code.updating: 更新邀請碼
  • invitation_code.updated: 更新成功

route.admin.invitation_codes.delete

檔案: routes/admin/invitationCodes.ts

刪除邀請碼 (Admin)。

Attributes:

  • invitation_code.id (string): 邀請碼 ID
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到邀請碼後
  • invitation_code.used_count (number, conditional): 已使用次數
    • 條件: 找到邀請碼後

Events:

  • invitation_code.fetching: 取得邀請碼
  • invitation_code.not_found: 找不到邀請碼
  • invitation_code.has_been_used: 邀請碼已被使用
  • invitation_code.deleting: 刪除邀請碼
  • invitation_code.deleted: 刪除成功

route.admin.invitation_codes.list

檔案: routes/admin/invitationCodes.ts

列出邀請碼清單 (Admin)。

Attributes:

  • invitation_codes.has_user_permissions (boolean): 使用者是否有特定權限
  • invitation_codes.count (number): 邀請碼數量

Events:

  • invitation_codes.fetching: 取得邀請碼列表
  • invitation_codes.fetched: 取得成功

route.admin.invitation_codes.bulkCreate

檔案: routes/admin/invitationCodes.ts

批次建立邀請碼 (Admin)。

Attributes:

  • invitation_codes.bulk.count (number): 批次數量
  • invitation_codes.bulk.ticket_id (string): 票券 ID
  • ticket.id (string): 票券 ID
  • event.id (string, conditional): 活動 ID
    • 條件: 找到票券後
  • invitation_codes.created_count (number): 實際建立數量

Events:

  • invitation_codes.checking_ticket: 檢查票券
  • invitation_codes.ticket_not_found: 找不到票券
  • invitation_codes.generating_codes: 生成邀請碼
  • invitation_codes.generation_failed: 生成失敗
  • invitation_codes.creating_batch: 批次建立
  • invitation_codes.batch_created: 批次建立成功

route.admin.invitation_codes.sendEmail

檔案: routes/admin/invitationCodes.ts

發送邀請碼 Email (Admin)。

Attributes:

  • invitation_code.email.recipient.masked (string): 遮罩的收件人 email
  • invitation_code.code.masked (string): 遮罩的邀請碼
  • invitation_code.id (string, conditional): 邀請碼 ID
    • 條件: 找到邀請碼後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到邀請碼後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到邀請碼後
  • invitation_code.event_id (string, conditional): 活動 ID (重複)
    • 條件: 找到邀請碼後
  • invitation_code.ticket_id (string, conditional): 票券 ID (重複)
    • 條件: 找到邀請碼後

Events:

  • invitation_code.fetching: 取得邀請碼
  • invitation_code.not_found: 找不到邀請碼
  • invitation_code.sending_email: 發送 email
  • invitation_code.email_sent: Email 發送成功

推薦相關 (Referrals)

route.admin.referrals.overview

檔案: routes/admin/referrals.ts

推薦機制總覽統計 (Admin)。

Attributes:

  • referrals.total_count (number): 總推薦數
  • referrals.conversion_rate (number): 轉換率
  • referrals.top_referrers_count (number): 前幾名推薦者數量

Events:

  • referrals.fetching_stats: 取得統計資料
  • referrals.fetching_top_referrers: 取得排行榜

route.admin.referrals.leaderboard

檔案: routes/admin/referrals.ts

推薦排行榜 (Admin)。

Attributes:

  • referrals.leaderboard.limit (number): 限制筆數
  • referrals.leaderboard.count (number): 實際回傳筆數

Events:

  • referrals.fetching_leaderboard: 取得排行榜
  • referrals.leaderboard_fetched: 取得成功

route.admin.referrals.tree

檔案: routes/admin/referrals.ts

推薦樹狀圖 (Admin)。

Attributes:

  • referrals.tree.registration_id (string): 報名 ID
  • registration.id (string, conditional): 推薦 ID
    • 條件: 找到報名記錄且有推薦碼時

Events:

  • referrals.fetching_tree: 取得推薦樹
  • referrals.registration_not_found: 找不到報名記錄
  • referrals.building_tree: 建立樹狀結構
  • referrals.tree_built: 建立成功

route.admin.referrals.qualified

檔案: routes/admin/referrals.ts

達標推薦者名單 (Admin)。

Attributes:

  • referrals.qualified.min_referrals (number): 最小推薦數
  • referrals.qualified.total_count (number): 總數
  • referrals.qualified.filtered_count (number): 篩選後數量

Events:

  • referrals.fetching_qualified: 取得達標者
  • referrals.qualified_filtered: 篩選完成

route.admin.referrals.draw

檔案: routes/admin/referrals.ts

推薦者抽獎 (Admin)。

Attributes:

  • referrals.draw.min_referrals (number): 最小推薦數
  • referrals.draw.count (number): 抽選人數
  • referrals.draw.eligible_count (number): 符合資格人數
  • referrals.draw.actual_count (number): 實際抽選人數

Events:

  • referrals.fetching_candidates: 取得候選人
  • referrals.no_eligible_candidates: 無符合資格者
  • referrals.performing_draw: 執行抽選
  • referrals.draw_completed: 抽選完成

route.admin.referrals.stats

檔案: routes/admin/referrals.ts

推薦統計報表 (Admin)。

Attributes:

  • referrals.stats.usage_count (number): 推薦碼使用次數
  • referrals.stats.total_registrations (number): 總報名數
  • referrals.stats.conversion_rate (number): 轉換率
  • referrals.stats.top_sources_count (number): 熱門來源數量

Events:

  • referrals.fetching_usage_data: 取得使用資料
  • referrals.calculating_daily_stats: 計算每日統計
  • referrals.fetching_registration_count: 取得報名數
  • referrals.calculating_top_sources: 計算熱門來源
  • referrals.stats_calculated: 統計完成

route.referrals.get_referral_link

檔案: routes/public/referrals.ts

取得推薦連結。

Attributes:

  • registration.id.masked (string): 遮罩的報名 ID
  • registration.id (string, conditional): 報名 ID
    • 條件: 找到報名記錄後
  • registration.status (string, conditional): 報名狀態
    • 條件: 找到報名記錄後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名記錄後
  • referral.id (string, conditional): 推薦 ID
    • 條件: 建立或找到推薦碼後
  • referral.code (string, conditional): 推薦碼
    • 條件: 建立或找到推薦碼後

Events:

  • referral.fetch_registration: 取得報名記錄
  • referral.fetch_existing: 取得現有推薦碼
  • referral.generate_code: 生成推薦碼
  • referral.create: 建立推薦碼

route.referrals.get_referral_stats

檔案: routes/public/referrals.ts

取得個人推薦統計。

Attributes:

  • registration.id.masked (string): 遮罩的報名 ID
  • user.authenticated (boolean): 是否已認證
  • user.id (string, conditional): 使用者 ID
    • 條件: 已認證時
  • referral.id (string, conditional): 推薦 ID
    • 條件: 找到推薦碼後
  • referral.total_count (number): 推薦總數
  • referral.successful_count (number): 成功推薦數

Events:

  • auth.check_session: 檢查 session
  • referral.fetch: 取得推薦碼
  • referral.fetch_usages: 取得使用記錄

route.referrals.validate_referral

檔案: routes/public/referrals.ts

驗證推薦碼。

Attributes:

  • referral.code (string): 推薦碼
  • event.id (string): 活動 ID
  • referral.id (string, conditional): 推薦 ID
    • 條件: 找到推薦碼後
  • referral.registration_status (string, conditional): 報名狀態
    • 條件: 找到推薦碼後

Events:

  • referral.validate: 驗證推薦碼

報名相關 (Registrations)

route.public.registrations.create

檔案: routes/public/registrations.ts

建立新報名。

Attributes:

  • registration.email.masked (string): 遮罩的 email
  • event.id (string): 活動 ID
  • ticket.id (string): 票券 ID
  • user.id (string): 使用者 ID
  • ticket.sold_count (number): 已售數量
  • ticket.quantity (number): 總數量
  • invitation_code.id (string, conditional): 邀請碼 ID
    • 條件: 使用邀請碼時
  • invitation_code.used_count (number, conditional): 邀請碼已使用次數
    • 條件: 使用邀請碼時
  • referral_code.id (string, conditional): 推薦碼 ID
    • 條件: 使用推薦碼時
  • registration.id (string, conditional): 報名 ID
    • 條件: 成功建立後

Events:

  • checking_existing_registration: 檢查已存在報名
  • user_already_registered: 已報名
  • fetching_event_and_ticket: 取得活動和票券
  • event.not_found: 找不到活動
  • ticket.not_found: 找不到票券
  • ticket.sold_out: 票券售完
  • ticket.not_yet_on_sale: 尚未開賣
    • ticket.saleStart: 開賣時間
  • ticket.sale_ended: 販售結束
    • ticket.saleEnd: 結束時間
  • validating_required_invitation_code: 驗證必要邀請碼
  • invitation_code.missing: 缺少邀請碼
  • invitation_code.invalid: 無效邀請碼
  • invitation_code.expired: 邀請碼過期
  • invitation_code.not_yet_valid: 邀請碼尚未生效
  • invitation_code.usage_limit_exceeded: 邀請碼達使用上限
  • invitation_code.wrong_ticket: 邀請碼不適用此票券
  • checking_sms_verification: 檢查簡訊驗證
  • sms_verification.not_verified: 未完成簡訊驗證
  • validating_referral_code: 驗證推薦碼
  • referral_code.invalid: 無效推薦碼
  • validating_form_data: 驗證表單資料
  • form_validation.failed: 表單驗證失敗
  • starting_registration_transaction: 開始交易
  • registration_transaction.success: 交易成功
    • registration.id: 報名 ID
  • sending_confirmation_email: 發送確認 email
  • confirmation_email.failed: Email 發送失敗
  • dispatching_webhook: 發送 webhook
  • webhook.failed: Webhook 失敗
  • transaction_error.ticket_sold_out: 交易中票券售完
  • transaction_error.already_registered: 交易中已報名
  • transaction_error.invitation_code_invalid: 交易中邀請碼無效
  • transaction_error.invitation_code_limit: 交易中邀請碼達上限
  • transaction_error.conflict: 交易衝突
    • prisma.error_code: Prisma 錯誤碼
  • transaction_error.duplicate_email: Email 重複

route.public.registrations.list

檔案: routes/public/registrations.ts

列出使用者報名清單。

Attributes:

  • user.id (string): 使用者 ID
  • registrations.count (number): 報名數量

Events:

  • fetching_user_registrations: 取得使用者報名
  • processing_registrations: 處理報名資料

route.public.registrations.get

檔案: routes/public/registrations.ts

取得單一報名詳情。

Attributes:

  • user.id (string): 使用者 ID
  • registration.id (string): 報名 ID
  • registration.status (string, conditional): 報名狀態
    • 條件: 找到報名後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到報名後

Events:

  • fetching_registration: 取得報名
  • registration.not_found: 找不到報名

route.public.registrations.update

檔案: routes/public/registrations.ts

更新報名資料。

Attributes:

  • user.id (string): 使用者 ID
  • registration.id (string): 報名 ID
  • registration.status (string, conditional): 報名狀態
    • 條件: 找到報名後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到報名後

Events:

  • form_data.invalid: 表單資料無效
  • fetching_registration_and_form_fields: 取得報名和表單欄位
  • registration.not_found: 找不到報名
  • registration.not_confirmed: 報名未確認
  • event.already_started: 活動已開始
  • edit_deadline.passed: 編輯截止時間已過
  • ticket_sale.ended: 票券販售結束
  • validating_form_data: 驗證表單資料
  • form_validation.failed: 表單驗證失敗
  • updating_registration: 更新報名

route.public.registrations.cancel

檔案: routes/public/registrations.ts

取消報名。

Attributes:

  • user.id (string): 使用者 ID
  • registration.id (string): 報名 ID
  • registration.status (string, conditional): 報名狀態
    • 條件: 找到報名後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到報名後

Events:

  • fetching_registration: 取得報名
  • registration.not_found: 找不到報名
  • registration.not_confirmed: 報名未確認
  • event.already_started: 活動已開始
  • starting_cancellation_transaction: 開始取消交易
  • cancellation_transaction.success: 取消成功
  • sending_cancellation_email: 發送取消 email
  • cancellation_email.failed: Email 發送失敗
  • dispatching_webhook: 發送 webhook
  • webhook.failed: Webhook 失敗
  • transaction_error.already_cancelled: 已取消
  • transaction_error.conflict: 交易衝突
    • prisma.error_code: Prisma 錯誤碼

route.admin.registrations.list

檔案: routes/admin/registrations.ts

列出報名清單 (Admin)。

Attributes:

  • registrations.page (number): 頁碼
  • registrations.limit (number): 每頁筆數
  • registrations.filter.eventId (string): 篩選活動 ID
  • registrations.filter.status (string): 篩選狀態
  • registrations.filter.userId (string): 篩選使用者 ID
  • registrations.total (number): 總筆數
  • registrations.found (number): 找到筆數

Events:

  • database.query.count: 計數查詢
  • database.query.findMany: 查詢多筆
  • registrations.parse: 解析報名資料

route.admin.registrations.get

檔案: routes/admin/registrations.ts

取得報名詳情 (Admin)。

Attributes:

  • registration.id (string): 報名 ID
  • user.id (string, conditional): 使用者 ID
    • 條件: 找到報名後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到報名後
  • registration.status (string, conditional): 報名狀態
    • 條件: 找到報名後

Events:

  • database.query.findUnique: 查詢單筆
  • registration.not_found: 找不到報名
  • registration.parse: 解析報名

route.admin.registrations.update

檔案: routes/admin/registrations.ts

更新報名 (Admin)。

Attributes:

  • registration.id (string): 報名 ID
  • user.id (string, conditional): 使用者 ID
    • 條件: 找到報名後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到報名後
  • registration.status.old (string, conditional): 舊狀態
    • 條件: 找到報名後
  • registration.status.new (string, conditional): 新狀態
    • 條件: 更新狀態時

Events:

  • database.query.findUnique: 查詢單筆
  • registration.not_found: 找不到報名
  • registration.update.event_ended: 活動已結束
  • database.query.update: 更新資料
  • registration.updated: 更新成功

route.admin.registrations.export

檔案: routes/admin/registrations.ts

匯出報名資料 (Admin)。

Attributes:

  • export.format (string): 匯出格式 (csv, excel)
  • export.filter.eventId (string): 篩選活動 ID
  • export.filter.status (string): 篩選狀態
  • export.count (number): 匯出筆數
  • export.filename (string): 檔案名稱
  • export.size (number): 檔案大小 (bytes)

Events:

  • database.query.findMany: 查詢多筆
  • export.generate_csv: 生成 CSV

route.admin.registrations.delete

檔案: routes/admin/registrations.ts

刪除報名 (Admin)。

Attributes:

  • registration.id (string): 報名 ID
  • user.id (string, conditional): 使用者 ID
    • 條件: 找到報名後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到報名後
  • ticket.id (string, conditional): 票券 ID
    • 條件: 找到報名後
  • registration.ticketId (string, conditional): 票券 ID (重複)
    • 條件: 找到報名後

Events:

  • database.query.findUnique: 查詢單筆
  • registration.not_found: 找不到報名
  • database.query.delete: 刪除資料
  • database.query.update_ticket_count: 更新票券計數
  • registration.deleted: 刪除成功

route.admin.registrations.google_sheets_sync

檔案: routes/admin/registrations.ts

同步到 Google Sheets (Admin)。

Attributes:

  • googlesheets.eventId (string): 活動 ID
  • googlesheets.url.masked (string): 遮罩的 Google Sheets URL
  • googlesheets.spreadsheetId (string, conditional): 試算表 ID
    • 條件: 成功解析 URL 後
  • event.id (string, conditional): 活動 ID
    • 條件: 找到活動後
  • googlesheets.registrations.count (number, conditional): 報名筆數
    • 條件: 查詢報名後

Events:

  • googlesheets.invalid_url: URL 無效
  • database.query.findUnique: 查詢單筆
  • event.not_found: 找不到活動
  • database.query.findMany: 查詢多筆
  • googlesheets.export.start: 開始匯出
  • googlesheets.export.failed: 匯出失敗
    • error.message: 錯誤訊息
  • googlesheets.export.success: 匯出成功
  • database.query.update: 更新資料

活動相關 (Events)

route.public.events.get_info

檔案: routes/public/events.ts

取得活動公開資訊。

Attributes:

  • event.lookup_id (string): 查詢 ID (可能是 ID, slug 或短 ID)
  • event.id (string, conditional): 活動 ID
    • 條件: 找到活動後
  • event.slug (string, conditional): 活動 slug
    • 條件: 找到活動後

Events:

  • event.not_found: 找不到活動

route.public.events.get_tickets

檔案: routes/public/events.ts

取得活動可購買票券。

Attributes:

  • event.lookup_id (string): 查詢 ID
  • event.id (string, conditional): 活動 ID
    • 條件: 找到活動後
  • tickets.count (number): 票券數量

Events:

  • event.lookup: 查詢活動
  • event.not_found: 找不到活動
  • tickets.lookup: 查詢票券

route.public.events.list

檔案: routes/public/events.ts

列出所有活動。

Attributes:

  • events.filter.upcoming (boolean): 是否只顯示即將開始的活動
  • events.count (number): 活動數量

Events:

  • events.lookup: 查詢活動

route.public.events.get_stats

檔案: routes/public/events.ts

取得活動統計資訊。

Attributes:

  • event.lookup_id (string): 查詢 ID
  • event.id (string, conditional): 活動 ID
    • 條件: 找到活動後
  • stats.total_tickets (number): 總票券數
  • stats.sold_tickets (number): 已售票券數
  • stats.available_tickets (number): 可用票券數
  • stats.registration_rate (number): 報名率
  • stats.confirmed_registrations (number): 已確認報名數

Events:

  • event.lookup: 查詢活動
  • event.not_found: 找不到活動

route.public.events.get_form_fields

檔案: routes/public/events.ts

取得票券表單欄位。

Attributes:

  • ticket.id (string): 票券 ID
  • event.id (string, conditional): 活動 ID
    • 條件: 找到票券後
  • form_fields.count (number): 表單欄位數量

Events:

  • ticket.lookup: 查詢票券
  • ticket.not_found_or_inactive: 找不到或未啟用票券
  • form_fields.lookup: 查詢表單欄位

route.admin.events.create

檔案: routes/admin/events.ts

建立活動 (Admin)。

Attributes:

  • event.id (string, conditional): 活動 ID
    • 條件: 成功建立後

Events:

  • event.creating: 建立活動
  • event.created: 建立成功

route.admin.events.get

檔案: routes/admin/events.ts

取得活動詳情 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • event.tickets_count (number, conditional): 票券數量
    • 條件: 找到活動後
  • event.registrations_count (number, conditional): 報名數量
    • 條件: 找到活動後

Events:

  • event.fetching: 取得活動
  • event.not_found: 找不到活動

route.admin.events.update

檔案: routes/admin/events.ts

更新活動 (Admin)。

Attributes:

  • event.id (string): 活動 ID

Events:

  • event.fetching_existing: 取得現有活動
  • event.not_found: 找不到活動
  • event.updating: 更新活動
  • event.updated: 更新成功

route.admin.events.delete

檔案: routes/admin/events.ts

刪除活動 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • event.registrations_count (number, conditional): 報名數量
    • 條件: 找到活動後

Events:

  • event.checking_registrations: 檢查報名記錄
  • event.not_found: 找不到活動
  • event.has_registrations: 已有報名
  • event.deleting: 刪除活動
  • event.deleted: 刪除成功

route.admin.events.list

檔案: routes/admin/events.ts

列出活動清單 (Admin)。

Attributes:

  • events.filter.is_active (boolean): 是否篩選啟用狀態
  • events.has_user_permissions (boolean): 使用者是否有特定權限
  • events.user_permissions_count (number, conditional): 使用者權限數量
    • 條件: 有特定權限時
  • events.count (number): 活動數量

Events:

  • events.fetching: 取得活動列表
  • events.fetched: 取得成功

票券相關 (Tickets)

route.public.tickets.get_public_ticket

檔案: routes/public/tickets.ts

取得票券公開資訊。

Attributes:

  • ticket.id (string): 票券 ID
  • ticket.price (number, conditional): 價格
    • 條件: 找到票券後
  • ticket.quantity (number, conditional): 數量
    • 條件: 找到票券後
  • ticket.sold_count (number, conditional): 已售數量
    • 條件: 找到票券後
  • ticket.require_invite_code (boolean, conditional): 是否需要邀請碼
    • 條件: 找到票券後
  • ticket.require_sms_verification (boolean, conditional): 是否需要簡訊驗證
    • 條件: 找到票券後
  • ticket.available (number, conditional): 可用數量
    • 條件: 找到票券後

Events:

  • ticket.not_found_or_inactive: 找不到或未啟用票券

route.admin.tickets.create

檔案: routes/admin/tickets.ts

建立票券 (Admin)。

Attributes:

  • ticket.eventId (string): 活動 ID
  • ticket.price (number): 價格
  • ticket.quantity (number): 數量
  • ticket.requireInviteCode (boolean): 是否需要邀請碼
  • ticket.hidden (boolean): 是否隱藏
  • ticket.order (number): 排序
  • ticket.id (string, conditional): 票券 ID
    • 條件: 成功建立後

Events:

  • database.query.findUnique: 查詢單筆
  • event.not_found: 找不到活動
  • ticket.validation.invalid_date_format: 日期格式無效
  • ticket.validation.invalid_date_range: 日期範圍無效
  • ticket.validation.sale_end_after_event_start: 販售結束時間晚於活動開始
  • database.query.findFirst: 查詢第一筆
  • database.query.create: 建立資料
  • ticket.created: 建立成功

route.admin.tickets.get

檔案: routes/admin/tickets.ts

取得票券詳情 (Admin)。

Attributes:

  • ticket.id (string): 票券 ID
  • ticket.price (number, conditional): 價格
    • 條件: 找到票券後
  • ticket.sold_count (number, conditional): 已售數量
    • 條件: 找到票券後
  • ticket.registrations.count (number, conditional): 報名數量
    • 條件: 找到票券後

Events:

  • database.query.findUnique: 查詢單筆
  • ticket.not_found: 找不到票券

route.admin.tickets.update

檔案: routes/admin/tickets.ts

更新票券 (Admin)。

Attributes:

  • ticket.id (string): 票券 ID
  • ticket.quantity.new (number, conditional): 新數量
    • 條件: 更新數量時
  • ticket.price.new (number, conditional): 新價格
    • 條件: 更新價格時

Events:

  • database.query.findUnique: 查詢單筆
  • ticket.not_found: 找不到票券
  • ticket.validation.quantity_below_sold: 數量低於已售數量
    • ticket.quantity.new: 新數量
    • ticket.sold_count: 已售數量
  • ticket.validation.invalid_sale_start_format: 販售開始日期格式無效
  • ticket.validation.invalid_sale_end_format: 販售結束日期格式無效
  • ticket.validation.invalid_sale_date_range: 販售日期範圍無效
  • ticket.validation.sale_end_after_event_start: 販售結束時間晚於活動開始
  • database.query.update: 更新資料
  • ticket.updated: 更新成功

route.admin.tickets.delete

檔案: routes/admin/tickets.ts

刪除票券 (Admin)。

Attributes:

  • ticket.id (string): 票券 ID
  • ticket.registrations.count (number, conditional): 報名數量
    • 條件: 找到票券後

Events:

  • database.query.findUnique: 查詢單筆
  • ticket.not_found: 找不到票券
  • ticket.validation.has_registrations: 已有報名
  • database.query.delete: 刪除資料
  • ticket.deleted: 刪除成功

route.admin.tickets.list

檔案: routes/admin/tickets.ts

列出票券清單 (Admin)。

Attributes:

  • tickets.filter.eventId (string): 篩選活動 ID
  • tickets.filter.isActive (string): 篩選啟用狀態
  • tickets.found (number): 找到數量

Events:

  • database.query.findMany: 查詢多筆
  • tickets.calculate_availability: 計算可用性

route.admin.tickets.analytics

檔案: routes/admin/tickets.ts

取得票券分析 (Admin)。

Attributes:

  • ticket.id (string): 票券 ID
  • ticket.sold_count (number, conditional): 已售數量
    • 條件: 找到票券後
  • ticket.price (number, conditional): 價格
    • 條件: 找到票券後
  • analytics.totalSold (number): 總銷售數
  • analytics.totalRevenue (number): 總收入
  • analytics.availableQuantity (number): 可用數量

Events:

  • database.query.findUnique: 查詢單筆
  • ticket.not_found: 找不到票券
  • database.query.analytics: 查詢分析資料
  • analytics.calculated: 計算完成

route.admin.tickets.reorder

檔案: routes/admin/tickets.ts

重新排序票券 (Admin)。

Attributes:

  • tickets.reorder.count (number): 重新排序數量
  • tickets.eventId (string, conditional): 活動 ID
    • 條件: 驗證票券後

Events:

  • tickets.validation.empty_list: 列表為空
  • database.query.findMany: 查詢多筆
  • tickets.validation.some_not_found: 部分票券找不到
    • tickets.requested: 請求數量
    • tickets.found: 找到數量
  • tickets.validation.multiple_events: 多個活動
    • events.count: 活動數量
  • tickets.validation.duplicate_orders: 重複排序
  • database.transaction.reorder: 交易重新排序
  • tickets.reordered: 重新排序成功

簡訊驗證 (SMS Verification)

route.sms_verification.send

檔案: routes/public/smsVerification.ts

發送簡訊驗證碼。

Attributes:

  • auth.user.id (string): 使用者 ID
  • sms.phone.masked (string): 遮罩的手機號碼 (格式: ****XXXX)
  • sms.locale (string): 語系
  • sms.code.length (number): 驗證碼長度
  • sms_verification.attempt_number (number): 當日第幾次嘗試

Events:

  • sms_verification.unauthorized: 未授權
  • sms_verification.turnstile_validation_start: 開始驗證 Turnstile
  • sms_verification.turnstile_failed: Turnstile 驗證失敗
    • reason: 失敗原因
  • sms_verification.turnstile_validated: Turnstile 驗證成功
  • sms_verification.invalid_phone_format: 手機號碼格式無效
  • sms_verification.already_verified: 已驗證
  • sms_verification.phone_in_use: 手機號碼已被使用
  • sms_verification.rate_limit_check_start: 開始檢查速率限制
  • sms_verification.rate_limited: 達到速率限制
    • error: 限制訊息
  • sms_verification.rate_limit_passed: 通過速率限制
  • sms_verification.send_start: 開始發送簡訊
  • sms_verification.send_complete: 簡訊發送完成
  • sms_verification.send_failed: 簡訊發送失敗
  • sms_verification.transaction_conflict: 交易衝突

route.sms_verification.verify

檔案: routes/public/smsVerification.ts

驗證簡訊驗證碼。

Attributes:

  • auth.user.id (string): 使用者 ID
  • sms.phone.masked (string): 遮罩的手機號碼
  • sms.code.length (number): 驗證碼長度

Events:

  • sms_verification.unauthorized: 未授權
  • sms_verification.already_verified: 已驗證
  • sms_verification.lookup_code: 查詢驗證碼
  • sms_verification.code_not_found: 找不到驗證碼
  • sms_verification.code_expired: 驗證碼過期
  • sms_verification.phone_in_use: 手機號碼已被使用
  • sms_verification.update_verification: 更新驗證記錄
  • sms_verification.update_user: 更新使用者

route.sms_verification.get_status

檔案: routes/public/smsVerification.ts

取得手機驗證狀態。

Attributes:

  • auth.user.id (string): 使用者 ID
  • sms.phone_verified (boolean): 是否已驗證

Events:

  • sms_verification.unauthorized: 未授權

route.admin.sms_verification_logs.list

檔案: routes/admin/smsVerificationLogs.ts

取得簡訊驗證記錄 (Admin)。

Attributes:

  • sms_logs.page (number): 頁碼
  • sms_logs.limit (number): 每頁筆數
  • sms_logs.filter.userId (string): 篩選使用者 ID
  • sms_logs.filter.phoneNumber.masked (string): 篩選遮罩手機號碼
  • sms_logs.filter.verified (string): 篩選驗證狀態
  • sms_logs.total (number): 總筆數
  • sms_logs.found (number): 找到筆數

Events:

  • database.query.count: 計數查詢
  • database.query.findMany: 查詢多筆
  • sms_logs.sanitize: 清理資料

route.admin.sms_verification_logs.stats

檔案: routes/admin/smsVerificationLogs.ts

取得簡訊驗證統計 (Admin)。

Attributes:

  • sms_stats.type (string): 統計類型 "aggregate"
  • sms_stats.total_sent (number): 總發送數
  • sms_stats.total_verified (number): 總驗證數
  • sms_stats.total_expired (number): 總過期數
  • sms_stats.success_rate (number): 成功率
  • sms_stats.recent_count (number): 最近 7 天數量

Events:

  • database.query.aggregate: 聚合查詢
  • database.query.recent_activity: 查詢最近活動

sms.send

檔案: lib/sms.ts

發送簡訊 (底層)。

Attributes:

  • sms.recipient.masked (string): 遮罩的收件人號碼
  • sms.message.length (number): 訊息長度
  • sms.provider (string): 固定值 "twsms"
  • http.status_code (number): HTTP 狀態碼
  • sms.api.code (string): API 回應碼
  • sms.msgid (string): 訊息 ID

Events:

  • twsms.api.request: API 請求
  • twsms.api.error: API 錯誤
    • error.code: 錯誤碼
    • error.message: 錯誤訊息

sms.query_status

檔案: lib/sms.ts

查詢簡訊狀態 (底層)。

Attributes:

  • sms.recipient.masked (string): 遮罩的收件人號碼
  • sms.msgid (string): 訊息 ID
  • sms.provider (string): 固定值 "twsms"
  • http.status_code (number): HTTP 狀態碼
  • sms.api.code (string): API 回應碼
  • sms.status.code (string): 狀態碼
  • sms.status.text (string): 狀態文字

Events:

  • twsms.api.status_query: 狀態查詢

sms.send_verification_code

檔案: lib/sms.ts

發送驗證碼簡訊 (底層)。

Attributes:

  • sms.recipient.masked (string): 遮罩的收件人號碼
  • sms.type (string): 固定值 "verification_code"
  • sms.locale (string): 語系
  • sms.code.length (number): 驗證碼長度

Turnstile 驗證

turnstile.validate

檔案: lib/turnstile.ts

驗證 Cloudflare Turnstile token。

Attributes:

  • turnstile.token.length (number): Token 長度
  • turnstile.expected_action (string): 預期動作
  • turnstile.expected_hostname (string): 預期主機名稱
  • turnstile.remoteip.masked (string, conditional): 遮罩的遠端 IP
    • 條件: 提供 remoteip 時
  • http.status_code (number): HTTP 狀態碼
  • turnstile.token.age_minutes (number, conditional): Token 年齡 (分鐘)
    • 條件: 回應中有 challenge_ts 時

Events:

  • turnstile.validation.invalid_token_format: Token 格式無效
  • turnstile.validation.bypassed: 使用繞過密鑰
  • turnstile.validation.token_too_long: Token 太長
  • turnstile.validation.misconfigured: 設定錯誤
  • turnstile.api.request: API 請求
  • turnstile.validation.failed: 驗證失敗
    • error.codes: 錯誤碼列表
  • turnstile.validation.action_mismatch: 動作不符
    • expected: 預期動作
    • received: 實際動作
  • turnstile.validation.hostname_mismatch: 主機名稱不符
    • expected: 預期主機名稱
    • received: 實際主機名稱
  • turnstile.validation.token_age_warning: Token 年齡警告
    • age_minutes: 年齡 (分鐘)
  • turnstile.validation.timeout: 驗證逾時

turnstile.validate_with_retry

檔案: lib/turnstile.ts

重試驗證 Turnstile token。

Attributes:

  • turnstile.max_retries (number): 最大重試次數
  • turnstile.token.length (number): Token 長度
  • turnstile.idempotency_key (string): 冪等金鑰

Events:

  • turnstile.retry.attempt: 重試嘗試
    • attempt: 嘗試次數
    • max_retries: 最大重試次數
  • turnstile.retry.max_attempts_reached: 達到最大嘗試次數
  • turnstile.retry.backoff: 等待重試
    • backoff_ms: 等待時間 (毫秒)

電子郵件 (Email)

email.send_magic_link

檔案: utils/email.ts

發送登入魔法連結 email。

Attributes:

  • email.recipient.masked (string): 遮罩的收件人 email
  • email.type (string): 固定值 "magic_link"
  • email.provider (string): Email 提供商 (aws-ses, mailtrap)

Events:

  • {provider}.api.request: API 請求 (provider 為 aws-sesmailtrap)

email.send_registration_confirmation

檔案: utils/email.ts

發送報名確認 email。

Attributes:

  • email.recipient.masked (string): 遮罩的收件人 email
  • email.type (string): 固定值 "registration_confirmation"
  • email.provider (string): Email 提供商
  • event.id (string): 活動 ID
  • ticket.id (string): 票券 ID
  • registration.id (string): 報名 ID
  • user.id (string): 使用者 ID

Events:

  • {provider}.api.request: API 請求

email.send_cancellation

檔案: utils/email.ts

發送取消報名 email。

Attributes:

  • email.recipient.masked (string): 遮罩的收件人 email
  • email.type (string): 固定值 "cancellation"
  • email.provider (string): Email 提供商

Events:

  • {provider}.api.request: API 請求

email.send_invitation_code

檔案: utils/email.ts

發送邀請碼 email。

Attributes:

  • email.recipient.masked (string): 遮罩的收件人 email
  • email.type (string): 固定值 "invitation_code"
  • email.provider (string): Email 提供商
  • invitation_code.code (string): 邀請碼

Events:

  • {provider}.api.request: API 請求

email.calculate_recipients

檔案: utils/email.ts

計算郵件收件人。

Attributes:

  • email.has_filters (boolean): 是否有篩選條件
  • email.recipient_count (number): 收件人數量
  • registration.id (string, conditional): 報名 ID
    • 條件: 有收件人時 (第一筆的 ID)

email.send_campaign

檔案: utils/email.ts

發送郵件活動。

Attributes:

  • email.type (string): 固定值 "campaign"
  • email.provider (string): Email 提供商
  • email.total_recipients (number): 總收件人數
  • email.campaign.subject (string): 郵件主旨
  • registration.id (string, conditional): 報名 ID
    • 條件: 有收件人時 (第一筆的 ID)
  • email.sent_count (number): 成功發送數
  • email.failed_count (number): 失敗數

Events:

  • campaign.batch.start: 批次開始
    • batch.index: 批次索引
    • batch.size: 批次大小
  • campaign.batch.complete: 批次完成
    • batch.index: 批次索引
    • batch.sent: 已發送數
    • batch.failed: 失敗數

route.admin.email_campaigns.list

檔案: routes/admin/emailCampaigns.ts

列出郵件活動 (Admin)。

Attributes:

  • pagination.page (number): 頁碼
  • pagination.limit (number): 每頁筆數
  • campaigns.count (number): 活動數量
  • campaigns.total (number): 總數

Events:

  • query.campaigns.start: 開始查詢

route.admin.email_campaigns.create

檔案: routes/admin/emailCampaigns.ts

建立郵件活動 (Admin)。

Attributes:

  • campaign.name (string): 活動名稱
  • campaign.subject (string): 郵件主旨
  • campaign.id (string): 活動 ID
  • campaign.creator_id (string): 建立者 ID
  • campaign.status (string): 狀態

Events:

  • validation.failed: 驗證失敗
    • reason: missing_content
  • campaign.create.start: 開始建立

route.admin.email_campaigns.get_status

檔案: routes/admin/emailCampaigns.ts

取得郵件活動狀態 (Admin)。

Attributes:

  • campaign.id (string): 活動 ID
  • campaign.status (string, conditional): 狀態
    • 條件: 找到活動後
  • campaign.sent_count (number, conditional): 已發送數
    • 條件: 找到活動後
  • campaign.total_count (number, conditional): 總數
    • 條件: 找到活動後

Events:

  • query.campaign.start: 開始查詢
  • campaign.not_found: 找不到活動

route.admin.email_campaigns.preview

檔案: routes/admin/emailCampaigns.ts

預覽郵件活動 (Admin)。

Attributes:

  • campaign.id (string): 活動 ID

Events:

  • query.campaign.start: 開始查詢
  • campaign.not_found: 找不到活動
  • query.sample_registration.start: 查詢範例報名
  • preview.populate_sample_data: 填充範例資料

route.admin.email_campaigns.calculate_recipients

檔案: routes/admin/emailCampaigns.ts

計算收件人數量 (Admin)。

Attributes:

  • campaign.id (string): 活動 ID
  • recipients.count (number): 收件人數量

Events:

  • query.campaign.start: 開始查詢
  • campaign.not_found: 找不到活動
  • calculate_recipients.start: 開始計算

route.admin.email_campaigns.send

檔案: routes/admin/emailCampaigns.ts

發送郵件活動 (Admin)。

Attributes:

  • campaign.id (string): 活動 ID
  • campaign.send_now (boolean): 是否立即發送
  • campaign.status (string, conditional): 狀態
    • 條件: 找到活動後
  • recipients.count (number, conditional): 收件人數量
    • 條件: 計算收件人後
  • campaign.sent_count (number, conditional): 已發送數
    • 條件: 發送完成後
  • campaign.total_recipients (number, conditional): 總收件人數
    • 條件: 發送完成後

Events:

  • query.campaign.start: 開始查詢
  • campaign.not_found: 找不到活動
  • validation.failed: 驗證失敗
    • reason: already_sent, cancelled, no_recipients
  • campaign.scheduled: 已排程
  • calculate_recipients.start: 開始計算收件人
  • campaign.update_status_sending: 更新狀態為發送中
  • campaign.send_emails.start: 開始發送 email
  • campaign.send_emails.complete: 發送完成
  • campaign.send_failed: 發送失敗

route.admin.email_campaigns.cancel

檔案: routes/admin/emailCampaigns.ts

取消郵件活動 (Admin)。

Attributes:

  • campaign.id (string): 活動 ID
  • campaign.status (string, conditional): 狀態
    • 條件: 找到活動後

Events:

  • query.campaign.start: 開始查詢
  • campaign.not_found: 找不到活動
  • validation.failed: 驗證失敗
    • reason: already_sent
  • campaign.cancel.start: 開始取消

Webhooks

route.admin.webhooks.get

檔案: routes/admin/webhooks.ts

取得 webhook 設定 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • webhook.id (string, conditional): Webhook ID
    • 條件: 找到 webhook 後
  • webhook.isActive (boolean, conditional): 是否啟用
    • 條件: 找到 webhook 後
  • webhook.eventTypes.count (number, conditional): 事件類型數量
    • 條件: 找到 webhook 後

Events:

  • database.query.webhook: 查詢 webhook

route.admin.webhooks.create

檔案: routes/admin/webhooks.ts

建立 webhook (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • webhook.url.masked (string): 遮罩的 webhook URL
  • webhook.eventTypes.count (number): 事件類型數量
  • webhook.id (string, conditional): Webhook ID
    • 條件: 成功建立後
  • validation.error (string, conditional): 驗證錯誤
    • 條件: 驗證失敗時
  • validation.field (string, conditional): 驗證欄位
    • 條件: 驗證失敗時

Events:

  • database.query.event: 查詢活動
  • database.check.webhook_exists: 檢查 webhook 是否存在
  • database.create.webhook: 建立 webhook

route.admin.webhooks.update

檔案: routes/admin/webhooks.ts

更新 webhook (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • webhook.url.masked (string): 遮罩的 webhook URL
  • webhook.id (string, conditional): Webhook ID
    • 條件: 找到 webhook 後
  • validation.error (string, conditional): 驗證錯誤
    • 條件: 驗證失敗時
  • validation.field (string, conditional): 驗證欄位
    • 條件: 驗證失敗時

Events:

  • database.query.webhook: 查詢 webhook
  • webhook.reset_failure_tracking: 重置失敗追蹤
  • database.update.webhook: 更新 webhook

route.admin.webhooks.delete

檔案: routes/admin/webhooks.ts

刪除 webhook (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • webhook.id (string, conditional): Webhook ID
    • 條件: 找到 webhook 後

Events:

  • database.query.webhook: 查詢 webhook
  • database.delete.webhook: 刪除 webhook

route.admin.webhooks.test

檔案: routes/admin/webhooks.ts

測試 webhook (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • webhook.url.masked (string): 遮罩的 webhook URL
  • webhook.test.success (boolean): 測試是否成功

Events:

  • webhook.test.start: 開始測試
  • webhook.test.failed: 測試失敗
    • error.message: 錯誤訊息

route.admin.webhooks.getFailedDeliveries

檔案: routes/admin/webhooks.ts

取得失敗的 webhook 投遞 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • pagination.page (number): 頁碼
  • pagination.limit (number): 每頁筆數
  • deliveries.total (number): 總數
  • deliveries.returned (number): 回傳數

Events:

  • database.query.failed_deliveries: 查詢失敗投遞

route.admin.webhooks.retryDelivery

檔案: routes/admin/webhooks.ts

重試失敗的 webhook 投遞 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • delivery.id (string): 投遞 ID
  • webhook.retry.success (boolean): 重試是否成功

Events:

  • webhook.retry.start: 開始重試
  • webhook.retry.not_eligible: 不符合重試資格

使用者管理 (Users)

route.admin.users.list

檔案: routes/admin/users.ts

列出使用者清單 (Admin)。

Attributes:

  • user.filter.role (string): 篩選角色
  • user.filter.isActive (string): 篩選啟用狀態
  • user.count (number): 使用者數量

Events:

  • database.query.users: 查詢使用者
  • users.transform: 轉換資料

route.admin.users.get

檔案: routes/admin/users.ts

取得使用者詳情 (Admin)。

Attributes:

  • user.id (string): 使用者 ID
  • user.role (string, conditional): 角色
    • 條件: 找到使用者後
  • user.registrations.count (number, conditional): 報名數量
    • 條件: 找到使用者後
  • user.sessions.count (number, conditional): Session 數量
    • 條件: 找到使用者後

Events:

  • database.query.user: 查詢使用者

route.admin.users.update

檔案: routes/admin/users.ts

更新使用者 (Admin)。

Attributes:

  • user.id (string): 使用者 ID
  • user.role.new (string, conditional): 新角色
    • 條件: 更新角色時
  • validation.error (string, conditional): 驗證錯誤
    • 條件: 驗證失敗時
  • validation.field (string, conditional): 驗證欄位
    • 條件: 驗證失敗時
  • validation.validRoles (string, conditional): 有效角色列表
    • 條件: 驗證失敗時

Events:

  • database.query.existing_user: 查詢現有使用者
  • database.check.email_conflict: 檢查 email 衝突
  • database.update.user: 更新使用者

表單欄位 (Form Fields)

route.admin.event_form_fields.create

檔案: routes/admin/eventFormFields.ts

建立表單欄位 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • field.type (string): 欄位類型
  • field.order (number): 排序
  • field.required (boolean): 是否必填
  • field.id (string, conditional): 欄位 ID
    • 條件: 成功建立後

Events:

  • query.event.start: 開始查詢活動
  • event.not_found: 找不到活動
  • check.order_conflict: 檢查排序衝突
  • validation.failed: 驗證失敗
    • reason: order_conflict
  • field.create.start: 開始建立

route.admin.event_form_fields.get

檔案: routes/admin/eventFormFields.ts

取得表單欄位 (Admin)。

Attributes:

  • field.id (string): 欄位 ID
  • field.type (string, conditional): 欄位類型
    • 條件: 找到欄位後
  • field.required (boolean, conditional): 是否必填
    • 條件: 找到欄位後

Events:

  • query.field.start: 開始查詢
  • field.not_found: 找不到欄位

route.admin.event_form_fields.update

檔案: routes/admin/eventFormFields.ts

更新表單欄位 (Admin)。

Attributes:

  • field.id (string): 欄位 ID
  • update.has_order_change (boolean): 是否更新排序
  • update.has_type_change (boolean): 是否更新類型
  • field.event_id (string, conditional): 活動 ID
    • 條件: 找到欄位後

Events:

  • query.field.start: 開始查詢
  • field.not_found: 找不到欄位
  • check.order_conflict: 檢查排序衝突
  • validation.failed: 驗證失敗
    • reason: order_conflict
  • field.update.start: 開始更新

route.admin.event_form_fields.delete

檔案: routes/admin/eventFormFields.ts

刪除表單欄位 (Admin)。

Attributes:

  • field.id (string): 欄位 ID
  • field.event_id (string, conditional): 活動 ID
    • 條件: 找到欄位後
  • field.type (string, conditional): 欄位類型
    • 條件: 找到欄位後

Events:

  • query.field.start: 開始查詢
  • field.not_found: 找不到欄位
  • field.delete.start: 開始刪除

route.admin.event_form_fields.list

檔案: routes/admin/eventFormFields.ts

列出表單欄位清單 (Admin)。

Attributes:

  • filter.has_event_id (boolean): 是否有篩選活動 ID
  • filter.event_id (string, conditional): 篩選活動 ID
    • 條件: 有篩選時
  • fields.count (number): 欄位數量

Events:

  • query.event.start: 開始查詢活動
  • event.not_found: 找不到活動
  • query.fields.start: 開始查詢欄位

route.admin.event_form_fields.reorder

檔案: routes/admin/eventFormFields.ts

重新排序表單欄位 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • fields.count (number): 欄位數量

Events:

  • query.event.start: 開始查詢活動
  • event.not_found: 找不到活動
  • query.fields.verify: 驗證欄位
  • validation.failed: 驗證失敗
    • reason: fields_not_belong_to_event, duplicate_orders
  • reorder.transaction.start: 開始重新排序交易

活動儀表板 (Event Dashboard)

route.admin.event_dashboard.get

檔案: routes/admin/eventDashboard.ts

取得活動儀表板 (Admin)。

Attributes:

  • event.id (string): 活動 ID
  • registrations.total (number): 總報名數
  • registrations.confirmed (number): 已確認報名數
  • registrations.pending (number): 待處理報名數
  • registrations.cancelled (number): 已取消報名數
  • tickets.count (number): 票券數量
  • revenue.total (number): 總收入
  • referrals.total (number): 總推薦數
  • referrals.active_referrers (number): 活躍推薦者數
  • referrals.conversion_rate (number): 推薦轉換率

Events:

  • query.event.start: 開始查詢活動
  • event.not_found: 找不到活動
  • query.registration_stats.start: 開始查詢報名統計
  • query.tickets.start: 開始查詢票券
  • query.registration_trends.start: 開始查詢報名趨勢
  • query.referral_stats.start: 開始查詢推薦統計

行事曆 (Calendar)

route.calendar.get_event

檔案: routes/public/calendar.ts

取得活動行事曆檔案。

Attributes:

  • event.slug (string): 活動 slug
  • event.id (string, conditional): 活動 ID
    • 條件: 找到活動後
  • calendar.size (number): 行事曆檔案大小 (bytes)

Events:

  • calendar.generate_start: 開始生成
  • calendar.generate_complete: 生成完成

Google Sheets

google_sheets.authenticate

檔案: utils/google-sheets.ts

Google Sheets 認證。

Attributes:

  • google_sheets.service_account.masked (string): 遮罩的服務帳號 email

Events:

  • google_sheets.import_libraries: 匯入函式庫
  • google_sheets.parse_service_account: 解析服務帳號
  • google_sheets.create_jwt: 建立 JWT
  • google_sheets.authorize: 授權
  • google_sheets.create_client: 建立客戶端

google_sheets.export

檔案: utils/google-sheets.ts

匯出到 Google Sheets。

Attributes:

  • google_sheets.spreadsheet_id.masked (string): 遮罩的試算表 ID
  • google_sheets.registrations_count (number): 報名筆數
  • registration.id (string, conditional): 報名 ID
    • 條件: 有報名資料時 (第一筆的 ID)
  • google_sheets.sheet_name (string): 工作表名稱
  • google_sheets.sheet_exists (boolean): 工作表是否存在
  • google_sheets.form_fields_count (number): 表單欄位數量
  • google_sheets.total_columns (number): 總欄位數
  • google_sheets.total_rows (number): 總列數

Events:

  • google_sheets.get_client: 取得客戶端
  • google_sheets.get_spreadsheet: 取得試算表
  • google_sheets.create_sheet: 建立工作表
  • google_sheets.parse_data: 解析資料
  • google_sheets.prepare_headers: 準備標題列
  • google_sheets.prepare_rows: 準備資料列
  • google_sheets.clear_sheet: 清空工作表
  • google_sheets.write_data: 寫入資料

系統相關 (System)

route.system.health

檔案: routes/system.ts

健康檢查端點。

Attributes: (無)

Events: (無)


總結

本文件涵蓋了後端所有的 OrpenTelemetry spans 及其 attributes。每個 span 都標註了:

  1. 必要 attributes: 每次都會設定的屬性
  2. 條件式 attributes: 在特定條件下才會設定的屬性,並註明觸發條件
  3. Events: span 過程中記錄的事件,包含事件屬性

此文件可作為監控、除錯和效能分析的參考依據。

Copilot AI review requested due to automatic review settings January 25, 2026 15:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands OpenTelemetry instrumentation across backend utilities and route handlers by adding spans, events, and richer attributes (often with masking) to improve observability of auth, email, ticketing, registration, referral, webhook, calendar, and Turnstile flows.

Changes:

  • Added spans/events/status reporting around key route handlers (public + admin) and several utility operations.
  • Enriched span attributes with domain identifiers/counts and added masking for some sensitive identifiers.
  • Added additional tracing around Turnstile validation, magic-link auth, Google Sheets export/auth, and email sending.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
backend/utils/google-sheets.ts Adds tracing around Google Sheets auth and export steps with events/attributes.
backend/utils/email.ts Adds additional tracing attributes for email flows (registration confirmation, invitation code, campaign).
backend/routes/system.ts Adds a tracing span for the health route.
backend/routes/public/tickets.ts Adds tracing span + ticket attributes/events for public ticket lookup.
backend/routes/public/smsVerification.ts Adds tracing spans/events/attributes across SMS verification send/verify/status flows.
backend/routes/public/registrations.ts Adds richer tracing throughout registration create/list/get/update/cancel flows.
backend/routes/public/referrals.ts Adds tracing spans/events/attributes for referral link/stats/validation flows and parses localized ticket name.
backend/routes/public/invitationCodes.ts Adds tracing spans/events/attributes (including masking) for invitation code verify/info endpoints.
backend/routes/public/events.ts Adds tracing spans/events/attributes for event info/tickets/list/stats/form-fields endpoints.
backend/routes/public/calendar.ts Adds tracing span around calendar generation and propagates span into generator.
backend/routes/public/auth.ts Adds tracing for auth permissions endpoint with status/events.
backend/routes/admin/webhooks.ts Adds tracing across webhook CRUD, testing, failed-delivery listing and retry.
backend/routes/admin/users.ts Adds tracing across admin user list/get/update routes.
backend/routes/admin/tickets.ts Adds tracing across ticket CRUD, listing, analytics, and reorder endpoints.
backend/routes/admin/smsVerificationLogs.ts Adds tracing for SMS verification log listing + aggregate stats.
backend/routes/admin/registrations.ts Adds tracing for registration list/get/update/export/delete and Google Sheets sync.
backend/routes/admin/referrals.ts Adds tracing across referral admin endpoints (overview/leaderboard/tree/qualified/draw/stats).
backend/routes/admin/invitationCodes.ts Adds tracing across invitation code CRUD, bulk create, and send-email endpoints.
backend/routes/admin/events.ts Adds tracing across admin event CRUD and list endpoints.
backend/routes/admin/eventFormFields.ts Adds tracing across event form field CRUD/list/reorder endpoints.
backend/routes/admin/eventDashboard.ts Adds tracing span + attributes for event dashboard analytics endpoint.
backend/routes/admin/emailCampaigns.ts Adds tracing across email campaign list/create/preview/calc recipients/send/cancel endpoints.
backend/lib/turnstile.ts Adds tracing spans/events/attributes around Turnstile validation + retry logic.
backend/lib/auth.ts Adds tracing around magic-link sending/rate-limiting + related attributes/events.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@pan93412 pan93412 marked this pull request as draft January 25, 2026 15:24
@pan93412 pan93412 requested a review from Copilot January 25, 2026 16:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@pan93412 pan93412 force-pushed the tracing-improvement branch from 9b1c1ba to 54e1beb Compare January 25, 2026 16:07
@pan93412 pan93412 marked this pull request as ready for review January 25, 2026 16:11
@elvisdragonmao elvisdragonmao merged commit 0c3e2c1 into sitcon-tw:dev Jan 25, 2026
1 check passed
@pan93412 pan93412 deleted the tracing-improvement branch January 25, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants