Skip to content

feat: pipeline logs panel in editor and metrics pages#9

Merged
TerrifiedBug merged 3 commits intomainfrom
feat/pipeline-logs-panel
Mar 5, 2026
Merged

feat: pipeline logs panel in editor and metrics pages#9
TerrifiedBug merged 3 commits intomainfrom
feat/pipeline-logs-panel

Conversation

@TerrifiedBug
Copy link
Owner

Summary

  • Wire up the existing PipelineLogs component to the pipeline metrics page as a new "Logs" card section
  • Add a collapsible logs panel to the pipeline editor (bottom panel, alongside the existing metrics panel)
  • Add a logs toggle button (ScrollText icon) to the FlowToolbar with a red dot indicator when recent errors exist
  • Fix null-safe node access in PipelineLogs for logs without an associated node

How it works

  • Metrics page: Logs card appears below the charts, always visible, with level filtering and infinite scroll
  • Editor page: Toggle the logs panel from the toolbar; a lightweight background query polls for ERROR-level logs every 10s to show the red dot badge (disabled when panel is open to avoid redundant queries)
  • Both use the existing pipeline.logs tRPC endpoint with 5s auto-refresh

Test plan

  • Open a pipeline's metrics page → verify Logs card renders at bottom with level filters
  • Open the pipeline editor → verify ScrollText icon in toolbar
  • Click the logs button → verify bottom logs panel opens with pipeline logs
  • Deploy a pipeline with an error-producing config → verify red dot appears on logs button
  • Open logs panel → verify red dot disappears (panel shows errors directly)

Wire up the existing PipelineLogs component to both the pipeline
metrics page (as a new Logs card) and the pipeline editor (as a
collapsible bottom panel toggled from the toolbar).

The toolbar shows a red dot indicator when recent errors exist,
helping users spot pipeline issues during initial configuration.
@greptile-apps
Copy link

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR wires the existing PipelineLogs component into two new surfaces — the pipeline metrics page (always-visible card) and the pipeline editor (collapsible bottom panel) — and adds a toolbar error-badge with a lightweight background query for ERROR-level logs.

Key changes:

  • metrics/page.tsx: PipelineLogs rendered inside an explicit h-[400px] wrapper, correctly providing the required height constraint for the component's flex layout
  • page.tsx (editor): Adds logsOpen state toggle, errorCheckSince memoized to stable 24-hour window, recentErrorsQuery background poll with 10s refresh (disabled when panel open), and 300px bottom logs panel
  • flow-toolbar.tsx: ScrollText toggle button with optional red-dot badge for recent errors — clean, self-contained, follows existing metrics pattern
  • pipeline-logs.tsx: Null-safe guard on log.node?.name prevents crashes for pipeline-level logs without a node
  • pipeline.ts: Added since: z.date().optional() parameter to scope error-badge query to 24-hour window

Minor findings:

  • Auto-scroll effect in PipelineLogs fires on every 5-second poll, resetting scroll position even when no new logs arrive (can disrupt manual scroll-up to read older entries)
  • queryInput object in PipelineLogs recreated without memoization on every render (minor performance concern)

Confidence Score: 4/5

  • Safe to merge with minor UX polish recommended
  • The PR is fundamentally sound. All critical features are correctly implemented: the metrics page logs card works, the editor panel state management is correct with proper memoization of the time window, and the badge query uses appropriate filtering. The only remaining issues are two style-level concerns in PipelineLogs (auto-scroll behavior and object memoization) that don't affect correctness or safety. These are worth addressing before merge for better UX and performance, hence 4/5 instead of 5/5.
  • src/components/pipeline/pipeline-logs.tsx (minor style improvements recommended)

Sequence Diagram

