Skip to content

fix(webapp): Don't add internal logs to materialized view task_events_search_mv_v1e#3069

Open
mpcgrid wants to merge 11 commits intomainfrom
fix/add-condition-to-task_events_search_for_internal_logs
Open

fix(webapp): Don't add internal logs to materialized view task_events_search_mv_v1e#3069
mpcgrid wants to merge 11 commits intomainfrom
fix/add-condition-to-task_events_search_for_internal_logs

Conversation

@mpcgrid
Copy link
Contributor

@mpcgrid mpcgrid commented Feb 16, 2026

This will prevent internal logs to be added to the task_events_search_table

Closes #

✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing

Ran the migration, deleted the old invalid rows and ran new tasks.
The undesired logs are not added to the table.


Changelog

Updated the MATERIALIZED VIEW to also filter for trace_id != ''

@changeset-bot
Copy link

changeset-bot bot commented Feb 16, 2026

⚠️ No Changeset found

Latest commit: 34aae18

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

@mpcgrid mpcgrid changed the title Don't add internal logs to materialized task_events_search_mv_v1 Don't add internal logs to materialized view task_events_search_mv_v1e Feb 16, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 16, 2026

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

Walkthrough

Updates a ClickHouse materialized view to exclude empty trace_id values (migration adds the filter in Up, removes it in Down). Adds a new WhereCondition type and whereOr method to the ClickHouse query builder. Adjusts server-side log query logic to filter out empty trace_id, change cursor ordering, and use a new timeFilterFromTo shape that includes isDefault. Frontend changes include introducing a LogLevel component and adding a TRACE log level across UI and utils, 24-hour timestamp formatting, relocation of the Logs menu item, tweaks to LogsSearchInput URL handling, a Tailwind color change, and removal of two unused ClickHouse indexes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding a filter to prevent internal logs from being added to the task_events_search_mv_v1 materialized view.
Description check ✅ Passed The description covers all required sections from the template: testing steps, changelog entry, and a completed checklist; however, the issue reference remains as placeholder text.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/add-condition-to-task_events_search_for_internal_logs

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 and usage tips.

@mpcgrid mpcgrid marked this pull request as ready for review February 16, 2026 12:08
Copy link

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

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment on lines +1 to +31
-- +goose Up
-- We drop the existing MV and recreate it with the new filter condition
DROP VIEW IF EXISTS trigger_dev.task_events_search_mv_v1;

CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.task_events_search_mv_v1
TO trigger_dev.task_events_search_v1 AS
SELECT
environment_id,
organization_id,
project_id,
trace_id,
span_id,
run_id,
task_identifier,
start_time,
inserted_at,
message,
kind,
status,
duration,
parent_span_id,
attributes_text,
fromUnixTimestamp64Nano(toUnixTimestamp64Nano(start_time) + toInt64(duration)) AS triggered_timestamp
FROM trigger_dev.task_events_v2
WHERE
trace_id != '' -- New condition added here
AND kind != 'DEBUG_EVENT'
AND status != 'PARTIAL'
AND NOT (kind = 'SPAN_EVENT' AND attributes_text = '{}')
AND kind != 'ANCESTOR_OVERRIDE'
AND message != 'trigger.dev/start';

Choose a reason for hiding this comment

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

🚩 MV recreation does not backfill: pre-existing invalid rows remain in target table

The migration drops and recreates the materialized view with the new trace_id != '' filter, but materialized views in ClickHouse only apply to newly inserted data. Any rows already in trigger_dev.task_events_search_v1 with trace_id = '' will remain unless manually deleted. The PR description mentions "deleted the old invalid rows" during testing, but this migration alone does not clean up stale data. If deployed without a separate cleanup step (e.g., ALTER TABLE ... DELETE WHERE trace_id = ''), the existing invalid rows will persist in the search table indefinitely. This is likely already understood by the author based on the PR description, but there's no automated cleanup embedded in the migration itself.

Open in Devin Review

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql (1)

1-31: Up migration looks correct — but existing bad rows in the target table are not cleaned up.

The recreated MV will only filter new inserts. Rows with trace_id = '' already materialized into task_events_search_v1 will persist. The PR description mentions manual deletion, but consider adding an explicit ALTER TABLE ... DELETE (or DELETE FROM) in the up migration so this is reproducible across environments.

Suggested addition after the CREATE (line 31)
+-- Clean up previously materialized rows with empty trace_id
+ALTER TABLE trigger_dev.task_events_search_v1 DELETE WHERE trace_id = '';
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 921285c and a3afb8b.

📒 Files selected for processing (1)
  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
🧰 Additional context used
📓 Path-based instructions (1)
internal-packages/clickhouse/schema/**/*.sql

📄 CodeRabbit inference engine (CLAUDE.md)

internal-packages/clickhouse/schema/**/*.sql: ClickHouse migrations must use Goose format with -- +goose Up and -- +goose Down markers
Follow ClickHouse naming conventions: raw_ prefix for input tables, _v1, _v2 suffixes for versioning, _mv_v1 suffix for materialized views

Files:

  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : Follow ClickHouse naming conventions: `raw_` prefix for input tables, `_v1`, `_v2` suffixes for versioning, `_mv_v1` suffix for materialized views

Applied to files:

  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes

Applied to files:

  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : ClickHouse migrations must use Goose format with `-- +goose Up` and `-- +goose Down` markers

Applied to files:

  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
🔇 Additional comments (1)
internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql (1)

33-62: Down migration correctly reverts the change.

The column list and remaining WHERE conditions are identical to the up migration minus the trace_id != '' filter. Looks good.

Copy link

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

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment on lines +239 to +242
// This should be removed once we clear the old inserts, 30 DAYS, the materialized view excludes events without trace_id)
queryBuilder.where("trace_id != ''", {
environmentId,
});

Choose a reason for hiding this comment

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

🚩 Temporary query-side filter will need cleanup after 30-day retention window

The comment on line 239 states the trace_id != '' query-side filter should be removed once old inserts age out (30 days). Since the materialized view now excludes empty trace_id rows, only pre-existing rows in the target table need this filter. There's no tracking mechanism (e.g., a TODO issue link) to ensure this cleanup happens. Consider linking to a tracking issue to avoid leaving dead code.

Open in Devin Review

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)

239-242: Unnecessary parameter passed to parameterless WHERE clause.

The clause trace_id != '' contains no parameterized placeholder, yet { environmentId } is passed as the params argument. This is dead/misleading — environmentId is already correctly bound on Line 244. Remove the unused params object to avoid confusion.

Suggested fix
     // This should be removed once we clear the old inserts, 30 DAYS, the materialized view excludes events without trace_id)
-    queryBuilder.where("trace_id != ''", {
-      environmentId,
-    });
+    queryBuilder.where("trace_id != ''");
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a3afb8b and e19d9e8.

