@datares/logger
v0.1.0
Published
Official Node.js SDK for Datares Logger — structured log ingestion.
Maintainers
Readme
Datares Logger Node.js SDK
Official Node.js / TypeScript SDK for Datares Logger — structured log ingestion by Datares.
Requirements: Node.js 18+ (native fetch required)
Installation
npm install @datares/loggerQuick Start
import { Logger } from '@datares/logger';
const log = new Logger('dtr_live_...');
log.info('User logged in', 'auth', { user_id: 42 });
log.error('Payment failed', 'billing', { order_id: 99 });
log.warning('Disk space low', 'storage', { free_gb: 2 });
// Logs are buffered automatically and flushed when the process exits.
// Call log.flush() to flush immediately.Log Levels
| Method | Level |
|---|---|
| log.debug() | debug |
| log.info() | info |
| log.warning() | warning |
| log.error() | error |
| log.critical() | critical |
All convenience methods share the same signature:
log.info(message: string, service?: string, meta?: Record<string, unknown>): voidConfiguration
Pass a Config object as the second argument to the Logger constructor:
import { Logger, Config } from '@datares/logger';
const log = new Logger('dtr_live_...', new Config({
baseUrl: 'https://api.datares.id', // API endpoint
timeout: 10_000, // request timeout in ms
retries: 3, // max retries on 5xx (exponential back-off)
batchSize: 100, // auto-flush when buffer reaches this size
autoFlush: true, // flush on process 'beforeExit'
}));| Option | Default | Description |
|---|---|---|
| baseUrl | 'https://api.datares.id' | API base URL |
| timeout | 10000 | Request timeout per attempt in milliseconds |
| retries | 3 | Max retries on server errors (1s → 2s → 4s back-off) |
| batchSize | 100 | Auto-flush buffer when it reaches this many entries (1–500) |
| autoFlush | true | Register beforeExit handler to flush on process exit |
Sending Logs
Buffered (default)
The convenience methods (info(), error(), etc.) add entries to an internal buffer. The buffer flushes automatically when:
- It reaches
batchSizeentries, or - The Node.js process emits the
beforeExitevent (autoFlush: true)
const log = new Logger('dtr_live_...');
log.info('Request started', 'api');
log.debug('Cache miss', 'cache', { key: 'user:42' });
// ... more logs throughout your code ...
// Flush manually at any point:
await log.flush();Immediate (guaranteed delivery)
send() bypasses the buffer and sends immediately. It throws on failure, so use it when you need to know the log was received.
import { Logger, LogEntry, Level } from '@datares/logger';
// Single entry
await log.send(LogEntry.make(Level.Critical, 'Database connection lost', 'db'));
// Multiple entries
await log.send([
LogEntry.make(Level.Error, 'Order failed', 'checkout', { order_id: 5 }),
LogEntry.make(Level.Info, 'Retry queued', 'checkout', { order_id: 5 }),
]);LogEntry — full control
Use LogEntry.make() when you need a custom timestamp or want to use the Level constants:
import { LogEntry, Level } from '@datares/logger';
const entry = LogEntry.make(
Level.Warning, // or plain string: 'warning'
'High memory usage',
'worker',
{ usage_mb: 512 },
new Date(), // optional timestamp (server fills it otherwise)
);
log.log(entry); // add to buffer
// or
await log.send(entry); // send immediatelyError Handling
Buffered errors
When buffered logs fail to send (network error, server error), the error is passed to the error handler. The default handler writes to console.error. Override it with onError():
import { LoggerError } from '@datares/logger';
log.onError((err: LoggerError) => {
// e.g. forward to your alerting system
myAlerting.captureException(err);
});onError() returns this so it can be chained:
const log = new Logger('dtr_live_...')
.onError((err) => console.error('[Datares]', err.message));Immediate errors (send())
send() throws on failure. Catch specific error classes for granular handling:
import {
LoggerError,
AuthError,
RateLimitError,
ApiError,
} from '@datares/logger';
try {
await log.send(LogEntry.make(Level.Error, 'Critical failure', 'payments'));
} catch (err) {
if (err instanceof AuthError) {
// HTTP 401 / 403 — invalid or revoked API key
} else if (err instanceof RateLimitError) {
// HTTP 429 — wait before retrying
console.log(`Retry after ${err.retryAfter}s`);
} else if (err instanceof ApiError) {
// HTTP 4xx / 5xx — err.statusCode has the code
console.log(`API returned ${err.statusCode}`);
} else if (err instanceof LoggerError) {
// Network failure, payload too large, JSON encode failure, etc.
}
}| Error class | Cause |
|---|---|
| AuthError | HTTP 401 / 403 — invalid or suspended API key |
| RateLimitError | HTTP 429 — rate limit hit; err.retryAfter seconds |
| ApiError | HTTP 4xx / 5xx — err.statusCode has the code |
| LoggerError | Network failure, payload too large, JSON encode error |
API Limits
| Limit | Value | |---|---| | Max entries per request | 500 | | Max payload size | 5 MB | | Rate limit | 120 requests/min per key |
The SDK handles the 500-entry limit automatically by splitting large buffers into multiple requests. If a single serialized payload exceeds 5 MB, send() throws a LoggerError before making any HTTP call.
Express Integration
import express from 'express';
import { Logger, Config } from '@datares/logger';
const log = new Logger(process.env['DATARES_API_KEY'] ?? '', new Config({
batchSize: 50,
}));
const app = express();
app.use((req, _res, next) => {
log.info(`${req.method} ${req.path}`, 'http', {
ip: req.ip,
user_agent: req.headers['user-agent'],
});
next();
});
app.listen(3000);NestJS Integration
// datares-logger.module.ts
import { Module, Global } from '@nestjs/common';
import { Logger, Config } from '@datares/logger';
@Global()
@Module({
providers: [
{
provide: Logger,
useValue: new Logger(process.env['DATARES_API_KEY'] ?? '', new Config({
batchSize: 50,
})),
},
],
exports: [Logger],
})
export class DataresLoggerModule {}Then inject it anywhere:
import { Injectable } from '@nestjs/common';
import { Logger } from '@datares/logger';
@Injectable()
export class OrdersService {
constructor(private readonly log: Logger) {}
async createOrder(orderId: number): Promise<void> {
this.log.info('Order placed', 'orders', { order_id: orderId });
}
}Running Tests
npm install
npm testThe test suite runs on Node.js 18, 20, and 22 in CI (.gitlab-ci.yml). Tests use Vitest and mock global.fetch — no network calls are made.
