Skip to content

Conversation

@mpcgrid
Copy link
Collaborator

@mpcgrid mpcgrid commented Jan 15, 2026

Changelog

  • Removed EVENT_REPOSITORY_CLICKHOUSE_ROLLOUT_PERCENT
  • Added hasLogsPageAccess featureFlag for logs page
  • Replaced attributes with attributes_text for logs to reduce memory usage and improve query performance
  • Added support for event_v1 for logs, now depending on the settings the logs are fetched either from task_events_v1 or task_events_v2
  • Show an error in the interface in cast the repository store is postgres
Screenshot 2026-01-15 at 12 49 22

Testing

To change between where the query looks for logs there is the following logic

  1. organization.featureFlags (highest priority)
  2. global feature flags (via flags() function)
  3. env.EVENT_REPOSITORY_DEFAULT_STORE (fallback)

The feature flags are:
{"hasLogsPageAccess": true}
{"taskEventRepository": "clickhouse_v2"}

The accepted values are for taskEventRepository: postgres | clickhouse | clickhouse_v2
Changing the taskEventRepository value in DB is reflected instantly in the application.

added support for tasks_v1 for logs
cleaned the No logs message
extended LogsPresenter with BasePresenter for spans
@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

⚠️ No Changeset found

Latest commit: 5433907

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

This PR includes no changesets

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

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

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

