Browse Source

feat: add cumulativeCPUUsage to AppMetrics and CPUUsage (#41819)

This allows apps to measure their CPU usage over any given period
without worrying about other calls affecting the output,
as they would with `percentCPUUsage`.
rcombs 10 months ago
parent
commit
d8e4579e3c

+ 2 - 0
docs/api/structures/cpu-usage.md

@@ -2,6 +2,8 @@
 
 * `percentCPUUsage` number - Percentage of CPU used since the last call to getCPUUsage.
   First call returns 0.
+* `cumulativeCPUUsage` number (optional) - Total seconds of CPU time used since process
+  startup.
 * `idleWakeupsPerSecond` number - The number of average idle CPU wakeups per second
   since the last call to getCPUUsage. First call returns 0. Will always return 0 on
   Windows.

+ 11 - 4
shell/browser/api/electron_api_app.cc

@@ -1270,10 +1270,17 @@ std::vector<gin_helper::Dictionary> App::GetAppMetrics(v8::Isolate* isolate) {
     auto pid_dict = gin_helper::Dictionary::CreateEmpty(isolate);
     auto cpu_dict = gin_helper::Dictionary::CreateEmpty(isolate);
 
-    double usage =
-        process_metric.second->metrics->GetPlatformIndependentCPUUsage()
-            .value_or(0);
-    cpu_dict.Set("percentCPUUsage", usage / processor_count);
+    // Default usage percentage to 0 for compatibility
+    double usagePercent = 0;
+    if (auto usage = process_metric.second->metrics->GetCumulativeCPUUsage();
+        usage.has_value()) {
+      cpu_dict.Set("cumulativeCPUUsage", usage->InSecondsF());
+      usagePercent =
+          process_metric.second->metrics->GetPlatformIndependentCPUUsage(
+              *usage);
+    }
+
+    cpu_dict.Set("percentCPUUsage", usagePercent / processor_count);
 
 #if !BUILDFLAG(IS_WIN)
     cpu_dict.Set("idleWakeupsPerSecond",

+ 9 - 2
shell/common/api/electron_bindings.cc

@@ -274,8 +274,15 @@ v8::Local<v8::Value> ElectronBindings::GetCPUUsage(
     v8::Isolate* isolate) {
   auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
   int processor_count = base::SysInfo::NumberOfProcessors();
-  double usage = metrics->GetPlatformIndependentCPUUsage().value_or(0);
-  dict.Set("percentCPUUsage", usage / processor_count);
+
+  // Default usage percentage to 0 for compatibility
+  double usagePercent = 0;
+  if (auto usage = metrics->GetCumulativeCPUUsage(); usage.has_value()) {
+    dict.Set("cumulativeCPUUsage", usage->InSecondsF());
+    usagePercent = metrics->GetPlatformIndependentCPUUsage(*usage);
+  }
+
+  dict.Set("percentCPUUsage", usagePercent / processor_count);
 
   // NB: This will throw NOTIMPLEMENTED() on Windows
   // For backwards compatibility, we'll return 0

+ 1 - 0
spec/api-app-spec.ts

@@ -1442,6 +1442,7 @@ describe('app module', () => {
 
         types.push(entry.type);
         expect(entry.cpu).to.have.ownProperty('percentCPUUsage').that.is.a('number');
+        expect(entry.cpu).to.have.ownProperty('cumulativeCPUUsage').that.is.a('number');
         expect(entry.cpu).to.have.ownProperty('idleWakeupsPerSecond').that.is.a('number');
 
         expect(entry.memory).to.have.property('workingSetSize').that.is.greaterThan(0);

+ 2 - 0
spec/api-process-spec.ts

@@ -26,6 +26,7 @@ describe('process module', () => {
       it('returns a cpu usage object', async () => {
         const cpuUsage = await w.webContents.executeJavaScript('process.getCPUUsage()');
         expect(cpuUsage.percentCPUUsage).to.be.a('number');
+        expect(cpuUsage.cumulativeCPUUsage).to.be.a('number');
         expect(cpuUsage.idleWakeupsPerSecond).to.be.a('number');
       });
     });
@@ -124,6 +125,7 @@ describe('process module', () => {
       it('returns a cpu usage object', () => {
         const cpuUsage = process.getCPUUsage();
         expect(cpuUsage.percentCPUUsage).to.be.a('number');
+        expect(cpuUsage.cumulativeCPUUsage).to.be.a('number');
         expect(cpuUsage.idleWakeupsPerSecond).to.be.a('number');
       });
     });