Documentation
¶
Overview ¶
Package footprint records structured events about every CKV operation — build, query, MCP tool call — to two sinks:
- **slog** (stderr by default). Operator-readable.
- **JSONL** at <out>/footprint.jsonl, one object per line. Append- only, machine-readable. This is the *seed* of the future read-write working-memory MCP: the memory layer reads this log (or a SQLite mirror of it) to recall what was asked, what we answered, and how well it worked.
Schema stability matters: every event has the same envelope (timestamp, event, trace_id, latency_ms, error) plus an event-specific fields map. Adding new fields is non-breaking; renaming/removing is.
Index ¶
Constants ¶
const SchemaVersion = "1"
SchemaVersion is stamped into every event so downstream consumers (working memory MCP, eval harness) can detect breaking changes.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Event ¶
type Event struct {
Timestamp time.Time `json:"ts"`
SchemaVersion string `json:"schema_version"`
Event string `json:"event"`
TraceID string `json:"trace_id,omitempty"`
RunID string `json:"run_id,omitempty"`
LatencyMs int64 `json:"latency_ms,omitempty"`
Error string `json:"error,omitempty"`
Fields map[string]any `json:"fields,omitempty"`
}
Event is the on-the-wire shape: stable envelope + open Fields map.
type Logger ¶
type Logger struct {
// contains filtered or unexported fields
}
Logger fans events out to its configured sinks. Safe for concurrent use; the JSONL file is guarded by a sync.Mutex (writes are O(event size) so contention is negligible vs the embedding/store work).
func Discard ¶
func Discard() *Logger
Discard returns a Logger that writes nowhere. Useful in tests and in library callers that opt out of footprint recording.
func New ¶
New constructs a Logger. The slog sink is always installed (stderr when opts.Stderr is true; io.Discard otherwise). The JSONL sink is optional. Errors opening the JSONL file are returned; the slog sink stays operational either way.
func (*Logger) Close ¶
Close flushes/closes the JSONL sink and, when ProfilePath was set, writes the aggregated profile JSON. Idempotent.
func (*Logger) Emit ¶
Emit records a single event. Never returns; sink errors are written back to slog at WARN level. fields is alternating key/value (slog convention): Emit("build.start", "src", "/repo", "files", 42).
func (*Logger) RunID ¶
RunID returns the per-Logger run id; callers (MCP server, eval) may surface this so downstream consumers can group by session.
func (*Logger) Span ¶
Span starts a timed event; the returned done() closure emits the "<name>.done" event with latency_ms attached. extra accepts the same alternating key/value shape as Emit and is merged onto the done event.
Typical usage:
done := log.Span("query.search", "intent_hash", h, "k", k)
defer done("hits", len(hits), "citation_drops", drops)
When err is non-nil at done time, pass "error", err.Error() in extra (no special handling needed at this layer).
type Options ¶
type Options struct {
// JSONLPath: if non-empty, opens this file (append+create) and
// writes one Event per line. Pass <out>/footprint.jsonl to seed
// the working-memory MCP.
JSONLPath string
// Stderr controls whether human-readable slog output goes to
// stderr. Default true. Set false for tests that snapshot stdout.
Stderr bool
// RunID is propagated onto every event so memory recall can group
// by session. Optional; auto-generated when empty.
RunID string
// Level controls the minimum slog level emitted to stderr. Zero
// value (slog.LevelInfo) keeps the documented default. Operators
// raise to LevelWarn for noisier-tool integrations or lower to
// LevelDebug for incident triage.
Level slog.Level
// ProfilePath, when non-empty, instructs Close to aggregate every
// emitted event by name (count + latency_ms p50/p95/sum) and
// write the summary as JSON to this path. Useful for build /
// query throughput audits without parsing the raw JSONL.
ProfilePath string
}
Options configure a Logger. Zero value gives stderr-only (no JSONL).