Skip to content

Commit

Permalink
use regional approach
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart committed Oct 21, 2024
1 parent 594b304 commit 89b14ee
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 82 deletions.
57 changes: 44 additions & 13 deletions packages/effect/src/Inspectable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* @since 2.0.0
*/

import type { FiberRefs } from "./index.js"
import type * as FiberRefs from "./FiberRefs.js"
import { globalValue } from "./GlobalValue.js"
import { hasProperty, isFunction } from "./Predicate.js"

/**
Expand Down Expand Up @@ -39,7 +40,7 @@ export const toJSON = (x: unknown): unknown => {
} else if (Array.isArray(x)) {
return x.map(toJSON)
}
return x
return redact(x)
}

/**
Expand Down Expand Up @@ -89,14 +90,13 @@ export abstract class Class {
*/
export const toStringUnknown = (
u: unknown,
whitespace: number | string | undefined = 2,
context?: FiberRefs.FiberRefs
whitespace: number | string | undefined = 2
): string => {
if (typeof u === "string") {
return u
}
try {
return typeof u === "object" ? stringifyCircular(u, whitespace, context) : String(u)
return typeof u === "object" ? stringifyCircular(u, whitespace) : String(u)
} catch (_) {
return String(u)
}
Expand All @@ -107,8 +107,7 @@ export const toStringUnknown = (
*/
export const stringifyCircular = (
obj: unknown,
whitespace?: number | string | undefined,
context?: FiberRefs.FiberRefs
whitespace?: number | string | undefined
): string => {
let cache: Array<unknown> = []
const retVal = JSON.stringify(
Expand All @@ -117,8 +116,8 @@ export const stringifyCircular = (
typeof value === "object" && value !== null
? cache.includes(value)
? undefined // circular reference
: cache.push(value) && (context && isRedactable(value)
? value[RedactableId](context)
: cache.push(value) && (redactableState.fiberRefs !== undefined && isRedactable(value)
? value[symbolRedactable](redactableState.fiberRefs)
: value)
: value,
whitespace
Expand All @@ -129,18 +128,50 @@ export const stringifyCircular = (

/**
* @since 3.10.0
* @category redactable
*/
export interface Redactable {
readonly [RedactableId]: (fiberRefs: FiberRefs.FiberRefs) => unknown
readonly [symbolRedactable]: (fiberRefs: FiberRefs.FiberRefs) => unknown
}

/**
* @since 3.10.0
* @category type ids
* @category redactable
*/
export const RedactableId: unique symbol = Symbol.for("effect/Inspectable/Redactable")
export const symbolRedactable: unique symbol = Symbol.for("effect/Inspectable/Redactable")

/**
* @since 3.10.0
* @category redactable
*/
export const isRedactable = (u: unknown): u is Redactable => typeof u === "object" && u !== null && RedactableId in u
export const isRedactable = (u: unknown): u is Redactable =>
typeof u === "object" && u !== null && symbolRedactable in u

const redactableState = globalValue("effect/Inspectable/redactableState", () => ({
fiberRefs: undefined as FiberRefs.FiberRefs | undefined
}))

/**
* @since 3.10.0
* @category redactable
*/
export const withRedactableContext = <A>(context: FiberRefs.FiberRefs, f: () => A): A => {
const prev = redactableState.fiberRefs
redactableState.fiberRefs = context
try {
return f()
} finally {
redactableState.fiberRefs = prev
}
}

/**
* @since 3.10.0
* @category redactable
*/
export const redact = (u: unknown): unknown => {
if (isRedactable(u) && redactableState.fiberRefs !== undefined) {
return u[symbolRedactable](redactableState.fiberRefs)
}
return u
}
24 changes: 11 additions & 13 deletions packages/effect/src/internal/cause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ import * as Chunk from "../Chunk.js"
import * as Either from "../Either.js"
import * as Equal from "../Equal.js"
import type * as FiberId from "../FiberId.js"
import type * as FiberRefs from "../FiberRefs.js"
import { constFalse, constTrue, dual, identity, pipe } from "../Function.js"
import { globalValue } from "../GlobalValue.js"
import * as Hash from "../Hash.js"
import * as HashSet from "../HashSet.js"
import { NodeInspectSymbol, stringifyCircular, toJSON } from "../Inspectable.js"
import { NodeInspectSymbol, toJSON } from "../Inspectable.js"
import * as Option from "../Option.js"
import { pipeArguments } from "../Pipeable.js"
import type { Predicate, Refinement } from "../Predicate.js"
Expand Down Expand Up @@ -973,12 +972,11 @@ export const reduceWithContext = dual<
/** @internal */
export const pretty = <E>(cause: Cause.Cause<E>, options?: {
readonly renderErrorCause?: boolean | undefined
readonly context?: FiberRefs.FiberRefs
}): string => {
if (isInterruptedOnly(cause)) {
return "All fibers interrupted without errors."
}
return prettyErrors<E>(cause, options?.context).map(function(e) {
return prettyErrors<E>(cause).map(function(e) {
if (options?.renderErrorCause !== true || e.cause === undefined) {
return e.stack
}
Expand All @@ -1000,14 +998,14 @@ const renderErrorCause = (cause: PrettyError, prefix: string) => {

class PrettyError extends globalThis.Error implements Cause.PrettyError {
span: undefined | Span = undefined
constructor(originalError: unknown, context?: FiberRefs.FiberRefs) {
constructor(originalError: unknown) {
const originalErrorIsObject = typeof originalError === "object" && originalError !== null
const prevLimit = Error.stackTraceLimit
Error.stackTraceLimit = 1
super(
prettyErrorMessage(originalError, context),
prettyErrorMessage(originalError),
originalErrorIsObject && "cause" in originalError && typeof originalError.cause !== "undefined"
? { cause: new PrettyError(originalError.cause, context) }
? { cause: new PrettyError(originalError.cause) }
: undefined
)
if (this.message === "") {
Expand Down Expand Up @@ -1044,12 +1042,12 @@ class PrettyError extends globalThis.Error implements Cause.PrettyError {
* 1) If the input `u` is already a string, it's considered a message.
* 2) If `u` is an Error instance with a message defined, it uses the message.
* 3) If `u` has a user-defined `toString()` method, it uses that method.
* 4) Otherwise, it uses `Inspectable.stringifyCircular` to produce a string representation and uses it as the error message,
* 4) Otherwise, it uses `JSON.stringify` to produce a string representation and uses it as the error message,
* with "Error" added as a prefix.
*
* @internal
*/
export const prettyErrorMessage = (u: unknown, context?: FiberRefs.FiberRefs): string => {
export const prettyErrorMessage = (u: unknown): string => {
// 1)
if (typeof u === "string") {
return u
Expand All @@ -1072,7 +1070,7 @@ export const prettyErrorMessage = (u: unknown, context?: FiberRefs.FiberRefs): s
// something's off, rollback to json
}
// 4)
return stringifyCircular(u, undefined, context)
return JSON.stringify(u)
}

const locationRegex = /\((.*)\)/
Expand Down Expand Up @@ -1127,14 +1125,14 @@ const prettyErrorStack = (message: string, stack: string, span?: Span | undefine
const spanSymbol = Symbol.for("effect/SpanAnnotation")

/** @internal */
export const prettyErrors = <E>(cause: Cause.Cause<E>, context?: FiberRefs.FiberRefs): Array<PrettyError> =>
export const prettyErrors = <E>(cause: Cause.Cause<E>): Array<PrettyError> =>
reduceWithContext(cause, void 0, {
emptyCase: (): Array<PrettyError> => [],
dieCase: (_, unknownError) => {
return [new PrettyError(unknownError, context)]
return [new PrettyError(unknownError)]
},
failCase: (_, error) => {
return [new PrettyError(error, context)]
return [new PrettyError(error)]
},
interruptCase: () => [],
parallelCase: (_, l, r) => [...l, ...r],
Expand Down
28 changes: 15 additions & 13 deletions packages/effect/src/internal/fiberRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -827,18 +827,20 @@ export class FiberRuntime<in out A, in out E = never> extends Effectable.Class<A
if (HashSet.size(loggers) > 0) {
const clockService = Context.get(this.getFiberRef(defaultServices.currentServices), clock.clockTag)
const date = new Date(clockService.unsafeCurrentTimeMillis())
for (const logger of loggers) {
logger.log({
fiberId: this.id(),
logLevel,
message,
cause,
context: contextMap,
spans,
annotations,
date
})
}
Inspectable.withRedactableContext(contextMap, () => {
for (const logger of loggers) {
logger.log({
fiberId: this.id(),
logLevel,
message,
cause,
context: contextMap,
spans,
annotations,
date
})
}
})
}
}

Expand Down Expand Up @@ -1491,7 +1493,7 @@ export const tracerLogger = globalValue(
attributes["effect.logLevel"] = logLevel.label

if (cause !== null && cause._tag !== "Empty") {
attributes["effect.cause"] = internalCause.pretty(cause, { renderErrorCause: true, context })
attributes["effect.cause"] = internalCause.pretty(cause, { renderErrorCause: true })
}

span.value.event(
Expand Down
Loading

0 comments on commit 89b14ee

Please sign in to comment.