Skip to content

fix: select query_logs dialect via logsDialect - #357

Merged
Rodriguespn merged 3 commits into
mainfrom
feat/logs-dialect
Aug 10, 2026
Merged

fix: select query_logs dialect via logsDialect#357
Rodriguespn merged 3 commits into
mainfrom
feat/logs-dialect

Conversation

@Rodriguespn

@Rodriguespn Rodriguespn commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Adds an optional logsDialect ('clickhouse' | 'bigquery') to DebuggingOperations so each platform declares which SQL its logs endpoint speaks. query_logs then picks its whole dialect-appropriate description and sql param hint from a single lookup table, instead of hardcoding ClickHouse copy — no environment-conditional prose the model has to reason about. Defaults to 'clickhouse' when unset, so existing platform implementers are unaffected.

Implements Matt's logsDialect suggestion raised in the #333 review.

Why: it lets query_logs roll out across every environment without env-specific branching. Hosted stays ClickHouse; self-hosted/CLI can keep its BigQuery-backed logs endpoint and declare logsDialect: 'bigquery'. This unblocks shipping the MCP server to self-hosted (studio) regardless of whether it's on BigQuery or ClickHouse, rather than holding the studio image back until self-hosted moves to ClickHouse.

Note

The comment sketched "reuse the get_logs description for bigquery" — I instead give query_logs a proper BigQuery-dialect description, since get_logs describes a service param while query_logs takes sql. The BigQuery sql hint mirrors the canonical Logflare self-hosted schema (cross join unnest(metadata)); worth confirming when studio wires up the platform.

Refs AI-1046

Add an optional `logsDialect` ('clickhouse' | 'bigquery') to
`DebuggingOperations` so each platform declares which SQL its logs
endpoint speaks. `query_logs` picks the whole dialect-appropriate
description and `sql` param hint from a single `queryLogsByDialect`
table instead of hardcoding ClickHouse copy — no environment-conditional
prose the model has to reason about.

Defaults to 'clickhouse' when unset, so existing platform implementers
are unaffected. Hosted (api-platform) declares 'clickhouse'; the tool
gating (`hidden: Boolean(queryLogs)`) is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Rodriguespn Rodriguespn changed the title feat: select query_logs dialect via logsDialect fix: select query_logs dialect via logsDialect Aug 10, 2026
Assemble the per-dialect description and `sql` hint from shared wording,
supplying only the two parts that differ per dialect: the dialect `name`
and the `schemaHint`. The ClickHouse description and `sql` hint remain
byte-identical to before.

Correct the BigQuery hint to match the real self-hosted Logflare
implementation (apps/studio/lib/api/self-hosted/logs.ts): per-service
source tables with fields nested under `metadata` (read via
`cross join unnest(metadata)`), dropping `function_logs` /
`workflow_run_logs`, which self-hosted does not serve. Verified
end-to-end against a local self-hosted stack: query_logs passes
BigQuery-dialect SQL through to Logflare and returns real logs.

Also assert in tests that the BigQuery hint omits the unsupported sources.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coveralls

coveralls commented Aug 10, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 31418601124

Warning

No base build found for commit 798806b on main.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 96.512%

Details

  • Patch coverage: 51 of 51 lines across 2 files are fully covered (100%).

Uncovered Changes

No uncovered changes found.

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 3030
Covered Lines: 2945
Line Coverage: 97.19%
Relevant Branches: 382
Covered Branches: 348
Branch Coverage: 91.1%
Branches in Coverage %: Yes
Coverage Strength: 50.05 hits per line

💛 - Coveralls

@Rodriguespn
Rodriguespn marked this pull request as ready for review August 10, 2026 14:18
@Rodriguespn
Rodriguespn requested a review from a team as a code owner August 10, 2026 14:18
@Rodriguespn Rodriguespn added the publish-preview Runs `publish-preview` workflow to publish preview packages via https://pkg.pr.new/ label Aug 10, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/@supabase/mcp-server-postgrest@30a7065
pnpm add https://pkg.pr.new/@supabase/mcp-server-supabase@30a7065
pnpm add https://pkg.pr.new/@supabase/mcp-utils@30a7065

commit: 30a7065

