BetterstackExceptionLogger is the Logger component’s Better Stack error-tracking backend. It wraps the official @sentry/node SDK to capture exceptions — with tags, contexts, breadcrumbs, and extra data — and ship them, along with structured logs, to Better Stack’s Sentry-compatible ingest. It implements the framework’s ILogger interface, so call sites stay provider-agnostic and you can swap the backend without touching the code that emits errors.
Why Better Stack Exceptions
- Rich exception capture. Errors are sent through Sentry with tags, contexts, and breadcrumbs for full debugging detail.
- Exception-aware
error(). Pass anIExceptionand its name, status, date, and structured stack trace are attached automatically. - Structured logs too.
warn,info,debug,log, andsuccessship as Sentry logs alongside your exceptions. - Sentry-compatible ingest. Reuses the Sentry SDK against Better Stack’s DSN, so existing Sentry tooling applies.
- Buffered delivery.
flush()drains pending events before the process exits. - Container-managed. Registered with
@decorator.logger()and resolved from the container.
Installation
BetterstackExceptionLogger ships with @ooneex/logger and depends on the Sentry Node SDK.
Environment variables
| Variable | Required | Purpose |
|---|---|---|
BETTERSTACK_EXCEPTION_LOGGER_APPLICATION_TOKEN | Yes | Better Stack application token used in the Sentry DSN. Missing throws LoggerException (TOKEN_REQUIRED). |
BETTERSTACK_EXCEPTION_LOGGER_INGESTING_HOST | Yes | Better Stack ingesting host used in the DSN. Missing throws LoggerException (EXCEPTION_LOG_FAILED). |
BetterstackExceptionLogger is constructed, so misconfiguration fails fast at startup.
How it works
On construction, the backend callsSentry.init() with a DSN assembled from your application token and ingesting host, enabling logs and full trace sampling. error() opens a Sentry scope: a string message is captured as an Error with a breadcrumb (and your data as extras), while an IException is captured with exception.name/exception.status tags, an exception context (name, status, date, stack), a breadcrumb, and your data as extras. The remaining levels ship as Sentry logs — warn, info, and debug map directly, and log/success use info with a level field (LOG / SUCCESS). Delivery is buffered; flush() waits up to two seconds to drain it.
| Method | Purpose |
|---|---|
init() | No-op; the SDK is initialized in the constructor. |
error(message, data?) | Capture an exception. message may be a string or IException. |
warn(message, data?) | Ship a warning log. |
info(message, data?) | Ship an informational log. |
debug(message, data?) | Ship a debug log. |
log(message, data?) | Ship a general log (sent as info with level: "LOG"). |
success(message, data?) | Ship a success log (sent as info with level: "SUCCESS"). |
flush() | Drain pending events (up to 2s). |
Usage
error() accepts a plain message or an IException — when given an exception it attaches the name, status, date, and structured stack trace:
Use in the app
In an@ooneex/app application, register BetterstackExceptionLogger on the onException slot of your App config. Unlike the general loggers array, onException of AppConfigType is typed as a single LoggerClassType and is the dedicated slot for the backend that handles uncaught exceptions — the framework registers it with the container and routes exceptions to it at startup.
loggers handles your normal application logs while onException sends uncaught exceptions to Better Stack — the two slots are independent, so you can keep terminal output in development and still capture exceptions remotely.
Set BETTERSTACK_EXCEPTION_LOGGER_APPLICATION_TOKEN and BETTERSTACK_EXCEPTION_LOGGER_INGESTING_HOST in your .env.yml (or environment) so the SDK can initialize. You can also inject the logger directly to capture handled errors inside your domain logic:
Exceptions
BetterstackExceptionLogger throws LoggerException on misconfiguration, carrying a machine-readable key.
| Key | When |
|---|---|
TOKEN_REQUIRED | Constructed without BETTERSTACK_EXCEPTION_LOGGER_APPLICATION_TOKEN. |
EXCEPTION_LOG_FAILED | Constructed without BETTERSTACK_EXCEPTION_LOGGER_INGESTING_HOST. |
Best practices
- Call
flush()on exit. Delivery is buffered; drain it before the process terminates so you don’t drop the last events. - Log exceptions as exceptions. Pass the
IExceptiontoerror()so its name, status, date, and stack trace are captured as Sentry context. - Attach context via
data. Pass identifiers (order id, user id) asdataso they land as Sentry extras for debugging. - Keep the token and host in the environment. Load both from
.env; never hard-code them. - Use it for error tracking. For general structured log shipping, pair it with Better Stack Logger.