feat: add download action for pod logs#299
Conversation
Signed-off-by: A69SHUBHAM <spacekrai0@gmail.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Code Review
This pull request introduces the ability to fetch, view, and download Kubernetes pod logs from the dashboard. It adds a new tRPC procedure getPodLogs and updates the frontend to fetch and display these logs alongside the YAML configuration. However, two critical issues were identified: first, refetching queries in pod-management.tsx relies on a potentially stale selectedPod state, which should be resolved by fetching directly using tRPC utils; second, returning the raw response from readNamespacedPodLog in the tRPC router will cause serialization errors, so only response.body should be returned.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const [yamlResponse, logsResponse] = await Promise.all([ | ||
| podYamlQuery.refetch(), | ||
| podLogsQuery.refetch() | ||
| ]); | ||
| const yaml = yamlResponse.data || pod.yaml || ""; | ||
| // Ensure logs is a string | ||
| let logsText = ""; | ||
| if (typeof logsResponse.data === 'string') { | ||
| logsText = logsResponse.data; | ||
| } else if (logsResponse.data && typeof logsResponse.data === 'object') { | ||
| logsText = JSON.stringify(logsResponse.data, null, 2); | ||
| } else { | ||
| logsText = pod.logs || "No logs available."; | ||
| } | ||
|
|
||
| setSelectedPod({ ...pod, yaml, logs: logsText }); | ||
| setShowPodDetails(true); | ||
| } catch (err) { | ||
| setError("Failed to fetch pod YAML"); | ||
| setError("Failed to fetch pod details"); | ||
| console.error(err) | ||
| } | ||
| }, [podYamlQuery]) | ||
| }, [podYamlQuery, podLogsQuery]) |
There was a problem hiding this comment.
There is a critical bug here: when handlePodClick is called, selectedPod is still null (or holds the previously selected pod). Since podYamlQuery and podLogsQuery are defined using selectedPod?.namespace and selectedPod?.name, calling .refetch() on them will execute the queries with stale or empty parameters from the previous render cycle, rather than the parameters of the newly clicked pod.
To fix this, use utils.podRouter.getPodYaml.fetch and utils.podRouter.getPodLogs.fetch directly with the clicked pod's properties. This guarantees that the correct pod's details are fetched immediately and avoids any race conditions or hook dependency issues. Note that once this is applied, both podYamlQuery and podLogsQuery hooks become unused and can be cleaned up.
const [yaml, logs] = await Promise.all([
utils.podRouter.getPodYaml.fetch({
namespace: pod.namespace,
name: pod.name
}),
utils.podRouter.getPodLogs.fetch({
namespace: pod.namespace,
name: pod.name
})
]);
setSelectedPod({ ...pod, yaml: yaml || "", logs: logs || "No logs available." });
setShowPodDetails(true);
} catch (err) {
setError("Failed to fetch pod details");
console.error(err)
}
}, [utils])
| const response = await k8sCoreApi.readNamespacedPodLog({ | ||
| name, | ||
| namespace, | ||
| }); | ||
| return response; |
There was a problem hiding this comment.
In @kubernetes/client-node, readNamespacedPodLog returns an object of type { response: http.IncomingMessage; body: string; }. Returning the entire response object directly will attempt to serialize the http.IncomingMessage object (which contains circular references and sockets) over tRPC, causing a serialization error.
Instead, you should return response.body to only send the actual log string.
| const response = await k8sCoreApi.readNamespacedPodLog({ | |
| name, | |
| namespace, | |
| }); | |
| return response; | |
| const response = await k8sCoreApi.readNamespacedPodLog({ | |
| name, | |
| namespace, | |
| }); | |
| return response.body; |
| const podLogsQuery = trpc.podRouter.getPodLogs.useQuery( | ||
| { | ||
| namespace: selectedPod?.namespace || "", | ||
| name: selectedPod?.name || "" | ||
| }, | ||
| { | ||
| enabled: false, | ||
| onError: (err) => { | ||
| console.error("Error fetching pod logs:", err); | ||
| setError(`Pod Logs API error: ${err.message}`); | ||
| }, | ||
| }, | ||
| ); |
Summary
This PR adds a download action for pod logs.
Users can now download the currently displayed log output as a
.logfile directly from the pod details view.Changes
Verification
Closes #298