Last active
August 23, 2023 21:29
-
-
Save borispoehland/1a1a2c5ddbfda85f4e094290d2c2d656 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { FiberId, FiberRefs, HashMap, List } from 'effect' | |
import { Cause, Effect, Logger, pipe } from 'effect' | |
import type { AnnotationValue } from 'effect/Logger' | |
import type { LogLevel } from 'effect/LoggerLevel' | |
import type { LogSpan } from 'effect/LoggerSpan' | |
import pino from 'pino' | |
import type { WithRequired } from '@/types/helpers' | |
const pinoLogger = pino() | |
const defaultLogLevel = 'info' | |
const pinoMappings: Record<LogLevel['_tag'], pino.Level> = { | |
All: defaultLogLevel, | |
Fatal: 'fatal', | |
Error: 'error', | |
Warning: 'warn', | |
Info: defaultLogLevel, | |
Debug: 'debug', | |
Trace: 'trace', | |
None: defaultLogLevel, | |
} | |
interface ILogger { | |
readonly fiberId: FiberId.FiberId | |
readonly logLevel: LogLevel | |
readonly message: unknown | |
readonly cause: Cause.Cause<unknown> | |
readonly context: FiberRefs.FiberRefs | |
readonly spans: List.List<LogSpan> | |
readonly annotations: HashMap.HashMap<string, AnnotationValue> | |
readonly date: Date | |
} | |
interface ICaptureEvent { | |
distinct_id: string | |
event: string | |
properties: object | |
} | |
// sends your log to your logging service, e.g. posthog | |
function capture(event: ICaptureEvent) { | |
return fetch(`${process.env.NEXT_PUBLIC_POSTHOG_HOST}/capture`, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
body: JSON.stringify({ | |
api_key: process.env.NEXT_PUBLIC_POSTHOG_KEY, | |
...event, | |
}), | |
}) | |
} | |
export function directLogger({ | |
logLevel, | |
message, | |
cause, | |
date, | |
}: WithRequired<Partial<ILogger>, 'logLevel' | 'message' | 'cause' | 'date'>) { | |
const level = pinoMappings[logLevel._tag] | |
const isError = level === 'error' | |
const event = isError ? 'Error occured' : `[${logLevel.label}]` | |
const log = { cause, message, date } | |
pinoLogger[level](log, event) | |
if (isError) { | |
return capture({ | |
distinct_id: 'errors', | |
event: event, | |
properties: log, | |
}) | |
} | |
} | |
export const logger = Logger.make(directLogger) | |
const layer = Logger.replace(Logger.defaultLogger, logger) | |
export function getLogger<E, A>(program: Effect.Effect<never, E, A>) { | |
return Effect.provideLayer( | |
pipe( | |
program, | |
Effect.tap((result) => { | |
return Effect.logDebug('Fetch succeeded', result as undefined) | |
}), | |
Effect.tapError((error) => { | |
return Effect.logError('Fetch failed', Cause.fail(error)) | |
}) | |
// Logger.withMinimumLogLevel(LoggerLevel.Debug) | |
), | |
layer | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fetchEffect = Effect.try(() => fetch('https://example.com')) | |
const program = fetchEffect.pipe(getLogger) | |
// executes the fetch, debug logs the success and error logs the failure | |
// error logs are automatically sent to external service, if you wish so | |
await Effect.runPromise(program) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment