storage

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 28, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CompactResult

type CompactResult struct {
	BytesBefore int64 `json:"bytes_before"`
	BytesAfter  int64 `json:"bytes_after"`
	Reclaimed   int64 `json:"reclaimed"`
}

CompactResult reports bytes before and after a CHECKPOINT + VACUUM cycle.

type DB

type DB struct {
	// contains filtered or unexported fields
}

func Open

func Open(path string) (*DB, error)

func (*DB) ActiveSessionID

func (d *DB) ActiveSessionID() string

func (*DB) ActiveSessionLabel

func (d *DB) ActiveSessionLabel() string

func (*DB) Close

func (d *DB) Close() error

func (*DB) Compact

func (d *DB) Compact() (*CompactResult, error)

Compact runs CHECKPOINT followed by VACUUM to return free pages to the OS.

func (*DB) CreateImportedSession

func (d *DB) CreateImportedSession(label string) (*Session, error)

func (*DB) CreateSession

func (d *DB) CreateSession(label string, isBaseline bool) (*Session, error)

func (*DB) DeleteSession

func (d *DB) DeleteSession(id string) error

func (*DB) GetMetricSeries

func (d *DB) GetMetricSeries(f MetricSeriesFilter) ([]*Metric, error)

GetMetricSeries returns every data point matching the filter, ordered by timestamp ascending. Histogram percentiles arrive as separate rows; callers split them apart by attributes.percentile.

func (*DB) GetServiceMap

func (d *DB) GetServiceMap(sessionID string) (*ServiceMapData, error)

func (*DB) GetSession

func (d *DB) GetSession(id string) (*Session, error)

func (*DB) GetSpan

func (d *DB) GetSpan(spanID string) (*Span, error)

func (*DB) GetSpansBySession

func (d *DB) GetSpansBySession(sessionID string) ([]*Span, error)

GetSpansBySession returns all spans for a session, ordered by start time.

func (*DB) GetStats

func (d *DB) GetStats(sessionID string) (*Stats, error)

func (*DB) GetStorageBreakdown

func (d *DB) GetStorageBreakdown() (*StorageBreakdown, error)

GetStorageBreakdown returns per-table sizes via duckdb_tables() and a per-session estimate based on the serialised span attribute lengths.

func (*DB) GetTrace

func (d *DB) GetTrace(traceID string) ([]*Span, error)

func (*DB) GetTraceIssues

func (d *DB) GetTraceIssues(traceID string) ([]*TraceIssue, error)

func (*DB) InsertLintWarning

func (d *DB) InsertLintWarning(w *LintWarning) error

func (*DB) InsertLog

func (d *DB) InsertLog(l *Log) error

func (*DB) InsertMetric

func (d *DB) InsertMetric(m *Metric) error

InsertMetric stores one metric data point.

func (*DB) InsertSpan

func (d *DB) InsertSpan(s *Span) error

func (*DB) InsertSpanEvents

func (d *DB) InsertSpanEvents(events []*SpanEvent) error

InsertSpanEvents bulk-inserts the events attached to a span. Empty input is a no-op; on error any rows inserted before the failure are not rolled back (events are best-effort, not transactional, like spans).

func (d *DB) InsertSpanLinks(links []*SpanLink) error

InsertSpanLinks bulk-inserts links emitted by a span. Best-effort: not transactional, mirroring InsertSpanEvents.

func (*DB) ListEventsBySpan

func (d *DB) ListEventsBySpan(spanID string) ([]*SpanEvent, error)

ListEventsBySpan returns the events attached to a single span, in time order.

func (d *DB) ListIncomingLinks(linkedTraceID string) ([]*SpanLink, error)

ListIncomingLinks returns every link in the store whose target is the given trace ID — the "who links into this trace?" reverse lookup.

func (*DB) ListLinksBySpan

func (d *DB) ListLinksBySpan(spanID string) ([]*SpanLink, error)

ListLinksBySpan returns the outbound links emitted by a single span.

func (*DB) ListLinksByTrace

func (d *DB) ListLinksByTrace(traceID string) ([]*SpanLink, error)

ListLinksByTrace returns all span_links whose trace_id matches — used to bulk-attach links to spans when serving GET /api/traces/:id so the waterfall can show the link badge without a per-span round-trip.

func (*DB) ListLintWarnings

func (d *DB) ListLintWarnings(sessionID string) ([]*LintWarning, error)

func (*DB) ListLogs

func (d *DB) ListLogs(f LogFilter) ([]*Log, error)

