Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type { IXtermCore } from './xterm-private.js';
import type { IMenu } from '../../../../platform/actions/common/actions.js';
import type { Barrier } from '../../../../base/common/async.js';
import type { IProgressState } from '@xterm/addon-progress';
import type { TerminalEditorInput } from './terminalEditorInput.js';

export const ITerminalService = createDecorator<ITerminalService>('terminalService');
export const ITerminalConfigurationService = createDecorator<ITerminalConfigurationService>('terminalConfigurationService');
Expand Down Expand Up @@ -84,7 +85,7 @@ export interface ITerminalInstanceService {
* @param launchConfig The shell launch config.
* @param target The target of the terminal.
*/
createInstance(launchConfig: IShellLaunchConfig, target: TerminalLocation): ITerminalInstance;
createInstance(launchConfig: IShellLaunchConfig, target: TerminalLocation, editorOptions?: TerminalEditorLocation): ITerminalInstance;

/**
* Gets the registered backend for a remote authority (undefined = local). This is a convenience
Expand Down Expand Up @@ -409,7 +410,7 @@ export interface ITerminalEditorService extends ITerminalInstanceHost {
revealActiveEditor(preserveFocus?: boolean): Promise<void>;
resolveResource(instance: ITerminalInstance): URI;
reviveInput(deserializedInput: IDeserializedTerminalEditorInput): EditorInput;
getInputFromResource(resource: URI): EditorInput;
getInputFromResource(resource: URI): TerminalEditorInput;
}

export const terminalEditorId = 'terminalEditor';
Expand Down
32 changes: 28 additions & 4 deletions src/vs/workbench/contrib/terminal/browser/terminalTelemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,26 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { getWindowById } from '../../../../base/browser/dom.js';
import { isAuxiliaryWindow } from '../../../../base/browser/window.js';
import { timeout } from '../../../../base/common/async.js';
import { Event } from '../../../../base/common/event.js';
import { Disposable, DisposableStore } from '../../../../base/common/lifecycle.js';
import { basename } from '../../../../base/common/path.js';
import { ITelemetryService } from '../../../../platform/telemetry/common/telemetry.js';
import { TerminalCapability } from '../../../../platform/terminal/common/capabilities/capabilities.js';
import type { IShellLaunchConfig, ShellIntegrationInjectionFailureReason } from '../../../../platform/terminal/common/terminal.js';
import { TerminalLocation, type IShellLaunchConfig, type ShellIntegrationInjectionFailureReason } from '../../../../platform/terminal/common/terminal.js';
import type { IWorkbenchContribution } from '../../../common/contributions.js';
import { ILifecycleService } from '../../../services/lifecycle/common/lifecycle.js';
import { ITerminalService, type ITerminalInstance } from './terminal.js';
import { ITerminalEditorService, ITerminalService, type ITerminalInstance } from './terminal.js';

export class TerminalTelemetryContribution extends Disposable implements IWorkbenchContribution {
static ID = 'terminalTelemetry';

constructor(
@ILifecycleService lifecycleService: ILifecycleService,
@ITerminalService terminalService: ITerminalService,
@ITerminalEditorService terminalEditorService: ITerminalEditorService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
) {
super();
Expand All @@ -28,6 +31,7 @@ export class TerminalTelemetryContribution extends Disposable implements IWorkbe
const store = new DisposableStore();
this._store.add(store);


await Promise.race([
// Wait for process ready so the shell launch config is fully resolved, then
// allow another 10 seconds for the shell integration to be fully initialized
Expand All @@ -40,16 +44,28 @@ export class TerminalTelemetryContribution extends Disposable implements IWorkbe
Event.toPromise(lifecycleService.onWillShutdown, store),
]);

this._logCreateInstance(instance);
// Determine window status, this is done some time after the process is ready and could
// reflect the terminal being moved.
let isInAuxWindow = false;
try {
const input = terminalEditorService.getInputFromResource(instance.resource);
const windowId = input.group?.windowId;
isInAuxWindow = !!(windowId && isAuxiliaryWindow(getWindowById(windowId, true).window));
} catch {
}

this._logCreateInstance(instance, isInAuxWindow);
this._store.delete(store);
}));
}

private _logCreateInstance(instance: ITerminalInstance): void {
private _logCreateInstance(instance: ITerminalInstance, isInAuxWindow: boolean): void {
const slc = instance.shellLaunchConfig;
const commandDetection = instance.capabilities.get(TerminalCapability.CommandDetection);

type TerminalCreationTelemetryData = {
location: string;

shellType: string;
promptType: string | undefined;

Expand All @@ -68,6 +84,8 @@ export class TerminalTelemetryContribution extends Disposable implements IWorkbe
owner: 'tyriar';
comment: 'Track details about terminal creation, such as the shell type';

location: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The location of the terminal.' };

shellType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The detected shell type for the terminal.' };
promptType: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The detected prompt type for the terminal.' };

Expand All @@ -83,6 +101,12 @@ export class TerminalTelemetryContribution extends Disposable implements IWorkbe
terminalSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The session ID of the terminal instance.' };
};
this._telemetryService.publicLog2<TerminalCreationTelemetryData, TerminalCreationTelemetryClassification>('terminal/createInstance', {
location: (instance.target === TerminalLocation.Panel
? 'view'
: instance.target === TerminalLocation.Editor
? (isInAuxWindow ? 'editor-auxwindow' : 'editor')
: 'unknown'),

shellType: getSanitizedShellType(slc),
promptType: commandDetection?.promptType,

Expand Down
Loading