sequenceDiagram
    participant Editor as Pipeline Editor (page.tsx)
    participant Toolbar as FlowToolbar
    participant LogsPanel as PipelineLogs
    participant TRPC as tRPC (pipeline.logs)
    participant DB as PostgreSQL (PipelineLog)

    Editor->>TRPC: background poll every 10s<br/>{ levels:["ERROR"], limit:1, since: errorCheckSince }<br/>(disabled when logsOpen=true)
    TRPC->>DB: SELECT WHERE level=ERROR AND timestamp>=since LIMIT 2
    DB-->>TRPC: items[]
    TRPC-->>Editor: { items, nextCursor }
    Editor->>Toolbar: hasRecentErrors = items.length > 0
    Toolbar-->>Editor: red dot visible on ScrollText icon

    Editor->>Toolbar: user clicks ScrollText
    Toolbar-->>Editor: onToggleLogs() → logsOpen=true
    Editor->>LogsPanel: render PipelineLogs (h-[300px])
    LogsPanel->>TRPC: infiniteQuery every 5s<br/>{ pipelineId, levels: activeLevels }
    TRPC->>DB: SELECT … ORDER BY timestamp DESC LIMIT 201
    DB-->>TRPC: items[], nextCursor
    TRPC-->>LogsPanel: pages[0].items
    LogsPanel-->>LogsPanel: reverse → chronological display<br/>auto-scroll to bottom

    LogsPanel->>TRPC: fetchNextPage (scroll to top)<br/>cursor = lastId
    TRPC->>DB: SELECT … cursor:lastId skip:1
    DB-->>TRPC: older items
    TRPC-->>LogsPanel: prepend older logs, restore scroll position
Loading

Comments Outside Diff (2)

  1. src/components/pipeline/pipeline-logs.tsx, line 70-74 (link)

    Auto-scroll effect resets position on every poll, even with no new logs

    The useEffect at line 70 depends on displayItems.length, which changes whenever logsQuery.data updates during polling. This means every 5-second refetch (whether or not new logs arrive) resets scroll to the bottom, overriding any manual scroll-up the user performed to read older entries.

    Consider depending on a stable "newest log id" instead:

    const newestLogId = displayItems[displayItems.length - 1]?.id;
    useEffect(() => {
      if (autoScrollRef.current && scrollRef.current) {
        scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
      }
    }, [newestLogId]);

    This way scroll only resets when an actual new log arrives, not on every polling cycle.

  2. src/components/pipeline/pipeline-logs.tsx, line 50-56 (link)

    queryInput object recreated on every render

    queryInput is constructed inline without useMemo, creating a new object reference on each render. While TanStack Query serializes keys deeply, passing an unstable object can cause unexpected behavior if Query Client ever compares by reference internally.

    Stabilize it with useMemo:

    const queryInput = useMemo(() => ({
      pipelineId,
      ...(activeLevels.size < ALL_LEVELS.length
        ? { levels: [...activeLevels] as LogLevel[] }
        : {}),
      ...(nodeId ? { nodeId } : {}),
    }), [pipelineId, activeLevels, nodeId]);

Last reviewed commit: ea53476

Comment on lines +163 to +169
const recentErrorsQuery = useQuery(
trpc.pipeline.logs.queryOptions(
{ pipelineId, levels: ["ERROR"], limit: 1 },
{ enabled: !!isDeployed && !logsOpen, refetchInterval: 10000 },
),
);
const hasRecentErrors = (recentErrorsQuery.data?.items?.length ?? 0) > 0;
Copy link

Choose a reason for hiding this comment

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

The error badge query fetches the single most recent ERROR log with no time-window filter. If a pipeline had an error 3 months ago and has been healthy since, hasRecentErrors remains permanently true — the red dot will always appear, even though the issue is long resolved.

The logs tRPC endpoint does not currently support time-window parameters. To fix this, consider:

  1. Adding a since / after parameter to the logs endpoint (e.g., last 24h)
  2. Threading it through this query: { levels: ["ERROR"], limit: 1, since: new Date(Date.now() - 24*60*60*1000) }
  3. Or at minimum, documenting in the UI that the badge reflects "any historical error" rather than recent ones

Without a recency bound, the signal degrades into noise for long-running pipelines.

@TerrifiedBug TerrifiedBug merged commit 52689e2 into main Mar 5, 2026
9 checks passed
@TerrifiedBug TerrifiedBug deleted the feat/pipeline-logs-panel branch March 5, 2026 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant