diff --git a/.changeset/workerd-logger-fix.md b/.changeset/workerd-logger-fix.md new file mode 100644 index 00000000000..fcfe8519571 --- /dev/null +++ b/.changeset/workerd-logger-fix.md @@ -0,0 +1,14 @@ +--- +"effect": patch +--- + +fix(Logger): Support Cloudflare Workers by treating workerd as TTY environment + +Fixes missing log messages in Cloudflare Workers where console.group methods are no-ops. + +The pretty logger now: +- Detects workerd runtime using `navigator.userAgent === 'Cloudflare-Workers'` +- Routes workerd to TTY logger mode instead of browser mode +- Disables console.group calls in workerd (similar to existing Bun handling) + +This ensures all log messages display correctly in Cloudflare Workers local development. \ No newline at end of file diff --git a/packages/effect/src/internal/logger.ts b/packages/effect/src/internal/logger.ts index 124b5e98f0f..811f1f79c73 100644 --- a/packages/effect/src/internal/logger.ts +++ b/packages/effect/src/internal/logger.ts @@ -332,7 +332,9 @@ const hasProcessStdout = typeof process === "object" && process.stdout !== null const processStdoutIsTTY = hasProcessStdout && process.stdout.isTTY === true +const isWorkerd = typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers" const hasProcessStdoutOrDeno = hasProcessStdout || "Deno" in globalThis +const shouldUseTTYMode = hasProcessStdoutOrDeno || isWorkerd /** @internal */ export const prettyLogger = (options?: { @@ -342,7 +344,7 @@ export const prettyLogger = (options?: { readonly mode?: "browser" | "tty" | "auto" | undefined }) => { const mode_ = options?.mode ?? "auto" - const mode = mode_ === "auto" ? (hasProcessStdoutOrDeno ? "tty" : "browser") : mode_ + const mode = mode_ === "auto" ? (shouldUseTTYMode ? "tty" : "browser") : mode_ const isBrowser = mode === "browser" const showColors = typeof options?.colors === "boolean" ? options.colors : processStdoutIsTTY || isBrowser const formatDate = options?.formatDate ?? defaultDateFormat @@ -357,6 +359,7 @@ const prettyLoggerTty = (options: { readonly formatDate: (date: Date) => string }) => { const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true + const supportsConsoleGroup = !processIsBun && !isWorkerd const color = options.colors ? withColor : withColorNoop return makeLogger( ({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => { @@ -389,7 +392,7 @@ const prettyLoggerTty = (options: { } log(firstLine) - if (!processIsBun) console.group() + if (supportsConsoleGroup) console.group() if (!Cause.isEmpty(cause)) { log(Cause.pretty(cause, { renderErrorCause: true })) @@ -407,7 +410,7 @@ const prettyLoggerTty = (options: { } } - if (!processIsBun) console.groupEnd() + if (supportsConsoleGroup) console.groupEnd() } ) }