diff --git a/src/vs/code/electron-main/app.ts b/src/vs/code/electron-main/app.ts index 05ebd48ea6b..a3efce99744 100644 --- a/src/vs/code/electron-main/app.ts +++ b/src/vs/code/electron-main/app.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { app, protocol, session, Session, systemPreferences, WebFrameMain } from 'electron'; +import { app, powerMonitor, protocol, session, Session, systemPreferences, WebFrameMain } from 'electron'; import { addUNCHostToAllowlist, disableUNCAccessRestrictions } from '../../base/node/unc.js'; import { validatedIpcMain } from '../../base/parts/ipc/electron-main/ipcMain.js'; import { hostname, release } from 'os'; @@ -611,7 +611,7 @@ export class CodeApplication extends Disposable { this.lifecycleMainService.phase = LifecycleMainPhase.AfterWindowOpen; // Post Open Windows Tasks - this.afterWindowOpen(); + this.afterWindowOpen(appInstantiationService); // Set lifecycle phase to `Eventually` after a short delay and when idle (min 2.5sec, max 5sec) const eventuallyPhaseScheduler = this._register(new RunOnceScheduler(() => { @@ -1374,7 +1374,7 @@ export class CodeApplication extends Disposable { }); } - private afterWindowOpen(): void { + private afterWindowOpen(instantiationService: IInstantiationService): void { // Windows: mutex this.installMutex(); @@ -1400,6 +1400,41 @@ export class CodeApplication extends Disposable { if (isMacintosh && app.runningUnderARM64Translation) { this.windowsMainService?.sendToFocused('vscode:showTranslatedBuildWarning'); } + + // Power telemetry + instantiationService.invokeFunction(accessor => { + const telemetryService = accessor.get(ITelemetryService); + + type PowerEvent = { + readonly idleState: string; + readonly idleTime: number; + readonly thermalState: string; + readonly onBattery: boolean; + }; + type PowerEventClassification = { + idleState: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The system idle state (active, idle, locked, unknown).' }; + idleTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The system idle time in seconds.' }; + thermalState: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The system thermal state (unknown, nominal, fair, serious, critical).' }; + onBattery: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether the system is running on battery power.' }; + owner: 'chrmarti'; + comment: 'Tracks OS power suspend and resume events for reliability insights.'; + }; + + const getPowerEventData = (): PowerEvent => ({ + idleState: powerMonitor.getSystemIdleState(60), + idleTime: powerMonitor.getSystemIdleTime(), + thermalState: powerMonitor.getCurrentThermalState(), + onBattery: powerMonitor.isOnBatteryPower() + }); + + this._register(Event.fromNodeEventEmitter(powerMonitor, 'suspend')(() => { + telemetryService.publicLog2('power.suspend', getPowerEventData()); + })); + + this._register(Event.fromNodeEventEmitter(powerMonitor, 'resume')(() => { + telemetryService.publicLog2('power.resume', getPowerEventData()); + })); + }); } private async installMutex(): Promise { diff --git a/src/vs/platform/native/electron-main/nativeHostMainService.ts b/src/vs/platform/native/electron-main/nativeHostMainService.ts index eb9f6511851..ee61af05310 100644 --- a/src/vs/platform/native/electron-main/nativeHostMainService.ts +++ b/src/vs/platform/native/electron-main/nativeHostMainService.ts @@ -47,7 +47,6 @@ import { zip } from '../../../base/node/zip.js'; import { IConfigurationService } from '../../configuration/common/configuration.js'; import { IProxyAuthService } from './auth.js'; import { AuthInfo, Credentials, IRequestService } from '../../request/common/request.js'; -import { ITelemetryService } from '../../telemetry/common/telemetry.js'; import { randomPath } from '../../../base/common/extpath.js'; export interface INativeHostMainService extends AddFirstParameterToFunctions /* only methods, not events */, number | undefined /* window ID */> { } @@ -71,8 +70,7 @@ export class NativeHostMainService extends Disposable implements INativeHostMain @IConfigurationService private readonly configurationService: IConfigurationService, @IRequestService private readonly requestService: IRequestService, @IProxyAuthService private readonly proxyAuthService: IProxyAuthService, - @IInstantiationService private readonly instantiationService: IInstantiationService, - @ITelemetryService private readonly telemetryService: ITelemetryService + @IInstantiationService private readonly instantiationService: IInstantiationService ) { super(); @@ -121,34 +119,6 @@ export class NativeHostMainService extends Disposable implements INativeHostMain this.onDidResumeOS = Event.fromNodeEventEmitter(powerMonitor, 'resume'); - // Telemetry for power events - type PowerEvent = { - readonly idleState: string; - readonly idleTime: number; - readonly thermalState: string; - readonly onBattery: boolean; - }; - type PowerEventClassification = { - idleState: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The system idle state (active, idle, locked, unknown).' }; - idleTime: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The system idle time in seconds.' }; - thermalState: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The system thermal state (unknown, nominal, fair, serious, critical).' }; - onBattery: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'Whether the system is running on battery power.' }; - owner: 'chrmarti'; - comment: 'Tracks OS power suspend and resume events for reliability insights.'; - }; - const getPowerEventData = (): PowerEvent => ({ - idleState: powerMonitor.getSystemIdleState(60), - idleTime: powerMonitor.getSystemIdleTime(), - thermalState: powerMonitor.getCurrentThermalState(), - onBattery: powerMonitor.isOnBatteryPower() - }); - this._register(Event.fromNodeEventEmitter(powerMonitor, 'suspend')(() => { - this.telemetryService.publicLog2('power.suspend', getPowerEventData()); - })); - this._register(Event.fromNodeEventEmitter(powerMonitor, 'resume')(() => { - this.telemetryService.publicLog2('power.resume', getPowerEventData()); - })); - this.onDidChangeColorScheme = this.themeMainService.onDidChangeColorScheme; this.onDidChangeDisplay = Event.debounce(Event.any(