@@ -50,44 +50,96 @@ export const LogId = {
5050 streamableHttpTransportCloseFailure : mongoLogId ( 1_006_006 ) ,
5151} as const ;
5252
53+ interface LogPayload {
54+ id : MongoLogId ;
55+ context : string ;
56+ message : string ;
57+ noRedaction ?: boolean | LoggerType | LoggerType [ ] ;
58+ }
59+
60+ export type LoggerType = "console" | "disk" | "mcp" ;
61+
5362export abstract class LoggerBase {
54- abstract log ( level : LogLevel , id : MongoLogId , context : string , message : string ) : void ;
63+ private defaultUnredactedLogger : LoggerType = "mcp" ;
5564
56- info ( id : MongoLogId , context : string , message : string ) : void {
57- this . log ( "info" , id , context , message ) ;
65+ public log ( level : LogLevel , payload : LogPayload ) : void {
66+ // If no explicit value is supplied for unredacted loggers, default to "mcp"
67+ const noRedaction = payload . noRedaction !== undefined ? payload . noRedaction : this . defaultUnredactedLogger ;
68+
69+ this . logCore ( level , {
70+ ...payload ,
71+ message : this . redactIfNecessary ( payload . message , noRedaction ) ,
72+ } ) ;
5873 }
5974
60- error ( id : MongoLogId , context : string , message : string ) : void {
61- this . log ( "error" , id , context , message ) ;
75+ protected abstract type : LoggerType ;
76+
77+ protected abstract logCore ( level : LogLevel , payload : LogPayload ) : void ;
78+
79+ private redactIfNecessary ( message : string , noRedaction : LogPayload [ "noRedaction" ] ) : string {
80+ if ( typeof noRedaction === "boolean" && noRedaction ) {
81+ // If the consumer has supplied noRedaction: true, we don't redact the log message
82+ // regardless of the logger type
83+ return message ;
84+ }
85+
86+ if ( typeof noRedaction === "string" && noRedaction === this . type ) {
87+ // If the consumer has supplied noRedaction: logger-type, we skip redacting if
88+ // our logger type is the same as what the consumer requested
89+ return message ;
90+ }
91+
92+ if (
93+ typeof noRedaction === "object" &&
94+ Array . isArray ( noRedaction ) &&
95+ this . type !== null &&
96+ noRedaction . indexOf ( this . type ) !== - 1
97+ ) {
98+ // If the consumer has supplied noRedaction: array, we skip redacting if our logger
99+ // type is included in that array
100+ return message ;
101+ }
102+
103+ return redact ( message ) ;
104+ }
105+
106+ info ( payload : LogPayload ) : void {
107+ this . log ( "info" , payload ) ;
62108 }
63- debug ( id : MongoLogId , context : string , message : string ) : void {
64- this . log ( "debug" , id , context , message ) ;
109+
110+ error ( payload : LogPayload ) : void {
111+ this . log ( "error" , payload ) ;
112+ }
113+ debug ( payload : LogPayload ) : void {
114+ this . log ( "debug" , payload ) ;
65115 }
66116
67- notice ( id : MongoLogId , context : string , message : string ) : void {
68- this . log ( "notice" , id , context , message ) ;
117+ notice ( payload : LogPayload ) : void {
118+ this . log ( "notice" , payload ) ;
69119 }
70120
71- warning ( id : MongoLogId , context : string , message : string ) : void {
72- this . log ( "warning" , id , context , message ) ;
121+ warning ( payload : LogPayload ) : void {
122+ this . log ( "warning" , payload ) ;
73123 }
74124
75- critical ( id : MongoLogId , context : string , message : string ) : void {
76- this . log ( "critical" , id , context , message ) ;
125+ critical ( payload : LogPayload ) : void {
126+ this . log ( "critical" , payload ) ;
77127 }
78128
79- alert ( id : MongoLogId , context : string , message : string ) : void {
80- this . log ( "alert" , id , context , message ) ;
129+ alert ( payload : LogPayload ) : void {
130+ this . log ( "alert" , payload ) ;
81131 }
82132
83- emergency ( id : MongoLogId , context : string , message : string ) : void {
84- this . log ( "emergency" , id , context , message ) ;
133+ emergency ( payload : LogPayload ) : void {
134+ this . log ( "emergency" , payload ) ;
85135 }
86136}
87137
88138export class ConsoleLogger extends LoggerBase {
89- log ( level : LogLevel , id : MongoLogId , context : string , message : string ) : void {
90- message = redact ( message ) ;
139+ protected type : LoggerType = "console" ;
140+
141+ protected logCore ( level : LogLevel , payload : LogPayload ) : void {
142+ const { id, context, message } = payload ;
91143 console . error ( `[${ level . toUpperCase ( ) } ] ${ id . __value } - ${ context } : ${ message } (${ process . pid } )` ) ;
92144 }
93145}
@@ -97,6 +149,8 @@ export class DiskLogger extends LoggerBase {
97149 super ( ) ;
98150 }
99151
152+ protected type : LoggerType = "disk" ;
153+
100154 static async fromPath ( logPath : string ) : Promise < DiskLogger > {
101155 await fs . mkdir ( logPath , { recursive : true } ) ;
102156
@@ -116,8 +170,8 @@ export class DiskLogger extends LoggerBase {
116170 return new DiskLogger ( logWriter ) ;
117171 }
118172
119- log ( level : LogLevel , id : MongoLogId , context : string , message : string ) : void {
120- message = redact ( message ) ;
173+ protected logCore ( level : LogLevel , payload : LogPayload ) : void {
174+ const { id , context , message } = payload ;
121175 const mongoDBLevel = this . mapToMongoDBLogLevel ( level ) ;
122176
123177 this . logWriter [ mongoDBLevel ] ( "MONGODB-MCP" , id , context , message ) ;
@@ -149,20 +203,25 @@ export class McpLogger extends LoggerBase {
149203 super ( ) ;
150204 }
151205
152- log ( level : LogLevel , _ : MongoLogId , context : string , message : string ) : void {
206+ type : LoggerType = "mcp" ;
207+
208+ protected logCore ( level : LogLevel , payload : LogPayload ) : void {
153209 // Only log if the server is connected
154210 if ( ! this . server ?. isConnected ( ) ) {
155211 return ;
156212 }
157213
158214 void this . server . server . sendLoggingMessage ( {
159215 level,
160- data : `[${ context } ]: ${ message } ` ,
216+ data : `[${ payload . context } ]: ${ payload . message } ` ,
161217 } ) ;
162218 }
163219}
164220
165- class CompositeLogger extends LoggerBase {
221+ export class CompositeLogger extends LoggerBase {
222+ // This is not a real logger type - it should not be used anyway.
223+ protected type : LoggerType = "composite" as unknown as LoggerType ;
224+
166225 private loggers : LoggerBase [ ] = [ ] ;
167226
168227 constructor ( ...loggers : LoggerBase [ ] ) {
@@ -178,11 +237,16 @@ class CompositeLogger extends LoggerBase {
178237 this . loggers = [ ...loggers ] ;
179238 }
180239
181- log ( level : LogLevel , id : MongoLogId , context : string , message : string ) : void {
240+ public log ( level : LogLevel , payload : LogPayload ) : void {
241+ // Override the public method to avoid the base logger redacting the message payload
182242 for ( const logger of this . loggers ) {
183- logger . log ( level , id , context , message ) ;
243+ logger . log ( level , payload ) ;
184244 }
185245 }
246+
247+ protected logCore ( ) : void {
248+ throw new Error ( "logCore should never be invoked on CompositeLogger" ) ;
249+ }
186250}
187251
188252const logger = new CompositeLogger ( new ConsoleLogger ( ) ) ;
0 commit comments