Skip to content

Commit 90aea5f

Browse files
committed
make logging more robust
1 parent 6fdeffc commit 90aea5f

File tree

3 files changed

+46
-45
lines changed

3 files changed

+46
-45
lines changed

src/lib/client/useLogger.ts

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
/* eslint-disable no-console */
21
import { useMemo } from 'react';
32
import type { ILogger } from '../types';
3+
import { createConsoleLogger } from '../utils';
44
import { WebviewLogger } from './WebviewLogger';
55
import type { VsCodeApi } from './types';
66

@@ -15,17 +15,3 @@ export function useLogger(tag: string, vscode?: VsCodeApi): ILogger {
1515
[vscode, tag]
1616
);
1717
}
18-
19-
export function createConsoleLogger(tag: string): ILogger {
20-
return {
21-
debug: (message: string, data?: Record<string, unknown>) =>
22-
console.debug(`[${tag}] ${message}`, data),
23-
info: (message: string, data?: Record<string, unknown>) =>
24-
console.info(`[${tag}] ${message}`, data),
25-
warn: (message: string, data?: Record<string, unknown>) =>
26-
console.warn(`[${tag}] ${message}`, data),
27-
error: (message: string, data?: Record<string, unknown>) =>
28-
console.error(`[${tag}] ${message}`, data),
29-
dispose: () => {},
30-
};
31-
}

src/lib/host/logger.ts

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import * as vscode from 'vscode';
21
import { LogLevel, type ILogger } from '../types';
3-
import { createConsoleLogger } from '../client/useLogger';
2+
import { createConsoleLogger } from '../utils';
3+
import type * as vscode from 'vscode';
44

55
export const disallowedLogKeys = ['password', 'secret', 'token', 'apiKey', 'apiSecret', 'content'];
66

@@ -16,12 +16,10 @@ function removePromptsFromData<T>(dictionary: T | undefined | null): T | undefin
1616
return dictionary;
1717
}
1818

19-
const clone = structuredClone(dictionary) as Record<string, unknown>;
20-
2119
try {
22-
for (const key in clone) {
23-
const value = clone[key];
24-
if (disallowedLogKeys.includes(key)) {
20+
const clone = structuredClone(dictionary) as Record<string, unknown>;
21+
for (const [key, value] of Object.entries(clone)) {
22+
if (disallowedLogKeys.includes(key.toLowerCase())) {
2523
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
2624
delete clone[key];
2725
continue;
@@ -33,12 +31,11 @@ function removePromptsFromData<T>(dictionary: T | undefined | null): T | undefin
3331
clone[key] = removePromptsFromData(value as Record<string, unknown>) as unknown;
3432
}
3533
}
34+
return clone as unknown as T;
3635
} catch (error) {
3736
console.error('Error processing log data:', error);
3837
return {} as T;
3938
}
40-
41-
return clone as unknown as T;
4239
}
4340

4441
/**
@@ -48,7 +45,7 @@ function removePromptsFromData<T>(dictionary: T | undefined | null): T | undefin
4845
class LoggerImpl {
4946
// eslint-disable-next-line sonarjs/public-static-readonly
5047
static outputChannel: vscode.OutputChannel | undefined = undefined;
51-
private static readonly consoleLogger = createConsoleLogger('RVW-IPC');
48+
private static readonly consoleLogger = createConsoleLogger('RVW');
5249

5350
public static debug(message: string, data: Record<string, unknown> | undefined = undefined) {
5451
this.log(LogLevel.DEBUG, message, data);
@@ -68,33 +65,27 @@ class LoggerImpl {
6865

6966
public static dispose() {
7067
this.outputChannel?.dispose();
68+
this.outputChannel = undefined;
7169
}
7270

7371
private static log(level: LogLevel, message: string, data: Record<string, unknown> | undefined) {
7472
const timestamp = new Date().toISOString().split('T')[1];
75-
const levelStr = LogLevel[level] || 'UNKNOWN';
7673
const cleanedData = removePromptsFromData(data);
77-
const line = `[${timestamp}] [${levelStr}] ${message}`;
7874
if (this.outputChannel === undefined) {
79-
switch (level) {
80-
case LogLevel.DEBUG: {
81-
this.consoleLogger.debug(line, cleanedData);
82-
break;
83-
}
84-
case LogLevel.INFO: {
85-
this.consoleLogger.info(line, cleanedData);
86-
break;
87-
}
88-
case LogLevel.WARN: {
89-
this.consoleLogger.warn(line, cleanedData);
90-
break;
91-
}
92-
case LogLevel.ERROR: {
93-
this.consoleLogger.error(line, cleanedData);
94-
break;
75+
const methodName = LogLevel[level].toLowerCase() as
76+
| undefined
77+
| keyof Omit<ILogger, 'dispose'>;
78+
if (methodName !== undefined && typeof this.consoleLogger[methodName] === 'function') {
79+
if (cleanedData === undefined) {
80+
this.consoleLogger[methodName](`[${timestamp}] ${message}`);
81+
} else {
82+
this.consoleLogger[methodName](`[${timestamp}] ${message}`, cleanedData);
9583
}
9684
}
9785
} else {
86+
const levelStr = LogLevel[level] || 'UNKNOWN';
87+
const line = `[${timestamp}] [${levelStr}] ${message}`;
88+
9889
if (cleanedData === undefined) {
9990
this.outputChannel.appendLine(line);
10091
} else {
@@ -108,9 +99,17 @@ class LoggerImpl {
10899
}
109100
}
110101

111-
export const Logger: ILogger & { setOutputChannel: (outputChannel: vscode.OutputChannel) => void } =
102+
export const Logger: ILogger & {
103+
setOutputChannel: (outputChannel: vscode.OutputChannel | undefined) => void;
104+
} =
105+
/**
106+
* Sets the VS Code output channel for the logger.
107+
* The logger takes ownership of the channel and will dispose it
108+
* when `Logger.dispose()` is called or when a new channel is set.
109+
* @param outputChannel The output channel to use for logging.
110+
*/
112111
{
113-
setOutputChannel: (outputChannel: vscode.OutputChannel) => {
112+
setOutputChannel: (outputChannel: vscode.OutputChannel | undefined) => {
114113
LoggerImpl.dispose();
115114
LoggerImpl.outputChannel = outputChannel;
116115
},

src/lib/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
/* eslint-disable no-console */
2+
import type { ILogger } from './types';
3+
14
/**
25
* Generate a unique ID for requests
36
*/
@@ -8,3 +11,16 @@ export function generateId(prefix: string): string {
811
export function getErrorMessage(error: unknown): string {
912
return error instanceof Error ? error.message : String(error);
1013
}
14+
export function createConsoleLogger(tag: string): ILogger {
15+
return {
16+
debug: (message: string, data?: Record<string, unknown>) =>
17+
console.debug(`[${tag}] ${message}`, data),
18+
info: (message: string, data?: Record<string, unknown>) =>
19+
console.info(`[${tag}] ${message}`, data),
20+
warn: (message: string, data?: Record<string, unknown>) =>
21+
console.warn(`[${tag}] ${message}`, data),
22+
error: (message: string, data?: Record<string, unknown>) =>
23+
console.error(`[${tag}] ${message}`, data),
24+
dispose: () => {},
25+
};
26+
}

0 commit comments

Comments
 (0)