Big Data 10 min read

How to Write and Test Snuba Queries in Sentry’s Data Platform

This guide walks through discovering Snuba datasets and entities, inspecting their schemas, building queries with the Python SDK or Sentry code, testing via the Web UI or curl, and interpreting request, response, and debugging information including HTTP status codes and ClickHouse metrics.

Hacker Afternoon Tea
Hacker Afternoon Tea
Hacker Afternoon Tea
How to Write and Test Snuba Queries in Sentry’s Data Platform

Explore Snuba Data Model

Snuba queries require selecting a dataset, an entity, and understanding the entity schema. Documentation of the data model is at https://getsentry.github.io/snuba/architecture/datamodel.html. Datasets are defined in snuba/datasets/factory.py (https://github.com/getsentry/snuba/blob/master/snuba/datasets/factory.py). List declared entities with: snuba entities list Typical output includes discover, errors, events, groups, groupedmessage, etc. Describe a specific entity, e.g. groupedmessage, with: snuba entities describe groupedmessage The command prints the column list, types, and relationship definitions. For groupedmessage the output shows columns such as offset UInt64, project_id UInt64, id UInt64, and a LEFT join to the events table on project_id = LEFT.project_id and id = LEFT.group_id.

Prepare Snuba Query

Snuba uses the SnQL language (https://getsentry.github.io/snuba/language/snql.html). The Python SDK ( getsentry/snuba-sdk – https://github.com/getsentry/snuba-sdk) provides classes to build a Query object. Example:

query = Query(
    dataset="discover",
    match=Entity("events"),
    select=[
        Column("title"),
        Function("uniq", [Column("event_id")], "uniq_events"),
    ],
    groupby=[Column("title")],
    where=[
        Condition(Column("timestamp"), Op.GT, datetime.datetime(2021, 1, 1)),
        Condition(Column("project_id"), Op.IN, Function("tuple", [1, 2, 3])),
    ],
    limit=Limit(10),
    offset=Offset(0),
    granularity=Granularity(3600),
)

Further details are in the SDK docs at https://getsentry.github.io/snuba-sdk/.

Send Query via Sentry

Sentry imports the Snuba SDK and provides a client API (see https://github.com/getsentry/sentry/blob/master/src/sentry/utils/snuba.py#L667). The API sends the Query object to Snuba and returns a dictionary containing data, meta, timing, and stats. Example response:

{
    "data": [{"title": "very bad", "uniq_events": 2}],
    "meta": [
        {"name": "title", "type": "String"},
        {"name": "uniq_events", "type": "UInt64"}
    ],
    "timing": {"...": "details ..."}
}

The meta section lists column names and ClickHouse‑inferred types.

Web UI Testing

Snuba ships a minimal Web UI reachable at http://localhost:1218/[DATASET]/snql. Paste a SnQL string into the query field; the JSON response matches the SDK output.

Sending Queries with curl

The Web UI performs a POST of a JSON payload. The same payload can be sent with curl or any HTTP client to the same endpoint.

Request and Response Formats

query

: string containing the SnQL query. dataset: name of the dataset (may also be part of the URL). debug: includes detailed ClickHouse statistics. consistent: forces single‑threaded ClickHouse execution and guarantees order consistency via the in_order load‑balancing setting (https://clickhouse.tech/docs/en/operations/settings/settings/#load_balancing-in_order). turbo: applies the TURBO_SAMPLE_RATE defined in Snuba settings and prevents the FINAL mode from being applied unintentionally.

HTTP Status Codes

200

– successful query. 400 – query validation failed (e.g., missing timestamp condition). 500 – ClickHouse‑related error such as timeout or connection issue. 429 – internal Snuba rate‑limiting.

Successful responses contain data, meta, timing, and stats. The stats dictionary includes fields such as clickhouse_table, final, sample, project_rate, global_rate, project_concurrent, global_concurrent, consistent, result_rows, result_cols, and query_id. The sql element shows the underlying ClickHouse query, and timing breaks down execution time into marks_ms stages (e.g., cache_get, cache_set, execute, prepare_query, validate_schema).

{
    "data": [],
    "meta": [{"name": "title", "type": "String"}],
    "timing": {
        "timestamp": 1621038379,
        "duration_ms": 95,
        "marks_ms": {
            "cache_get": 1,
            "cache_set": 4,
            "execute": 39,
            "prepare_query": 10,
            "validate_schema": 34
        }
    },
    "stats": {
        "clickhouse_table": "errors_local",
        "final": false,
        "referrer": "http://localhost:1218/events/snql",
        "sample": null,
        "project_rate": 0,
        "project_concurrent": 1,
        "global_rate": 0,
        "global_concurrent": 1,
        "consistent": false,
        "result_rows": 0,
        "result_cols": 1,
        "query_id": "f09f3f9e1c632f395792c6a4bfe7c4fe"
    },
    "sql": "SELECT (title AS _snuba_title) FROM errors_local PREWHERE equals((project_id AS _snuba_project_id), 1) WHERE equals(deleted, 0) AND greaterOrEquals((timestamp AS _snuba_timestamp), toDateTime('2021-05-01T00:00:00', 'Universal')) AND less(_snuba_timestamp, toDateTime('2021-05-11T00:00:00', 'Universal')) LIMIT 1000 OFFSET 0"
}

Query Validation Errors

When validation fails, Snuba returns a JSON error object, for example:

{
    "error": {
        "type": "invalid_query",
        "message": "missing >= condition on column timestamp for entity events"
    }
}

ClickHouse errors have a similar structure with type": "clickhouse" and a detailed message.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Data ModelingClickHouseSentryWeb UIQueryPython SDKSnuba
Hacker Afternoon Tea
Written by

Hacker Afternoon Tea

You might find something interesting here ^_^

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.