Skip to content

Commit 7e91a7a

Browse files
telemetry: add env type cloudDesktop-amzn & ec2-amzn (#5477)
* fix docstring Import the class so that it properly resolves in the docstring Signed-off-by: Nikolas Komonen <[email protected]> * telemetry: add env type `cloudDesktop-amzn` & `ec2-amzn` Problem: Anything that was a ssh-remote environment was labeled as `ec2` in our telemetry. But there are more nuanced cases for Amazon internal ssh connections. Solution: Add more specific checks for a Cloud Desktop and an internal ec2 Signed-off-by: Nikolas Komonen <[email protected]> --------- Signed-off-by: Nikolas Komonen <[email protected]>
1 parent ac4bbd4 commit 7e91a7a

File tree

4 files changed

+126
-8
lines changed

4 files changed

+126
-8
lines changed

packages/core/src/shared/telemetry/telemetryClient.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ export class DefaultTelemetryClient implements TelemetryClient {
108108
ClientID: this.clientId,
109109
OS: os.platform(),
110110
OSVersion: os.release(),
111-
ComputeEnv: getComputeEnvType(),
111+
ComputeEnv: await getComputeEnvType(),
112112
ParentProduct: vscode.env.appName,
113113
ParentProductVersion: vscode.version,
114114
MetricData: batch,
@@ -135,14 +135,14 @@ export class DefaultTelemetryClient implements TelemetryClient {
135135
AWSProductVersion: extensionVersion,
136136
OS: os.platform(),
137137
OSVersion: os.release(),
138-
ComputeEnv: getComputeEnvType(),
138+
ComputeEnv: await getComputeEnvType(),
139139
ParentProduct: vscode.env.appName,
140140
ParentProductVersion: vscode.version,
141141
Comment: feedback.comment,
142142
Sentiment: feedback.sentiment,
143143
})
144144
.promise()
145-
this.logger.debug(`ComputeEnv detected for telemetry: ${getComputeEnvType()}`)
145+
this.logger.debug(`ComputeEnv detected for telemetry: ${await getComputeEnvType()}`)
146146
this.logger.info('Successfully posted feedback')
147147
} catch (err) {
148148
this.logger.error(`Failed to post feedback: ${err}`)

packages/core/src/shared/telemetry/util.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@ import * as os from 'os'
99
import { getLogger } from '../logger'
1010
import { fromExtensionManifest, migrateSetting, Settings } from '../settings'
1111
import { memoize } from '../utilities/functionUtils'
12-
import { isInDevEnv, extensionVersion, isAutomation, isRemoteWorkspace } from '../vscode/env'
12+
import {
13+
isInDevEnv,
14+
extensionVersion,
15+
isAutomation,
16+
isRemoteWorkspace,
17+
isCloudDesktop,
18+
isAmazonInternalOs,
19+
} from '../vscode/env'
1320
import { addTypeName } from '../utilities/typeConstructors'
1421
import globals, { isWeb } from '../extensionGlobals'
1522
import { mapMetadata } from './telemetryLogger'
@@ -19,7 +26,7 @@ import { isValidationExemptMetric } from './exemptMetrics'
1926
import { isAmazonQ, isCloud9, isSageMaker } from '../../shared/extensionUtilities'
2027
import { randomUUID } from '../crypto'
2128
import { ClassToInterfaceType } from '../utilities/tsUtils'
22-
import { FunctionEntry } from './spans'
29+
import { FunctionEntry, type TelemetryTracer } from './spans'
2330
import { telemetry } from './telemetry'
2431

2532
const legacySettingsTelemetryValueDisable = 'Disable'
@@ -177,18 +184,29 @@ export function getUserAgent(
177184
return pairs.join(' ')
178185
}
179186

187+
/**
188+
* All the types of ENVs the extension can run in.
189+
*
190+
* NOTES:
191+
* - append `-amzn` for any environment internal to Amazon
192+
*/
180193
type EnvType =
181194
| 'cloud9'
182195
| 'cloud9-codecatalyst'
196+
| 'cloudDesktop-amzn'
183197
| 'codecatalyst'
184198
| 'local'
185199
| 'ec2'
200+
| 'ec2-amzn' // ec2 but with an internal Amazon OS
186201
| 'sagemaker'
187202
| 'test'
188203
| 'wsl'
189204
| 'unknown'
190205

191-
export function getComputeEnvType(): EnvType {
206+
/**
207+
* Returns the identifier for the environment that the extension is running in.
208+
*/
209+
export async function getComputeEnvType(): Promise<EnvType> {
192210
if (isCloud9('classic')) {
193211
return 'cloud9'
194212
} else if (isCloud9('codecatalyst')) {
@@ -197,7 +215,13 @@ export function getComputeEnvType(): EnvType {
197215
return 'codecatalyst'
198216
} else if (isSageMaker()) {
199217
return 'sagemaker'
200-
} else if (isRemoteWorkspace() && !isInDevEnv()) {
218+
} else if (isRemoteWorkspace()) {
219+
if (isAmazonInternalOs()) {
220+
if (await isCloudDesktop()) {
221+
return 'cloudDesktop-amzn'
222+
}
223+
return 'ec2-amzn'
224+
}
201225
return 'ec2'
202226
} else if (env.remoteName) {
203227
return 'wsl'

packages/core/src/shared/vscode/env.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as semver from 'semver'
77
import * as vscode from 'vscode'
88
import * as packageJson from '../../../package.json'
9+
import * as os from 'os'
910
import { getLogger } from '../logger'
1011
import { onceChanged } from '../utilities/functionUtils'
1112
import { ChildProcess } from '../utilities/childProcess'
@@ -94,6 +95,31 @@ export function isRemoteWorkspace(): boolean {
9495
return vscode.env.remoteName === 'ssh-remote'
9596
}
9697

98+
/**
99+
* There is Amazon Linux 2, but additionally an Amazon Linux 2 Internal.
100+
* The internal version is for Amazon employees only. And this version can
101+
* be used by either EC2 OR CloudDesktop. It is not exclusive to either.
102+
*
103+
* Use {@link isCloudDesktop()} to know if we are specifically using it.
104+
*
105+
* Example: `5.10.220-188.869.amzn2int.x86_64`
106+
*/
107+
export function isAmazonInternalOs() {
108+
return os.release().includes('amzn2int')
109+
}
110+
111+
/**
112+
* Returns true if we are in an internal Amazon Cloud Desktop
113+
*/
114+
export async function isCloudDesktop() {
115+
if (!isAmazonInternalOs()) {
116+
return false
117+
}
118+
119+
// This heuristic is explained in IDE-14524
120+
return (await new ChildProcess('/apollo/bin/getmyfabric').run().then((r) => r.exitCode)) === 0
121+
}
122+
97123
/** Returns true if OS is Windows. */
98124
export function isWin(): boolean {
99125
// if (isWeb()) {

packages/core/src/test/shared/vscode/env.test.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,30 @@
44
*/
55

66
import assert from 'assert'
7-
import { getEnvVars, getServiceEnvVarConfig } from '../../../shared/vscode/env'
7+
import {
8+
isCloudDesktop,
9+
getEnvVars,
10+
getServiceEnvVarConfig,
11+
isAmazonInternalOs as isAmazonInternalOS,
12+
} from '../../../shared/vscode/env'
13+
import { ChildProcess } from '../../../shared/utilities/childProcess'
14+
import * as sinon from 'sinon'
15+
import os from 'os'
16+
import vscode from 'vscode'
17+
import { getComputeEnvType } from '../../../shared/telemetry/util'
818

919
describe('env', function () {
20+
// create a sinon sandbox instance and instantiate in a beforeEach
21+
let sandbox: sinon.SinonSandbox
22+
23+
beforeEach(function () {
24+
sandbox = sinon.createSandbox()
25+
})
26+
27+
afterEach(function () {
28+
sandbox.restore()
29+
})
30+
1031
describe('getServiceEnvVarConfig', function () {
1132
const envVars: string[] = []
1233

@@ -56,4 +77,51 @@ describe('env', function () {
5677
assert.deepStrictEqual(envVar, expectedEnvVars)
5778
})
5879
})
80+
81+
function stubOsVersion(verson: string) {
82+
return sandbox.stub(os, 'release').returns(verson)
83+
}
84+
85+
it('isAmazonInternalOS', function () {
86+
const versionStub = stubOsVersion('5.10.220-188.869.amzn2int.x86_64')
87+
assert.strictEqual(isAmazonInternalOS(), true)
88+
89+
versionStub.returns('5.10.220-188.869.NOT_INTERNAL.x86_64')
90+
assert.strictEqual(isAmazonInternalOS(), false)
91+
})
92+
93+
it('isCloudDesktop', async function () {
94+
stubOsVersion('5.10.220-188.869.amzn2int.x86_64')
95+
96+
const runStub = sandbox.stub(ChildProcess.prototype, 'run').resolves({ exitCode: 0 } as any)
97+
assert.strictEqual(await isCloudDesktop(), true)
98+
99+
runStub.resolves({ exitCode: 1 } as any)
100+
assert.strictEqual(await isCloudDesktop(), false)
101+
})
102+
103+
describe('getComputeEnvType', async function () {
104+
it('cloudDesktop', async function () {
105+
sandbox.stub(vscode.env, 'remoteName').value('ssh-remote')
106+
stubOsVersion('5.10.220-188.869.amzn2int.x86_64')
107+
sandbox.stub(ChildProcess.prototype, 'run').resolves({ exitCode: 0 } as any)
108+
109+
assert.deepStrictEqual(await getComputeEnvType(), 'cloudDesktop-amzn')
110+
})
111+
112+
it('ec2-internal', async function () {
113+
sandbox.stub(vscode.env, 'remoteName').value('ssh-remote')
114+
stubOsVersion('5.10.220-188.869.amzn2int.x86_64')
115+
sandbox.stub(ChildProcess.prototype, 'run').resolves({ exitCode: 1 } as any)
116+
117+
assert.deepStrictEqual(await getComputeEnvType(), 'ec2-amzn')
118+
})
119+
120+
it('ec2', async function () {
121+
sandbox.stub(vscode.env, 'remoteName').value('ssh-remote')
122+
stubOsVersion('5.10.220-188.869.NOT_INTERNAL.x86_64')
123+
124+
assert.deepStrictEqual(await getComputeEnvType(), 'ec2')
125+
})
126+
})
59127
})

0 commit comments

Comments
 (0)