The changes add organization-aware event repository selection and runtime routing between ClickHouse v2, ClickHouse v1, and PostgreSQL (with PostgreSQL returning a ServiceValidationError). ClickHouse query builders and result shapes are versioned: metadata/attributes are replaced by attributes_text. Presenters, repositories, and routes select builders by store and handle validation errors. A new FEATURE_FLAG.hasLogsPageAccess gates Logs page access and is used in loaders and the side menu. UI: LogsTable drops the hasFilters prop and simplifies empty-state rendering.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description is incomplete and does not follow the required template structure with all necessary sections. Complete the PR description by adding all required template sections: issue reference (Closes #), full checklist with checkmarks, testing steps explanation, and any screenshots. Currently missing the issue reference and incomplete checklist.
Title check ❓ Inconclusive The title 'logs-page-fixes' is vague and generic, lacking specific details about the main changes such as feature flag additions, query builder versioning, or store configuration improvements. Use a more descriptive title that highlights key changes, such as 'Add logs page access control and event repository versioning' or 'Support configurable event stores for logs with feature flags'.

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

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e2e8dd4 and 5433907.

📒 Files selected for processing (3)
  • 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/v3/eventRepository/index.server.ts

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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
Copy link
Collaborator Author

mpcgrid commented Jan 15, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@claude
Copy link

claude bot commented Jan 15, 2026

PR Review: logs-page-fixes

Summary

This PR makes several improvements to the logs page functionality, including:

  • Adding support for ClickHouse v1 table queries (previously only v2 was supported)
  • Removing the EVENT_REPOSITORY_CLICKHOUSE_ROLLOUT_PERCENT environment variable
  • Adding a new hasLogsPageAccess feature flag
  • Fixing attribute handling to use attributes_text consistently
  • Removing unused hasFilters prop from LogsTable

Issues Found

1. Critical: Unused hasLogsPageAccess function in route loader

📍 apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx:61-93

The hasLogsPageAccess function is defined but never called in the loader. The loader at line 101-103 still only checks isAdmin:

if (!isAdmin) {
  throw redirect("/");
}

This means the new feature flag will not work as intended - users with the hasLogsPageAccess flag enabled will still be redirected. The function should be called and its result used in the access check.

Suggested fix:

const hasAccess = await hasLogsPageAccess(userId, user.admin, user.isImpersonating, organizationSlug);
if (!hasAccess) {
  throw redirect("/");
}

2. Inconsistency between SideMenu and route access control

📍 apps/webapp/app/components/navigation/SideMenu.tsx:272

The SideMenu shows the Logs link based on featureFlags.hasLogsPageAccess, but the route loader doesn't respect this flag. This creates a broken UX where users see the menu item but get redirected when clicking it.


Potential Issues

3. LogsListPresenter constructor doesn't call super() with arguments

📍 apps/webapp/app/presenters/v3/LogsListPresenter.server.ts:171-176

The presenter now extends BasePresenter but doesn't pass the replica to the parent constructor:

constructor(
  private readonly replica: PrismaClientOrTransaction,
  private readonly clickhouse: ClickHouse
) {
  super();  // Should be super(undefined, replica) or similar
}

While this works because the parent has default values, it's inconsistent - the class has its own replica field AND the parent has _replica. Consider either:

  • Using the parent's _replica instead of declaring a new one
  • Or not extending BasePresenter if the tracing methods aren't being used

4. Inconsistent string quotes in error messages

📍 apps/webapp/app/v3/eventRepository/index.server.ts:41,60

Mixed quote styles:

throw new Error('Organization not found when configuring event repository');
// vs
return { repository: eventRepository, store: 'postgres' };

Consider using double quotes consistently to match the rest of the codebase.


Minor Suggestions

5. Extra blank line in route file

📍 apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx:93-95

There's an extra blank line after the hasLogsPageAccess function that could be cleaned up.

6. Double blank line in LogsListPresenter

📍 apps/webapp/app/presenters/v3/LogsListPresenter.server.ts around the imports

There's an extra blank line in the import section that could be removed for consistency.


Code Quality

Positive aspects:

  • Good error handling with ServiceValidationError for store mismatches
  • Clean separation between v1 and v2 query builders
  • Proper use of feature flags for access control (once the bug is fixed)
  • Correct handling of attributes_text field instead of the generic attributes

Test coverage:

  • No tests appear to be added for the new functionality. Consider adding tests for:
    • getConfiguredEventRepository function
    • V1 query builders
    • The hasLogsPageAccess logic

Verdict

The PR has good intent but has a critical bug where the hasLogsPageAccess function is defined but never used in the route loader. This should be fixed before merging, as it will cause confusion when users have the feature flag enabled but still cannot access the logs page.

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: 2

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/presenters/v3/LogDetailPresenter.server.ts (1)

78-94: Remove dead code for log.metadata parsing.

The metadata column was removed from both query builders (getLogDetailQueryBuilderV1 and getLogDetailQueryBuilderV2) in commit c55ab1e. The log.metadata field will always be undefined, making the parsing block on lines 78-84 and the rawMetadata assignment on line 113 dead code. Either restore the metadata column to the queries if it's needed, or remove the unused metadata parsing logic.

🤖 Fix all issues with AI agents
In `@apps/webapp/app/components/logs/LogsTable.tsx`:
- Around line 127-129: The empty-state message currently shown in LogsTable when
logs.length === 0 still mentions filters even though hasFilters was removed;
update the BlankState usage in LogsTable (or the BlankState component itself) to
show a generic message like "No logs found." or to accept a prop that
differentiates filtered vs. empty results; specifically, either restore a
boolean (e.g., hasFilters) passed to BlankState from LogsTable based on current
filter state or change the displayed text in the BlankState call inside
LogsTable to a neutral message so users who haven't applied filters aren't
misled.

In
`@apps/webapp/app/routes/_app.orgs`.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx:
- Around line 61-93: The loader currently only checks isAdmin and redirects
non-admins, bypassing the feature flag check; replace that simple admin check
with an awaited call to hasLogsPageAccess(userId, isAdmin, isImpersonating,
organizationSlug) and use its boolean result to decide access; specifically,
remove or replace the if (!isAdmin) { throw redirect("/") } logic with: await
hasLogsPageAccess(...) and if it returns false then throw redirect("/"); ensure
you pass the same userId, isAdmin, isImpersonating, and organizationSlug
variables and keep existing redirect behavior for denied access.
🧹 Nitpick comments (3)
apps/webapp/app/v3/eventRepository/index.server.ts (1)

27-42: Consider using $replica for read operations.

The function queries organization data using prisma directly, but other parts of the codebase (e.g., RunsRepository, presenters) use $replica for read operations to distribute load. Additionally, the error thrown is a generic Error rather than ServiceValidationError used elsewhere in the codebase for validation errors.

♻️ Suggested improvements
+import { $replica } from "~/db.server";
+import { ServiceValidationError } from "~/v3/services/baseService.server";

 export async function getConfiguredEventRepository(
   organizationId: string
 ): Promise<{ repository: IEventRepository; store: string }> {
-  const organization = await prisma.organization.findFirst({
+  const organization = await $replica.organization.findFirst({
     select: {
       id: true,
       featureFlags: true,
     },
     where: {
       id: organizationId,
     },
   });

   if (!organization) {
-    throw new Error('Organization not found when configuring event repository');
+    throw new ServiceValidationError('Organization not found when configuring event repository');
   }
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)

545-555: Use const for the parsed attributes variable.

The attributes variable is never reassigned, so it should be declared with const instead of let.

♻️ Suggested fix
       if (log.status === "ERROR" && log.attributes_text) {
         try {
-          let attributes = JSON.parse(log.attributes_text) as ErrorAttributes;
+          const attributes = JSON.parse(log.attributes_text) as ErrorAttributes;

           if (attributes?.error?.message && typeof attributes.error.message === "string") {
             displayMessage = attributes.error.message;
           }
         } catch {
           // If attributes parsing fails, use the regular message
         }
       }
internal-packages/clickhouse/src/taskEvents.ts (1)

353-375: Consider renaming the result type for clarity.

The V1 detail builder uses LogDetailV2Result as its result type. While functionally correct (same schema), this naming could be confusing. Consider either:

  1. Creating a LogDetailResult type alias that both versions use
  2. Renaming LogDetailV2Result to LogDetailResult since it's shared
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4dc504d and c55ab1e.

📒 Files selected for processing (11)
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/env.server.ts
  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • 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.$logId.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/v3/featureFlags.server.ts
  • internal-packages/clickhouse/src/index.ts
  • internal-packages/clickhouse/src/taskEvents.ts
💤 Files with no reviewable changes (1)
  • apps/webapp/app/env.server.ts
🧰 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

Every Trigger.dev task must be exported; use task() function with unique id and run async function

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • internal-packages/clickhouse/src/taskEvents.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • internal-packages/clickhouse/src/index.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/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • internal-packages/clickhouse/src/taskEvents.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • internal-packages/clickhouse/src/index.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

In webapp development, access environment variables via env export from apps/webapp/app/env.server.ts; never use process.env directly

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.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

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • internal-packages/clickhouse/src/taskEvents.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • internal-packages/clickhouse/src/index.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/LogDetailPresenter.server.ts
  • apps/webapp/app/v3/featureFlags.server.ts
  • internal-packages/clickhouse/src/taskEvents.ts
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • internal-packages/clickhouse/src/index.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js}: Import from @trigger.dev/core using subpaths only; never import from root of @trigger.dev/core
Always import task definitions from @trigger.dev/sdk, never from @trigger.dev/sdk/v3 or deprecated client.defineJob pattern

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/components/navigation/SideMenu.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/v3/featureFlags.server.ts
  • internal-packages/clickhouse/src/taskEvents.ts
  • apps/webapp/app/components/logs/LogsTable.tsx
  • apps/webapp/app/v3/eventRepository/index.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
  • internal-packages/clickhouse/src/index.ts
🧠 Learnings (19)
📚 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/LogDetailPresenter.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • 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/LogDetailPresenter.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/services/**/*.server.{ts,tsx} : Organize services in the webapp following the pattern `app/v3/services/*/*.server.ts`

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.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/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 Learning: 2026-01-12T11:01:34.792Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-12T11:01:34.792Z
Learning: Applies to internal-packages/database/prisma/migrations/**/*.sql : Edit database schema in internal-packages/database/prisma/schema.prisma; remove extraneous lines from migrations related to BackgroundWorker, TaskRun tags, waitpoints, and SecretStore indexes

Applied to files:

  • internal-packages/clickhouse/src/taskEvents.ts
  • internal-packages/clickhouse/src/index.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: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 the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • internal-packages/clickhouse/src/index.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} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-01-12T11:01:34.792Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-12T11:01:34.792Z
Learning: Applies to **/*.{ts,tsx} : Every Trigger.dev task must be exported; use task() function with unique id and run async function

Applied to files:

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

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • internal-packages/clickhouse/src/index.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: 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 Trigger.dev project in `trigger.config.ts` using `defineConfig()` with project ref and task directories

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 logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • internal-packages/clickhouse/src/index.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
  • internal-packages/clickhouse/src/index.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 : Define global lifecycle functions (onStart, onSuccess, onFailure) in trigger.config.ts to apply to all tasks

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/**/*.{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/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 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/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/**/*.{ts,tsx,js,jsx} : Use `schedules.task()` for scheduled/cron tasks instead of regular `task()`

Applied to files:

  • internal-packages/clickhouse/src/index.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 lifecycle functions (init, cleanup, onStart, onSuccess, onFailure, handleError) for task event handling

Applied to files:

  • internal-packages/clickhouse/src/index.ts
🧬 Code graph analysis (4)
apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts (1)
apps/webapp/app/v3/eventRepository/index.server.ts (1)
  • getConfiguredEventRepository (27-61)
internal-packages/clickhouse/src/taskEvents.ts (2)
internal-packages/clickhouse/src/client/types.ts (1)
  • ClickhouseReader (60-199)
internal-packages/clickhouse/src/index.ts (1)
  • ClickHouseSettings (2-2)
apps/webapp/app/v3/eventRepository/index.server.ts (3)
apps/webapp/app/v3/eventRepository/eventRepository.types.ts (1)
  • IEventRepository (314-411)
apps/webapp/app/v3/eventRepository/clickhouseEventRepositoryInstance.server.ts (2)
  • clickhouseEventRepositoryV2 (11-14)
  • clickhouseEventRepository (6-9)
apps/webapp/app/v3/eventRepository/eventRepository.server.ts (1)
  • eventRepository (1441-1441)
internal-packages/clickhouse/src/index.ts (1)
internal-packages/clickhouse/src/taskEvents.ts (4)
  • getLogsListQueryBuilderV1 (329-351)
  • getLogDetailQueryBuilderV1 (353-375)
  • getLogsListQueryBuilderV2 (257-279)
  • getLogDetailQueryBuilderV2 (301-323)
⏰ 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). (20)
  • 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 / webapp / 🧪 Unit Tests: Webapp (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 (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
🔇 Additional comments (22)
apps/webapp/app/components/logs/LogsTable.tsx (1)

211-234: LGTM!

The BlankState component is well-structured with proper loading state handling. The colSpan=6 correctly accounts for all table columns including the menu column.

apps/webapp/app/v3/featureFlags.server.ts (1)

9-9: LGTM!

The new hasLogsPageAccess feature flag follows the established pattern, uses z.coerce.boolean() consistent with the hasQueryAccess flag, and integrates properly with the existing feature flag infrastructure.

Also applies to: 17-17

apps/webapp/app/v3/eventRepository/index.server.ts (1)

44-61: LGTM!

The resolution logic is well-documented with clear priority ordering, and the store selection matches the patterns used in getEventRepository and getV3EventRepository.

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

171-177: LGTM!

The class correctly extends BasePresenter and calls super() in the constructor. This aligns with the presenter pattern documented in learnings for apps/webapp/app/v3/presenters/**/*.server.ts.


368-383: Store-based query builder selection is well-implemented.

The conditional logic correctly routes to the appropriate ClickHouse version. Note that the repository from getConfiguredEventRepository is unused here since the presenter directly uses the ClickHouse query builders.


394-424: LGTM!

The conditional inserted_at PREWHERE clause correctly applies partition pruning only for the V2 table (which is partitioned by inserted_at), while start_time filtering in WHERE is applied for both versions. The inline comments clearly explain the reasoning.


137-152: LGTM!

The levelToKindsAndStatuses function provides a clean mapping from display levels to ClickHouse query constraints. The logic correctly handles the different level types including the special cases for ERROR and CANCELLED which map to statuses.

internal-packages/clickhouse/src/taskEvents.ts (3)

257-279: LGTM!

The V2 query builders are correctly renamed and target the task_events_v2 table. The column selection including attributes_text is consistent across both list and detail builders.

Also applies to: 301-323


329-375: The attributes_text column exists in task_events_v1 and is properly selected.

Verification confirms that attributes_text is a MATERIALIZED column in the task_events_v1 table schema (attributes_text String MATERIALIZED toJSONString(attributes)), and all columns selected by both getLogsListQueryBuilderV1 and getLogDetailQueryBuilderV1 are present in the schema. The queries are correct and will function as intended.


238-253: Schema change from metadata/attributes to attributes_text is properly handled.

The LogsListResult schema has been updated to use attributes_text instead of separate metadata and attributes fields. This is a breaking change, but verification confirms the only consumer—LogsListPresenter—has already been updated to correctly access attributes_text rather than the old fields.

internal-packages/clickhouse/src/index.ts (2)

26-29: LGTM!

The imports are well-organized, clearly versioned, and properly separate V1 and V2 query builders for the respective task event paths.


209-228: LGTM!

The version alignment is consistent: taskEvents uses V1 builders targeting task_events_v1 table, while taskEventsV2 uses V2 builders targeting task_events_v2 table. Settings are correctly passed through for both paths.

apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts (3)

5-6: LGTM!

Proper imports for organization-based store configuration and error handling.


29-43: LGTM!

The store detection and query builder selection logic is correct:

  • PostgreSQL throws a clear error since logs aren't supported there
  • V2 store uses V2 builder, otherwise falls back to V1 builder

The conditional branching is clean and maintainable.


87-91: LGTM!

Correctly parses attributes_text as the source for attributes data, aligning with the updated schema.

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs.$logId.tsx (2)

10-10: LGTM!

Correct import for error handling.


47-62: LGTM!

The error handling pattern is clean and appropriate:

  • ServiceValidationError maps to HTTP 400 (bad request) with the error message
  • Other errors are re-thrown to preserve stack traces and allow upstream error handling
  • This aligns with the presenter's store validation logic
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx (4)

3-3: LGTM!

Correct import for error handling in the loader.


126-140: LGTM!

The error handling pattern correctly catches ServiceValidationError and transforms it into a structured error object that the UI can handle gracefully. Other errors are re-thrown to preserve error boundaries.


195-215: LGTM!

Clean error-first rendering pattern that checks for the error object and displays a user-friendly callout before attempting to render the logs list.


230-230: LGTM!

Good use of TypeScript's Exclude utility type to ensure type safety by removing the error case from the list prop type, since error cases are handled separately in the parent component.

apps/webapp/app/components/navigation/SideMenu.tsx (1)

272-281: LGTM!

The visibility condition follows the established pattern used for the Query menu item (line 289) and correctly gates the Logs menu item behind:

  • Admin access, or
  • Impersonation, or
  • The hasLogsPageAccess feature flag

This is consistent with the codebase conventions.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

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

🤖 Fix all issues with AI agents
In `@apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts`:
- Around line 39-43: The comment incorrectly states "only v2 is supported for
log details" even though the code branches on isClickhouseV2 and calls
clickhouse.taskEventsV2.logDetailQueryBuilder() or
clickhouse.taskEvents.logDetailQueryBuilder(); update the inline comment to
reflect that both v1 and v2 are supported and that the code selects the
appropriate query builder based on the store (isClickhouseV2) rather than saying
only v2 is supported.
🧹 Nitpick comments (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx (1)

104-113: Minor formatting: add space after if.

The condition at line 111 is missing a space after if.

Suggested fix
- if(!canAccess) {
+ if (!canAccess) {
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c55ab1e and 172ec9e.

📒 Files selected for processing (3)
  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
🧰 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

Every Trigger.dev task must be exported; use task() function with unique id and run async function

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.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/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
**/*.{ts,tsx,js,jsx}

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

Use function declarations instead of default exports

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • 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/**/*.{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

In webapp development, access environment variables via env export from apps/webapp/app/env.server.ts; never use process.env directly

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.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

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
**/*.{js,ts,jsx,tsx,json,md,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.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:

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

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx,js}: Import from @trigger.dev/core using subpaths only; never import from root of @trigger.dev/core
Always import task definitions from @trigger.dev/sdk, never from @trigger.dev/sdk/v3 or deprecated client.defineJob pattern

Files:

  • apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts
  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
  • apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
🧠 Learnings (14)
📚 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/LogDetailPresenter.server.ts
  • 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/LogDetailPresenter.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: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 the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

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} : Attach metadata to task runs using the metadata option when triggering, and access/update it inside runs using metadata functions

Applied to files:

  • apps/webapp/app/presenters/v3/LogsListPresenter.server.ts
📚 Learning: 2026-01-12T11:01:34.792Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-12T11:01:34.792Z
Learning: Applies to **/*.{ts,tsx} : Every Trigger.dev task must be exported; use task() function with unique id and run async function

Applied to files:

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

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: 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 Trigger.dev project in `trigger.config.ts` using `defineConfig()` with project ref and task directories

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 logger methods (debug, log, info, warn, error) from `trigger.dev/sdk/v3` for structured logging in tasks

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.config.ts : Define global lifecycle functions (onStart, onSuccess, onFailure) in trigger.config.ts to apply to all tasks

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/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
📚 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/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx
🧬 Code graph analysis (3)
apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts (2)
apps/webapp/app/v3/eventRepository/index.server.ts (1)
  • getConfiguredEventRepository (27-61)
apps/webapp/app/v3/otlpExporter.server.ts (1)
  • store (113-123)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (5)
apps/webapp/app/utils/logUtils.ts (1)
  • LogLevel (5-5)
apps/webapp/app/models/runtimeEnvironment.server.ts (2)
  • displayableEnvironment (257-277)
  • findDisplayableEnvironment (279-310)
apps/webapp/app/v3/eventRepository/index.server.ts (1)
  • getConfiguredEventRepository (27-61)
apps/webapp/app/v3/eventRepository/common.server.ts (1)
  • convertDateToNanoseconds (53-55)
apps/webapp/app/v3/eventRepository/clickhouseEventRepository.server.ts (1)
  • convertDateToClickhouseDateTime (1931-1934)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx (4)
apps/webapp/app/v3/featureFlags.server.ts (1)
  • validateFeatureFlagValue (93-98)
apps/webapp/app/utils/pathBuilder.ts (1)
  • EnvironmentParamSchema (26-28)
apps/webapp/app/services/preferences/uiPreferences.server.ts (1)
  • setRootOnlyFilterPreference (40-44)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (1)
  • LogsList (99-99)
⏰ 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). (23)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
  • GitHub Check: typecheck / typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (15)
apps/webapp/app/presenters/v3/LogsListPresenter.server.ts (5)

11-23: LGTM - Imports are correctly organized.

The new imports for getConfiguredEventRepository, kindToLevel, LogLevel, LogLevelSchema, and BasePresenter are properly structured and use subpath exports as required by the coding guidelines.


171-177: LGTM - Class properly extends BasePresenter.

The LogsListPresenter now correctly extends BasePresenter with the super() call in the constructor, following the presenter pattern established in the codebase.


368-383: Store selection logic is well-structured.

The dynamic query builder selection based on store type is clean. The error for PostgreSQL provides a clear message for unsupported configurations.


394-424: Time filtering correctly differentiates v1 and v2 behavior.

The inserted_at partition pruning is correctly applied only for ClickHouse v2, while start_time filtering is applied for both versions. This ensures backward compatibility with v1 while leveraging v2's partition optimization.


545-555: No action requiredattributes_text is consistently available in both v1 and v2 query results. Both getLogsListQueryBuilderV1 and getLogsListQueryBuilderV2 select attributes_text in their columns, and the LogsListResult schema properly defines it as a required string field.

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.logs/route.tsx (5)

61-93: Access control implementation looks correct and addresses the previous review concern.

The hasLogsPageAccess function properly checks admin/impersonation status first, then falls back to organization feature flags. The loader now correctly calls this function.


135-148: Error handling pattern is well-implemented.

The .catch() block correctly catches ServiceValidationError and returns an error object instead of throwing, allowing graceful degradation in the UI. Other errors are re-thrown appropriately.


203-223: Error-first rendering handles the deferred error case correctly.

The "error" in result check properly discriminates between success and error states before passing data to LogsList.


238-238: Type narrowing with Exclude is the correct approach.

Using Exclude<..., { error: string }> ensures type safety by removing the error variant from the union type after the error check.


346-354: No issue found: RunsFilters component accepts the hasFilters prop.

The RunsFilters component includes hasFilters: boolean; in its type definition (line 326 of apps/webapp/app/components/runs/v3/RunFilters.tsx), and the prop is used throughout the component's logic. The code correctly passes this prop.

apps/webapp/app/presenters/v3/LogDetailPresenter.server.ts (5)

1-6: Imports look good.

The new imports for getConfiguredEventRepository and ServiceValidationError are correctly added to support the organization-aware repository selection pattern.


29-37: Store detection and error handling are correctly implemented.

The pattern aligns with getConfiguredEventRepository usage in other parts of the codebase. Throwing ServiceValidationError for PostgreSQL is appropriate since the logs page requires ClickHouse.


45-58: Query filters are correctly implemented.

The combination of spanId, traceId, and startTime uniquely identifies the log event, and the comment properly documents the reasoning.


88-105: Return object structure is well-implemented.

The ID format using :: separator maintains consistency with LogsListPresenter. The safe duration conversion handles potential type variations from ClickHouse responses.


78-86: No issues found. Both ClickHouse v1 and v2 query builders return the same LogDetailV2Result schema, which explicitly defines attributes_text: z.string(). The code correctly assumes attributes_text exists in both versions, and the try-catch pattern appropriately handles any JSON parsing errors.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@mpcgrid mpcgrid marked this pull request as ready for review January 15, 2026 10:13
@nicktrn nicktrn changed the title logs-page-fixes fix(webapp): logs page Jan 15, 2026
@mpcgrid mpcgrid merged commit 0b0df07 into main Jan 15, 2026
27 of 28 checks passed
@mpcgrid mpcgrid deleted the logs-page-fixes branch January 15, 2026 11:07
@vibe-kanban-cloud
Copy link

Review Complete

Your review story is ready!

View Story

Comment !reviewfast on this PR to re-generate the story.

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.

3 participants