Skip to content

Commit

Permalink
Log commands when using raw process APIs directly (microsoft#22326)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kartik Raj authored Oct 24, 2023
1 parent c3afea5 commit 1032709
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 6 deletions.
9 changes: 6 additions & 3 deletions src/client/common/process/proc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,24 @@ export class ProcessService extends EventEmitter implements IProcessService {
}

public execObservable(file: string, args: string[], options: SpawnOptions = {}): ObservableExecutionResult<string> {
const result = execObservable(file, args, options, this.env, this.processesToKill);
const execOptions = { ...options, doNotLog: true };
const result = execObservable(file, args, execOptions, this.env, this.processesToKill);
this.emit('exec', file, args, options);
return result;
}

public exec(file: string, args: string[], options: SpawnOptions = {}): Promise<ExecutionResult<string>> {
const promise = plainExec(file, args, options, this.env, this.processesToKill);
const execOptions = { ...options, doNotLog: true };
const promise = plainExec(file, args, execOptions, this.env, this.processesToKill);
this.emit('exec', file, args, options);
return promise;
}

public shellExec(command: string, options: ShellOptions = {}): Promise<ExecutionResult<string>> {
this.emit('exec', command, undefined, options);
const disposables = new Set<IDisposable>();
return shellExec(command, options, this.env, disposables).finally(() => {
const shellOptions = { ...options, doNotLog: true };
return shellExec(command, shellOptions, this.env, disposables).finally(() => {
// Ensure the process we started is cleaned up.
disposables.forEach((p) => {
try {
Expand Down
20 changes: 17 additions & 3 deletions src/client/common/process/rawProcessApis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { ExecutionResult, ObservableExecutionResult, Output, ShellOptions, Spawn
import { noop } from '../utils/misc';
import { decodeBuffer } from './decoder';
import { traceVerbose } from '../../logging';
import { WorkspaceService } from '../application/workspace';
import { ProcessLogger } from './logger';

const PS_ERROR_SCREEN_BOGUS = /your [0-9]+x[0-9]+ screen size is bogus\. expect trouble/;

Expand Down Expand Up @@ -49,12 +51,16 @@ function getDefaultOptions<T extends ShellOptions | SpawnOptions>(options: T, de

export function shellExec(
command: string,
options: ShellOptions = {},
options: ShellOptions & { doNotLog?: boolean } = {},
defaultEnv?: EnvironmentVariables,
disposables?: Set<IDisposable>,
): Promise<ExecutionResult<string>> {
const shellOptions = getDefaultOptions(options, defaultEnv);
traceVerbose(`Shell Exec: ${command} with options: ${JSON.stringify(shellOptions, null, 4)}`);
if (!options.doNotLog) {
const processLogger = new ProcessLogger(new WorkspaceService());
processLogger.logProcess(command, undefined, shellOptions);
}
return new Promise((resolve, reject) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const callback = (e: any, stdout: any, stderr: any) => {
Expand Down Expand Up @@ -90,12 +96,16 @@ export function shellExec(
export function plainExec(
file: string,
args: string[],
options: SpawnOptions = {},
options: SpawnOptions & { doNotLog?: boolean } = {},
defaultEnv?: EnvironmentVariables,
disposables?: Set<IDisposable>,
): Promise<ExecutionResult<string>> {
const spawnOptions = getDefaultOptions(options, defaultEnv);
const encoding = spawnOptions.encoding ? spawnOptions.encoding : 'utf8';
if (!options.doNotLog) {
const processLogger = new ProcessLogger(new WorkspaceService());
processLogger.logProcess(file, args, options);
}
const proc = spawn(file, args, spawnOptions);
// Listen to these errors (unhandled errors in streams tears down the process).
// Errors will be bubbled up to the `error` event in `proc`, hence no need to log.
Expand Down Expand Up @@ -192,12 +202,16 @@ function removeCondaRunMarkers(out: string) {
export function execObservable(
file: string,
args: string[],
options: SpawnOptions = {},
options: SpawnOptions & { doNotLog?: boolean } = {},
defaultEnv?: EnvironmentVariables,
disposables?: Set<IDisposable>,
): ObservableExecutionResult<string> {
const spawnOptions = getDefaultOptions(options, defaultEnv);
const encoding = spawnOptions.encoding ? spawnOptions.encoding : 'utf8';
if (!options.doNotLog) {
const processLogger = new ProcessLogger(new WorkspaceService());
processLogger.logProcess(file, args, options);
}
const proc = spawn(file, args, spawnOptions);
let procExited = false;
const disposable: IDisposable = {
Expand Down

0 comments on commit 1032709

Please sign in to comment.