func (*DB) ListMetricCatalog

func (d *DB) ListMetricCatalog(sessionID string) ([]*MetricCatalogEntry, error)

ListMetricCatalog returns one entry per (service, name) seen in the session. Pass "" to ignore the session filter.

func (*DB) ListServices

func (d *DB) ListServices() ([]string, error)

func (*DB) ListSessions

func (d *DB) ListSessions() ([]*Session, error)

func (*DB) ListSpans

func (d *DB) ListSpans(f SpanFilter) ([]*SpanRow, error)

ListSpans returns a flat list of spans with computed tag (n+1/slow/lint/error). Tags are derived from trace_issues (n+1), status_code (error), duration (slow), and lint_warnings (lint). Priority: n+1 > error > slow > lint.

func (*DB) ListTraceIssues

func (d *DB) ListTraceIssues(sessionID string) ([]*TraceIssue, error)

ListTraceIssues returns detector findings. An empty sessionID returns findings across all sessions (capped), mirroring ListLintWarnings.

func (*DB) ListTraceIssuesBySession

func (d *DB) ListTraceIssuesBySession(sessionID string) ([]*TraceIssue, error)

ListTraceIssuesBySession returns every detector finding for a session.

func (*DB) ListTraces

func (d *DB) ListTraces(f TraceFilter) ([]*TraceRow, error)

func (*DB) ListTracesInWindow

func (d *DB) ListTracesInWindow(f TraceOverlayFilter) ([]*TraceOverlay, error)

ListTracesInWindow returns root spans (traces) whose start_ns falls in the [FromNs, ToNs] window for use as chart overlay markers. Caps at f.Limit (default 50).

func (*DB) Path

func (d *DB) Path() string

Path returns the underlying DuckDB file path (":memory:" for in-memory DBs).

func (*DB) Prune

func (d *DB) Prune(cfg RetentionConfig, activeID string) (PruneResult, error)

Prune applies the retention policy. The activeID and any baseline sessions are never deleted, regardless of age or count.

func (*DB) Reset

func (d *DB) Reset() error

Reset wipes all telemetry data (spans, logs, lint warnings, trace issues, sessions). The active session pointer in memory is cleared.

func (*DB) SQL

func (d *DB) SQL() *sql.DB

SQL exposes the underlying *sql.DB for callers that need to run statements outside the curated API (seed fixtures, ad-hoc migrations). Prefer the typed methods above for anything in the hot path.

func (*DB) Search

func (d *DB) Search(query, sessionID string, limit int) ([]*SearchResult, error)

Search runs a cross-table search against spans, logs, sessions, and services. It also supports field:value filters; currently lint:<rule> (with the alias n+1 == n_plus_one) which returns traces flagged by the linter or detectors.

func (*DB) SetActiveSession

func (d *DB) SetActiveSession(id, label string)

func (*DB) SetBaseline

func (d *DB) SetBaseline(id string, isBaseline bool) error

func (*DB) UpsertTraceIssue

func (d *DB) UpsertTraceIssue(issue *TraceIssue) error

type LintWarning

type LintWarning struct {
	SpanID    string `json:"span_id"`
	TraceID   string `json:"trace_id"`
	SessionID string `json:"session_id"`
	RuleID    string `json:"rule_id"`
	Message   string `json:"message"`
	Severity  string `json:"severity"`
	CreatedAt int64  `json:"created_at"`
}

type Log

type Log struct {
	TimestampNs int64  `json:"timestamp_ns"`
	TraceID     string `json:"trace_id"`
	SpanID      string `json:"span_id"`
	Severity    int    `json:"severity"`
	Body        string `json:"body"`
	Attributes  string `json:"attributes"`
	ServiceName string `json:"service_name"`
	SessionID   string `json:"session_id"`
	ReceivedAt  int64  `json:"received_at"`
}

type LogFilter

type LogFilter struct {
	SessionID string
	TraceID   string
	SpanID    string
	Limit     int
	Page      int
}

type Metric

type Metric struct {
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Unit        string  `json:"unit"`
	Type        string  `json:"type"` // gauge | counter | histogram
	TimestampNs int64   `json:"timestamp_ns"`
	Value       float64 `json:"value"`
	Attributes  string  `json:"attributes"`
	ServiceName string  `json:"service_name"`
	SessionID   string  `json:"session_id"`
}

Metric is one data point of an OTLP metric (gauge, counter, or one percentile of a histogram). Histogram data points are stored as three rows (p50/p95/p99) with the percentile encoded in attributes.percentile.

