Skip to content

Commit

Permalink
improve safari support for Logger.pretty (#3235)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Jul 11, 2024
1 parent cb9f8a1 commit 6684b4c
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/moody-beers-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

improve safari support for Logger.pretty
5 changes: 5 additions & 0 deletions .changeset/stupid-readers-retire.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

fix span stack rendering when stack function returns undefined
5 changes: 5 additions & 0 deletions .changeset/ten-points-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

align UnsafeConsole group types with web apis
4 changes: 2 additions & 2 deletions packages/effect/src/Console.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ export interface UnsafeConsole {
dir(item: any, options?: any): void
dirxml(...args: ReadonlyArray<any>): void
error(...args: ReadonlyArray<any>): void
group(label?: string | undefined): void
groupCollapsed(label?: string | undefined): void
group(...args: ReadonlyArray<any>): void
groupCollapsed(...args: ReadonlyArray<any>): void
groupEnd(): void
info(...args: ReadonlyArray<any>): void
log(...args: ReadonlyArray<any>): void
Expand Down
10 changes: 7 additions & 3 deletions packages/effect/src/internal/cause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1100,9 +1100,13 @@ const prettyErrorStack = (message: string, stack: string, span?: Span | undefine
const stackFn = spanToTrace.get(current)
if (typeof stackFn === "function") {
const stack = stackFn()
const locationMatch = stack.match(locationRegex)
const location = locationMatch ? locationMatch[1] : stack.replace(/^at /, "")
out.push(` at ${current.name} (${location})`)
if (typeof stack === "string") {
const locationMatch = stack.match(locationRegex)
const location = locationMatch ? locationMatch[1] : stack.replace(/^at /, "")
out.push(` at ${current.name} (${location})`)
} else {
out.push(` at ${current.name}`)
}
} else {
out.push(` at ${current.name}`)
}
Expand Down
114 changes: 98 additions & 16 deletions packages/effect/src/internal/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,15 +400,25 @@ const logLevelColors: Record<LogLevel.LogLevel["_tag"], ReadonlyArray<string>> =
Error: [colors.red],
Fatal: [colors.bgBrightRed, colors.black]
}
const logLevelStyle: Record<LogLevel.LogLevel["_tag"], string> = {
None: "",
All: "",
Trace: "color:gray",
Debug: "color:blue",
Info: "color:green",
Warning: "color:orange",
Error: "color:red",
Fatal: "background-color:red;color:white"
}

const defaultDateFormat = (date: Date): string =>
`${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${
date.getSeconds().toString().padStart(2, "0")
}.${date.getMilliseconds().toString().padStart(3, "0")}`

const processStdoutIsTTY = typeof process === "object" && "stdout" in process && process.stdout.isTTY === true
const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true
const hasWindow = typeof window === "object"
const isWorker = typeof self === "object" && self.constructor && self.constructor.name.includes("Worker")

/** @internal */
export const prettyLogger = (options?: {
Expand All @@ -418,21 +428,31 @@ export const prettyLogger = (options?: {
readonly mode?: "browser" | "tty" | "auto" | undefined
}) => {
const mode_ = options?.mode ?? "auto"
const mode = mode_ === "auto" ? (hasWindow ? "browser" : "tty") : mode_
const mode = mode_ === "auto" ? (hasWindow || isWorker ? "browser" : "tty") : mode_
const isBrowser = mode === "browser"
const showColors = typeof options?.colors === "boolean" ? options.colors : processStdoutIsTTY || isBrowser
const color = showColors ? withColor : withColorNoop
const formatDate = options?.formatDate ?? defaultDateFormat
return isBrowser
? prettyLoggerBrowser({ colors: showColors, formatDate })
: prettyLoggerTty({ colors: showColors, formatDate, stderr: options?.stderr === true })
}

const prettyLoggerTty = (options: {
readonly colors: boolean
readonly stderr: boolean
readonly formatDate: (date: Date) => string
}) => {
const processIsBun = typeof process === "object" && "isBun" in process && process.isBun === true
const color = options.colors && processStdoutIsTTY ? withColor : withColorNoop
return makeLogger<unknown, void>(
({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => {
const services = FiberRefs.getOrDefault(context, defaultServices.currentServices)
const console = Context.get(services, consoleTag).unsafe
const log = options?.stderr === true ? console.error : console.log
const log = options.stderr === true ? console.error : console.log

const message = Arr.ensure(message_)

let firstLine = color(`[${formatDate(date)}]`, colors.white)
let firstLine = color(`[${options.formatDate(date)}]`, colors.white)
+ ` ${color(logLevel.label, ...logLevelColors[logLevel._tag])}`
+ ` (${_fiberId.threadName(fiberId)})`

Expand All @@ -454,18 +474,11 @@ export const prettyLogger = (options?: {
}
}

if (isBrowser) {
console.groupCollapsed(firstLine)
} else {
log(firstLine)
if (!processIsBun) console.group()
}
log(firstLine)
if (!processIsBun) console.group()

if (!Cause.isEmpty(cause)) {
if (isBrowser) {
console.error(Cause.pretty(cause, { renderErrorCause: true }))
} else {
log(Cause.pretty(cause, { renderErrorCause: true }))
}
log(Cause.pretty(cause, { renderErrorCause: true }))
}

if (messageIndex < message.length) {
Expand All @@ -484,3 +497,72 @@ export const prettyLogger = (options?: {
}
)
}

const prettyLoggerBrowser = (options: {
readonly colors: boolean
readonly formatDate: (date: Date) => string
}) => {
const color = options.colors ? "%c" : ""
return makeLogger<unknown, void>(
({ annotations, cause, context, date, fiberId, logLevel, message: message_, spans }) => {
const services = FiberRefs.getOrDefault(context, defaultServices.currentServices)
const console = Context.get(services, consoleTag).unsafe
const message = Arr.ensure(message_)

let firstLine = `${color}[${options.formatDate(date)}]`
const firstParams = []
if (options.colors) {
firstParams.push("color:gray")
}
firstLine += ` ${color}${logLevel.label}${color} (${_fiberId.threadName(fiberId)})`
if (options.colors) {
firstParams.push(logLevelStyle[logLevel._tag], "")
}
if (List.isCons(spans)) {
const now = date.getTime()
const render = renderLogSpanLogfmt(now)
for (const span of spans) {
firstLine += " " + render(span)
}
}

firstLine += ":"

let messageIndex = 0
if (message.length > 0) {
const firstMaybeString = structuredMessage(message[0])
if (typeof firstMaybeString === "string") {
firstLine += ` ${color}${firstMaybeString}`
if (options.colors) {
firstParams.push("color:blue")
}
messageIndex++
}
}

console.groupCollapsed(firstLine, ...firstParams)

if (!Cause.isEmpty(cause)) {
console.error(Cause.pretty(cause, { renderErrorCause: true }))
}

if (messageIndex < message.length) {
for (; messageIndex < message.length; messageIndex++) {
console.log(message[messageIndex])
}
}

if (HashMap.size(annotations) > 0) {
for (const [key, value] of annotations) {
if (options.colors) {
console.log(`%c${key}:`, "color:gray", value)
} else {
console.log(`${key}:`, value)
}
}
}

console.groupEnd()
}
)
}

0 comments on commit 6684b4c

Please sign in to comment.