Skip to content

Bugfix/inaccurate process metrics#6257

Merged
sid-bruno merged 3 commits intousebruno:mainfrom
chirag-bruno:bugfix/inaccurate-process-metrics
Dec 2, 2025
Merged

Bugfix/inaccurate process metrics#6257
sid-bruno merged 3 commits intousebruno:mainfrom
chirag-bruno:bugfix/inaccurate-process-metrics

Conversation

@chirag-bruno
Copy link
Collaborator

@chirag-bruno chirag-bruno commented Dec 1, 2025

Description

This PR addresses https://usebruno.atlassian.net/browse/BRU-2192 and tries to provide a detailed view of Process metrics (Main and Sub Processes)

Screen.Recording.2025-11-18.at.1.50.26.PM.1.mov

Contribution Checklist:

  • The pull request only addresses one issue or adds one feature.
  • The pull request does not introduce any breaking changes
  • I have added screenshots or gifs to help explain the change if applicable.
  • I have read the contribution guidelines.
  • Create an issue and link to the pull request.

Summary by CodeRabbit

  • New Features
    • Performance panel now includes a dropdown to switch between cumulative system metrics and individual process views.
    • Per-process monitoring shows CPU, memory, uptime and PID details alongside the cumulative view.
  • Style
    • Updated visual theming, layout, and responsive styling for the Performance panel and processes table.
  • Bug Fixes
    • View resets to cumulative if a selected process is no longer available.

✏️ Tip: You can customize this high-level summary in your review settings.

- Replace tabs with dropdown selector for process filtering
- Add per-process view with same card layout as cumulative view
- Implement VS Code-style process monitoring using app.getAppMetrics()
- Add process details including PID, CPU, memory, and uptime
- Update memory formatting to handle bytes correctly
- Improve UI with styled dropdown and consistent card ordering
@sid-bruno
Copy link
Collaborator

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

✅ 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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Walkthrough

Adds per-process metrics emission in the system-monitor backend and a process-select UI in the DevTools Performance panel, enabling cumulative or per-process views; includes extensive presentational styling for the new Performance panel.

Changes

Cohort / File(s) Change Summary
Backend: system monitor
packages/bruno-electron/src/app/system-monitor.js
Builds a processes array from metrics (pid, title, memory in bytes, cpu, type, creationTime), updates total memory calculation, and includes processes in emitted systemResources and fallbackStats.
Frontend: component logic
packages/bruno-app/src/components/Devtools/Performance/index.js
Adds selectedPid state, memoized processOptions and selected process lookup, renders a dropdown selector (cumulative vs per-process), implements renderCumulativeView / renderProcessView, and auto-resets selection when a PID disappears.
Frontend: styling
packages/bruno-app/src/components/Devtools/Performance/StyledWrapper.js
Introduces comprehensive styling for the Performance panel: header, selector, table, status badges, spacing, typography, theme-driven colors, responsive and hover/focus behaviors (purely presentational).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to:
    • system-monitor.js memory unit conversion and consistency across consumers.
    • Shape and stability of systemResources.processes (fields and types).
    • selectedPid lifecycle and auto-reset edge cases when processes appear/disappear.
    • Memoization dependencies in index.js to avoid unnecessary re-renders.
    • StyledWrapper specificity and any unintended style leakage.

Poem

🛠️ Tiny processes hum, their counters bright,
A selector opens, toggling day and night,
Bytes and CPU in tidy rows align,
Cumulative or single—observe the line,
A styled panel sings, performance in sight.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main purpose of the changeset—fixing inaccurate process metrics by correcting memory calculations and adding detailed process information to the performance panel.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment on lines +90 to +95
{ value: 'cumulative', label: 'Cumulative (All Processes)' },
...processes.map((process) => ({
value: String(process.pid),
label: `PID ${process.pid}${process.title ? ` - ${process.title}` : ''}${process.type ? ` (${process.type})` : ''}`
}))
];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we make this a little more readable by moving it to a function outside the react component that takes in the process obj

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed. Moved the code outside the component

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)
packages/bruno-electron/src/app/system-monitor.js (1)

63-72: Normalize memory units between main metrics and fallback