Comment thread packages/mcp-server-supabase/src/tools/debugging-tools.ts
clickhouse: buildQueryLogsCopy({
name: 'ClickHouse',
schemaHint:
"Logs are exposed through a `logs` table; filter by `source` (e.g. 'edge_logs', 'postgres_logs', 'function_edge_logs', 'function_logs', 'auth_logs', 'storage_logs', 'realtime_logs', 'workflow_run_logs') and read nested fields via `log_attributes['<key>']`.",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated, but in my testing I noticed a postgrest_logs table available in staging not part of this list.

I gather this is just an example not meant to be exhaustive, but I wonder:

  • Will agents reliably discover the list of available sources before querying? Is there risk of hallucination if our description doesn't match the real full schema?
  • Will they understand what each log source represents? For example, will they know what function_edge_logs means compared to function_logs?

Not something we need to solve in this PR but maybe worth revisiting w/ evals.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @mattrossman. I dug in and made a change plus stood up evals to keep us honest about it. Result below.

The log set is genuinely incomplete. I checked a live self-hosted Logflare catalog (_analytics.sources) and it exposes postgREST.logs.prod and pgbouncer.logs.prod, neither of which we listed. So I trimmed it to a few representative examples marked non-exhaustive, and added a discovery step, for both dialects:

ClickHouse — from:

A read-only ClickHouse SQL query to run against the project's unified logs stream. Logs are exposed through a logs table; filter by source (e.g. 'edge_logs', 'postgres_logs', 'function_edge_logs', 'function_logs', 'auth_logs', 'storage_logs', 'realtime_logs', 'workflow_run_logs') and read nested fields via log_attributes['<key>'].

to:

A read-only ClickHouse SQL query to run against the project's unified logs stream. Logs are exposed through a logs table; filter by source (common values include 'edge_logs', 'postgres_logs', and 'function_edge_logs', but this list is not exhaustive — run select distinct source from logs to discover the sources available for this project) and read nested fields via log_attributes['<key>'].

BigQuery — from:

A read-only BigQuery SQL query to run against the project's unified logs stream. Each service has its own source table (e.g. 'edge_logs', 'postgres_logs', 'function_edge_logs', 'auth_logs', 'storage_logs', 'realtime_logs'); nested fields live under metadata, read via cross join unnest(metadata) as m and then m.<field> (unnest further for nested structs such as m.request or m.parsed).

to:

A read-only BigQuery SQL query to run against the project's logs. Each service has its own source table (common ones include 'edge_logs', 'postgres_logs', and 'function_edge_logs', but the set is not exhaustive — other per-service tables, e.g. Data API and pooler logs, also exist); read nested fields by cross joining unnest(metadata) as m and then m.<field> (unnest further for nested structs such as m.request or m.parsed).

(BigQuery has no unified stream to select distinct source from, so it names the real-but-unlisted families instead. I also fixed "unified logs stream" → "logs" there, since it's per-table.)


Created 2 evals to answer both questions

Two "ephemeral" regression evals, pinned to this PR's preview build: supabase/evals#185. CI run across gpt-5.4-mini + claude-code sonnet 5 — all 4 pairs pass:

Eval gpt-5.4-mini (codex) claude-code sonnet 5
logs-002 (undescribed source) ✅ 3/3 ✅ 3/3
logs-003 (function streams) ✅ 2/3 ✅ 3/3

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answering directly to your questions:

do agents discover sources / is there hallucination risk?

investigate-logs-002-undescribed-source-discovery: the root cause (permission denied for table orders, 403) lives only in postgrest_logs, which the description never lists.

Result: both models solved it and neither hallucinated

  • both first enumerated the available sources (select … group by source / distinct source)
  • then queried postgrest_logs by name.

So they don't blindly trust the listed set; given the unified stream they discover what's actually there.

do they understand function_edge_logs vs function_logs?

investigate-logs-003-function-stream-disambiguation: the bug (charging dollars as cents) is only in the runtime console (function_logs), while the request stream (function_edge_logs) shows healthy 200s.

Result: both models surfaced the runtime bug and weren't fooled by the 200s.

  • claude-code sonnet 5 specifically queried the function_logs stream (understood the distinction, 3/3);
  • gpt-5.4-mini reached it by content-filtering the unified stream rather than naming the source (2/3).

@mattrossman mattrossman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested the preview build working against staging. Agreed this logsDialect approach adds flexibility for easier migration to query_logs across environments.

Based on eval findings (supabase/evals#185): capable models query the
unified `logs` stream and filter by content/`log_attributes` rather than
relying on the enumerated source list, and reach sources the description
never lists. The exhaustive-looking list added little and risked reading
as complete (false authority → missed sources).

Shrink the ClickHouse `sql` hint's source list to three representative
examples marked non-exhaustive, and point the model at
`select distinct source from logs` to discover the rest — so correctness
no longer depends on a frozen list staying current. Apply the same
non-exhaustive framing to BigQuery (no unified stream to enumerate, so it
names the real-but-unlisted Data API / pooler tables instead), and fix
the BigQuery copy to say "logs" rather than "unified logs stream" via a
per-dialect `logsNoun`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Rodriguespn
Rodriguespn merged commit 80ff453 into main Aug 10, 2026
7 checks passed
@supabase-releaser supabase-releaser Bot mentioned this pull request Aug 10, 2026
Rodriguespn pushed a commit that referenced this pull request Aug 10, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>mcp-utils: 0.6.0</summary>

##
[0.6.0](mcp-utils-v0.5.1...mcp-utils-v0.6.0)
(2026-08-10)


### Features

* hide tools from tools/list
([#334](#334))
([d80471a](d80471a))
</details>

<details><summary>mcp-server-supabase: 0.10.0</summary>

##
[0.10.0](mcp-server-supabase-v0.9.0...mcp-server-supabase-v0.10.0)
(2026-08-10)


### ⚠ BREAKING CHANGES

* add query_logs tool for custom log queries
([#333](#333))

### Features

* add --content-api-url flag and SUPABASE_CONTENT_API_URL env var
([#343](#343))
([6fcaaa3](6fcaaa3))
* add query_logs tool for custom log queries
([#333](#333))
([798806b](798806b))
* hide tools from tools/list
([#334](#334))
([d80471a](d80471a))


### Bug Fixes

* hide read-only mode
([#349](#349))
([5cda067](5cda067))
* **pg-meta:** pair composite FK columns positionally to avoid cartesi…
([#317](#317))
([10af00b](10af00b))
* select query_logs dialect via logsDialect
([#357](#357))
([80ff453](80ff453))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: supabase-releaser[bot] <223506987+supabase-releaser[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

publish-preview Runs `publish-preview` workflow to publish preview packages via https://pkg.pr.new/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants