Documentation
¶
Overview ¶
Package trace provides the lightweight correlation primitives the gojira crawl uses to emit a reconstructable fan-out tree of log records.
A run is one crawl invocation; it owns a Span tree. Each span carries:
- [RunID] — the same value across every record of one run.
- [SpanID] — a fresh opaque short ID per logical unit of work.
- [ParentSpanID] — the SpanID of whoever enqueued this work.
- [TicketID] — the Jira issue key when work is issue-scoped.
- [Phase] — one of the PhaseFetch, PhaseParse, … labels.
- [Depth] — the issue's crawl depth (root = 0).
Span values are pure values: copy freely, no synchronization. The Span.Logger method returns a *slog.Logger pre-tagged with the span's non-empty correlation attributes, so every record the returned logger emits is auto-correlated without callers having to repeat With(...) at each call site.
IDs are opaque short hex strings drawn from crypto/rand. They are NOT path/hierarchical IDs — a crawl that bleeds across projects or boards is not sequential, so encoding lineage in the ID itself would lie about structure. The parent link reconstructs the tree without misrepresenting it.
This package has no project-internal imports; it depends only on the Go standard library.
Index ¶
Constants ¶
const ( PhaseFetch = "fetch" PhaseParse = "parse" PhaseHierarchyJQL = "hierarchy_jql" PhaseDevStatus = "dev_status" PhaseRender = "render" PhaseStore = "store" PhaseEnqueue = "enqueue" )
Phase labels a unit of work in the crawl pipeline. Producers stamp the current phase onto each span so records can be grouped, counted, and timed per phase without parsing free-text messages.
const ( AttrRunID = "run_id" AttrSpanID = "span_id" AttrParentSpanID = "parent_span_id" AttrTicketID = "ticket_id" AttrPhase = "phase" AttrDepth = "depth" AttrTraceStream = "trace_stream" )
Attribute keys for the canonical slog correlation fields. Centralising them here keeps producers (crawl, client/httplog) and consumers (jq filters, future TUI/MCP frontends) in agreement on names.
const ( StreamResponse = "response" // external/data side (HTTP round-tripper) StreamStream = "stream" // internal/orchestration side (events/fan-out) )
Trace-stream values. Both streams share run/ticket/span ids so a reader can pivot from "this response" to "the stream activity it caused" without re-correlating manually.
Variables ¶
This section is empty.
Functions ¶
func LoggerFrom ¶
LoggerFrom returns the logger stored on ctx by WithLogger, or nil if none has been set. A nil return is the caller's signal to fall back to a package-level or default logger.
func NewRunID ¶
func NewRunID() string
NewRunID returns an opaque short identifier for a single crawl invocation: 12 hex characters (6 random bytes) — collision-resistant enough for the scale this tool runs at while staying short enough to scan visually in a terminal.
func NewSpanID ¶
func NewSpanID() string
NewSpanID returns an opaque short identifier for one unit of work: 10 hex characters (5 random bytes). Slightly shorter than RunID because spans are far more numerous within a single run.
func WithLogger ¶
WithLogger returns a derived context carrying lg, so a downstream component (notably the HTTP round-tripper added in phase-c-httptrace-1) can retrieve the active span-bound logger via LoggerFrom and tag its own records with the same correlation attributes.
Types ¶
type Span ¶
type Span struct {
// RunID is constant across every span and every record of a run.
RunID string
// SpanID identifies this unit of work uniquely within the run.
SpanID string
// ParentSpanID links to the span that enqueued/spawned this one.
// Empty for a root span.
ParentSpanID string
// TicketID is the Jira issue key (e.g. "PROJ-1417") when the
// span is issue-scoped. Empty for cross-cutting work (the root
// span, an end-of-run summary, etc.).
TicketID string
// Phase labels what this span is doing; see [PhaseFetch] et al.
Phase string
// Depth is the crawl depth at which this span operates; 0 for
// the root and for seed issues, incremented by [Span.Child] when
// fan-out enqueues children.
Depth int
}
Span is a single unit of work in the crawl, carrying the correlation identity that ties its log lines (and the HTTP requests it triggers) into a reconstructable fan-out tree. Span is a value type; copy freely. There is no mutability concern.
func NewRoot ¶
func NewRoot() Span
NewRoot mints a fresh root span — a new [RunID] and a fresh [SpanID] with no parent. The Phase / TicketID / Depth fields remain zero-valued because the root represents the whole invocation, not a specific per-issue task.
func (Span) Child ¶
Child mints a new span under s: same [RunID], a fresh [SpanID], and ParentSpanID set to s.SpanID. The supplied phase, ticketID, and depth become the child's identity.
This is the only fan-out primitive: every per-issue or per-API-call span in the crawl goes through Child, so the parent_span_id linkage is consistent across the codebase.
func (Span) Logger ¶
Logger returns base annotated with this span's non-empty correlation attributes via slog.Logger.With, so every record the returned logger emits is auto-tagged with run_id / span_id / parent_span_id (when present) / ticket_id / phase / depth.
A nil base is replaced with slog.Default so the method is safe to call from anywhere a logger may not have been threaded through yet. Empty correlation fields (e.g. the root span has no parent) are omitted rather than logged as empty strings, keeping records terse. Depth is always included because 0 is a meaningful value (the root / seed level) and the difference between "depth=0" and "absent" is information that downstream consumers can rely on.