From a73549539bb205169189158532c32d0fc44b104e Mon Sep 17 00:00:00 2001 From: Asher Date: Wed, 12 Jun 2024 15:09:45 -0800 Subject: [PATCH] Cache unchanging telemetry data Might make sense to cache the rest as well, and evict from the cache periodically. For now this is enough to fix a hang I often see in our deployment of Coder. Might only be surfacing now because new telemetry calls were added to startup. --- CHANGELOG.md | 7 +++++ patches/telemetry.diff | 60 ++++++++++++++++++++++++++---------------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54225db3f..73961f680 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,13 @@ Code v99.99.999 ## Unreleased +Code v1.90.0 + +### Fixed + +- Cache a call to get CPU information used in telemetry that could result in a + lack responsiveness if it was particularly slow. + ## [4.90.0](https://github.com/coder/code-server/releases/tag/v4.90.0) - 2024-06-11 Code v1.90.0 diff --git a/patches/telemetry.diff b/patches/telemetry.diff index 52d2e2287..50ce7a7ea 100644 --- a/patches/telemetry.diff +++ b/patches/telemetry.diff @@ -50,50 +50,66 @@ Index: code-server/lib/vscode/src/vs/server/node/telemetryClient.ts =================================================================== --- /dev/null +++ code-server/lib/vscode/src/vs/server/node/telemetryClient.ts -@@ -0,0 +1,55 @@ +@@ -0,0 +1,71 @@ +import { AppInsightsCore, IExtendedTelemetryItem, ITelemetryItem } from '@microsoft/1ds-core-js'; +import * as https from 'https'; +import * as http from 'http'; +import * as os from 'os'; + ++interface SystemInfo { ++ measurements: Record; ++ properties: Record; ++} ++ +export class TelemetryClient extends AppInsightsCore { ++ private readonly systemInfo: SystemInfo = { ++ measurements: {}, ++ properties: {}, ++ }; ++ + public constructor( + private readonly endpoint: string, -+ private readonly machineId: string, -+ private readonly isContainer: Boolean | undefined) { ++ machineId: string, ++ isContainer: boolean | undefined) { + super(); ++ ++ // os.cpus() can take a very long time sometimes (personally I see 1-2 ++ // seconds in a Coder workspace). This adds up significantly, especially ++ // when many telemetry requests are sent during startup, which can cause ++ // connection timeouts. Try to cache as much as we can. ++ try { ++ const cpus = os.cpus(); ++ this.systemInfo.measurements.cores = cpus.length; ++ this.systemInfo.properties['common.cpuModel'] = cpus[0].model; ++ } catch (error) {} ++ ++ try { ++ this.systemInfo.properties['common.shell'] = os.userInfo().shell; ++ this.systemInfo.properties['common.release'] = os.release(); ++ this.systemInfo.properties['common.arch'] = os.arch(); ++ } catch (error) {} ++ ++ this.systemInfo.properties['common.remoteMachineId'] = machineId; ++ this.systemInfo.properties['common.isContainer'] = isContainer; + } + + public override track(item: IExtendedTelemetryItem | ITelemetryItem): void { + const options = item.baseData || {} -+ if (!options.properties) { -+ options.properties = {}; ++ options.measurements = { ++ ...(options.measurements || {}), ++ ...this.systemInfo.measurements, + } -+ if (!options.measurements) { -+ options.measurements = {}; ++ options.properties = { ++ ...(options.properties || {}), ++ ...this.systemInfo.properties, + } + + try { -+ const cpus = os.cpus(); -+ options.measurements.cores = cpus.length; -+ options.properties['common.cpuModel'] = cpus[0].model; -+ } catch (error) {} -+ -+ try { + options.measurements.memoryFree = os.freemem(); + options.measurements.memoryTotal = os.totalmem(); + } catch (error) {} + + try { -+ options.properties['common.shell'] = os.userInfo().shell; -+ options.properties['common.release'] = os.release(); -+ options.properties['common.arch'] = os.arch(); -+ } catch (error) {} -+ -+ options.properties['common.remoteMachineId'] = this.machineId; -+ options.properties['common.isContainer'] = this.isContainer; -+ -+ try { + const request = (/^http:/.test(this.endpoint) ? http : https).request(this.endpoint, { + method: 'POST', + headers: {