Documentation
¶
Overview ¶
Package query implements the structured Honeycomb-style query builder: a JSON AST that callers send, translated by Build into parameterized SQL over the spans or logs tables.
The wire shape is the same struct, so a POST /api/query handler can decode straight into it with encoding/json.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func FormatDisplay ¶ added in v0.6.0
FormatDisplay produces a single-line, Honeycomb-style one-glance summary of a query for the history list view — "SELECT COUNT WHERE x = y GROUP BY z". It's intentionally lossy: SELECTs collapse multiple aggregations into a comma list, filter values render via %v, HAVING/ORDER BY aren't surfaced. If you want the full AST, rehydrate from query_json.
func HashQuery ¶ added in v0.6.0
HashQuery returns a stable content hash of the query suitable for query_history deduplication. Time-range bounds are excluded — two runs of "same query, different wall-clock window" dedupe to one history row. BucketMS and granularity (if present) are included because they're meaningful to the result shape.
Types ¶
type AggOp ¶
type AggOp string
AggOp is the aggregation function. Names mirror Honeycomb's query builder.
const ( OpCount AggOp = "count" // COUNT(*) OpCountField AggOp = "count_field" // COUNT(field) — rows where field IS NOT NULL OpCountDistinct AggOp = "count_distinct" // COUNT(DISTINCT field) OpSum AggOp = "sum" OpAvg AggOp = "avg" OpMin AggOp = "min" OpMax AggOp = "max" OpP001 AggOp = "p001" OpP01 AggOp = "p01" OpP05 AggOp = "p05" OpP10 AggOp = "p10" OpP25 AggOp = "p25" OpP50 AggOp = "p50" OpP75 AggOp = "p75" OpP90 AggOp = "p90" OpP95 AggOp = "p95" OpP99 AggOp = "p99" OpP999 AggOp = "p999" // Rate aggregations compute the per-second delta of the underlying // aggregation between consecutive time buckets. They require bucket_ms // to be set; the first bucket in each group emits NULL (no prior point // to diff against). The underlying aggregations are SUM/AVG/MAX // respectively — the rate layer is a post-processing step in the // executor, not a SQL expression. OpRateSum AggOp = "rate_sum" OpRateAvg AggOp = "rate_avg" OpRateMax AggOp = "rate_max" )
type Aggregation ¶
type Aggregation struct {
Op AggOp `json:"op"`
Field string `json:"field,omitempty"`
Alias string `json:"alias,omitempty"`
}
Aggregation is one entry in SELECT.
type Column ¶
type Column struct {
Name string `json:"name"`
Type string `json:"type"` // "string" | "int" | "float" | "bool" | "time"
}
Column describes one output column of a compiled query — used by both the executor (for scanning) and the HTTP response.
type Compiled ¶
type Compiled struct {
SQL string
Args []any
Columns []Column
// HasBucket reports whether the query included a time bucket; when true,
// the first column is the bucket time and callers should group rows into
// time-series lines keyed by the GROUP BY tuple.
HasBucket bool
// GroupKeys holds the aliases of GROUP BY expressions (used to split
// rows into series).
GroupKeys []string
// Rates describes post-processing transforms that turn underlying SUM/
// AVG/MAX columns into per-second deltas. Executor applies them after
// scanning the rows from SQLite.
Rates []RateSpec
}
Compiled is the output of Build — a parameterized SQL statement plus the column metadata for decoding the result rows.
func Build ¶
Build translates a validated Query into a parameterized SQL statement against the unified `events` table. Dataset selects a signal_type='…' preset filter prepended to the WHERE clause. Field references route to real columns when the key is whitelisted; otherwise they fall through to json_extract(attributes, '$."<key>"').
An empty Select means raw-rows mode: Build emits SELECT <fixed columns> and lets the caller iterate events instead of aggregates.
The caller must have invoked Query.Validate() first — Build assumes its input is well-formed.
type Dataset ¶
type Dataset string
Dataset pins a query to exactly one signal type: spans/logs query the shared events table with a signal_type predicate; metrics query the metric_events table. Cross-signal queries are not supported — each table has its own column set, so a mixed-signal SELECT can't be expressed without a UNION that doesn't pay for its complexity.
type Filter ¶
type Filter struct {
Field string `json:"field"`
Op FilterOp `json:"op"`
Value any `json:"value,omitempty"`
}
Filter is one WHERE/HAVING predicate.
type FilterOp ¶
type FilterOp string
FilterOp is the comparison operator. For SQL codegen, the equality-style operators are used literally as the operator between field and "?".
const ( FilterEq FilterOp = "=" FilterNe FilterOp = "!=" FilterGt FilterOp = ">" FilterGe FilterOp = ">=" FilterLt FilterOp = "<" FilterLe FilterOp = "<=" FilterIn FilterOp = "in" FilterNotIn FilterOp = "!in" FilterExists FilterOp = "exists" FilterNotExist FilterOp = "!exists" FilterContains FilterOp = "contains" FilterNotContain FilterOp = "!contains" FilterStartsWith FilterOp = "starts-with" FilterNotStartWith FilterOp = "!starts-with" FilterEndsWith FilterOp = "ends-with" FilterNotEndWith FilterOp = "!ends-with" )
type JSONTime ¶
JSONTime accepts RFC3339Nano strings or integer nanoseconds in the payload. The underlying storage is a time.Time; Unix() extracts nanoseconds for the SQL layer.
func (*JSONTime) UnmarshalJSON ¶
type Order ¶
type Order struct {
Field string `json:"field"`
Dir string `json:"dir,omitempty"` // "asc" | "desc" (default desc)
}
Order is one ORDER BY entry. The field may be a raw attribute name or one of the SELECT aliases.
type Query ¶
type Query struct {
Dataset Dataset `json:"dataset"`
TimeRange TimeRange `json:"time_range"`
Select []Aggregation `json:"select"`
Where []Filter `json:"where,omitempty"`
GroupBy []string `json:"group_by,omitempty"`
OrderBy []Order `json:"order_by,omitempty"`
Having []Filter `json:"having,omitempty"`
Limit int `json:"limit,omitempty"`
// BucketMS, when > 0, groups rows into time buckets of that size and
// emits a `bucket_ns` column as the first SELECT entry. Use this for
// time-series charts.
BucketMS int64 `json:"bucket_ms,omitempty"`
}
Query is the wire-level structured query.