Skip to content

Add combined logs for multi-pod workloads - #2418

Open
krishantt wants to merge 1 commit into
freelensapp:mainfrom
krishantt:combined-pod-logs
Open

krishantt wants to merge 1 commit into
freelensapp:mainfrom
krishantt:combined-pod-logs

Conversation

@krishantt

@krishantt krishantt commented Aug 15, 2026

Copy link
Copy Markdown

Fixes #687.

Adds a "Logs" action to the workload context menu for Deployments,
DaemonSets, StatefulSets, ReplicaSets, and Jobs that opens a single
dock tab merging the logs of every child pod. Lines from all pods are
interleaved chronologically (by the leading RFC3339 timestamp the
Kubernetes API attaches to each line) and tagged with a per-pod color
so it's easy to tell which pod a given line came from at a glance, per
@MatiasRoje's suggestion on #687 ("Probably in different colors
depending on the pod"). Single-pod log tabs are unchanged.

This covers the same need as the now-unmaintained
freelens-multi-pod-logs
extension referenced in #687, brought into core per the option
@robertobandini and @MatiasRoje favored in that thread. It doesn't
touch the separate, larger logs-rendering rework (virtual list -> xterm,
selection-during-scroll) raised in #1170 and referenced from #687 --
that's scoped as its own follow-up.

  • merge-pod-logs.ts: k-way merge across each pod's log lines, with a
    deterministic per-pod ANSI color assigned by hashing the pod name.
    The whole tagged line (pod-name tag and message) is colored, not
    just the tag, so lines stay legible whether or not "Show timestamps"
    is on.
  • store.ts: fetches each pod's logs in parallel (Promise.allSettled)
    and only blanks the tab if every pod's fetch fails, so one pod being
    briefly unreachable doesn't wipe out logs still streaming from the
    rest of a combined tab.
  • resource-selector.tsx: combined tabs show a "N pods" badge (with a
    tooltip listing pod names) instead of the single-pod switcher.
  • logs-view-model.ts / download-all-logs-for-pods.injectable.ts:
    downloading a combined tab's logs is named after the owning
    workload rather than any single pod.

Manually verified against a 3-replica Deployment on a local cluster,
including with "Show timestamps" toggled on.

| Model: claude-sonnet-5

Adds a "Logs" action to the workload context menu for Deployments,
DaemonSets, StatefulSets, ReplicaSets, and Jobs that opens a single
dock tab merging the logs of every child pod, chronologically
interleaved and tagged with a per-pod color so lines from different
pods are distinguishable at a glance. Single-pod tabs are unaffected.

Coloring covers the full log line (tag and message), not just the
pod-name tag, so it stays legible whether or not "Show timestamps" is
on.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@robertobandini

Copy link
Copy Markdown
Member

Hi @krishantt!

Thank you very much for this PR, and sorry for the long silence on it! Combined logs for workloads are one of the most requested features here (#687 and #1460), so we are really glad you took it on.

A note on the red checks: the workflows never actually ran, GitHub did not start them for fork PRs that weekend. I ran the same checks locally on top of the current main (install, DI registration, type check, the logs and kube-object store unit tests, biome) and everything is green. I am closing and reopening the PR right after this comment only to retrigger the real CI, nothing else.

I went through the code and I have a few points before the review from the core team:

  1. The list of pods is a snapshot taken when the tab is opened (mergedPodIds). After a rollout or a scale the tab keeps polling pods that no longer exist, and once the first pod is gone the header disappears. It would be great if the tab followed the workload at each refresh (for a Deployment through its ReplicaSets).
  2. Every refresh fires one request per pod in parallel. On a DaemonSet with many nodes that is dozens of requests every 10 seconds through the proxy. A concurrency cap, or a limit on the number of pods with a hint in the UI, would keep it safe.
  3. sinceTime for the incremental loads is the newest timestamp across all pods plus one second, so a pod slightly behind loses lines at every tick. A per pod sinceTime would fix it.
  4. The ANSI color codes end up in the downloaded .log files, from both "Download" and "Download all". Plain [pod-name] tags in the files would be nicer. Also "Download all" merges without timestamps when "Show timestamps" is off, so the order is not chronological there.
  5. The AbortError fix in kube-object.store.ts looks good, but it is unrelated to this feature: could you split it into its own small PR? Easier to review and to mention in the changelog.

The public logTabStore.createWorkloadTab extension API also changes its behaviour (combined tab, title with the workload name): fine for v2, we just need to note it in the migration notes.

Do you have time to look at these? If you prefer, we can also push the fixes on your branch ourselves, keeping your authorship of course. Thanks again!

@robertobandini

Copy link
Copy Markdown
Member

Hi @krishantt, a quick follow-up with some numbers, since I spent the afternoon with your branch on a 3-node kind cluster (current main plus your commit, unpackaged build, driven with Playwright).

The good part first: the combined tab works as described on Deployments, DaemonSets, StatefulSets and Jobs, the container switch applies to all pods, and a single-pod workload behaves exactly as before. Nice work!

What I measured on the points from my previous comment:

  • Rollout: after kubectl rollout restart all three pods were replaced, the header with Namespace, Owner, Pods and Container disappeared, and the tab kept showing the old pods with no new lines (point 1).
  • Incremental refresh: in 38 seconds of streaming at one line per second per pod, the combined tab lost 5 lines out of about 120 (2 on one pod, 3 on another, always single lines at a tick boundary), while a single-pod tab lost 0 out of 20 in the same conditions (point 3).
  • Downloads: the "Visible logs" file contains two escape sequences per line (point 4).
  • Colors: on the Light theme the bright cyan and bright green lines are nearly unreadable on the white background, and in two runs out of three two pods got almost the same tint (blue and bright blue, yellow and bright yellow). A smaller palette without the bright variants, or coloring only the pod tag, would probably read better on both themes.

Two things I want to be clear are not yours: "Download > All logs" does nothing in production builds of the current main, single-pod tabs included, because the dropdown wraps the call in act from react-dom/test-utils and React 19 has no React.act in production. I am opening a separate fix for that. And the log list not following the tail after opening behaves the same on main.

Thanks again!

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.

Feature Request: Add support for deployment / stateful set logs

2 participants