UNPKG

@logtape/sentry

Version:

LogTape Sentry sink

79 lines (75 loc) 2.56 kB
import type { LogRecord, Sink } from "@logtape/logtape"; import { type Client, getClient, type ParameterizedString } from "@sentry/core"; // deno-lint-ignore no-unused-vars import type util from "node:util"; function getParameterizedString(record: LogRecord): ParameterizedString { let result = ""; let tplString = ""; const tplValues: string[] = []; for (let i = 0; i < record.message.length; i++) { if (i % 2 === 0) { result += record.message[i]; tplString += String(record.message[i]).replaceAll("%", "%%"); } else { const value = inspect(record.message[i]); result += value; tplString += `%s`; tplValues.push(value); } } const paramStr = new String(result) as ParameterizedString; paramStr.__sentry_template_string__ = tplString; paramStr.__sentry_template_values__ = tplValues; return result; } /** * A platform-specific inspect function. In Deno, this is {@link Deno.inspect}, * and in Node.js/Bun it is {@link util.inspect}. If neither is available, it * falls back to {@link JSON.stringify}. * * @param value The value to inspect. * @returns The string representation of the value. */ const inspect: (value: unknown) => string = // @ts-ignore: Deno global "Deno" in globalThis && "inspect" in globalThis.Deno && // @ts-ignore: Deno global typeof globalThis.Deno.inspect === "function" // @ts-ignore: Deno global ? globalThis.Deno.inspect // @ts-ignore: Node.js global : "util" in globalThis && "inspect" in globalThis.util && // @ts-ignore: Node.js global globalThis.util.inspect === "function" // @ts-ignore: Node.js global ? globalThis.util.inspect : JSON.stringify; /** * Gets a LogTape sink that sends logs to Sentry. * @param client The Sentry client. If omitted, the global default client is * used. * @returns A LogTape sink that sends logs to Sentry. */ export function getSentrySink(client?: Client): Sink { return (record: LogRecord) => { const message = getParameterizedString(record); if (client == null) client = getClient(); if (record.level === "error" && record.properties.error instanceof Error) { const { error, ...rest } = record.properties; client?.captureException(error, { data: { message, ...rest, }, }); } else { client?.captureMessage( message, record.level === "trace" ? "debug" : record.level, { data: record.properties, }, ); } }; }