tracing
Tracing, observability, and instrumentation conventions for the Ghost codebase. MUST READ before adding or modifying: tracing spans, #[tracing::instrument] attributes, tracing::info_span!() calls, OTel semantic convention fields (gen_ai.*), span hierarchy, or any observability-related code. Failure to follow these conventions produces inconsistent telemetry.
- License 许可
- MIT
- 所属仓库
- mrtolkien/GHOST
- 最近更新
- 2026-04-24
- Stars
- ★ 5
- Forks
- 0
01 前言 Front Matter
- name
- tracing
- description
- Tracing, observability, and instrumentation conventions for the Ghost codebase. MUST READ before adding or modifying: tracing spans, #[tracing::instrument] attributes, tracing::info_span!() calls, OTel semantic convention fields (gen_ai.*), span hierarchy, or any observability-related code. Failure to follow these conventions produces inconsistent telemetry.
03 SKILL.md 正文
Observability Conventions (NON-NEGOTIABLE)
Instrument meaningful execution boundaries, not every function. Prioritize: provider API calls, tool executions, agent/job entry points, DB mutations, and embedding ops. Keep small helpers and pure functions uninstrumented.
Span Naming — {verb} {object}, Low Cardinality
Source: https://opentelemetry.io/blog/2025/how-to-name-your-spans/
Follow the OTel-recommended {verb} {object} pattern for all span names. The verb
describes the action; the object describes what is acted upon. This keeps span names
low-cardinality (aggregatable for P95 latency, dashboards, alerts).
Rules
- Never embed run-dependent values in span names. IDs, file paths, query strings, user names, and tool names belong in attributes, not the span name.
- Name the operation, not the outcome. Use
validate input— notvalidation_failed. Record the outcome in span status or an attribute. - Keep names short and stable. Two words is ideal. Three is the max.
Current span names
| Span Name | Attributes (run-dependent) |
|---|---|
boot ghost |
— |
create provider |
provider, endpoint |
create session_chat |
— |
embed batch |
model, batch_size |
embed source |
source_table, source_id |
embed sources |
sources, embedded, skipped + info event with file list |
execute agent |
gen_ai.agent.name, gen_ai.agent.id |
execute resume |
— |
fetch url crawl4ai |
url |
fetch url reqwest |
url |
import crawl |
topic |
import git |
topic |
import page |
topic |
import references |
source, topic, url |
orchestrate response |
session_id |
process file_changes |
count |
process file_change |
kind, path |
reboot session |
old_session_id |
receive discord message |
— |
reconcile embeddings |
— |
request completion |
gen_ai.system, gen_ai.request.model, etc. |
resume agent bg |
agent_id |
run lua agent |
— |
run lua agent with history |
— |
run tool |
gen_ai.tool.name, params_preview |
run tools |
— |
search web |
query |
send message |
channel_id, content_len |
start agent |
gen_ai.agent.name |
start scheduler |
— |
start watcher |
— |
Bad vs Good
| Bad (high cardinality) | Good |
|---|---|
tool: note_write |
run tool |
watcher: note |
process file_change |
agent: research-agent |
execute agent |
openai_compatible.request |
request completion |
ghost.startup |
boot ghost |
OTel GenAI Semantic Conventions (Mandatory for Provider Calls)
Source: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/
All LLM provider calls must record these fields on the request completion span:
gen_ai.system— provider name (e.g.openrouter)gen_ai.operation.name— always"chat"gen_ai.request.model— model ID sent in the requestgen_ai.response.model— model ID returned by the providergen_ai.response.id— response identifiergen_ai.response.finish_reasons— stop reasongen_ai.usage.input_tokens/gen_ai.usage.output_tokensgen_ai.usage.cache_read_input_tokens/gen_ai.usage.cache_creation_input_tokens
Span Hierarchy — Keep It Shallow (2-3 Levels Max)
receive discord message->orchestrate response->request completion/run toolexecute agent/run lua agent->request completion/run toolboot ghost->start scheduler/start watcher/create provider- Never wrap a single delegation call in a span
Implementation Rules
- Use
#[tracing::instrument(name = "verb object", skip_all, fields(key = %val))]— always set an explicitnameon info-level spans at execution boundaries - Use
tracing::info_span!("verb object", key = val)for programmatic spans — never interpolate dynamic values into the span name string - Use
tracing::Span::current().record()to fill response fields at span completion - Use
tracing::info!()/warn!()/error!()for discrete events within spans - Do not duplicate information between a span and a child log event
- Log all errors with full context before propagating
- Provider request/response bodies: logged as
gen_ai.input.messages/gen_ai.output.messagesat info level insiderequest completionspans - Debug-level DB/internal spans may omit
name =(function name default is fine) - OTLP export is conditional on the
OTEL_EXPORTER_OTLP_ENDPOINTenv var — when unset, tracing emits to stderr only (no spans are exported) - Default RUST_LOG:
warn,ghost=info,chromiumoxide=error,usvg=off,resvg=off,fontdb=off,html5ever=off
04 同仓库更多 Skills
system-management
Use when reading or changing GHOST configuration (providers, models, timing, compaction, services, any config.toml key), adding or switching LLM providers, answering questions about GHOST's own features or capabilities, a CLI tool is missing or "not found", services need starting/stopping/debugging, updating GHOST to a newer version, managing the Nix shell environment, or troubleshooting GHOST setup.
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
writing-plans
Use when you have a spec or requirements for a multi-step task, before touching code. Write comprehensive implementation plans assuming the engineer has zero context for our codebase and questionable taste.
verification
Use when about to claim work is complete, fixed, or passing, before committing or creating PRs. Requires running verification commands and confirming output before making any success claims. Evidence before assertions, always.
tdd
Use when implementing any feature or bugfix, before writing implementation code. Write the test first. Watch it fail. Write minimal code to pass.
systematic-debugging
Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes