Skip to content

Instantly share code, notes, and snippets.

@borispoehland
Last active August 23, 2023 21:29
Show Gist options
  • Save borispoehland/1a1a2c5ddbfda85f4e094290d2c2d656 to your computer and use it in GitHub Desktop.
Save borispoehland/1a1a2c5ddbfda85f4e094290d2c2d656 to your computer and use it in GitHub Desktop.
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
)
}
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