📒 Files selected for processing (1)
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : ClickHouse migrations must use Goose format with `-- +goose Up` and `-- +goose Down` markers
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : Follow ClickHouse naming conventions: `raw_` prefix for input tables, `_v1`, `_v2` suffixes for versioning, `_mv_v1` suffix for materialized views
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2175
File: apps/webapp/app/services/environmentMetricsRepository.server.ts:202-207
Timestamp: 2025-06-14T08:07:46.625Z
Learning: In apps/webapp/app/services/environmentMetricsRepository.server.ts, the ClickHouse methods (getTaskActivity, getCurrentRunningStats, getAverageDurations) intentionally do not filter by the `tasks` parameter at the ClickHouse level, even though the tasks parameter is accepted by the public methods. This is done on purpose as there is not much benefit from adding that filtering at the ClickHouse layer.
📚 Learning: 2025-06-14T08:07:46.625Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2175
File: apps/webapp/app/services/environmentMetricsRepository.server.ts:202-207
Timestamp: 2025-06-14T08:07:46.625Z
Learning: In apps/webapp/app/services/environmentMetricsRepository.server.ts, the ClickHouse methods (getTaskActivity, getCurrentRunningStats, getAverageDurations) intentionally do not filter by the `tasks` parameter at the ClickHouse level, even though the tasks parameter is accepted by the public methods. This is done on purpose as there is not much benefit from adding that filtering at the ClickHouse layer.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-02-06T19:53:38.843Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/presenters/v3/DeploymentListPresenter.server.ts:233-237
Timestamp: 2026-02-06T19:53:38.843Z
Learning: When constructing Vercel dashboard URLs from deployment IDs, always strip the dpl_ prefix from the ID. Implement this by transforming the ID with .replace(/^dpl_/, "") before concatenating into the URL: https://vercel.com/${teamSlug}/${projectName}/${cleanedDeploymentId}. Consider centralizing this logic in a small helper (e.g., getVercelDeploymentId(id) or a URL builder) and add tests to verify both prefixed and non-prefixed inputs.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Deno Runtime

@mpcgrid mpcgrid changed the title Don't add internal logs to materialized view task_events_search_mv_v1e fix(webapp): Don't add internal logs to materialized view task_events_search_mv_v1e Feb 17, 2026
@matt-aitken matt-aitken force-pushed the fix/add-condition-to-task_events_search_for_internal_logs branch from e19d9e8 to 964fd37 Compare February 17, 2026 16:24
Copy link

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

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 6 additional findings in Devin Review.

Open in Devin Review

Comment on lines 458 to +469
>
{(user.admin || user.isImpersonating || featureFlags.hasLogsPageAccess) && (
<SideMenuItem
name="Logs"
icon={LogsIcon}
activeIconColor="text-logs"
inactiveIconColor="text-logs"
to={v3LogsPath(organization, project, environment)}
data-action="logs"
badge={<AlphaBadge />}
isCollapsed={isCollapsed}
/>

Choose a reason for hiding this comment

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

🟡 Logs menu item now hidden for users with hasLogsPageAccess but not hasQueryAccess

Moving the Logs SideMenuItem into the "Insights" SideMenuSection introduces an additional visibility gate. The "Insights" section is guarded by (user.admin || user.isImpersonating || featureFlags.hasQueryAccess) at line 448. Inside it, the Logs item is separately guarded by (user.admin || user.isImpersonating || featureFlags.hasLogsPageAccess) at line 459.

Root Cause

Previously, the Logs item lived in the main navigation area and was only gated by hasLogsPageAccess. Now it's nested inside a section gated by hasQueryAccess. These are independent feature flags defined in apps/webapp/app/v3/featureFlags.server.ts:8-9.

A regular (non-admin, non-impersonating) user who has hasLogsPageAccess=true but hasQueryAccess=false (or undefined) will no longer see the Logs menu item, because the enclosing "Insights" section won't render at all.

Impact: Users who were previously granted Logs access via the hasLogsPageAccess feature flag but lack hasQueryAccess will lose the navigation link to the Logs page. The route itself is still accessible via direct URL, but the menu item is invisible.

Prompt for agents
In apps/webapp/app/components/navigation/SideMenu.tsx, the Logs SideMenuItem (lines 458-469) was moved inside the Insights SideMenuSection which is gated by hasQueryAccess (line 448). This means users with only hasLogsPageAccess but not hasQueryAccess can no longer see the Logs navigation item. There are two approaches to fix this: 1) Update the Insights section gate at line 448 to also include hasLogsPageAccess: change the condition to (user.admin || user.isImpersonating || featureFlags.hasQueryAccess || featureFlags.hasLogsPageAccess). 2) Move the Logs SideMenuItem back outside the Insights section, into the main navigation area where it was before.
Open in Devin Review

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/webapp/app/components/navigation/SideMenu.tsx (1)

448-470: ⚠️ Potential issue | 🟠 Major

Logs item is unreachable if user has hasLogsPageAccess but not hasQueryAccess.

The Insights section (line 448) requires hasQueryAccess, but the Logs item (line 459) has a separate guard on hasLogsPageAccess. These are independent boolean flags with no logical relationship. If a user only has hasLogsPageAccess enabled, the parent section won't render and the Logs link becomes inaccessible despite the user having permission.

Add featureFlags.hasLogsPageAccess to the section's guard condition:

