@@ -28,7 +28,7 @@ import { randomUUID } from '../crypto'
2828import { ClassToInterfaceType } from '../utilities/tsUtils'
2929import { FunctionEntry , type TelemetryTracer } from './spans'
3030import { telemetry } from './telemetry'
31- import { v5 as uuidV5 } from 'uuid'
31+ import { v4 as uuidV4 , v5 as uuidV5 } from 'uuid'
3232
3333const legacySettingsTelemetryValueDisable = 'Disable'
3434const legacySettingsTelemetryValueEnable = 'Enable'
@@ -98,33 +98,59 @@ export function convertLegacy(value: unknown): boolean {
9898 * can be used in conjunction with the client ID to differntiate between
9999 * different VS Code windows on a users machine.
100100 *
101- * ### Rules:
102- *
103- * - On startup of a new application instance, a new session ID must be created.
104- * - This identifier must be a `UUID`, it is enforced by the telemetry service.
105- * - The session ID must be different from all other IDs on the machine
106- * - A session ID exists until the application instance is terminated.
107- * It should never be used again after termination.
108- * - All extensions on the same application instance MUST return the same session ID.
109- * - This will allow us to know which of our extensions (eg Q vs Toolkit) are in the
110- * same VS Code window.
111- *
112- * `vscode.env.sessionId` behaves as described aboved, EXCEPT its
113- * value looks close to a UUID by does not exactly match it (has additional characters).
114- * As a result we process it through uuidV5 which creates a proper UUID from it.
115- * uuidV5 is idempotent, so as long as `vscode.env.sessionId` returns the same value,
116- * we will get the same UUID.
101+ * See spec: https://quip-amazon.com/9gqrAqwO5FCE
117102 */
118- export const getSessionId = once ( ( ) => uuidV5 ( vscode . env . sessionId , sessionIdNonce ) )
119- /**
120- * This is an arbitrary nonce that is used in creating a v5 UUID for Session ID. We only
121- * have this since the spec requires it.
122- * - This should ONLY be used by {@link getSessionId}.
123- * - This value MUST NOT change during runtime, otherwise {@link getSessionId} will lose its
124- * idempotency. But, if there was a reason to change the value in a PR, it would not be an issue.
125- * - This is exported only for testing.
126- */
127- export const sessionIdNonce = '44cfdb20-b30b-4585-a66c-9f48f24f99b5' as const
103+ export const getSessionId = once ( ( ) => SessionId . getSessionId ( ) )
104+
105+ class SessionId {
106+ public static getSessionId ( ) {
107+ // This implementation does not work in web
108+ if ( ! isWeb ( ) ) {
109+ return this . _getSessionId ( )
110+ }
111+ // A best effort at a sessionId just for web mode
112+ return this . _getVscSessionId ( )
113+ }
114+
115+ /**
116+ * This implementation assumes that the `globalThis` is shared between extensions in the same
117+ * Extension Host, so we can share a global variable that way.
118+ *
119+ * This does not seem to work on web mode since the `globalThis` is not shared due to WebWorker design
120+ */
121+ private static _getSessionId ( ) {
122+ const global = globalThis as any
123+ if ( global . amzn_sessionId === undefined ) {
124+ ; ( globalThis as any ) . amzn_sessionId = uuidV4 ( )
125+ }
126+ return global . amzn_sessionId
127+ }
128+
129+ /**
130+ * `vscode.env.sessionId` looks close to a UUID by does not exactly match it (has additional characters).
131+ * As a result we process it through uuidV5 which creates a proper UUID from it.
132+ * uuidV5 is idempotent, so as long as `vscode.env.sessionId` returns the same value,
133+ * we will get the same UUID.
134+ *
135+ * We were initially using this implementation for all session ids, but it has some caveats:
136+ * - If the extension host crashes, sesionId stays the same since the parent VSC process defines it and that does not crash.
137+ * We wanted it to generate a new sessionId on ext host crash.
138+ * - This value may not be reliable, see the following sessionId in telemetry, it contains many events
139+ * all from different client ids: `sessionId: cabea8e7-a8a1-5e51-a60e-07218f4a5937`
140+ */
141+ private static _getVscSessionId ( ) {
142+ return uuidV5 ( vscode . env . sessionId , this . sessionIdNonce )
143+ }
144+ /**
145+ * This is an arbitrary nonce that is used in creating a v5 UUID for Session ID. We only
146+ * have this since the spec requires it.
147+ * - This should ONLY be used by {@link getSessionId}.
148+ * - This value MUST NOT change during runtime, otherwise {@link getSessionId} will lose its
149+ * idempotency. But, if there was a reason to change the value in a PR, it would not be an issue.
150+ * - This is exported only for testing.
151+ */
152+ private static readonly sessionIdNonce = '44cfdb20-b30b-4585-a66c-9f48f24f99b5'
153+ }
128154
129155/**
130156 * Calculates the clientId for the current profile. This calculation is performed once
0 commit comments