@ruizrica/mako-sdk
v0.2.1
Published
Mako monitoring SDK for JavaScript and Node.js — capture errors, structured logs, and breadcrumbs to your self-hosted Mako ingestion API.
Maintainers
Readme
@ruizrica/mako-sdk
Mako monitoring SDK for JavaScript and Node.js — send errors (with stack traces), structured logs, and rich context to your self-hosted Mako ingestion API. Events are batched and delivered over HTTP with retries on transient failures.
Install
npm install @ruizrica/mako-sdkWhat you can do
- Errors —
captureException()parses stack frames (filename, line, column, in-app vsnode_modules) and attaches breadcrumbs, tags, extras, and user. - Messages —
captureMessage()for log-style events with optional level. - HTTP requests —
setupFetchIntegration()patchesfetchandXMLHttpRequestto emit arequestitem per call (method, url, status, duration, size). - Pageviews —
setupRouterIntegration()capturespushState/replaceState/popstateand emits apageviewitem per route change, including the initial load. - Breadcrumbs —
addBreadcrumb()keeps a ring buffer (size configurable) attached to the next error. - Context —
setUser(),setTag(),setExtra()apply to subsequent events until cleared. - Structured logging — named
MakoLoggerinstances (debug/info/warn/error/fatal) sendlogenvelopes with optional structureddata. - Sampling & filtering —
sampleRate(0–1) and optionalbeforeSendhook to drop or rewrite events before they leave the process. - Global handlers — optional browser / Node integrations for uncaught errors and unhandled rejections.
Browser auto-instrumentation
import {
Mako,
setupBrowserIntegration,
setupFetchIntegration,
setupRouterIntegration,
} from '@ruizrica/mako-sdk';
Mako.init({ dsn: '<your DSN>' });
setupBrowserIntegration(); // window.onerror + unhandledrejection
setupFetchIntegration(); // fetch + XHR -> request items
setupRouterIntegration(); // pushState/popstate -> pageview itemsThe fetch integration filters out the SDK's own /api/v1/envelope requests so it never traces itself.
Quick start
import { Mako } from '@ruizrica/mako-sdk';
Mako.init({
dsn: process.env.MAKO_DSN!, // see DSN format below
environment: typeof process !== 'undefined' ? process.env.NODE_ENV : undefined,
release: typeof process !== 'undefined' ? process.env.npm_package_version : undefined,
});Mako is the MakoClient singleton. Call Mako.init({ dsn }) once before Mako.getInstance(), loggers, or integrations.
DSN
The DSN is a URL your Mako project gives you. It encodes the host, public key, and API path. The SDK posts JSON envelopes to /api/v1/envelope on that host with an Authorization header using the DSN scheme and the same DSN string you pass to Mako.init.
Shape (illustrative):
https://<public_key>@<your-mako-host>/api/v1/<project_id>Typical practice:
- Node —
MAKO_DSN(or your own secret name) from environment or secrets manager. - Browser — only use a browser-safe key your server issues for the client; bundle tools often expose
import.meta.env/process.env.NEXT_PUBLIC_*depending on your framework.
Never commit production DSNs to source control.
Configuration (MakoConfig)
| Option | Default | Description |
|--------|---------|-------------|
| dsn | — | Required for Mako.init. Ingestion URL / credential string. |
| environment | '' | e.g. production, staging; sent on events. |
| release | '' | App version or git SHA; sent on events. |
| sampleRate | 1.0 | Random drop for all events before send (0–1). |
| maxBreadcrumbs | 100 | Max breadcrumbs kept in memory. |
| batchSize | 30 | Flush when this many items are queued. |
| flushInterval | 5000 | Periodic flush interval in ms. |
| debug | false | Logs redacted DSN and failed sends to the console. |
| beforeSend | — | (event) => event \| null — return null to drop the event. |
| tracesSampleRate | 0.0 | Present on the type for forward compatibility; not yet applied by the client. |
Browser and Node integrations
After Mako.init, optional helpers register global error handlers:
- Browser —
setupBrowserIntegration()hookswindow.onerrorandunhandledrejection. - Node —
setupNodeIntegration()hooksuncaughtExceptionandunhandledRejection(fatal level for uncaught exceptions).
import { Mako, setupBrowserIntegration } from '@ruizrica/mako-sdk';
Mako.init({ dsn: '…' });
setupBrowserIntegration();import { Mako, setupNodeIntegration } from '@ruizrica/mako-sdk';
Mako.init({ dsn: '…' });
setupNodeIntegration();Remove hooks with teardownBrowserIntegration() / teardownNodeIntegration() when needed.
Manual capture and context
const client = Mako.getInstance();
client.setUser({ id: 'user-123', email: '[email protected]' });
client.setTag('region', 'eu-west');
client.setExtra('checkout_step', 2);
client.addBreadcrumb({
category: 'navigation',
message: 'Opened checkout',
level: 'info',
});
try {
// …
} catch (err) {
client.captureException(err as Error, { step: 'payment' }, 'error');
}
client.captureMessage('Deployment finished', 'info');captureException accepts optional context (merged into event context) and severity (error, fatal, etc.). Each capture returns an event id string.
Structured logging
const client = Mako.getInstance();
const authLog = client.getLogger('auth');
authLog.info('Session started', { sessionId: '…' });
authLog.error('Token refresh failed', { status: 401 });
// Shorthand for the unnamed logger
client.log.warn('Rate limit approaching');Logger output respects sampleRate and beforeSend like other events.
Flush, close, and tests
await client.flush()— send queued items immediately (e.g. before exit in serverless).client.close()— stop the batch timer and dispose the batcher.Mako.resetInstance()— clear the singleton (useful in tests); callclose()on the instance first if it was initialized.
Advanced: lower-level exports
The default client uses HttpTransport + Batcher internally. The package also exports BeaconTransport (unload-friendly sendBeacon / fetch with keepalive) and OfflineQueue / BreadcrumbBuffer if you build a custom pipeline. See dist/index.d.ts after install for signatures.
Requirements
- JavaScript / TypeScript app with
fetchavailable (modern browsers and Node 18+). - A running Mako stack that exposes the envelope ingestion route expected by your DSN.
For TypeScript, import types such as MakoConfig from @ruizrica/mako-sdk or rely on editor hints from dist/index.d.ts.