Proposed fix
-            {(user.admin || user.isImpersonating || featureFlags.hasQueryAccess) && (
+            {(user.admin || user.isImpersonating || featureFlags.hasQueryAccess || featureFlags.hasLogsPageAccess) && (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/navigation/SideMenu.tsx` around lines 448 - 470,
The Insights parent section currently only renders when (user.admin ||
user.isImpersonating || featureFlags.hasQueryAccess) which prevents the Logs
SideMenuItem from being shown to users who only have
featureFlags.hasLogsPageAccess; update the parent SideMenuSection render
condition (the JSX that wraps SideMenuSection) to include
featureFlags.hasLogsPageAccess in the OR expression so it becomes (user.admin ||
user.isImpersonating || featureFlags.hasQueryAccess ||
featureFlags.hasLogsPageAccess), leaving the existing inner guard for the Logs
SideMenuItem intact (referencing the SideMenuSection component and the Logs
SideMenuItem).
🧹 Nitpick comments (5)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)

275-299: excluded_statuses param is overwritten on each loop iteration with the same value — fragile.

Every iteration that has filter.kinds pushes a condition with excluded_statuses: ["ERROR", "CANCELLED"]. Since Object.assign merges all params, the repeated key is benign today but will silently break if different levels ever need different exclusions.

Consider defining excluded_statuses once outside the loop:

Proposed fix
     if (levels && levels.length > 0) {
       const conditions: WhereCondition[] = [];
+      // Define shared params outside the loop to avoid repeated overwrites
+      const sharedParams = { excluded_statuses: ["ERROR", "CANCELLED"] };

       for (let i = 0; i < levels.length; i++) {
         const filter = levelToKindsAndStatuses(levels[i]);

         if (filter.kinds && filter.kinds.length > 0) {
           conditions.push({
             clause: `kind IN {kinds_${i}: Array(String)} AND status NOT IN {excluded_statuses: Array(String)}`,
             params: {
               [`kinds_${i}`]: filter.kinds,
-              excluded_statuses: ["ERROR", "CANCELLED"],
+              ...sharedParams,
             },
           });
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts` around lines 275 -
299, The loop that builds conditions for levels uses the same params key
excluded_statuses on every iteration which overwrites/duplicates the key;
extract const excludedStatuses = ["ERROR","CANCELLED"] outside the for loop and
reference that single value in each condition (or supply a single params object
for excluded_statuses and reuse its key) so you do not reassign the same param
name per iteration; update the code that builds conditions (see
levelToKindsAndStatuses, WhereCondition entries, and queryBuilder.whereOr) to
use the single excludedStatuses reference rather than embedding a new
excluded_statuses array inside each pushed params object.
apps/webapp/app/components/primitives/DateTime.tsx (1)

341-357: Splitting formatDateTimeAccurate into two separate formatters may produce locale-dependent differences.

Previously a single Intl.DateTimeFormat call handled both date and time parts together (allowing the formatter to choose locale-appropriate separators). Now two separate formatters are concatenated with a space. For most locales this is fine, but some locales may produce slightly different output (e.g., an "at" separator between date and time in certain locales like en-US with certain options). Worth a quick manual check across your supported locales.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/primitives/DateTime.tsx` around lines 341 - 357,
The current split into datePart and timePart can change locale-specific
separators; update formatDateTimeAccurate to build the full string with a single
Intl.DateTimeFormat that includes both date and time options
(month/day/hour/minute/second/fractionalSecondDigits/timeZone/hour12) or
alternatively use formatToParts on one combined formatter and reassemble parts
to preserve the locale's native separator; adjust where datePart/timePart are
used and keep locales, timeZone, hour12, and fractionalSecondDigits references
so the combined formatter mirrors the original behavior.
apps/webapp/tailwind.config.js (1)

169-169: logs now shares colors.pink[500] with batches and environmentVariables.

This is fine if intentional, but three sidebar icons using the same color token may reduce visual distinctiveness. Consider whether a unique color would help users distinguish the Logs item at a glance.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/tailwind.config.js` at line 169, The Logs sidebar color is
currently set to the same token as batches and environmentVariables (const logs
= colors.pink[500]); change the logs color to a unique token to improve visual
distinctiveness — locate the const logs declaration in tailwind.config.js and
replace colors.pink[500] with an appropriate alternative (e.g., colors.teal[500]
or another distinct colors.<shade> value) and verify the change propagates where
logs is used in the sidebar rendering code so only Logs uses the new token while
batches and environmentVariables keep their original token.
internal-packages/clickhouse/src/client/queryBuilder.ts (2)

53-65: Parameter key collisions in whereOr are silently overwritten.

Object.assign(this.params, condition.params) will silently overwrite if two conditions share a param key with different values. This is the same pattern used by where(), so it's consistent, but whereOr amplifies the risk since multiple conditions are batched together.

The current caller in LogsListPresenter mitigates this with indexed keys (kinds_${i}, statuses_${i}), though excluded_statuses is repeated with the same value across iterations — benign but fragile.

Consider at minimum a debug-mode assertion or a doc comment warning callers to use unique param names across conditions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal-packages/clickhouse/src/client/queryBuilder.ts` around lines 53 -
65, The whereOr method currently merges condition.params into this.params using
Object.assign which silently overwrites colliding keys; update whereOr (and
comment similarly near where) to detect duplicate parameter keys before merging
and either throw or assert in debug/development mode (e.g., when NODE_ENV !==
'production') with a clear message mentioning the colliding key(s), or
alternatively prefix/index keys automatically; reference the whereOr method and
this.params (and note LogsListPresenter callers) so maintainers know where to
locate and validate calling code to ensure unique param names.

53-65: Identical whereOr implementations in both builder classes.

This duplicates the same logic. Consistent with existing where/whereIf duplication, so not blocking, but worth noting for a future extraction into a shared mixin or base class.

Also applies to: 175-187

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal-packages/clickhouse/src/client/queryBuilder.ts` around lines 53 -
65, The whereOr implementation is duplicated across builder classes (function
whereOr in queryBuilder.ts and the other builder around lines 175-187); extract
the shared logic into a single reusable helper or base class method to avoid
duplication: create a private/shared method (e.g., buildWhereOr or
appendWhereOr) that takes WhereCondition[] and performs the empty-check,
parenthesized clause join, pushes to whereClauses and merges params, then
replace each class's whereOr to call that helper; ensure the helper updates the
same properties (whereClauses and params) so behavior remains identical to the
current where/whereIf implementations.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e19d9e8 and 3316ff7.

📒 Files selected for processing (9)
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/components/primitives/DateTime.tsx
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/tailwind.config.js
  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
  • internal-packages/clickhouse/schema/018_drop_unused_task_events_v2_indexes.sql
  • internal-packages/clickhouse/src/client/queryBuilder.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal-packages/clickhouse/schema/017_update_materialized_conditions_to_task_events_search_v1.sql
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • internal-packages/clickhouse/src/client/queryBuilder.ts
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/components/primitives/DateTime.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/components/primitives/DateTime.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • internal-packages/clickhouse/src/client/queryBuilder.ts
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/tailwind.config.js
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/components/primitives/DateTime.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/components/primitives/DateTime.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/components/primitives/DateTime.tsx
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • internal-packages/clickhouse/src/client/queryBuilder.ts
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/tailwind.config.js
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/components/primitives/DateTime.tsx
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • internal-packages/clickhouse/src/client/queryBuilder.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
internal-packages/clickhouse/schema/**/*.sql

📄 CodeRabbit inference engine (CLAUDE.md)

internal-packages/clickhouse/schema/**/*.sql: ClickHouse migrations must use Goose format with -- +goose Up and -- +goose Down markers
Follow ClickHouse naming conventions: raw_ prefix for input tables, _v1, _v2 suffixes for versioning, _mv_v1 suffix for materialized views

Files:

  • internal-packages/clickhouse/schema/018_drop_unused_task_events_v2_indexes.sql
🧠 Learnings (25)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/components/primitives/DateTime.tsx
📚 Learning: 2026-01-28T14:15:09.778Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:09.778Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, enforce the maxPeriodDays limit based only on the from date (fromValue) using dateRangeToDays(fromValue) to reflect data retention limits. The to date should be ignored for retention checks. Ensure any retention-window logic or validations rely solely on the fromValue, and update related comments/tests if needed.

Applied to files:

  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2025-08-14T20:37:30.914Z
Learnt from: nicktrn
Repo: triggerdotdev/trigger.dev PR: 2390
File: apps/webapp/app/runEngine/services/batchTrigger.server.ts:787-795
Timestamp: 2025-08-14T20:37:30.914Z
Learning: The webapp uses ts-reset which provides better TypeScript type narrowing for common patterns like filter(Boolean), making explicit type guards unnecessary in many cases.

Applied to files:

  • apps/webapp/app/components/runs/v3/SharedFilters.tsx
📚 Learning: 2026-02-03T18:27:49.039Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx:553-555
Timestamp: 2026-02-03T18:27:49.039Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx, the menu buttons (like the Edit button with PencilSquareIcon) intentionally have no text labels - only icons are shown in the TableCellMenu. This is a deliberate UI design pattern for compact icon-only menu items.

Applied to files:

  • apps/webapp/app/components/navigation/SideMenu.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Applied to files:

  • apps/webapp/tailwind.config.js
📚 Learning: 2026-01-28T14:15:15.011Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:15.011Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, the maxPeriodDays limit for date ranges should only check the from date (via dateRangeToDays(fromValue)) because it enforces data retention limits—how far back in history queries can reach. The to date is irrelevant for retention-based limits.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/v3/presenters/**/*.server.{ts,tsx} : Organize presenters in the webapp following the pattern `app/v3/presenters/*/*.server.ts` to move complex loader code into classes

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure OpenTelemetry instrumentations and exporters in trigger.config.ts for enhanced logging

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : Use zod for validation in packages/core and apps/webapp

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Always import tasks from `trigger.dev/sdk`, never use `trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The SDK at packages/trigger-sdk is an isomorphic TypeScript SDK

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-06-14T08:07:46.625Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2175
File: apps/webapp/app/services/environmentMetricsRepository.server.ts:202-207
Timestamp: 2025-06-14T08:07:46.625Z
Learning: In apps/webapp/app/services/environmentMetricsRepository.server.ts, the ClickHouse methods (getTaskActivity, getCurrentRunningStats, getAverageDurations) intentionally do not filter by the `tasks` parameter at the ClickHouse level, even though the tasks parameter is accepted by the public methods. This is done on purpose as there is not much benefit from adding that filtering at the ClickHouse layer.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-02-06T19:53:38.843Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/presenters/v3/DeploymentListPresenter.server.ts:233-237
Timestamp: 2026-02-06T19:53:38.843Z
Learning: When constructing Vercel dashboard URLs from deployment IDs, always strip the dpl_ prefix from the ID. Implement this by transforming the ID with .replace(/^dpl_/, "") before concatenating into the URL: https://vercel.com/${teamSlug}/${projectName}/${cleanedDeploymentId}. Consider centralizing this logic in a small helper (e.g., getVercelDeploymentId(id) or a URL builder) and add tests to verify both prefixed and non-prefixed inputs.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-01-28T16:57:47.620Z
Learnt from: samejr
Repo: triggerdotdev/trigger.dev PR: 2964
File: apps/webapp/app/components/AskAI.tsx:121-141
Timestamp: 2026-01-28T16:57:47.620Z
Learning: In the trigger.dev webapp codebase, the Button component (apps/webapp/app/components/primitives/Buttons) does not spread unknown props to the underlying <button> element—it only passes specific props (type, disabled, onClick, name, value, ref, form, autoFocus). When using Radix UI's TooltipTrigger with asChild, a span wrapper around the Button is necessary to receive Radix props (aria-describedby, onPointerEnter, onPointerLeave, data-state) while the Button handles its own behavior. Directly making the Button the child of TooltipTrigger with asChild will break accessibility and tooltip functionality.

Applied to files:

  • apps/webapp/app/components/primitives/DateTime.tsx
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes

Applied to files:

  • internal-packages/clickhouse/schema/018_drop_unused_task_events_v2_indexes.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : Follow ClickHouse naming conventions: `raw_` prefix for input tables, `_v1`, `_v2` suffixes for versioning, `_mv_v1` suffix for materialized views

Applied to files:

  • internal-packages/clickhouse/schema/018_drop_unused_task_events_v2_indexes.sql
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/clickhouse/schema/**/*.sql : ClickHouse migrations must use Goose format with `-- +goose Up` and `-- +goose Down` markers

Applied to files:

  • internal-packages/clickhouse/schema/018_drop_unused_task_events_v2_indexes.sql
🧬 Code graph analysis (3)
apps/webapp/app/components/logs/LogsTable.tsx (2)
apps/webapp/app/components/primitives/DateTime.tsx (1)
  • DateTimeAccurate (333-333)
apps/webapp/app/components/primitives/Buttons.tsx (1)
  • Button (296-329)
apps/webapp/app/components/navigation/SideMenu.tsx (3)
apps/webapp/app/components/navigation/SideMenuItem.tsx (1)
  • SideMenuItem (9-119)
apps/webapp/app/utils/pathBuilder.ts (1)
  • v3LogsPath (502-508)
apps/webapp/app/components/AlphaBadge.tsx (1)
  • AlphaBadge (5-23)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (3)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)
  • timeFilterFromTo (217-257)
apps/webapp/app/v3/eventRepository/clickhouseEventRepository.server.ts (1)
  • convertDateToClickhouseDateTime (1931-1934)
internal-packages/clickhouse/src/client/queryBuilder.ts (1)
  • WhereCondition (7-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
🔇 Additional comments (4)
internal-packages/clickhouse/schema/018_drop_unused_task_events_v2_indexes.sql (1)

1-22: LGTM!

Clean migration with proper Goose markers, IF EXISTS/IF NOT EXISTS guards, and a correct Down that restores the original index definitions. The comments explaining why these indexes are unused are helpful. As per coding guidelines, ClickHouse migrations use Goose format with proper markers and naming conventions.

apps/webapp/app/components/logs/LogsTable.tsx (1)

163-163: LGTM — 24-hour format is appropriate for log timestamps.

apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)

217-257: LGTM — isDefault propagation is consistent across all branches.

The extended return type { from: Date; to: Date; isDefault: boolean } is correctly populated in every code path.

apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)

8-8: Remove unused timeFilters import.

The timeFilters import is not used in this file. Only timeFilterFromTo is referenced (line 149).

Proposed fix
-import { timeFilterFromTo, timeFilters } from "~/components/runs/v3/SharedFilters";
+import { timeFilterFromTo } from "~/components/runs/v3/SharedFilters";
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts`:
- Around line 224-227: The where call in LogsListPresenter.server.ts is passing
an unused params object to queryBuilder.where("trace_id != ''", { environmentId
}); — remove the second argument so the clause stands alone (i.e., call
queryBuilder.where("trace_id != ''")). Ensure environmentId continues to be set
only where intended (the other queryBuilder.params assignment for environmentId
should remain) to avoid duplicating/overwriting params in the query builder.

---

Outside diff comments:
In `@apps/webapp/app/components/navigation/SideMenu.tsx`:
- Around line 448-470: The Insights parent section currently only renders when
(user.admin || user.isImpersonating || featureFlags.hasQueryAccess) which
prevents the Logs SideMenuItem from being shown to users who only have
featureFlags.hasLogsPageAccess; update the parent SideMenuSection render
condition (the JSX that wraps SideMenuSection) to include
featureFlags.hasLogsPageAccess in the OR expression so it becomes (user.admin ||
user.isImpersonating || featureFlags.hasQueryAccess ||
featureFlags.hasLogsPageAccess), leaving the existing inner guard for the Logs
SideMenuItem intact (referencing the SideMenuSection component and the Logs
SideMenuItem).

---

Nitpick comments:
In `@apps/webapp/app/components/primitives/DateTime.tsx`:
- Around line 341-357: The current split into datePart and timePart can change
locale-specific separators; update formatDateTimeAccurate to build the full
string with a single Intl.DateTimeFormat that includes both date and time
options (month/day/hour/minute/second/fractionalSecondDigits/timeZone/hour12) or
alternatively use formatToParts on one combined formatter and reassemble parts
to preserve the locale's native separator; adjust where datePart/timePart are
used and keep locales, timeZone, hour12, and fractionalSecondDigits references
so the combined formatter mirrors the original behavior.

In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts`:
- Around line 275-299: The loop that builds conditions for levels uses the same
params key excluded_statuses on every iteration which overwrites/duplicates the
key; extract const excludedStatuses = ["ERROR","CANCELLED"] outside the for loop
and reference that single value in each condition (or supply a single params
object for excluded_statuses and reuse its key) so you do not reassign the same
param name per iteration; update the code that builds conditions (see
levelToKindsAndStatuses, WhereCondition entries, and queryBuilder.whereOr) to
use the single excludedStatuses reference rather than embedding a new
excluded_statuses array inside each pushed params object.

In `@apps/webapp/tailwind.config.js`:
- Line 169: The Logs sidebar color is currently set to the same token as batches
and environmentVariables (const logs = colors.pink[500]); change the logs color
to a unique token to improve visual distinctiveness — locate the const logs
declaration in tailwind.config.js and replace colors.pink[500] with an
appropriate alternative (e.g., colors.teal[500] or another distinct
colors.<shade> value) and verify the change propagates where logs is used in the
sidebar rendering code so only Logs uses the new token while batches and
environmentVariables keep their original token.

In `@internal-packages/clickhouse/src/client/queryBuilder.ts`:
- Around line 53-65: The whereOr method currently merges condition.params into
this.params using Object.assign which silently overwrites colliding keys; update
whereOr (and comment similarly near where) to detect duplicate parameter keys
before merging and either throw or assert in debug/development mode (e.g., when
NODE_ENV !== 'production') with a clear message mentioning the colliding key(s),
or alternatively prefix/index keys automatically; reference the whereOr method
and this.params (and note LogsListPresenter callers) so maintainers know where
to locate and validate calling code to ensure unique param names.
- Around line 53-65: The whereOr implementation is duplicated across builder
classes (function whereOr in queryBuilder.ts and the other builder around lines
175-187); extract the shared logic into a single reusable helper or base class
method to avoid duplication: create a private/shared method (e.g., buildWhereOr
or appendWhereOr) that takes WhereCondition[] and performs the empty-check,
parenthesized clause join, pushes to whereClauses and merges params, then
replace each class's whereOr to call that helper; ensure the helper updates the
same properties (whereClauses and params) so behavior remains identical to the
current where/whereIf implementations.

Comment on lines +224 to +227
// This should be removed once we clear the old inserts, 30 DAYS, the materialized view excludes events without trace_id)
queryBuilder.where("trace_id != ''", {
environmentId,
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unnecessary params passed to the trace_id != '' clause.

The clause "trace_id != ''" doesn't reference any parameters, yet { environmentId } is passed as params. This silently sets environmentId in the builder's params map (which is then redundantly set again on line 229). Remove the params to avoid confusion:

Proposed fix
-    queryBuilder.where("trace_id != ''", {
-      environmentId,
-    });
+    queryBuilder.where("trace_id != ''");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// This should be removed once we clear the old inserts, 30 DAYS, the materialized view excludes events without trace_id)
queryBuilder.where("trace_id != ''", {
environmentId,
});
// This should be removed once we clear the old inserts, 30 DAYS, the materialized view excludes events without trace_id)
queryBuilder.where("trace_id != ''");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts` around lines 224 -
227, The where call in LogsListPresenter.server.ts is passing an unused params
object to queryBuilder.where("trace_id != ''", { environmentId }); — remove the
second argument so the clause stands alone (i.e., call
queryBuilder.where("trace_id != ''")). Ensure environmentId continues to be set
only where intended (the other queryBuilder.params assignment for environmentId
should remain) to avoid duplicating/overwriting params in the query builder.

Copy link

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

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.

View 8 additional findings in Devin Review.

Open in Devin Review

Comment on lines 31 to 35
if (text.trim()) {
params.set("search", text.trim());
replace({ search: text.trim() });
} else {
params.delete("search");
del("search");
}

Choose a reason for hiding this comment

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

🔴 handleSubmit no longer resets cursor/direction params when searching

When the user submits a search query by pressing Enter, the old code explicitly deleted cursor and direction URL params to reset pagination. The new code uses replace({ search: text.trim() }) which only sets/updates the search param but preserves all other existing URL params.

Root Cause and Impact

The old code at LogsSearchInput.tsx did:

params.delete("cursor");
params.delete("direction");

The new code calls replace({ search: text.trim() }), which internally calls set(new URLSearchParams(location.search), values) at apps/webapp/app/hooks/useSearchParam.ts:13. The set function only modifies keys present in the values object, so cursor and direction remain in the URL.

Impact: If the user has scrolled down (triggering infinite scroll which sets a cursor param), then types a new search and presses Enter, the stale cursor param remains in the URL. This causes the server to apply cursor-based pagination to the new search results, potentially returning an empty or incorrect page instead of starting from the beginning.

Suggested change
if (text.trim()) {
params.set("search", text.trim());
replace({ search: text.trim() });
} else {
params.delete("search");
del("search");
}
const handleSubmit = useCallback(() => {
if (text.trim()) {
replace({ search: text.trim(), cursor: undefined, direction: undefined });
} else {
del(["search", "cursor", "direction"]);
}
}, [text, replace, del]);
Open in Devin Review

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

navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}, [location.pathname, location.search, navigate]);
del(["search", "cursor", "direction"]);
}, []);

