TypeScript SDK
The TypeScript SDK (@scailabs/scailog) is the Node.js emit side of ScaiLog:
createLogger plus pi() give you GDPR-native structured logging that ships
entries over a Unix socket to the local scailog-agent. It is wire-compatible
with the Python, Go, and .NET SDKs — a TS-emitted entry is encrypted at ingest
and decrypts correctly through DSAR.
Install#
1 | |
The package is distributed as Node ESM with bundled type definitions, and has no runtime dependencies.
Emit a log entry#
Create a logger with your tenant and service, then call a level method with a
call_site_id, a constant message, and an options object. Wrap any
personal-information value in pi():
1 2 3 4 5 6 7 8 9 10 11 12 | |
The call returns the entry's ULID eventId. Plain fields (method) are stored
in cleartext and must stay PI-free; pi() fields are encrypted at ingest and
never enter the plaintext full-text index. Keep variable data in fields, not in
the message.
Log levels#
Six methods with the same signature
level(site, message, opts?), where opts is
{ subject?, fields?, traceId?, requestId? }:
1 2 3 4 5 6 | |
Contract rules#
The SDK enforces the shared ScaiLog contract before an entry leaves the process,
throwing an Error on a violation:
call_site_id(first arg) must match^[A-Z0-9]+(-[A-Z0-9]+){2,}$. TheAUTO-/SCAILOG-prefixes are reserved.pi(value, type)marks a field as personal information; markers attach to fields only, never to the message.- A
pi()field requiressubject— enforced client-side (SUBJECT_REQUIRED) and again at the server. - Reserved field names (
event_id,tenant,msg, …) are rejected.
Context propagation#
withContext() — backed by Node's AsyncLocalStorage — propagates subject,
traceId, and requestId across await boundaries, so request handlers don't
thread them through every call. The logger uses the ambient context as defaults;
explicit options on a call override it, and nested scopes inherit and can
override:
1 2 3 4 5 6 | |
Configuration#
createLogger({ tenant, service, environment?, socketPath? }) constructs a
logger explicitly. environment defaults to prod, and socketPath defaults to
$SCAILOG_SOCKET or /run/scailog/agent.sock.
defaultLogger() builds one from the environment instead, reading
SCAILOG_TENANT (default default), SCAILOG_SERVICE (default unknown),
SCAILOG_ENV (default prod), and SCAILOG_SOCKET.
Flush before exit#
Entries are queued and sent by a background sender as NDJSON over the socket. If the queue is full or the socket is unavailable, the entry is written to stderr in the same NDJSON shape (with PI values redacted) rather than being silently dropped. Before a short-lived process exits, drain the queue:
1 2 | |