Skip to content

Commit ca14f5e

Browse files
committed
Fix logging on V8
1 parent 2940224 commit ca14f5e

File tree

1 file changed

+172
-19
lines changed

1 file changed

+172
-19
lines changed

src/logging.ts

Lines changed: 172 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,118 @@ interface LoggerOptions {
1616

1717
const DEFAULT_LOGGER_NAME = 'mcp-use'
1818

19+
// Environment detection function (similar to telemetry)
20+
function isNodeJSEnvironment(): boolean {
21+
try {
22+
// Check for Cloudflare Workers specifically
23+
if (typeof navigator !== 'undefined' && navigator.userAgent?.includes('Cloudflare-Workers')) {
24+
return false
25+
}
26+
27+
// Check for other edge runtime indicators
28+
if (typeof (globalThis as any).EdgeRuntime !== 'undefined' || typeof (globalThis as any).Deno !== 'undefined') {
29+
return false
30+
}
31+
32+
// Check for Node.js specific globals that are not available in edge environments
33+
const hasNodeGlobals = (
34+
typeof process !== 'undefined'
35+
&& typeof process.platform !== 'undefined'
36+
&& typeof __dirname !== 'undefined'
37+
)
38+
39+
// Check for Node.js modules
40+
const hasNodeModules = (
41+
typeof fs !== 'undefined'
42+
&& typeof createLogger === 'function'
43+
)
44+
45+
return hasNodeGlobals && hasNodeModules
46+
}
47+
catch {
48+
return false
49+
}
50+
}
51+
52+
// Simple console logger for non-Node.js environments
53+
class SimpleConsoleLogger {
54+
private _level: LogLevel
55+
private name: string
56+
57+
constructor(name: string = DEFAULT_LOGGER_NAME, level: LogLevel = 'info') {
58+
this.name = name
59+
this._level = level
60+
}
61+
62+
private shouldLog(level: LogLevel): boolean {
63+
const levels = ['error', 'warn', 'info', 'http', 'verbose', 'debug', 'silly']
64+
const currentIndex = levels.indexOf(this._level)
65+
const messageIndex = levels.indexOf(level)
66+
return messageIndex <= currentIndex
67+
}
68+
69+
private formatMessage(level: LogLevel, message: string): string {
70+
const timestamp = new Date().toLocaleTimeString('en-US', { hour12: false })
71+
return `${timestamp} [${this.name}] ${level}: ${message}`
72+
}
73+
74+
error(message: string): void {
75+
if (this.shouldLog('error')) {
76+
console.error(this.formatMessage('error', message))
77+
}
78+
}
79+
80+
warn(message: string): void {
81+
if (this.shouldLog('warn')) {
82+
console.warn(this.formatMessage('warn', message))
83+
}
84+
}
85+
86+
info(message: string): void {
87+
if (this.shouldLog('info')) {
88+
console.info(this.formatMessage('info', message)) // eslint-disable-line no-console
89+
}
90+
}
91+
92+
debug(message: string): void {
93+
if (this.shouldLog('debug')) {
94+
console.debug(this.formatMessage('debug', message)) // eslint-disable-line no-console
95+
}
96+
}
97+
98+
http(message: string): void {
99+
if (this.shouldLog('http')) {
100+
console.log(this.formatMessage('http', message)) // eslint-disable-line no-console
101+
}
102+
}
103+
104+
verbose(message: string): void {
105+
if (this.shouldLog('verbose')) {
106+
console.log(this.formatMessage('verbose', message)) // eslint-disable-line no-console
107+
}
108+
}
109+
110+
silly(message: string): void {
111+
if (this.shouldLog('silly')) {
112+
console.log(this.formatMessage('silly', message)) // eslint-disable-line no-console
113+
}
114+
}
115+
116+
// Make it compatible with Winston interface
117+
get level(): LogLevel {
118+
return this._level
119+
}
120+
121+
set level(newLevel: LogLevel) {
122+
this._level = newLevel
123+
}
124+
}
125+
19126
function resolveLevel(env: string | undefined): LogLevel {
20-
switch (env?.trim()) {
127+
// Safely access environment variables
128+
const envValue = (typeof process !== 'undefined' && process.env) ? env : undefined
129+
130+
switch (envValue?.trim()) {
21131
case '2':
22132
return 'debug'
23133
case '1':
@@ -40,10 +150,21 @@ const emojiFormatter = printf(({ level, message, label, timestamp }) => {
40150
})
41151

42152
export class Logger {
43-
private static instances: Record<string, WinstonLogger> = {}
153+
private static instances: Record<string, WinstonLogger | SimpleConsoleLogger> = {}
154+
private static simpleInstances: Record<string, SimpleConsoleLogger> = {}
44155
private static currentFormat: 'minimal' | 'detailed' | 'emoji' = 'minimal'
45156

46-
public static get(name: string = DEFAULT_LOGGER_NAME): WinstonLogger {
157+
public static get(name: string = DEFAULT_LOGGER_NAME): WinstonLogger | SimpleConsoleLogger {
158+
// Use simple console logger in non-Node.js environments
159+
if (!isNodeJSEnvironment()) {
160+
if (!this.simpleInstances[name]) {
161+
const debugEnv = (typeof process !== 'undefined' && process.env?.DEBUG) || undefined
162+
this.simpleInstances[name] = new SimpleConsoleLogger(name, resolveLevel(debugEnv))
163+
}
164+
return this.simpleInstances[name]
165+
}
166+
167+
// Use Winston logger in Node.js environments
47168
if (!this.instances[name]) {
48169
this.instances[name] = createLogger({
49170
level: resolveLevel(process.env.DEBUG),
@@ -76,37 +197,50 @@ export class Logger {
76197

77198
public static configure(options: LoggerOptions = {}): void {
78199
const { level, console = true, file, format = 'minimal' } = options
79-
const resolvedLevel = level ?? resolveLevel(process.env.DEBUG)
200+
const debugEnv = (typeof process !== 'undefined' && process.env?.DEBUG) || undefined
201+
const resolvedLevel = level ?? resolveLevel(debugEnv)
80202

81203
this.currentFormat = format
82204
const root = this.get()
83205

84206
root.level = resolvedLevel
85207

86-
root.clear()
208+
// For non-Node.js environments, just update the level
209+
if (!isNodeJSEnvironment()) {
210+
Object.values(this.simpleInstances).forEach((logger) => {
211+
logger.level = resolvedLevel
212+
})
213+
return
214+
}
215+
216+
// Winston-specific configuration for Node.js environments
217+
const winstonRoot = root as WinstonLogger
218+
winstonRoot.clear()
87219

88220
if (console) {
89-
root.add(new transports.Console())
221+
winstonRoot.add(new transports.Console())
90222
}
91223

92224
if (file) {
93225
const dir = path.dirname(path.resolve(file))
94226
if (!fs.existsSync(dir)) {
95227
fs.mkdirSync(dir, { recursive: true })
96228
}
97-
root.add(new transports.File({ filename: file }))
229+
winstonRoot.add(new transports.File({ filename: file }))
98230
}
99231

100-
// Update all existing loggers with new format
232+
// Update all existing Winston loggers with new format
101233
Object.values(this.instances).forEach((logger) => {
102-
logger.level = resolvedLevel
103-
logger.format = combine(
104-
colorize(),
105-
splat(),
106-
label({ label: DEFAULT_LOGGER_NAME }),
107-
timestamp({ format: 'HH:mm:ss' }),
108-
this.getFormatter(),
109-
)
234+
if (logger && 'format' in logger) {
235+
logger.level = resolvedLevel
236+
;(logger as WinstonLogger).format = combine(
237+
colorize(),
238+
splat(),
239+
label({ label: DEFAULT_LOGGER_NAME }),
240+
timestamp({ format: 'HH:mm:ss' }),
241+
this.getFormatter(),
242+
)
243+
}
110244
})
111245
}
112246

@@ -118,10 +252,21 @@ export class Logger {
118252
level = 'info'
119253
else level = 'info'
120254

121-
Object.values(this.instances).forEach((logger) => {
255+
// Update both simple and Winston loggers
256+
Object.values(this.simpleInstances).forEach((logger) => {
122257
logger.level = level
123258
})
124-
process.env.DEBUG = enabled ? (enabled === true ? '2' : String(enabled)) : '0'
259+
260+
Object.values(this.instances).forEach((logger) => {
261+
if (logger) {
262+
logger.level = level
263+
}
264+
})
265+
266+
// Safely set environment variable
267+
if (typeof process !== 'undefined' && process.env) {
268+
process.env.DEBUG = enabled ? (enabled === true ? '2' : String(enabled)) : '0'
269+
}
125270
}
126271

127272
public static setFormat(format: 'minimal' | 'detailed' | 'emoji'): void {
@@ -130,5 +275,13 @@ export class Logger {
130275
}
131276
}
132277

133-
Logger.configure()
278+
// Only configure Winston features if in Node.js environment
279+
if (isNodeJSEnvironment()) {
280+
Logger.configure()
281+
}
282+
else {
283+
// For non-Node.js environments, just initialize with defaults
284+
Logger.configure({ console: true })
285+
}
286+
134287
export const logger = Logger.get()

0 commit comments

Comments
 (0)