Choose a reason for hiding this comment

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

🔴 handleClear has stale closure due to missing del dependency

The handleClear callback has an empty dependency array [] but captures del from the enclosing scope. Since del is a useCallback that depends on [location, navigate] (apps/webapp/app/hooks/useSearchParam.ts:30), it gets a new reference whenever the URL changes.

Stale Closure Explanation

With useCallback(..., []), handleClear is created once and never updated. It captures the initial del reference. When the URL changes (e.g., user applies time filters, task filters, or scrolls to load more logs which adds cursor params), del gets a new identity that reads from the updated location.search. However, handleClear still holds the original del which reads from the original location.search.

When the user clicks the clear button after the URL has changed, the stale del reconstructs the URL from the old location, potentially reverting or losing other filter params that were added after the component first mounted.

Impact: Clicking "Clear search" after changing other filters could revert those filter changes, causing unexpected UI behavior.

Suggested change
}, []);
}, [del]);
Open in Devin Review

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

Comment on lines 458 to +469
>
{(user.admin || user.isImpersonating || featureFlags.hasLogsPageAccess) && (
<SideMenuItem
name="Logs"
icon={LogsIcon}
activeIconColor="text-logs"
inactiveIconColor="text-logs"
to={v3LogsPath(organization, project, environment)}
data-action="logs"
badge={<AlphaBadge />}
isCollapsed={isCollapsed}
/>

Choose a reason for hiding this comment

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

🚩 Logs menu item now nested under Insights section with additional gate

The Logs menu item was moved from the main navigation section into the "Insights" collapsible section in SideMenu.tsx:458-469. It's now nested inside the (user.admin || user.isImpersonating || featureFlags.hasQueryAccess) gate for the Insights section AND its own (user.admin || user.isImpersonating || featureFlags.hasLogsPageAccess) gate. This means users who have hasLogsPageAccess but NOT hasQueryAccess will lose access to the Logs menu item — the outer Insights section won't render at all if hasQueryAccess is false. This may be intentional (coupling logs access to the insights feature group) or an oversight worth confirming with the team.

Open in Devin Review

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/webapp/app/components/logs/LogsSearchInput.tsx (1)

23-28: Extract search parameter value outside effect to avoid dependency on function reference.

The value function from useSearchParams() is created with useCallback([location]), so it gets a new reference whenever the location changes. Depending on value directly in the effect causes unnecessary runs. Extract the result to a variable outside the effect:

Suggested refactor
+  const currentSearch = value("search") ?? "";
+
   // Update text when URL search param changes (only when not focused to avoid overwriting user input)
   useEffect(() => {
-    const urlSearch = value("search") ?? "";
-    if (urlSearch !== text && !isFocused) {
-      setText(urlSearch);
+    if (currentSearch !== text && !isFocused) {
+      setText(currentSearch);
     }
-  }, [value, text, isFocused]);
+  }, [currentSearch, text, isFocused]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/logs/LogsSearchInput.tsx` around lines 23 - 28,
The effect depends on the `value` callback which changes identity with location;
call `value("search")` once outside the `useEffect` and store it in a local
`urlSearch` variable, then update the effect to use that `urlSearch` (and remove
`value` from the dependency array), keeping `text` and `isFocused` as deps and
using `setText` when `urlSearch !== text && !isFocused`; update references in
`LogsSearchInput.tsx` to use the new `urlSearch` variable and adjust the
`useEffect` dependency array accordingly.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3316ff7 and 8a52095.

📒 Files selected for processing (4)
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure log level in trigger.config.ts using `logLevel` property

Applied to files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/components/logs/LogLevel.tsx
  • apps/webapp/app/components/logs/LogsSearchInput.tsx
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/components/logs/LogsSearchInput.tsx
📚 Learning: 2025-07-12T18:00:06.163Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/utils/searchParams.ts:16-18
Timestamp: 2025-07-12T18:00:06.163Z
Learning: The `objectToSearchParams` function in `apps/webapp/app/utils/searchParams.ts` is used to generate URL parameters from objects and is separate from code that parses incoming search parameters. Changes to this function only affect places where it's used to create URLs, not places that parse search parameters from external sources.

Applied to files:

  • apps/webapp/app/components/logs/LogsSearchInput.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure OpenTelemetry instrumentations and exporters in trigger.config.ts for enhanced logging

Applied to files:

  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks

Applied to files:

  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
🧬 Code graph analysis (2)
apps/webapp/app/components/logs/LogLevel.tsx (3)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)
  • LogEntry (72-72)
apps/webapp/app/utils/cn.ts (1)
  • cn (77-79)
apps/webapp/app/utils/logUtils.ts (1)
  • getLevelColor (98-111)
apps/webapp/app/components/LogLevelTooltipInfo.tsx (3)
apps/webapp/app/components/logs/LogLevel.tsx (1)
  • LogLevel (5-16)
apps/webapp/app/utils/logUtils.ts (1)
  • LogLevel (5-5)
apps/webapp/app/components/primitives/Paragraph.tsx (1)
  • Paragraph (88-107)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (25)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
🔇 Additional comments (5)
apps/webapp/app/components/logs/LogLevel.tsx (1)

1-16: Clean extraction of the LogLevel component.

Good use of import type for the type-only import and proper reuse of existing getLevelColor utility. The component is well-scoped and follows project conventions.

apps/webapp/app/components/LogLevelTooltipInfo.tsx (1)

15-40: Good consistency — tooltip now uses the same LogLevel badge as the table.

This ensures visual consistency between the tooltip descriptions and the actual log level badges rendered in LogsTable.

apps/webapp/app/components/logs/LogsTable.tsx (2)

10-15: Clean import update — getLevelColor correctly removed, LogLevel component added.

The getLevelBoxShadow function (Lines 44–56) remains appropriately as it serves a distinct purpose (row-level inset shadow) separate from the badge styling now handled by LogLevel.


164-164: 24-hour timestamp formatting looks good.

Passing hour12={false} to DateTimeAccurate is a clean approach for consistent log timestamp display.

apps/webapp/app/components/logs/LogsSearchInput.tsx (1)

79-91: Accessory UI with clear button looks good.

Clean integration of the clear button alongside the shortcut key indicator. The e.preventDefault() + e.stopPropagation() in handleClear properly prevents the click from bubbling to the input's blur handler.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/webapp/app/components/logs/LogsSearchInput.tsx`:
- Around line 38-43: handleClear currently captures a stale del reference
because its useCallback has an empty dependency array; update the useCallback
for handleClear to include del in its dependency array (i.e., change from [] to
[del]) so the memoized callback updates when the del function from
useSearchParams changes — locate the handleClear function in LogsSearchInput.tsx
and modify its dependency array accordingly.

---

Nitpick comments:
In `@apps/webapp/app/components/logs/LogsSearchInput.tsx`:
- Around line 23-28: The effect depends on the `value` callback which changes
identity with location; call `value("search")` once outside the `useEffect` and
store it in a local `urlSearch` variable, then update the effect to use that
`urlSearch` (and remove `value` from the dependency array), keeping `text` and
`isFocused` as deps and using `setText` when `urlSearch !== text && !isFocused`;
update references in `LogsSearchInput.tsx` to use the new `urlSearch` variable
and adjust the `useEffect` dependency array accordingly.

Comment on lines +38 to +43
const handleClear = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
e.stopPropagation();
setText("");
const params = new URLSearchParams(location.search);
params.delete("search");
params.delete("cursor");
params.delete("direction");
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}, [location.pathname, location.search, navigate]);
del(["search", "cursor", "direction"]);
}, []);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, find the LogsSearchInput.tsx file
fd "LogsSearchInput.tsx" --type f

