@@ -9,6 +9,7 @@ export class MultiTransportLogger implements LogOutputChannel {
99 private readonly _logger : WinstonLogger ;
1010 private readonly _logFileBaseName : string ;
1111 private readonly _logFileStorageUri : Uri ;
12+ private _currentBlockLevel : string | undefined ;
1213
1314 readonly logLevel : LogLevel ;
1415 readonly onDidChangeLogLevel : Event < LogLevel > ;
@@ -35,7 +36,11 @@ export class MultiTransportLogger implements LogOutputChannel {
3536 } ) ;
3637
3738 this . _logger = createLogger ( {
38- level : 'debug' , // Default level
39+ // Use the transport's own level set so 'trace' is a recognised level name
40+ // and maps correctly to outputChannel.trace() instead of falling through
41+ // to appendLine() in the default case.
42+ levels : LogOutputChannelTransport . config . levels ,
43+ level : MultiTransportLogger . toWinstonLevel ( this . _outputChannel . logLevel ) ,
3944 format : format . combine (
4045 format . timestamp ( { format : 'YYYY-MM-DD HH:mm:ss' } ) ,
4146 format . errors ( { stack : true } ) ,
@@ -49,6 +54,26 @@ export class MultiTransportLogger implements LogOutputChannel {
4954 this . _dailyFileTransport ,
5055 ] ,
5156 } ) ;
57+
58+ this . _outputChannel . onDidChangeLogLevel ( level => {
59+ if ( level === LogLevel . Off ) {
60+ this . _logger . silent = true ;
61+ } else {
62+ this . _logger . silent = false ;
63+ this . _logger . level = MultiTransportLogger . toWinstonLevel ( level ) ;
64+ }
65+ } ) ;
66+ }
67+
68+ private static toWinstonLevel ( level : LogLevel ) : string {
69+ switch ( level ) {
70+ case LogLevel . Trace : return 'trace' ;
71+ case LogLevel . Debug : return 'debug' ;
72+ case LogLevel . Info : return 'info' ;
73+ case LogLevel . Warning : return 'warn' ;
74+ case LogLevel . Error : return 'error' ;
75+ default : return 'info' ;
76+ }
5277 }
5378
5479 getOuptutChannelName ( ) : string {
@@ -86,8 +111,44 @@ export class MultiTransportLogger implements LogOutputChannel {
86111 appendLine ( value : string ) : void {
87112 const lines = value . split ( '\n' ) ;
88113
114+ // Logback server stderr pattern:
115+ // %-4relative [%thread] %-5level %logger{35} %msg %n
116+ // e.g. "1234 [main] WARN org.opencds.SomeClass Some message"
117+ const logbackPattern = / ^ \d + \s + \[ \S + \] \s + ( T R A C E | D E B U G | I N F O | W A R N | E R R O R ) \s + / i;
118+
119+ // vscode-languageclient LSP trace pattern: "[Trace - HH:MM:SS AM] ..."
120+ // The header and its params body arrive in separate appendLine() calls, so
121+ // _currentBlockLevel persists the detected level across calls.
122+ const lspTracePattern = / ^ \[ ( T r a c e | D e b u g | I n f o | W a r n | E r r o r ) \s + - \s + / i;
123+
124+ // If this call starts with an LSP trace header, update the persisted level.
125+ for ( const line of lines ) {
126+ if ( ! line . trim ( ) ) continue ;
127+ const m = lspTracePattern . exec ( line ) ;
128+ if ( m ) this . _currentBlockLevel = m [ 1 ] . toUpperCase ( ) ;
129+ break ;
130+ }
131+
132+ const logAtLevel = ( level : string | undefined , line : string ) => {
133+ switch ( level ) {
134+ case 'TRACE' : this . _logger . log ( 'trace' , line ) ; break ;
135+ case 'DEBUG' : this . _logger . debug ( line ) ; break ;
136+ case 'WARN' : this . _logger . warn ( line ) ; break ;
137+ case 'ERROR' : this . _logger . error ( line ) ; break ;
138+ default : this . _logger . info ( line ) ; break ;
139+ }
140+ } ;
141+
89142 lines . forEach ( line => {
90- if ( line ) this . _logger . info ( line ) ;
143+ if ( ! line ) return ;
144+ const logbackMatch = logbackPattern . exec ( line ) ;
145+ if ( logbackMatch ) {
146+ // Server log lines carry their own level — use it directly.
147+ logAtLevel ( logbackMatch [ 1 ] . toUpperCase ( ) , line ) ;
148+ } else {
149+ // LSP trace lines (header + continuation) use the persisted block level.
150+ logAtLevel ( this . _currentBlockLevel , line ) ;
151+ }
91152 } ) ;
92153 }
93154
0 commit comments