The main path derives totalMemory and processes[i].memory from metric.memory.workingSetSize (returned by Electron's app.getAppMetrics() in kilobytes), while the fallback path uses process.memoryUsage().rss (which is in bytes). Both values flow into the same systemResources.memory field consumed by the UI.

Since the frontend multiplies systemResources.memory by 1024 before formatting, it expects kilobytes. When the fallback path triggers, memory readings will be approximately 1024 times larger than normal, causing incorrect display values and breaking any memory-based thresholds.

Normalize both code paths to use the same unit (recommend converting workingSetSize to bytes to match rss), and update the frontend to treat systemResources.memory and process.memory consistently.

🧹 Nitpick comments (2)
packages/bruno-app/src/components/Devtools/Performance/StyledWrapper.js (1)

119-348: New performance header and processes-table styling look consistent

The new header, selector, and table styles align with the markup in Performance/index.js and fit the existing theming approach. Only minor nit: the hard-coded badge/CPU colors (#ef4444, #f59e0b, etc.) could be moved into the theme later for easier theming, but that’s optional.

packages/bruno-app/src/components/Devtools/Performance/index.js (1)

65-83: Remove or wire up unused trend / IconChartLine in SystemResourceCard

SystemResourceCard accepts a trend prop and renders an <IconChartLine />, but:

  • IconChartLine is not imported.
  • None of the current call sites pass trend, so this code is effectively dead but will break as soon as someone starts using that prop.

I’d either import IconChartLine and start using trend, or simplify the card by dropping the trend prop and the extra markup until it’s needed.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd72ee5 and 079d58f.

📒 Files selected for processing (3)
  • packages/bruno-app/src/components/Devtools/Performance/StyledWrapper.js (1 hunks)
  • packages/bruno-app/src/components/Devtools/Performance/index.js (2 hunks)
  • packages/bruno-electron/src/app/system-monitor.js (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/bruno-electron/src/app/system-monitor.js (1)
packages/bruno-app/src/components/StopWatch/index.js (1)
  • currentTime (4-4)
packages/bruno-app/src/components/Devtools/Performance/index.js (1)
packages/bruno-app/src/components/Devtools/Performance/StyledWrapper.js (1)
  • StyledWrapper (3-349)

- Convert memory from KB to bytes in system-monitor.js (workingSetSize * 1024)
- Remove incorrect multiplication in Performance component (memory already in bytes)
- Ensure all memory values are consistently normalized to bytes throughout the app
- Fix memory comparison thresholds to use bytes consistently
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)
packages/bruno-app/src/components/Devtools/Performance/index.js (1)

83-92: Missing import: IconChartLine will cause a runtime error.

IconChartLine is used on line 85 but not imported. If trend is ever truthy, this throws a ReferenceError.

Add the missing import:

 import {
   IconCpu,
   IconDatabase,
   IconClock,
   IconServer,
-  IconChevronDown
+  IconChevronDown,
+  IconChartLine
 } from '@tabler/icons';

Or remove the trend section if it's unused:

-      {trend && (
-        <div className={`resource-trend ${trend > 0 ? 'up' : trend < 0 ? 'down' : 'stable'}`}>
-          <IconChartLine size={12} strokeWidth={1.5} />
-          <span>
-            {trend > 0 ? '+' : ''}
-            {trend.toFixed(1)}
-            %
-          </span>
-        </div>
-      )}
🧹 Nitpick comments (2)
packages/bruno-app/src/components/Devtools/Performance/index.js (1)

57-73: Consider hoisting pure utility functions outside the component.

formatBytes and formatUptime have no dependencies on component state or props. Moving them outside Performance avoids recreating them on each render.

+const formatBytes = (bytes) => {
+  if (bytes === 0) return '0 Bytes';
+  const k = 1024;
+  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
+  const i = Math.floor(Math.log(bytes) / Math.log(k));
+  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+};
+
+const formatUptime = (seconds) => {
+  const hours = Math.floor(seconds / 3600);
+  const minutes = Math.floor((seconds % 3600) / 60);
+  const secs = Math.floor(seconds % 60);
+
+  if (hours > 0) return `${hours}h ${minutes}m ${secs}s`;
+  if (minutes > 0) return `${minutes}m ${secs}s`;
+  return `${secs}s`;
+};
+
 const Performance = () => {
   // ...remove formatBytes and formatUptime from here
packages/bruno-electron/src/app/system-monitor.js (1)

71-87: Use const instead of var for processes

processes is never reassigned, so const communicates intent better and avoids accidental mutation; everything else in this block looks consistent and well‑structured.

-      const uptime = (currentTime - this.startTime) / 1000;
-      var processes = metrics.map((metric) => ({
+      const uptime = (currentTime - this.startTime) / 1000;
+      const processes = metrics.map((metric) => ({
         pid: metric.pid,
         title: metric.title,
         memory: metric.memory.workingSetSize * 1024,
         cpu: metric.cpu.percentCPUUsage,
         type: metric.type || 'unknown',
         creationTime: metric.creationTime
       }));
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 079d58f and 672e92d.

📒 Files selected for processing (2)
  • packages/bruno-app/src/components/Devtools/Performance/index.js (2 hunks)
  • packages/bruno-electron/src/app/system-monitor.js (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (CODING_STANDARDS.md)

**/*.{js,jsx,ts,tsx}: Use 2 spaces for indentation. No tabs, just spaces
Stick to single quotes for strings
Always add semicolons at the end of statements
No trailing commas
Always use parentheses around parameters in arrow functions, even for single parameters
For multiline constructs, put opening braces on the same line, and ensure consistency. Minimum 2 elements for multiline
No newlines inside function parentheses. Keep 'em tight
Space before and after the arrow in arrow functions. () => {} is good
No space between function name and parentheses. func() not func ()
Semicolons go at the end of the line, not on a new line
Names for functions need to be concise and descriptive
Add in JSDoc comments to add more details to the abstractions if needed
Avoid single line abstractions where all that's being done is increasing the call stack with one additional function
Add in meaningful comments instead of obvious ones where complex code flow is explained properly

Files:

  • packages/bruno-electron/src/app/system-monitor.js
  • packages/bruno-app/src/components/Devtools/Performance/index.js
🧬 Code graph analysis (1)
packages/bruno-app/src/components/Devtools/Performance/index.js (1)
packages/bruno-app/src/components/Devtools/Performance/StyledWrapper.js (1)
  • StyledWrapper (3-349)
⏰ 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). (6)
  • GitHub Check: Playwright E2E Tests
  • GitHub Check: SSL Tests - macOS
  • GitHub Check: Unit Tests
  • GitHub Check: SSL Tests - Linux
  • GitHub Check: SSL Tests - Windows
  • GitHub Check: CLI Tests
🔇 Additional comments (8)
packages/bruno-app/src/components/Devtools/Performance/index.js (6)

1-10: LGTM on imports structure.

Imports are clean and properly organized.


12-20: LGTM on process options extraction.

Clean extraction of label logic outside the component, addressing prior feedback.


22-55: LGTM on component setup and IPC lifecycle.

Proper initialization, error handling, and cleanup.


96-113: LGTM on memoization and PID reset logic.

Correct dependencies and defensive reset when the selected process disappears.


174-180: Same memory unit verification applies here.

Ensure process.memory is in bytes from the backend. The threshold comparison process.memory > (500 * 1024 * 1024) and formatBytes(process.memory) assume bytes.


205-229: LGTM on the main render and dropdown implementation.

Clean, accessible dropdown with proper label association and conditional view rendering.

packages/bruno-electron/src/app/system-monitor.js (2)

63-69: Memory unit conversion aligns totals with process memory usage

Switching totalMemory to use metric.memory.workingSetSize * 1024 keeps it in the same unit as memory.rss from process.memoryUsage() (bytes) and makes aggregated vs fallback memory comparable. This is a solid, low‑risk fix.


100-108: Fallback payload shape matches primary payload

Adding timestamp and an empty processes: [] to fallbackStats keeps the schema consistent with systemResources, which should simplify the consumer UI logic and avoid null/undefined checks. Looks good.

@sid-bruno sid-bruno merged commit bc4062b into usebruno:main Dec 2, 2025
8 checks passed
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.

2 participants