Repository: triggerdotdev/trigger.dev

Length of output: 120


🏁 Script executed:

# Then examine its content
cat -n "apps/webapp/app/components/logs/LogsSearchInput.tsx"

Repository: triggerdotdev/trigger.dev

Length of output: 4003


🏁 Script executed:

# Find the useSearchParams hook implementation
fd "useSearchParam" --type f --extension ts --extension tsx

Repository: triggerdotdev/trigger.dev

Length of output: 108


🏁 Script executed:

# Read the useSearchParams hook implementation
cat -n "apps/webapp/app/hooks/useSearchParam.ts"

Repository: triggerdotdev/trigger.dev

Length of output: 2675


Add del to useCallback dependency array in handleClear.

handleClear uses the del function from useSearchParams() but has an empty dependency array. The del function is a memoized callback that depends on location and navigate (from useSearchParams hook), making it a new reference whenever those change. Without del in the dependency array, handleClear captures a stale closure. This is inconsistent with handleSubmit (line 36) which correctly includes [text, replace, del] and will trigger react-hooks/exhaustive-deps lint warnings.

Proposed fix
   const handleClear = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
     e.preventDefault();
     e.stopPropagation();
     setText("");
     del(["search", "cursor", "direction"]);
-  }, []);
+  }, [del]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const handleClear = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
e.stopPropagation();
setText("");
const params = new URLSearchParams(location.search);
params.delete("search");
params.delete("cursor");
params.delete("direction");
navigate(`${location.pathname}?${params.toString()}`, { replace: true });
}, [location.pathname, location.search, navigate]);
del(["search", "cursor", "direction"]);
}, []);
const handleClear = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
e.stopPropagation();
setText("");
del(["search", "cursor", "direction"]);
}, [del]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/logs/LogsSearchInput.tsx` around lines 38 - 43,
handleClear currently captures a stale del reference because its useCallback has
an empty dependency array; update the useCallback for handleClear to include del
in its dependency array (i.e., change from [] to [del]) so the memoized callback
updates when the del function from useSearchParams changes — locate the
handleClear function in LogsSearchInput.tsx and modify its dependency array
accordingly.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
apps/webapp/app/components/logs/LogsLevelFilter.tsx (1)

31-46: getLevelBadgeColor duplicates getLevelColor from logUtils.ts.

Both functions return identical class strings for every level. Consider importing getLevelColor from ~/utils/logUtils instead of maintaining a parallel copy.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/logs/LogsLevelFilter.tsx` around lines 31 - 46,
The getLevelBadgeColor function duplicates getLevelColor from logUtils.ts;
remove the duplicate implementation in LogsLevelFilter.tsx and import
getLevelColor from "~/utils/logUtils", then replace calls to getLevelBadgeColor
with getLevelColor (or have getLevelBadgeColor proxy to getLevelColor) ensuring
the LogLevel type is preserved and any exported symbol usages in the component
are updated to use the imported function.
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx (1)

