@kilnjs/telemetry
v0.1.3
Published
Error reporting for KilnJS: a Sentry reporter core hands its failures to, declared as a module
Downloads
413
Readme
@kilnjs/telemetry
Error reporting for KilnJS, as a module core is given rather than one it contains. Sentry is the backend.
Core raises and describes its failures - it is where the failures are - but
it reaches no telemetry service of its own, and has no @sentry/node in its
dependencies. Where a report goes is the application's to decide.
Install
yarn add @kilnjs/telemetryimport { telemetry } from "@kilnjs/telemetry";
export default {
modules: [telemetry()],
} satisfies AppConfig;Declare it first in modules, so a failure in any of the others is reported
rather than only logged.
Settings
Its own, read where it is declared. Two ways in, and both work: the options
passed to telemetry(), and the environment. What is passed wins, field at a
time, so a build can set the release and leave the DSN in the environment.
| | | |
| --- | --- | --- |
| dsn | SENTRY_DSN | where reports go. Absent reports nowhere |
| release | SENTRY_RELEASE | which build this is. Set by the build |
| environment | NODE_ENV | which deployment this is |
| sampleRate | SENTRY_SAMPLE_RATE | 1 - the fraction of failures sent |
| tracesSampleRate | SENTRY_TRACES_SAMPLE_RATE | absent, so nothing is traced |
| sendDefaultPii | SENTRY_SEND_PII | false - cookies, headers and IPs |
| enableLogs | SENTRY_ENABLE_LOGS | true |
| debug | SENTRY_DEBUG | false - what the client says about itself |
| beforeSend | | the last word on what leaves this process |
| integrations | | added to what this package declares, never instead |
telemetry({
release: "1.4.0",
sampleRate: 0.25,
beforeSend: (event) => (event.user ? { ...event, user: undefined } : event),
});Each is declared to kiln env by this module rather than by core, which has
no idea what a report is. An application without it installed is never asked
for any of them, and one that passes dsn as an option is reported as having
supplied it rather than as missing it.
sendDefaultPii is the one worth reading twice: it decides whether a caller's
own cookies, headers and address leave the process, so it is off until
something says otherwise. beforeSend is where an application drops or
rewrites a field that nothing else should see.
An integrations array is appended to this package's own pino integration
rather than replacing it, because core reports through pino and an integration
list that dropped it would leave every logged failure unreported.
No DSN is a working configuration. Nothing is registered, and core logs what it would have reported - which is what a development machine wants. Outside development the module says so once at boot, because a server that declared it and has no DSN is almost certainly missing one.
Nothing is ever silent
Core's reportTelemetryError logs when no reporter is registered, so a server
that declares this module is choosing a destination, not switching reporting
on. A failure is never lost by leaving the module out:
reportTelemetryError(error) → the reporter, if one is registered
→ the log, if none is (and always in development)A module registers with registerTelemetry, from @kilnjs/core/telemetry.
The last one wins, because a server reports to one place:
registerTelemetry({
error: (error, data) => { ... },
warning: (warning, data) => { ... },
flush: async (timeoutMs) => { ... },
});data is what core assembled: the environment, the error's own context, and
whatever the request could say about itself. Writing another backend is
implementing those three.
It arrives redacted. Core takes the field names that are never worth reporting out of every report before any reporter sees it, at any depth, along with cycles and anything enormous, so a reporter does not have to: a context built out of a parsed body reaches here with its password already gone. The error object itself is handed over as it is, because it is the application's, so a reporter that serialises an error's own properties is the one place a context can still reach a backend whole. This one does not.
What it does not do
Sentry's pino integration forwards logs as well as errors, and that has to be installed before the logger it patches exists. A module is declared by the application, which core reads after its own logger is up, so log forwarding is not part of this. Errors and warnings are reported either way, which is what the seam is for.
flushTelemetry() runs on shutdown, so the report that explains why a process
went away is sent before it does.
Development
yarn verify # ts:check, lint, build, exports:check, testThe tests reach no Sentry project: what they cover is how the settings are read and what the module registers.