type MetricCatalogEntry

type MetricCatalogEntry struct {
	Name        string `json:"name"`
	Description string `json:"description"`
	Unit        string `json:"unit"`
	Type        string `json:"type"`
	ServiceName string `json:"service_name"`
	SampleCount int    `json:"sample_count"`
}

MetricCatalogEntry summarizes one (name, service) metric stream.

type MetricSeriesFilter

type MetricSeriesFilter struct {
	Name      string
	Service   string
	SessionID string
	FromNs    int64 // inclusive; 0 = no lower bound
	ToNs      int64 // inclusive; 0 = no upper bound
}

MetricSeriesFilter scopes a series query.

type PruneResult

type PruneResult struct {
	DeletedByAge     int   `json:"deleted_by_age"`
	DeletedByCount   int   `json:"deleted_by_count"`
	DeletedBySize    int   `json:"deleted_by_size"`
	FinalSessions    int   `json:"final_sessions"`
	FinalDBSizeBytes int64 `json:"final_db_size_bytes"`
}

PruneResult summarizes what a Prune run did. Useful for logging and tests.

type RetentionConfig

type RetentionConfig struct {
	MaxAge         time.Duration // delete sessions older than this
	MaxSessions    int           // keep at most this many sessions
	MaxDBSizeBytes int64         // shrink to at most this many bytes on disk
}

RetentionConfig describes the retention policy applied by Prune. A zero value for any field disables that particular limit.

type SearchResult

type SearchResult struct {
	Kind      string `json:"kind"` // "trace" | "span" | "session" | "service" | "log"
	TraceID   string `json:"trace_id"`
	SpanID    string `json:"span_id,omitempty"`
	Title     string `json:"title"`
	Subtitle  string `json:"subtitle"`
	SessionID string `json:"session_id"`
}

SearchResult is one item returned by the global search.

type ServiceMapData

type ServiceMapData struct {
	Nodes []*ServiceMapNode `json:"nodes"`
	Edges []*ServiceMapEdge `json:"edges"`
}

type ServiceMapEdge

type ServiceMapEdge struct {
	From          string `json:"from"`
	To            string `json:"to"`
	CallCount     int    `json:"call_count"`
	AvgDurationNs int64  `json:"avg_duration_ns"`
	ErrorCount    int    `json:"error_count"`
}

type ServiceMapNode

type ServiceMapNode struct {
	ID         string             `json:"id"`
	SpanCount  int                `json:"span_count"`
	ErrorCount int                `json:"error_count"`
	P95Ns      int64              `json:"p95_ns"`
	TopOps     []ServiceMapOpStat `json:"top_operations"`
}

type ServiceMapOpStat

type ServiceMapOpStat struct {
	Name  string `json:"name"`
	Count int    `json:"count"`
	P95Ns int64  `json:"p95_ns"`
}

ServiceMapOpStat is one (operation name, count, p95) entry for the node inspector panel. Capped server-side to keep the response cheap.

type Session

type Session struct {
	ID         string `json:"id"`
	Label      string `json:"label"`
	CreatedAt  int64  `json:"created_at"`
	IsBaseline bool   `json:"is_baseline"`
	IsImported bool   `json:"is_imported"`
	SpanCount  int    `json:"span_count"`
	TraceCount int    `json:"trace_count"`
	Services   string `json:"services"`
}

type SessionSize

type SessionSize struct {
	ID          string `json:"id"`
	Label       string `json:"label"`
	ApproxBytes int64  `json:"approx_bytes"`
	SpanCount   int    `json:"span_count"`
}

type Span

type Span struct {
	TraceID       string       `json:"trace_id"`
	SpanID        string       `json:"span_id"`
	ParentSpanID  string       `json:"parent_span_id"`
	ServiceName   string       `json:"service_name"`
	Name          string       `json:"name"`
	Kind          int          `json:"kind"`
	StartNs       int64        `json:"start_ns"`
	EndNs         int64        `json:"end_ns"`
	DurationNs    int64        `json:"duration_ns"`
	StatusCode    int          `json:"status_code"`
	StatusMessage string       `json:"status_message"`
	Attributes    string       `json:"attributes"`
	Resource      string       `json:"resource"`
	SessionID     string       `json:"session_id"`
	SessionLabel  string       `json:"session_label"`
	ReceivedAt    int64        `json:"received_at"`
	Events        []*SpanEvent `json:"events"`
	Links         []*SpanLink  `json:"links"`
}