43-43: validLevels is duplicated across three locations — reuse the canonical export.

validLogLevels is already exported from ~/utils/logUtils.ts (line 7) with the identical value. This same array is also duplicated in resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts (line 13). Import validLogLevels from logUtils in both routes to avoid drift.

Proposed fix
-import type { LogLevel } from "~/utils/logUtils";
+import { validLogLevels } from "~/utils/logUtils";
+import type { LogLevel } from "~/utils/logUtils";

 // Valid log levels for filtering
-const validLevels: LogLevel[] = ["TRACE", "DEBUG", "INFO", "WARN", "ERROR"];
+const validLevels = validLogLevels;

Or simply use validLogLevels directly in parseLevelsFromUrl.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
at line 43, Replace the duplicated local array validLevels with the canonical
exported validLogLevels from ~/utils/logUtils.ts: remove the const validLevels
declaration in route.tsx, add an import for validLogLevels, and update any
references (e.g., inside parseLevelsFromUrl) to use validLogLevels; also do the
same replacement in
resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts so
both routes reuse the single exported symbol.
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)

277-301: excluded_statuses param name collides across loop iterations.

Every kinds-based condition reuses the literal param name excluded_statuses. If two levels both produce a kinds condition (e.g., ["TRACE", "ERROR"]), the param is set twice in separate WhereCondition objects. This works today only because the value is always ["ERROR", "CANCELLED"]. If a future level needs a different exclusion list the shared name will silently overwrite one value.

