RunReveal Explorer & Search: Querying Your Data Directly

The Interface Sitting on Top of Everything in Part 2
Part 2 covered the logs table and the ClickHouse foundation underneath RunReveal. This part covers how you actually touch that table day to day — the Explorer, RunReveal's log search and query interface.
It's easy to undersell this as "just a search bar," and I almost did exactly that in the first article of this series before realizing how much is actually packed into it.
RunReveal's own description calls it a compact, single-page interface with sidebar navigation, saved queries with full version history, and AI-powered query assistance built in — not a separate add-on chat window bolted to the side.
Layout
The explorer is organized into a few consistent pieces:
A collapsible sidebar listing every queryable table, grouped by category: the main logs table, source-specific views, and any custom views you've created. Expand a table to see its schema and columns without leaving the page.
A top bar and filter section for building filters without hand-writing WHERE clauses — filters are type-aware, so a timestamp field gets different filter operators than a string field.
A time-series histogram showing event volume across your selected window, which is the fastest way to spot a spike or a gap before you've written a single line of SQL.
A saved queries sidebar, and a query editor you can drop into directly when a filter-builder UI isn't expressive enough for what you're trying to ask.

Saved Queries Actually Have Version History
Every time you save a query, RunReveal creates a new version rather than overwriting the last one.
That's a small detail that matters more than it sounds like — it means a saved detection-adjacent query you're iterating on keeps a real history, so if a change makes it worse, going back is a click rather than a rewrite from memory.
Saved queries also carry their full parameters and settings with them, and every exploration state — filters, table, time range — can be shared as a URL, which makes handing a specific query off to a teammate genuinely simple.
The AI Assistant Is Actually Useful Here
You can describe what you want in plain language and the assistant generates a SQL query from that description, which you then review before running — it doesn't execute blind on your behalf.
The more interesting piece is what happens when a query fails: the assistant reads the actual error, proposes a fix, and lets you review the corrected query before applying it.
For anyone who's spent time debugging a ClickHouse syntax error at 2am during an actual incident, that's not a gimmick feature.
Two Timestamps, and Why It Actually Matters
RunReveal stores two separate timestamps on every normalized event, and which one you filter on has a real, measurable performance impact — this is documented explicitly, not something I had to discover by trial and error for once.

receivedAt — when RunReveal ingested the event. Indexed as part of the primary key, consistent across every source regardless of how that source reports time, and correctly accounts for delayed log delivery.
Use this for time filtering, detections, and any scheduled query.
eventTime — when the activity actually happened, according to the original source. Not indexed, so filtering on it is slower, and it can be missing or inconsistent depending on the source.
Use it for displaying the original event time, not for filtering.
-----------------------------------------------------------------------------------------------------------
The docs' own example, and it's a good one: filtering on receivedAt is marked as the correct pattern; filtering on eventTime alone is explicitly flagged as something to avoid for anything performance-sensitive. If a query feels slower than it should, this is the first thing worth checking.
-----------------------------------------------------------------------------------------------------------
Query Performance, in Practice
A short list of habits the documentation calls out directly, all of which match what I'd already learned the hard way testing detections in Part 6:
Use source-specific views (aws_cloudtrail_logs, okta_logs, github_logs, and others) instead of querying the raw logs table and filtering sourceType yourself.
Filter on primary-key and indexed fields first — sourceType, then receivedAt, then sourceID — before adding other conditions, matching how the table itself is physically organized.
Start with a small time range to validate a query, then widen it. A one-hour window while testing is dramatically faster to iterate on than starting with thirty days.
Select only the columns you actually need in an aggregation query rather than pulling everything.
Platform Tables — Querying RunReveal About Itself
This is the part that genuinely surprised me.
Explorer doesn't just query your ingested logs — there's a whole second category of platform tables that let you query RunReveal's own operational data with the same SQL interface:
detections — the base table for every detection run, one row per finding, regardless of whether it ever escalated to a signal or alert. Useful for answering "has this ever matched anything" without digging through the UI.
scheduled_query_runs — execution metadata for every scheduled detection run: runtime, the exact SQL that executed, parameters, and error messages if a run failed.
runreveal_source_volumes — per-minute event counts and approximate ingested bytes, bucketed by source. This is the raw data behind the kind of volume-anomaly agent covered in Part 8.
Ingestion and pipeline error tables — failed schema validation events, complete with the original raw log that failed, plus per-pipeline-step dropped-byte metrics.
Health check subscription tables — the underlying data behind the destination health checks covered in Part 2.
A workspace audit trail table — who did what, when, from which IP.
Threat intelligence indicator feeds — a built-in table of known-bad IPs you can join against your own traffic directly in SQL.

Why this matters beyond curiosity: every dashboard, health check, and agent report in this platform is ultimately just a query against tables you can also query yourself. Nothing here is a black box — if you don't trust a number a dashboard is showing you, you can go verify it directly against the same table it reads from.
-------------------------------------------------------Dean-----------------------------------------------
Part 4 goes the other direction — not how you query data, but what happens to it in flight before it's ever stored: transforms, filtering, dropping, masking, sampling, and enrichment.



Comments