@hemia/horus
v0.0.2
Published
SDK de captura de errores para Horus (estilo Sentry, foco NestJS).
Readme
@hemia/horus
SDK de captura de errores para Horus. Atrapa excepciones en Node/NestJS y en el browser y las manda a Horus, que se encarga del resto (fingerprint, agrupación en issues, sanitización de secretos, dedup).
Un solo paquete, tres entradas:
| Import | Para |
|---|---|
| @hemia/horus | núcleo (Node, cualquier backend) |
| @hemia/horus/nestjs | filtro global de NestJS |
| @hemia/horus/browser | instrumenta fetch + traceparent |
Cómo funciona
El SDK es deliberadamente tonto: arma un JSON y lo postea con un header. Toda la inteligencia vive en el server.
captureException(err)
│ POST /api/ingest/event (header: x-horus-key)
▼
Horus server ──► sanitiza ──► fingerprint ──► agrupa en Issue ──► dedup por event_id- No reintenta ni encola. Si la red falla, lo loguea y sigue. Un SDK de telemetría jamás debe tumbar a la app que observa.
- No sanitiza en cliente. El server redacta
authorization,cookie,password,token, etc. No se duplica esa lista. - Corre igual en Node y browser: usa
fetch,cryptoyError.stacknativos. Cero dependencias en runtime.
Instalación
npm install @hemia/horus@nestjs/common y @nestjs/core son peers opcionales: solo hacen falta si usas la
entrada /nestjs.
Uso — NestJS
// main.ts
import * as Horus from "@hemia/horus";
Horus.init({
endpoint: process.env.HORUS_URL!, // https://horus.hemia.dev
key: process.env.HORUS_KEY!, // public_key del proyecto (no es secreto); fija el environment
release: "[email protected]",
});// app.module.ts — registro global; Nest inyecta el HttpAdapter solo
import { Module } from "@nestjs/common";
import { APP_FILTER } from "@nestjs/core";
import { HorusExceptionFilter } from "@hemia/horus/nestjs";
@Module({
providers: [{ provide: APP_FILTER, useClass: HorusExceptionFilter }],
})
export class AppModule {}Con eso, toda excepción no manejada que devuelva 5xx se captura automáticamente. Las 4xx (validación, auth) se ignoran porque no son bugs. Nest responde como siempre.
Uso — Browser (SvelteKit, Vue, etc.)
import * as Horus from "@hemia/horus";
import { instrumentFetch } from "@hemia/horus/browser";
Horus.init({
endpoint: import.meta.env.VITE_HORUS_URL,
key: import.meta.env.VITE_HORUS_KEY,
release: "[email protected]",
});
instrumentFetch(); // cada fetch lleva traceparent; 5xx y fallos de red se auto-capturanCorrelación front + back
instrumentFetch() inyecta un header traceparent (W3C) en cada fetch. El filtro de
NestJS lo lee y lo guarda como trace_id del evento del backend. Si esa request falla,
el browser captura su propio error con el mismo trace_id. En Horus los dos eventos
quedan unidos:
GET /api/traces/<traceparent> → [ evento de medsync-web, evento de medsync-api ]Captura manual
Horus.captureException(err, { tags: { feature: "billing" } });
Horus.captureMessage("pago conciliado fuera de tiempo", "warning");
// contexto que se adjunta a todos los eventos siguientes
Horus.configure({ user: { id: "u_123" }, tags: { region: "mx" } });
user.idse hashea en el server; Horus nunca guarda PII en claro.
API
| Función | Qué hace |
|---|---|
| init(config) | configura y engancha uncaughtException / unhandledRejection |
| captureException(err, ctx?) | reporta un error con su stack |
| captureMessage(msg, level?) | reporta un mensaje sin excepción |
| configure(scope) | fija user / tags para los próximos eventos |
| instrumentFetch(opts?) | (browser) añade traceparent y auto-captura fallos |
| HorusExceptionFilter | (nestjs) filtro global, captura 5xx |
level: fatal · error · warning · info · debug.
Qué NO hace (a propósito)
Reintentos/cola, breadcrumbs, sanitización en cliente, performance/tracing completo, source maps. Se añaden cuando un caso real lo pida, no antes. El server ya cubre fingerprint, agrupación, dedup y scrubbing.