Consider indexing it like the other params (excluded_statuses_${i}) for safety:

Proposed fix
          conditions.push({
-            clause: `kind IN {kinds_${i}: Array(String)} AND status NOT IN {excluded_statuses: Array(String)}`,
+            clause: `kind IN {kinds_${i}: Array(String)} AND status NOT IN {excluded_statuses_${i}: Array(String)}`,
             params: {
               [`kinds_${i}`]: filter.kinds,
-              excluded_statuses: ["ERROR", "CANCELLED"],
+              [`excluded_statuses_${i}`]: ["ERROR", "CANCELLED"],
             },
           });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts` around lines 277 -
301, The kinds-based WhereCondition is reusing the literal param name
excluded_statuses across iterations causing collisions; update the clause and
params in the block that builds the kinds condition (inside the loop that calls
levelToKindsAndStatuses) to use a unique param name per iteration (e.g.,
`excluded_statuses_${i}`) and set params: { [`excluded_statuses_${i}`]:
["ERROR","CANCELLED"], [`kinds_${i}`]: filter.kinds } so each WhereCondition
created for level i uses its own excluded_statuses param; this touches the code
that constructs WhereCondition objects and the call to queryBuilder.whereOr
remains unchanged.
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts (1)

57-70: as any cast defeats the purpose of Zod validation.

LogsListOptionsSchema.parse(...) already returns a properly typed value. The as any cast on line 70 discards that type information. If the schema output type doesn't match LogsListOptions, fix the schema or the type rather than casting.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/webapp/app/routes/resources.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
around lines 57 - 70, The value returned by LogsListOptionsSchema.parse(...) is
being force-cast to any (on the options variable), which discards Zod's type
safety; remove the "as any" and let TypeScript infer the correct type from
LogsListOptionsSchema.parse, or explicitly type options using z.infer<typeof
LogsListOptionsSchema> or the existing LogsListOptions type; if there's a
mismatch between LogsListOptions and the schema, fix the schema or the
LogsListOptions definition so they align (adjust LogsListOptionsSchema or
LogsListOptions) and then drop the "as any" cast in the options assignment.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a52095 and 34aae18.

📒 Files selected for processing (7)
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/utils/logUtils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/webapp/app/components/LogLevelTooltipInfo.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

**/*.{ts,tsx}: Always import tasks from @trigger.dev/sdk, never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and have a unique id property with no timeouts in the run function

Files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Import from @trigger.dev/core using subpaths only, never import from root

Files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Access environment variables via env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : When editing the Prisma schema, remove extraneous migration lines related to specific tables: `_BackgroundWorkerToBackgroundWorkerFile`, `_BackgroundWorkerToTaskQueue`, `_TaskRunToTaskRunTag`, `_WaitpointRunConnections`, `_completedWaitpoints`, `SecretStore_key_idx`, and unrelated `TaskRun` indexes
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure log level in trigger.config.ts using `logLevel` property

Applied to files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks

Applied to files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/components/logs/LogsLevelFilter.tsx
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2026-02-11T16:50:14.167Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx:126-131
Timestamp: 2026-02-11T16:50:14.167Z
Learning: In apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx, MetricsDashboard entities are intentionally scoped to the organization level, not the project level. The dashboard lookup should filter by organizationId only (not projectId), allowing dashboards to be accessed across projects within the same organization. The optional projectId field on MetricsDashboard serves other purposes and should not be used as an authorization constraint.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure OpenTelemetry instrumentations and exporters in trigger.config.ts for enhanced logging

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • apps/webapp/app/utils/logUtils.ts
📚 Learning: 2025-09-03T14:35:52.384Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2464
File: apps/webapp/app/utils/pathBuilder.ts:144-146
Timestamp: 2025-09-03T14:35:52.384Z
Learning: In the trigger.dev codebase, organization slugs are safe for URL query parameters and don't require URL encoding, as confirmed by the maintainer in apps/webapp/app/utils/pathBuilder.ts.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2026-02-03T18:27:40.429Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx:553-555
Timestamp: 2026-02-03T18:27:40.429Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx, the menu buttons (e.g., Edit with PencilSquareIcon) in the TableCellMenu are intentionally icon-only with no text labels as a compact UI pattern. This is a deliberate design choice for this route; preserve the icon-only behavior for consistency in this file.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2026-02-10T16:18:48.654Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2980
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx:512-515
Timestamp: 2026-02-10T16:18:48.654Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx, environment.queueSizeLimit is a per-queue maximum that is configured at the environment level, not a shared limit across all queues. Each queue can have up to environment.queueSizeLimit items queued independently.

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/**/*.{ts,tsx} : When importing from `trigger.dev/core` in the webapp, use subpath exports from the package.json instead of importing from the root path

Applied to files:

  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : Use zod for validation in packages/core and apps/webapp

Applied to files:

  • apps/webapp/app/utils/logUtils.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-01-28T14:15:15.011Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2953
File: apps/webapp/app/components/runs/v3/SharedFilters.tsx:441-452
Timestamp: 2026-01-28T14:15:15.011Z
Learning: In apps/webapp/app/components/runs/v3/SharedFilters.tsx, the maxPeriodDays limit for date ranges should only check the from date (via dateRangeToDays(fromValue)) because it enforces data retention limits—how far back in history queries can reach. The to date is irrelevant for retention-based limits.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/v3/presenters/**/*.server.{ts,tsx} : Organize presenters in the webapp following the pattern `app/v3/presenters/*/*.server.ts` to move complex loader code into classes

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-07-12T18:06:04.133Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 2264
File: apps/webapp/app/services/runsRepository.server.ts:172-174
Timestamp: 2025-07-12T18:06:04.133Z
Learning: In apps/webapp/app/services/runsRepository.server.ts, the in-memory status filtering after fetching runs from Prisma is intentionally used as a workaround for ClickHouse data delays. This approach is acceptable because the result set is limited to a maximum of 100 runs due to pagination, making the performance impact negligible.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-02-04T16:34:48.876Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/vercel.connect.tsx:13-27
Timestamp: 2026-02-04T16:34:48.876Z
Learning: In apps/webapp/app/routes/vercel.connect.tsx, configurationId may be absent for "dashboard" flows but must be present for "marketplace" flows. Enforce this with a Zod superRefine and pass installationId to repository methods only when configurationId is defined (omit the field otherwise).

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-06-14T08:07:46.625Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2175
File: apps/webapp/app/services/environmentMetricsRepository.server.ts:202-207
Timestamp: 2025-06-14T08:07:46.625Z
Learning: In apps/webapp/app/services/environmentMetricsRepository.server.ts, the ClickHouse methods (getTaskActivity, getCurrentRunningStats, getAverageDurations) intentionally do not filter by the `tasks` parameter at the ClickHouse level, even though the tasks parameter is accepted by the public methods. This is done on purpose as there is not much benefit from adding that filtering at the ClickHouse layer.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to internal-packages/database/**/*.{ts,tsx} : Use Prisma for database interactions in internal-packages/database with PostgreSQL

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `tasks.trigger()` with type-only imports to trigger tasks from backend code without importing the task implementation

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `trigger.dev/sdk/v3` for all imports in Trigger.dev tasks

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to **/*.{ts,tsx} : Always import tasks from `trigger.dev/sdk`, never use `trigger.dev/sdk/v3` or deprecated `client.defineJob` pattern

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: The SDK at packages/trigger-sdk is an isomorphic TypeScript SDK

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-02-06T19:53:38.843Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/presenters/v3/DeploymentListPresenter.server.ts:233-237
Timestamp: 2026-02-06T19:53:38.843Z
Learning: When constructing Vercel dashboard URLs from deployment IDs, always strip the dpl_ prefix from the ID. Implement this by transforming the ID with .replace(/^dpl_/, "") before concatenating into the URL: https://vercel.com/${teamSlug}/${projectName}/${cleanedDeploymentId}. Consider centralizing this logic in a small helper (e.g., getVercelDeploymentId(id) or a URL builder) and add tests to verify both prefixed and non-prefixed inputs.

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
🧬 Code graph analysis (5)
apps/webapp/app/components/logs/LogsTable.tsx (4)
apps/webapp/app/components/primitives/DateTime.tsx (1)
  • DateTimeAccurate (333-333)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)
  • LogLevel (19-19)
apps/webapp/app/utils/logUtils.ts (1)
  • LogLevel (5-5)
apps/webapp/app/components/logs/LogLevel.tsx (1)
  • LogLevel (5-16)
apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts (2)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)
  • LogLevel (19-19)
apps/webapp/app/utils/logUtils.ts (1)
  • LogLevel (5-5)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx (2)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)
  • LogLevel (19-19)
apps/webapp/app/utils/logUtils.ts (1)
  • LogLevel (5-5)
apps/webapp/app/utils/logUtils.ts (1)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)
  • LogLevel (19-19)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (3)
apps/webapp/app/components/runs/v3/SharedFilters.tsx (1)
  • timeFilterFromTo (217-257)
apps/webapp/app/v3/eventRepository/clickhouseEventRepository.server.ts (1)
  • convertDateToClickhouseDateTime (1931-1934)
internal-packages/clickhouse/src/client/queryBuilder.ts (1)
  • WhereCondition (7-10)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (27)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: sdk-compat / Bun Runtime
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
  • GitHub Check: sdk-compat / Cloudflare Workers
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: sdk-compat / Deno Runtime
  • GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: typecheck / typecheck
🔇 Additional comments (7)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (3)

111-121: Verify the TRACE / INFO mapping changes align with the materialized view.

TRACE → kinds: ["SPAN"] and INFO no longer includes "SPAN". Previously SPANs would have shown under INFO; now they appear under TRACE. Users who previously filtered by INFO to see spans will no longer see them — this is a behavioral change worth noting in release comms.

Also, levelToKindsAndStatuses and kindToLevel in logUtils.ts must stay in sync. kindToLevel("SPAN", …) now returns "TRACE" (line 90 of logUtils.ts), which is consistent with this mapping. Looks correct.


304-318: Cursor pagination refactored to composite (triggered_timestamp, trace_id) — looks correct.

The lexicographic comparison via OR correctly implements < cursor for a DESC ordered pair. The comment block clearly explains the logic.


151-156: Switched to timeFilterFromTo — LGTM.

Cleaner than the old approach; defaultPeriod fallback to "1h" is consistent with the route's defaultPeriod param.

apps/webapp/app/components/logs/LogsLevelFilter.tsx (1)

18-24: TRACE addition looks good.

Ordering and color are consistent with the rest of the TRACE integration.

apps/webapp/app/components/logs/LogsTable.tsx (1)

52-53: TRACE integration in the table looks clean.

Box shadow, LogLevel component usage, and 24-hour timestamp formatting are all consistent with the broader changes.

Also applies to: 166-166, 175-175

apps/webapp/app/utils/logUtils.ts (2)

4-7: TRACE additions to schema and valid levels — LGTM.

Schema, type, and validLogLevels are all in sync.


89-90: SPAN → TRACE mapping is consistent with the presenter.

levelToKindsAndStatuses("TRACE") returns { kinds: ["SPAN"] } and kindToLevel("SPAN", …) returns "TRACE" — the round-trip is correct.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts`:
- Around line 226-229: Remove the redundant params object passed to the
queryBuilder.where call that uses the literal clause "trace_id != ''";
specifically, update the queryBuilder.where("trace_id != ''", { environmentId })
invocation in LogsListPresenter.server.ts to call queryBuilder.where("trace_id
!= ''") and keep the existing separate filter that uses environmentId (the other
where call), so environmentId is not passed into the trace_id clause.

In
`@apps/webapp/app/routes/resources.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts:
- Line 13: The file defines a duplicated constant validLevels; replace it by
importing and using the shared validLogLevels from ~/utils/logUtils instead of
defining validLevels locally. Locate the occurrence of validLevels in this route
(apps/webapp...logs.ts) and update any references to use validLogLevels,
removing the local const definition so the route reuses the centralized
validLogLevels symbol.

---

Nitpick comments:
In `@apps/webapp/app/components/logs/LogsLevelFilter.tsx`:
- Around line 31-46: The getLevelBadgeColor function duplicates getLevelColor
from logUtils.ts; remove the duplicate implementation in LogsLevelFilter.tsx and
import getLevelColor from "~/utils/logUtils", then replace calls to
getLevelBadgeColor with getLevelColor (or have getLevelBadgeColor proxy to
getLevelColor) ensuring the LogLevel type is preserved and any exported symbol
usages in the component are updated to use the imported function.

In `@apps/webapp/app/presenters/v3/LogsListPresenter.server.ts`:
- Around line 277-301: The kinds-based WhereCondition is reusing the literal
param name excluded_statuses across iterations causing collisions; update the
clause and params in the block that builds the kinds condition (inside the loop
that calls levelToKindsAndStatuses) to use a unique param name per iteration
(e.g., `excluded_statuses_${i}`) and set params: { [`excluded_statuses_${i}`]:
["ERROR","CANCELLED"], [`kinds_${i}`]: filter.kinds } so each WhereCondition
created for level i uses its own excluded_statuses param; this touches the code
that constructs WhereCondition objects and the call to queryBuilder.whereOr
remains unchanged.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx:
- Line 43: Replace the duplicated local array validLevels with the canonical
exported validLogLevels from ~/utils/logUtils.ts: remove the const validLevels
declaration in route.tsx, add an import for validLogLevels, and update any
references (e.g., inside parseLevelsFromUrl) to use validLogLevels; also do the
same replacement in
resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts so
both routes reuse the single exported symbol.

In
`@apps/webapp/app/routes/resources.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.logs.ts:
- Around line 57-70: The value returned by LogsListOptionsSchema.parse(...) is
being force-cast to any (on the options variable), which discards Zod's type
safety; remove the "as any" and let TypeScript infer the correct type from
LogsListOptionsSchema.parse, or explicitly type options using z.infer<typeof
LogsListOptionsSchema> or the existing LogsListOptions type; if there's a
mismatch between LogsListOptions and the schema, fix the schema or the
LogsListOptions definition so they align (adjust LogsListOptionsSchema or
LogsListOptions) and then drop the "as any" cast in the options assignment.

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.

2 participants