Custom Logger
Most of the time I don't care about timestamps and fibers from Effect's Logger, so I am using my own custom logger. Don't worry about how to construct custom loggers. This will only display the log level in square brackets and the message, appending additional logs like the LogSpan with a semicolon.
// constructing the custom logger
export const logger = Logger.make(({ logLevel, message, spans, date }) => {
const nowMillis = date.getTime();
const stringMessage = serializeUnknown(message);
let output = `[${logLevel.label}] `;
if (stringMessage.length > 0) {
output = output + stringMessage;
}
if (List.isCons(spans)) {
output = output + '; ';
let first = true;
for (const span of spans) {
if (first) {
first = false;
} else {
output = output + ' ';
}
output = output + pipe(span, LogSpan.render(nowMillis));
}
}
globalThis.console.log(output);
});
// helper function to serialize unknown types
export const serializeUnknown = (u: unknown): string => {
try {
return typeof u === 'object' ? JSON.stringify(u) : String(u);
} catch (_) {
return String(u);
}
};
// main program to be executed
const program = Effect.gen(function* (_) {
yield* _(Effect.log('Hello World!'));
});
// constructing a layer where the default logger is replaced with the custom logger
// layer<never, never, never>
const layer = Logger.replace(Logger.defaultLogger, logger);
// we can provide layers to effects - the layer (i.e. context) is now provided to the program
const programWithCustomLogger = program.pipe(Effect.provide(layer));
// execute the program
Effect.runSync(programWithCustomLogger);