npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@datares/logger

v0.1.0

Published

Official Node.js SDK for Datares Logger — structured log ingestion.

Readme

Datares Logger Node.js SDK

Pipeline Latest Release

Official Node.js / TypeScript SDK for Datares Logger — structured log ingestion by Datares.

Requirements: Node.js 18+ (native fetch required)


Installation

npm install @datares/logger

Quick 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>): void

Configuration

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 batchSize entries, or
  • The Node.js process emits the beforeExit event (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 immediately

Error 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 test

The 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.