type SpanEvent

type SpanEvent struct {
	SpanID     string `json:"span_id"`
	TraceID    string `json:"trace_id"`
	SessionID  string `json:"session_id"`
	TimeNs     int64  `json:"time_ns"`
	Name       string `json:"name"`
	Attributes string `json:"attributes"`
}

type SpanFilter

type SpanFilter struct {
	SessionID string
	Sort      string // "time" | "dur" | "name"
	Limit     int
}
type SpanLink struct {
	SpanID        string `json:"span_id"`
	TraceID       string `json:"trace_id"`
	SessionID     string `json:"session_id"`
	LinkedTraceID string `json:"linked_trace_id"`
	LinkedSpanID  string `json:"linked_span_id"`
	TraceState    string `json:"trace_state"`
	Attributes    string `json:"attributes"`
}

SpanLink is a causal/relational pointer from one span to another span (potentially in a different trace). OTel uses these for fan-out work items, batched jobs, async retries — anywhere a span was caused by something not on its direct parent chain.

type SpanRow

type SpanRow struct {
	Span
	Tag string `json:"tag,omitempty"`
}

type Stats

type Stats struct {
	SpanCount       int   `json:"span_count"`
	TraceCount      int   `json:"trace_count"`
	LogCount        int   `json:"log_count"`
	DBSize          int64 `json:"db_size"`
	SessionCount    int   `json:"session_count"`
	OldestSessionAt int64 `json:"oldest_session_at"`
}

type StorageBreakdown

type StorageBreakdown struct {
	Tables           []TableStat   `json:"tables"`
	Sessions         []SessionSize `json:"sessions"` // top 10 by approx bytes
	WALBytes         int64         `json:"wal_bytes"`
	MainBytes        int64         `json:"main_bytes"`
	LastCheckpointAt int64         `json:"last_checkpoint_at"`
}

StorageBreakdown gives a per-table and per-session storage summary for the Settings UI and the `spaniel compact` command.

type TableStat

type TableStat struct {
	Name        string `json:"name"`
	RowCount    int64  `json:"row_count"`
	ApproxBytes int64  `json:"approx_bytes"`
}

type TraceFilter

type TraceFilter struct {
	SessionID string
	Service   string
	Limit     int
	Page      int
}

type TraceIssue

type TraceIssue struct {
	ID            string `json:"id"`
	TraceID       string `json:"trace_id"`
	SessionID     string `json:"session_id"`
	Kind          string `json:"kind"`
	Fingerprint   string `json:"fingerprint"`
	Count         int    `json:"count"`
	WastedNs      int64  `json:"wasted_ns"`
	ParentSpanID  string `json:"parent_span_id"`
	ExampleSpanID string `json:"example_span_id"`
	CreatedAt     int64  `json:"created_at"`
}

func (*TraceIssue) AsLintWarning

func (i *TraceIssue) AsLintWarning() *LintWarning

AsLintWarning renders a detector finding as a lint warning so the lint view can show detector issues (e.g. N+1) alongside semantic-convention warnings.

type TraceOverlay

type TraceOverlay struct {
	TraceID    string `json:"trace_id"`
	Op         string `json:"op"`
	Service    string `json:"service"`
	StatusCode int    `json:"status_code"`
	StartNs    int64  `json:"start_ns"`
	EndNs      int64  `json:"end_ns"`
	DurationNs int64  `json:"duration_ns"`
}

TraceOverlay is the lightweight row returned to the frontend for the metrics chart overlay + correlated-traces panel — just enough to draw a marker and link out to /traces/:id.

type TraceOverlayFilter

type TraceOverlayFilter struct {
	Service   string
	SessionID string
	FromNs    int64
	ToNs      int64
	Limit     int
}

TraceOverlayFilter scopes the "traces during this window" query used by the metrics chart overlay. Service narrows by the metric's service name; SessionID by the active session when set. FromNs/ToNs are inclusive.

type TraceRow

type TraceRow struct {
	TraceID      string `json:"trace_id"`
	ServiceName  string `json:"service_name"`
	Name         string `json:"name"`
	StatusCode   int    `json:"status_code"`
	StartNs      int64  `json:"start_ns"`
	EndNs        int64  `json:"end_ns"`
	DurationNs   int64  `json:"duration_ns"`
	SessionID    string `json:"session_id"`
	SessionLabel string `json:"session_label"`
	HasN1        bool   `json:"has_n1"`
	SpanCount    int    `json:"span_count"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL