Skip to content

Releases: PostHog/snuffle

snuffle 0578b13

Choose a tag to compare

@github-actions github-actions released this 08 Oct 09:20
0578b13
fix(logql): close SQL injection and unbounded range loops (#12)

- Keep the regexp parser pattern and capture-group indexes in separate
  fields. A label named __regex no longer puts the raw pattern into SQL.
- Cap Loki range queries at 11000 points per series, reject timestamps
  that overflow int64 nanoseconds when aligned to the step, and count
  steps by index instead of ts += step.
- Return an error for a lone '!' in a LogQL label filter instead of
  looping forever.
- Normalize /loki/api/v1/label/<name>/... in request metrics so caller
  text never becomes a metric label value.
- Add a fuzz test that sends queries through the HTTP API, records every
  SQL statement, and checks that user text stays inside SQL literals.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

snuffle 7d7e22e

Choose a tag to compare

@github-actions github-actions released this 01 Oct 14:11
7d7e22e
feat(metrics): compact histogram quantiles for all counter functions,…

snuffle 89dda2a

Choose a tag to compare

@github-actions github-actions released this 23 Sep 16:40
89dda2a
feat(metrics): read the PostHog metrics4 schema (#10)

* feat(metrics): read the PostHog metrics4 schema

The posthog layout reads metrics4_samples, metrics4_series,
metrics4_attributes, and metrics4_names, and writes to metrics4_input.

metrics4_samples stores the points of one series-hour in parallel arrays.
Range reads and the range pushdown filter the points of each row to the
window and combine the rows of a series-hour with groupArrayArray. Instant
reads and histogram reads expand the arrays with ARRAY JOIN. Series
selection filters metrics4_series on the hour buckets of the window. Every
sample read adds indexHint(arrayMin(timestamp_arr) <= maxt AND
arrayMax(timestamp_arr) >= mint) for the minmax skip indexes on those
expressions.

The PostHog e2e suites and the test schema move to the metrics4 tables.

Generated-By: PostHog Desktop
Task-Id: 212188a2-7ee4-44ee-b2ae-581e72136474

* feat(metrics): read mixed native and classic histogram rows

Capture folds a complete classic histogram scrape into one native row and
writes the parts of a split scrape as plain _bucket, _count, and _sum rows.
Both forms now read together: stored component series no longer suppress the
virtual histogram series, and a stored series and a virtual series with the
same label set merge into one series by timestamp, with the stored sample
winning on a shared timestamp. The fast-path histogram check and the source
lookup are bound to the query window.

Generated-By: PostHog Desktop
Task-Id: 212188a2-7ee4-44ee-b2ae-581e72136474

* fix(metrics): sort virtual histogram series built from several sources

Capture gives each folded bound set its own series, so one label set can
collect points from several stored series that arrive ordered by series.
Sort the merged samples before the engine reads them.

Generated-By: PostHog Desktop
Task-Id: 212188a2-7ee4-44ee-b2ae-581e72136474

snuffle 8264f6e

Choose a tag to compare

@github-actions github-actions released this 21 Sep 08:51
8264f6e
Restore native schema range query fast paths

snuffle e0bdc04

Choose a tag to compare

@github-actions github-actions released this 18 Sep 13:04
e0bdc04
Push range counter aggregations down to ClickHouse (#9)

* Push range counter aggregations down to ClickHouse

Range queries of the shape `agg by (...) (F(selector[w]))` over the PostHog
layout now run in one ClickHouse query when F is increase, delta, rate, irate,
idelta or a bare selector. ClickHouse sorts each series into arrays, computes
the MetricsQL rollup at every step and aggregates across series, so one row per
group and step returns to Go instead of every raw sample.

The engine path reads PostHog float samples as one RowBinary payload per
series and iterates float series in place. The query log records the
ClickHouse, evaluation and encoding time of every request.

Generated-By: PostHog Desktop
Task-Id: 8ac0a9e0-3731-4a96-8538-5537a08cbefc

* Rewrite range pushdown comments

Generated-By: PostHog Desktop
Task-Id: e87db87e-6854-4575-9551-c11cc5ecd4d1

* feat(metrics): push offset range aggregations down to ClickHouse

A selector offset shifts the steps ClickHouse evaluates and the output
timestamps stay unshifted. An offset on the aggregate, which the MetricsQL
rewrite turns into a default_rollup over a subquery, evaluates the aggregate
on the epoch-aligned step grid that covers the shifted range; Go then reads
the latest grid point within the MetricsQL window before each shifted step,
as the engine does for the subquery.

Generated-By: PostHog Desktop
Task-Id: 212188a2-7ee4-44ee-b2ae-581e72136474
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* perf(metrics): read PostHog samples as typed delta arrays

The engine path read one RowBinary string per series. An opaque string of
raw 8-byte integers and doubles compresses poorly: 12 MiB with LZ4 for a
24-hour read of 2.2M samples. The same samples as typed arrays of timestamp
deltas and values move 1.5 MiB, and the ClickHouse statement no longer waits
on the socket.

Generated-By: PostHog Desktop
Task-Id: 212188a2-7ee4-44ee-b2ae-581e72136474
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* perf(metrics): compress ClickHouse traffic with ZSTD

CH_COMPRESSION selects the codec for native protocol blocks in both
directions and defaults to zstd. On a 24-hour read of 1974 series the
sample arrays moved 0.8 MiB instead of 1.5 MiB with LZ4 at the same
ClickHouse CPU; lz4 and none stay available.

Generated-By: PostHog Desktop
Task-Id: 212188a2-7ee4-44ee-b2ae-581e72136474
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>

snuffle 35ad3b1

Choose a tag to compare

@github-actions github-actions released this 17 Sep 13:17
35ad3b1
Expose Snuffle ClickHouse read bytes (#7)

Generated-By: PostHog Desktop
Task-Id: 27db5717-ddaf-492f-8298-3ce9ceb6661a

snuffle c150d99

Choose a tag to compare

@github-actions github-actions released this 16 Sep 16:31
c150d99
feat(metrics): metric name rollup search, per-series labels, and virt…

snuffle fe1d6cf

Choose a tag to compare

@github-actions github-actions released this 15 Sep 07:38
fe1d6cf
Use series projection for remote-write lookups

snuffle dee1cb7

Choose a tag to compare

@github-actions github-actions released this 15 Sep 08:08
dee1cb7
Reduce known-series cache overhead

snuffle a20223a

Choose a tag to compare

@github-actions github-actions released this 15 Sep 11:56
a20223a
fix(metrics): improve PromQL selector windows and counter queries (#4)

* fix(metrics): preserve lookback in PostHog PromQL queries

Generated-By: PostHog Desktop
Task-Id: 52a64169-b741-47be-ab09-da69151123f8

* fix(metrics): apply MetricsQL selector and counter rules

Generated-By: PostHog Desktop
Task-Id: 52a64169-b741-47be-ab09-da69151123f8

* docs: keep PromQL compatibility wording

Generated-By: PostHog Desktop
Task-Id: 52a64169-b741-47be-ab09-da69151123f8

* fix(metrics): address review findings for MetricsQL selector windows

Copy the range result instead of compacting the engine matrix in place, so
the engine does not return the same point buffer to its pool twice.

Restore the instant SQL fast paths: the internal default_rollup of an instant
query reads the lookback window, so the fast path unwraps it to the selector.
Range fast paths cannot reproduce automatic selector windows or MetricsQL
counter calculations, so the dead range SQL paths are removed.

Keep Prometheus functions that MetricsQL does not define by carrying their
names through the MetricsQL parser. Leave the selector arguments of timestamp
and absent untouched, use the library rollup argument index, and resolve
implicit windows inside a subquery against the subquery step.

Evaluate running_sum as a post-pass over the range result instead of a
doubled subquery. Guard the rate divisor, record query stats after the NaN
filter, and update README and PERFORMANCE for the paths that run.

Generated-By: PostHog Desktop
Task-Id: 46a47e68-6b45-4bbc-9303-303608734206

* fix(metrics): keep nested running_sum through a subquery

The ClickHouse e2e test evaluates running_sum inside quantile. The outermost
running_sum still runs on the range result; a nested one runs as a subquery
that spans the range from the aligned start.

Generated-By: PostHog Desktop
Task-Id: 46a47e68-6b45-4bbc-9303-303608734206