Skip to content

feat: logs search v2 - #4615

Draft
carderne wants to merge 9 commits into
mainfrom
feat/log-search-v2
Draft

feat: logs search v2#4615
carderne wants to merge 9 commits into
mainfrom
feat/log-search-v2

Conversation

@carderne

@carderne carderne commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a new global logs search path with a smaller search representation, asynchronous indexing, and bounded controls for building history. Existing reads remain on v1 by default.

task_events_search_v2

  • Replaces v1's raw attributes_text and two ngrambf_v1 indexes with one capped, normalized search_text column and one ClickHouse text index using the ngrams tokenizer.
  • Stores the extracted error_message and only the fields needed by the logs list.
  • Adds the full pagination key and a stable projection fingerprint to the sorting key. ReplacingMergeTree removes retry copies during merges.
  • Adds a granule-level minmax(inserted_at) source index to prune projector windows in newly written source parts.

Sync strategy

  • Replaces v1's insert-triggered materialized view with an asynchronous projector. An indexing failure delays search freshness instead of failing the source insert.
  • Runs every minute over fixed, half-open inserted_at windows behind a configurable safety delay, using ClickHouse time for the cutoff.
  • Stores live and historical watermarks in PostgreSQL and uses a PostgreSQL lease for singleton, ordered processing. Live catch-up runs before historical work.
  • Uses the same projection query for bounded backfill, with authenticated pause, resume, status, and cancellation controls plus lag and failure telemetry.

Environment variables and enabling v2

  • LOGS_SEARCH_TABLE_VERSION selects v1 or v2 reads and defaults to v1.
  • LOGS_SEARCH_PROJECTOR_ENABLED defaults to disabled. LOGS_SEARCH_PROJECTOR_CLICKHOUSE_URL can route projector writes separately, while additional settings bound work, time, rows, memory, and threads.
  • Backfill has a separate enable flag plus range and age limits. The v2 table starts empty, so forward projection and any required backfill must complete before switching reads to v2.

Webapp changes

  • Changes the Logs page default range from one hour to one day, with an explicit option to search seven days after no matches.
  • Requires at least three normalized characters in both the browser and server while preserving Unicode, paths, URLs, numbers, booleans, and identifiers.
  • Uses one bounded, tenant-scoped query with keyset pagination. Safety limits fail visibly rather than returning incomplete results.
  • Fetches a bounded number of extra rows and removes retry copies in the webapp. The fingerprint is part of the cursor so tied rows paginate safely.
  • Centralizes Logs access checks, fixes Logs-only sidebar access, and keeps log detail reads on the source table.

Supporting changes

  • Adds parameterized ClickHouse command() support, per-client request timeouts, and command summaries.
  • Adds unit and ClickHouse integration coverage for normalization, windows, retries, timestamp clamping, leases, backfill, and admin controls.

Prereqs

Project closed source windows with durable watermarks and leases. Keep v2 reads and backfill disabled by default until sufficient history exists.
Fetch bounded extra rows and remove duplicate projection identities in the application. Keep exact keyset pagination while background merges collapse physical copies.
Create the scheduled-projector schema directly in migration 038 and remove the intermediate migration.
@changeset-bot

changeset-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: cc3213c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 010f945c-8ee2-41e7-a121-f32d69678646

📥 Commits

Reviewing files that changed from the base of the PR and between d789149 and cc3213c.

📒 Files selected for processing (1)
  • internal-packages/clickhouse/schema/039_create_task_events_search_v2.sql
