You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.5 KiB
131 lines
4.5 KiB
import type {
|
|
Transport,
|
|
ConsoleTransportOptions,
|
|
HttpTransportOptions,
|
|
LogEntry
|
|
} from './types.ts';
|
|
|
|
import { LogLevel } from './types.ts';
|
|
|
|
// ============================================================================
|
|
// CONSOLE TRANSPORT
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Transport que emite los logs a la consola del navegador/Node.
|
|
* Es el transport por defecto si no se especifica ninguno en `LogrOptions`.
|
|
*
|
|
* Usa el método de consola apropiado según el nivel:
|
|
* DEBUG → console.debug, INFO → console.info, WARN → console.warn, ERROR → console.error
|
|
*
|
|
* @example
|
|
* createLogr(i18n, { transports: [consoleTransport()] })
|
|
*
|
|
* @example
|
|
* // Sin timestamp ni prefijo
|
|
* consoleTransport({ timestamp: false, prefix: false })
|
|
*/
|
|
export function consoleTransport(options: ConsoleTransportOptions = {}): Transport {
|
|
const { timestamp: showTimestamp = true, prefix: showPrefix = true } = options;
|
|
|
|
return {
|
|
write(entry: LogEntry, resolvedMessage: string): void {
|
|
const args: unknown[] = [];
|
|
|
|
if (showTimestamp) args.push(entry.timestamp.toISOString());
|
|
if (showPrefix) args.push(`[${entry.category}]`);
|
|
args.push(resolvedMessage);
|
|
|
|
// Solo añade el contexto si existe — evita un '' vacío al final de cada línea
|
|
if (entry.context) args.push(entry.context);
|
|
|
|
switch (entry.level) {
|
|
case LogLevel.DEBUG: console.debug(...args as [unknown, ...unknown[]]); break;
|
|
case LogLevel.INFO: console.info (...args as [unknown, ...unknown[]]); break;
|
|
case LogLevel.WARN: console.warn (...args as [unknown, ...unknown[]]); break;
|
|
case LogLevel.ERROR: console.error(...args as [unknown, ...unknown[]]); break;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// ============================================================================
|
|
// HTTP TRANSPORT
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Transport que envía las entradas de log a un endpoint HTTP remoto via POST.
|
|
* Útil para servicios de logging centralizados (Datadog, Logtail, custom APIs...).
|
|
*
|
|
* El envío es fire-and-forget — los errores de red se loguean en consola
|
|
* pero no interrumpen el flujo de la aplicación.
|
|
*
|
|
* Nota: no incluye retry ni batching. Para alto volumen considera un transport
|
|
* personalizado con cola y reintentos.
|
|
*
|
|
* @example
|
|
* httpTransport({
|
|
* url : 'https://logs.myapp.com/ingest',
|
|
* headers: { 'Authorization': 'Bearer my-token' },
|
|
* level : LogLevel.ERROR
|
|
* })
|
|
*/
|
|
export function httpTransport(options: HttpTransportOptions): Transport {
|
|
// Usa la constante del enum en lugar del magic number 3
|
|
const minLevel = options.level ?? LogLevel.ERROR;
|
|
|
|
return {
|
|
write(entry: LogEntry, resolvedMessage: string): void {
|
|
if (entry.level < minLevel) return;
|
|
|
|
const payload = {
|
|
timestamp: entry.timestamp.toISOString(),
|
|
level : entry.level,
|
|
category : entry.category,
|
|
message : resolvedMessage,
|
|
context : entry.context,
|
|
};
|
|
|
|
// Fire-and-forget — no bloqueamos el hilo principal
|
|
fetch(options.url, {
|
|
method : 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
...options.headers,
|
|
},
|
|
body: JSON.stringify(payload),
|
|
}).catch(err => {
|
|
console.error('[logr:httpTransport] Failed to send log:', err);
|
|
});
|
|
}
|
|
};
|
|
}
|
|
|
|
// ============================================================================
|
|
// CALLBACK TRANSPORT
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Transport que invoca una función callback por cada entrada de log.
|
|
* Es el transport más flexible — ideal para integraciones custom,
|
|
* tests, o cuando necesitas lógica de routing entre destinos.
|
|
*
|
|
* @example
|
|
* // Integración con Sentry
|
|
* callbackTransport((entry, message) => {
|
|
* if (entry.level >= LogLevel.ERROR) {
|
|
* Sentry.captureMessage(message, { extra: entry.context });
|
|
* }
|
|
* })
|
|
*
|
|
* @example
|
|
* // En tests — captura los logs sin output a consola
|
|
* const captured: string[] = [];
|
|
* callbackTransport((_, message) => captured.push(message))
|
|
*/
|
|
export function callbackTransport(
|
|
fn: (entry: LogEntry, resolvedMessage: string) => void
|
|
): Transport {
|
|
return { write: fn };
|
|
}
|