66import { normalize } from 'path'
77import * as vscode from 'vscode'
88import winston from 'winston'
9- import { BaseLogger , LogLevel , compareLogLevel } from './logger'
9+ import { BaseLogger , LogLevel , LogTopic , compareLogLevel } from './logger'
1010import { OutputChannelTransport } from './outputChannelTransport'
1111import { isSourceMappingAvailable } from '../vscode/env'
1212import { formatError , ToolkitError , UnknownError } from '../errors'
@@ -21,12 +21,26 @@ class ErrorLog {
2121 ) { }
2222}
2323
24+ /* Format the message with topic header */
25+ function prependTopic ( topic : string , message : string | Error ) : string | ErrorLog {
26+ if ( typeof message === 'string' ) {
27+ // TODO: remove this after all calls are migrated and topic is a required param.
28+ if ( topic === 'unknown' ) {
29+ return message
30+ }
31+ return `${ topic } : ` + message
32+ } else if ( message instanceof Error ) {
33+ return new ErrorLog ( topic , message )
34+ }
35+ return message
36+ }
37+
2438// Need to limit how many logs are actually tracked
2539// LRU cache would work well, currently it just dumps the least recently added log
2640const logmapSize : number = 1000
41+
2742export class ToolkitLogger extends BaseLogger implements vscode . Disposable {
2843 private readonly logger : winston . Logger
29- /* topic is used for header in log messages, default is 'Unknown' */
3044 private disposed : boolean = false
3145 private idCounter : number = 0
3246 private logMap : { [ logID : number ] : { [ filePath : string ] : string } } = { }
@@ -111,20 +125,6 @@ export class ToolkitLogger extends BaseLogger implements vscode.Disposable {
111125 } )
112126 }
113127
114- /* Format the message with topic header */
115- private addTopicToMessage ( message : string | Error ) : string | ErrorLog {
116- if ( typeof message === 'string' ) {
117- // TODO: remove this after all calls are migrated and topic is a required param.
118- if ( this . topic === 'unknown' ) {
119- return message
120- }
121- return `${ this . topic } : ` + message
122- } else if ( message instanceof Error ) {
123- return new ErrorLog ( this . topic , message )
124- }
125- return message
126- }
127-
128128 private mapError ( level : LogLevel , err : Error ) : Error | string {
129129 // Use ToolkitError.trace even if we have source mapping (see below), because:
130130 // 1. it is what users will see, we want visibility into that when debugging
@@ -141,17 +141,16 @@ export class ToolkitLogger extends BaseLogger implements vscode.Disposable {
141141 }
142142
143143 override sendToLog ( level : LogLevel , message : string | Error , ...meta : any [ ] ) : number {
144- const messageWithTopic = this . addTopicToMessage ( message )
145144 if ( this . disposed ) {
146145 throw new Error ( 'Cannot write to disposed logger' )
147146 }
148147
149148 meta = meta . map ( ( o ) => ( o instanceof Error ? this . mapError ( level , o ) : o ) )
150149
151- if ( messageWithTopic instanceof ErrorLog ) {
152- this . logger . log ( level , '%O' , messageWithTopic , ...meta , { logID : this . idCounter } )
150+ if ( message instanceof Error ) {
151+ this . logger . log ( level , '%O' , message , ...meta , { logID : this . idCounter } )
153152 } else {
154- this . logger . log ( level , messageWithTopic , ...meta , { logID : this . idCounter } )
153+ this . logger . log ( level , message , ...meta , { logID : this . idCounter } )
155154 }
156155
157156 this . logMap [ this . idCounter % logmapSize ] = { }
@@ -200,3 +199,44 @@ export class ToolkitLogger extends BaseLogger implements vscode.Disposable {
200199 }
201200 }
202201}
202+
203+ /**
204+ * Wraps a `ToolkitLogger` and defers to it for everything except `topic`.
205+ */
206+ export class TopicLogger extends BaseLogger implements vscode . Disposable {
207+ /**
208+ * Wraps a `ToolkitLogger` and defers to it for everything except `topic`.
209+ */
210+ public constructor (
211+ topic : LogTopic ,
212+ private logger : ToolkitLogger
213+ ) {
214+ super ( )
215+ this . topic = topic
216+ }
217+
218+ override setLogLevel ( logLevel : LogLevel ) : void {
219+ this . logger . setLogLevel ( logLevel )
220+ }
221+
222+ override logLevelEnabled ( logLevel : LogLevel ) : boolean {
223+ return this . logger . logLevelEnabled ( logLevel )
224+ }
225+
226+ override getLogById ( logID : number , file : vscode . Uri ) : string | undefined {
227+ return this . logger . getLogById ( logID , file )
228+ }
229+
230+ override enableDebugConsole ( ) : void {
231+ this . logger . enableDebugConsole ( )
232+ }
233+
234+ override sendToLog ( level : LogLevel , message : string | Error , ...meta : any [ ] ) : number {
235+ if ( typeof message === 'string' ) {
236+ message = prependTopic ( this . topic , message ) as string
237+ }
238+ return this . logger . sendToLog ( level , message , meta )
239+ }
240+
241+ public async dispose ( ) : Promise < void > { }
242+ }
0 commit comments