本文へ移動
cccskills
無料GitHub で公開

logging

Structured logging conventions for DraftForge backend (Django/Celery/Daphne) and frontend (React). This skill should be used when adding log statements, creating new modules, debugging with logs, or reviewing logging patterns. Covers structlog usage, system/subsystem taxonomy, required fields, log levels, and Grafana query patterns.

インストール方法を見る

含まれるファイル(4)

  • SKILL.md10.1 KB
  • references/backend.md3.6 KB
  • references/frontend.md2.3 KB
  • references/grafana-loki.md4.6 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Structured Logging

DraftForge uses structlog (backend) for structured JSON logging exported to Grafana Cloud via OpenTelemetry. All logs use a system/subsystem taxonomy for filtering.

Backend: Quick Start

from telemetry.logging import get_logger
log = get_logger(__name__)

# Structured log — event name first, then kwargs
log.info("order_created", system="tournament", subsystem="registration", draft_id=5, user_id=42)

Never use f-strings or % formatting in log messages. The first argument is always an event name (snake_case). All context goes in kwargs.

System / Subsystem Taxonomy

Every log MUST include system and subsystem kwargs. These are the primary Grafana filter dimensions.

Two-axis taxonomy: system / subsystem answer where the code lives (single value, label-friendly). tags: list[str] is an optional secondary axis answering what domains this log concerns (multi-value, for cross-cutting queries like "show me everything related to signups"). When tags are set, also set tags_csv (comma-joined string) for clean LogQL =~ filtering (Loki's | json flattens lists as tags_0, tags_1 which is awkward to filter). Bind tags via discord_log_context for interaction-flow logs, or pass explicitly for one-off cross-cutting logs.

systemsubsystemtagsWhereWhat
herodraftconnection—consumers.pyWS connect/disconnect, captain state, kicks
herodraftheartbeat—herodraft_tick.pyHeartbeat staleness checks, heartbeat-triggered pauses
herodrafttimer—herodraft_tick.pyTick loop lifecycle, tick broadcast, timeout auto-pick, resume
websocketheartbeat—consumers_base.pyHeartbeat receive, captain register/unregister (generic WS infra)
websocketconnection—telemetry/websocket.pyGeneric WS connect/disconnect/receive instrumentation
herodraftview—app/functions/herodraft_views.pyHeroDraft HTTP actions: create, roll, choice/pick submit, abandon, reset
celerytask—telemetry/celery.pyGeneric Celery task lifecycle bookends (started/completed/failed)
eventsdiscord—events/tasks.py (cron sync, non-interaction tasks like sync_discord_events)Cron-driven event sync to Discord that isn't triggered by an interaction
eventsscheduling—events/tasks.pyEvent generation, signup opening, repeaters
tournamentdiscord—discordbot/tasks.pyTournament DMs, bracket notifications
avatarsendpoint—user/internal/avatar.pyInternal endpoints: list-linked-users, list-guild-ids, bulk-update + invalidate
avatarsrefresh—app/tasks/avatar_refresh.py::refresh_avatars_batchedDaily Celery beat: read guild-member cache, diff against DB, POST bulk-update
avatarssingle—app/tasks/avatar_refresh.py::refresh_single_user_avatar + helpersSingle-user refresh: Discord API fetch + per-user update_user_avatar
avatarslegacy—app/tasks/avatar_refresh.py::refresh_discord_avatars / refresh_all_discord_dataOlder per-user fanout tasks (predates the batched path)
discordlease—discordbot/tasks.py, app/views/internal.pyDiscordMessageLog stale-lease sweep (pending NULL >5min, failed >1h)
discordinteraction["events","signup"]discordbot/components.py, discordbot/signup_responses.py, discordbot/log_context.pyDiscord-bot UI plumbing + response delivery: button/modal/select callbacks
discorddispatch["events","signup"]events/discord/dispatch.pynotify_* dispatch visibility (queued vs skipped); threads interaction_id to Celery
discordcelery["events","signup"]events/tasks.py (Discord-dispatching tasks)celery_task_started/finished/failed bookend logs
cacheinvalidate—app/cache_utils.pyPer-object cacheops invalidation fired from transaction.on_commit
websocketbroadcast—app/broadcast.pyDraft / herodraft event + state broadcast to channel groups (kind field distinguishes draft/herodraft/herodraft_state)
authinternal—app/auth.pyInternal-service auth (X-Internal-Token): IP-allowlist rejects, invalid-token failures
authsocial—app/pipelines.pyDiscord OAuth social-auth pipeline: account reclaim/merge, username matching
authmerge—app/discord_accounts.pyDiscord account de-dup / merge
tournamentdraft, registration, user—app/models.py, app/functions/tournament.pyDraft build/pick/rebuild, captain/team registration, per-user avatar refresh
apiserializer, routing, main, csv_import, joke—app/serializers.py, app/views*.py, app/views/csv_import.py, backend/urls.pyDRF serializer mutations, view cache-miss, CSV import, env/routing
userfunctions—app/functions/user.pyProfile-update request/validate/apply
appsignals—app/signals.pyModel signal handlers (org/league user create, herodraft cleanup)
internal_clienthttp—app/internal_client/__init__.pyInternal HTTP client JSON-parse failures
discordbot, utils, views, channels, roles, users—discordbot/**Bot lifecycle, message utils, slash views, channel/role/user services
eventstasks, services, views, dispatch—events/**Event task lifecycle, signup services, manual fire, tournament-link dispatch
steamapi, game_linking, match, mmr, stats, model, league_sync, retry—steam/**Steam API, account/game linking, match fetch/store, MMR/stats, league sync, retry
bracketgenerate, model—bracket/**Bracket generation + model-level cache logging
orgviews—org/views.pyOrg admin actions (user delete/merge)
commonutils—common/utils.pyShared utility warnings (CI/IP detection)

Add new systems/subsystems as features grow. Keep systems coarse (feature area), subsystems functional (what role the code plays).

Cross-System Correlation

Logs that span multiple systems carry an interaction_id (Discord interaction) or request_id (web request) so a single user action can be traced across processes.

For Discord interactions, the discord_log_context async CM in discordbot/log_context.py binds:

  • interaction_id — primary correlation key (Discord-generated, unique per click)
  • discord_user_id, discord_username, channel_id, guild_id
  • custom_id, event_id, interaction_type
  • tags=["events","signup"] (or other prefix-derived tags)
  • tags_csv="events,signup" (flat string for clean LogQL filtering)

These propagate via structlog.contextvars.merge_contextvars through await and sync_to_async. They also propagate across Celery .delay() calls when the dispatch site passes interaction_id as a kwarg and the task calls bind_contextvars(interaction_id=...) at entry.

OTel trace_id and span_id are injected automatically by the _add_otel_trace_context processor in telemetry/logging.py. At a 10% sample rate, the trace_id is in every log line for that 10%; for the other 90%, rely on interaction_id for log-side correlation.

Grafana query patterns

# Single user click
{service_name="backend"} | json | interaction_id="<id>"

# Cross-cutting: anything signup-related
{service_name="backend"} | json | tags_csv=~".*signup.*"

# Discord code that touches events
{service_name="backend"} | json | system="discord" | tags_csv=~".*events.*"

Log Levels

LevelWhenExported to Grafana?
DEBUGPer-request/per-tick detail, heartbeat receivedNo (prod=INFO)
INFOState transitions, lifecycle events, periodic healthYes
WARNINGAnomalies that self-recover (stale heartbeat, slow tick)Yes
ERRORFailures requiring attention (broadcast failed, API error)Yes

Required Fields

Beyond system and subsystem, include relevant entity IDs:

  • draft_id — for anything draft-related
  • user_id / username — for user-scoped actions
  • event_id — for event system logs
  • duration_s / elapsed_ms — for timing-sensitive operations
  • reason — for skipped/stopped/failed actions
  • error — for exception context (str(e), never the full traceback)

References

Grafana Queries

# All herodraft heartbeat logs
{service_name="backend"} | json | system="herodraft" | subsystem="heartbeat"

# Slow ticks
{service_name="backend"} | json | event="tick_slow"

# All errors across systems
{service_name="backend"} | json | level="error"

# Filter by draft
{service_name="backend"} | json | draft_id="42"

Run these from the CLI with gcx (context draftforge → kettle.grafana.net). Pass --agent=false or Claude Code's auto agent-mode suppresses the output:

gcx logs query '{service_name="backend"} | json | level="error"' --since 24h -o raw --agent=false

The discord service mixes structlog JSON with plain-text discord.py lines, so | json drops half of them — use line filters (|= "ERROR") there. Full examples (error breakdown, silence detection, request/trace correlation): references/grafana-loki.md.

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

aesthetic

無料

Create aesthetically beautiful interfaces following proven design principles. Use when building UI/UX, analyzing designs from inspiration sites, generating design images with ai-multimodal, implementing visual hierarchy and color theory, adding micro-interactions, or creating design documentation. Includes workflows for capturing and analyzing inspiration screenshots with chrome-devtools and ai-multimodal, iterative design image generation until aesthetic standards are met, and comprehensive design system guidance covering BEAUTIFUL (aesthetic principles), RIGHT (functionality/accessibility), SATISFYING (micro-interactions), and PEAK (storytelling) stages. Integrates with chrome-devtools, ai-multimodal, media-processing, ui-styling, and web-frameworks skills.

日本語の概要は準備中です。原文の説明を表示しています。

kettleofketchup/DraftForge152026年9月14日 更新

Proper usage of Bash and file operation tools. Use this skill when executing shell commands, writing files, or when tempted to use echo/cat/heredoc to pipe content to files. Prevents permission circumvention patterns like piping multiline content through echo instead of using Write tool. Covers Bash tool, Write tool, Edit tool, and Read tool best practices.

日本語の概要は準備中です。原文の説明を表示しています。

kettleofketchup/DraftForge152026年9月14日 更新

brand

無料

DraftForge brand/theming review. Flags raw <button> over PrimaryButton/SecondaryButton, hardcoded violet/slate over brand tokens, inline styles, missing UserAvatar/EntityBreadcrumb.

日本語の概要は準備中です。原文の説明を表示しています。

kettleofketchup/DraftForge152026年9月14日 更新

Browser automation, debugging, and performance analysis using Puppeteer CLI scripts. Use for automating browsers, taking screenshots, analyzing performance, monitoring network traffic, web scraping, form automation, and JavaScript debugging.

日本語の概要は準備中です。原文の説明を表示しています。

kettleofketchup/DraftForge152026年9月14日 更新

Django Redis caching with django-cacheops. This skill should be used when implementing caching, adding cache invalidation, optimizing API performance, modifying models that affect cached data, or debugging cache-related issues in the Django backend.

日本語の概要は準備中です。原文の説明を表示しています。

kettleofketchup/DraftForge152026年9月14日 更新

Frontend development guidelines for React/TypeScript applications. Modern patterns including Suspense, lazy loading, useSuspenseQuery, file organization with features directory, MUI v7 styling, TanStack Router, performance optimization, and TypeScript best practices. Use when creating components, pages, features, fetching data, styling, routing, or working with frontend code.

日本語の概要は準備中です。原文の説明を表示しています。

kettleofketchup/DraftForge152026年9月14日 更新

kettleofketchup のスキルをすべて見る

このスキルの問題を報告する