📜 Recent review details
⏰ Context from checks skipped due to timeout. (23)
  • GitHub Check: report
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (11, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (12, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (8, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (7, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (4, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (6, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (1, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (5, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (10, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (9, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (3, 12)
  • GitHub Check: webapp / 🧪 Unit Tests: Webapp (2, 12)
  • GitHub Check: obsmap / 🧪 Unit Tests: Observability Map
  • GitHub Check: fk-cascade-guard / fk-cascade-guard
  • GitHub Check: typecheck / typecheck
  • GitHub Check: internal / 🧪 Unit Tests: Internal
  • GitHub Check: e2e-webapp / 🧪 E2E Tests: Webapp
  • GitHub Check: runops-guard / runops-guard
  • GitHub Check: code-quality / code-quality
  • GitHub Check: audit
  • GitHub Check: audit
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (1)
internal-packages/clickhouse/schema/[0-9][0-9][0-9]_*.sql

📄 CodeRabbit inference engine (internal-packages/clickhouse/CLAUDE.md)

internal-packages/clickhouse/schema/[0-9][0-9][0-9]_*.sql: Migration file numbering: name files as 0(N+1)_descriptive_name.sql where N is the largest existing migration number in schema/; rebase and renumber if main adds migrations before opening a PR
DDL in migrations must be idempotent: use ALTER TABLE ... ADD COLUMN IF NOT EXISTS, CREATE TABLE IF NOT EXISTS, DROP TABLE IF EXISTS, ADD INDEX IF NOT EXISTS, DROP INDEX IF EXISTS, and CREATE MATERIALIZED VIEW IF NOT EXISTS forms to allow out-of-order and retry-safe application

Files:

  • internal-packages/clickhouse/schema/039_create_task_events_search_v2.sql
🔇 Additional comments (1)
internal-packages/clickhouse/schema/039_create_task_events_search_v2.sql (1)

3-3: LGTM!


Walkthrough

Added a ClickHouse V2 search table and projection pipeline with persistent state, leases, backfills, telemetry, scheduled processing, and admin controls. Updated log search normalization, minimum-length validation, bounded pagination, cursor handling, and period expansion. Centralized logs access checks across navigation and routes. Added ClickHouse command support, runtime configuration, database state storage, and integration tests.

Merge Risk: 🟠 High · up to cc321

This PR adds asynchronous log indexing and a new search path, but unresolved configuration and data-correctness issues could prevent the webapp from starting in existing deployments or create incorrect projected timestamps and search behavior. These issues should be fixed before merging.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: logs search v2.
Description check ✅ Passed The description gives a detailed technical summary and covers the main changes, although it omits the template checklist, testing, changelog, and screenshots sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/log-search-v2

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Observability map

As of cc3213c.

20/100 over 426 measured of 442 entry points (base 20, no change)

What this PR changed

route base head now failing
/admin/api/v1/logs-search-projector new 50 request-context

FIX FIRST

  • /api/v1/projects/:projectRef/envvars (sensitive) - auth-boundary, request-context
  • /auth/sso (sensitive) - auth-boundary, request-context
  • /_app/orgs/:organizationSlug/settings/team (sensitive) - error-classification, auth-scope, request-context

AUDIT 3 of 50 sensitive mutations record an actor. 47 without one.
CONTEXT 22 of 426 entry points name a tenant on a failure path. 325 appear only here, 39 of them sensitive, in the JSON rather than the fix list.

What the score is made of
CHECKS
  error-classification  179 applicable, 102 pass,   0 sole, global without it 12
  auth-boundary          62 applicable,  57 pass,   0 sole, global without it 17
  auth-scope             19 applicable,  17 pass,   0 sole, global without it 20
  request-context       426 applicable,  22 pass, 225 sole, global without it 64
  audit-trail            50 applicable,   3 pass,   0 sole, not in the score

The score and findings here are report-only and never gate the merge. Separately, a required test suite keeps this tool's symbol and route lists in sync with the code they name, and can fail a pull request that renames or removes a symbol they reference, or that adds the first route with a segment they anticipate. Each failure names the list to edit. The rules and their reasons: internal-packages/observability-map/README.md.

coderabbitai[bot]

This comment was marked as resolved.

@carderne
carderne marked this pull request as ready for review August 14, 2026 09:27
devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

Open in Devin Review

Comment thread internal-packages/clickhouse/src/taskEventsSearchProjector.ts
Comment thread apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
Comment on lines +26 to +43
projection_fingerprint UInt128 DEFAULT reinterpretAsUInt128(
sipHash128(trace_id, span_id, run_id, start_time)
),

INDEX idx_run_id run_id TYPE bloom_filter(0.001) GRANULARITY 1,
INDEX idx_search_text search_text
TYPE text(tokenizer = 'ngrams', preprocessor = lowerUTF8(search_text))
)
ENGINE = ReplacingMergeTree
PARTITION BY toDate(triggered_timestamp)
ORDER BY (
organization_id,
environment_id,
triggered_timestamp,
trace_id,
span_id,
projection_fingerprint
)

@devin-ai-integration devin-ai-integration Bot Aug 14, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔍 ReplacingMergeTree dedup key can collapse two genuinely distinct events

The v2 sorting/dedup key is (organization_id, environment_id, triggered_timestamp, trace_id, span_id, projection_fingerprint) where projection_fingerprint = sipHash128(trace_id, span_id, run_id, start_time). Span events reuse their parent span's span_id (apps/webapp/app/v3/eventRepository/clickhouseEventRepository.server.ts:590, :626), so two records on the same span that share an identical start_time (e.g. two span events recorded at the same nanosecond, or a zero-duration span event coinciding exactly with a zero-duration span) hash identically and would be silently merged into one row by ReplacingMergeTree — permanent loss of a log line, not just a retry-copy collapse. v1's plain MergeTree kept both. Log records are safe because otlpTransform.server.ts:124 mints a fresh span_id per log. If exact-timestamp collisions are considered possible, adding kind/message (or an insert sequence) to the fingerprint would make the identity total.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

devin-ai-integration[bot]

This comment was marked as resolved.

Renumber search_v2 table migration to 039 and drop the inserted_at
index DDL, which now ships as standalone migration 038.
@carderne
carderne marked this pull request as draft August 14, 2026 13:23

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Devin Review found 4 new potential issues.

Open in Devin Review

Comment thread apps/webapp/app/services/logsSearchProjectorInstance.server.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant