mrkeyoor.com_
Sat 08 Aug 21:01 UTC
npmWeb Backendupdated 08 Aug 2026

hot-shots

A Node.js client for emitting StatsD metrics to Datadog's DogStatsD agent, Telegraf, the OpenTelemetry Collector StatsD receiver or a classic StatsD daemon. It sends counters, gauges, sets, timings and histograms over UDP, TCP, Unix domain sockets or a supplied stream, with tags, sampling, buffering, child clients and optional client-side aggregation. Datadog mode also supports distributions, events, service checks, origin detection, cardinality hints and client telemetry.

Verdict

The practical Node choice when a StatsD-compatible agent is already part of your platform, especially for DogStatsD features and high-volume local emission. Do not mistake a local socket write for durable telemetry, and choose OpenTelemetry directly when StatsD is only an accidental legacy hop.

API stability4/5The constructor plus increment, gauge, timing, histogram, set, event, check, childClient, flush and close methods follow a long-lived StatsD client shape. The README says releases attempt semantic versioning, and the current major makes its Node floor explicit. Complexity lowers the score: behavior changes by transport, backend and buffering mode, and overloaded method signatures can make TypeScript upgrades or callback assumptions more delicate than the surface first appears.
Docs5/5The README documents every constructor option, environment-variable precedence, metric overload, backend capability difference, error route, callback mode, shutdown limitation, UDS build constraint, aggregation rule, sanitization behavior and telemetry metric. It includes CommonJS, ESM and TypeScript examples. The page is long, but the table of contents and unusually candid sections on dropped packets and callback semantics answer the production questions most client libraries omit.
Maintenance5/5Version 17.1.0 was published on July 25, 2026 and the repository was pushed on August 2. It is not archived, its fetched GitHub snapshot showed zero combined open issues and pull requests, and current documentation covers Node 18, modern Datadog environment variables, OpenTelemetry Collector compatibility, aggregation caps and UDS retry backoff. Publishing is limited to one named maintainer with two-factor authentication, which is transparent but still a bus-factor consideration.
Ecosystem4/5The package recorded 4,158,112 downloads in the measured week and explicitly supports four receiver families: DogStatsD, Telegraf, OpenTelemetry Collector's StatsD receiver and classic StatsD. It handles UDP, TCP, UDS and custom streams. The score stops short of five because StatsD extensions are fragmented by backend, and modern instrumentation ecosystems increasingly center on OpenTelemetry APIs rather than client-specific StatsD calls.

Use it if

  • Your infrastructure already runs a StatsD-compatible local agent or collector and application code only needs to emit metrics
  • You need DogStatsD tags, distributions, events, service checks or Unix socket delivery from Node
  • You want to reduce packet volume through buffering or client-side aggregation of hot counters, gauges and sets
  • You need the same client to target Datadog, Telegraf, OpenTelemetry Collector or classic StatsD with documented protocol switches
Skip it if

Setup reality

npm install hot-shots has no mandatory dependencies, but it does not install or configure a metrics daemon. With no transport settings it resolves Datadog-related environment variables and otherwise sends UDP to local port 8125, so a development process can appear healthy while every packet goes nowhere. Decide on StatsD, DogStatsD, Telegraf or the OpenTelemetry receiver first because tags, histograms, sets, timestamps, distributions, events and checks are not supported equally. Node 18 or newer is required; the shipped declarations require TypeScript 4 or newer. UDP and TCP need host, port and network policy. Datadog UDS needs the optional unix-dgram native module, a mounted socket path, node-gyp tooling and a non-Windows host. Buffering changes callbacks from asynchronous send results into synchronous queued notifications; later flush failures go to errorHandler. Aggregation further delays counts, gauges and sets, caps distinct contexts at 5,000 by default, and bypasses several metric forms. Set errorHandler on the root client, monitor client telemetry, and control tag cardinality before production. Metrics sent in process exit handlers will not complete because the event loop has already stopped. Flush and close from SIGTERM, SIGINT or another graceful shutdown path, and wait for the callback before exiting.

Patterns

Create a production UDP clientcreate-client

import StatsD from 'hot-shots';

const metrics = new StatsD({
  host: process.env.STATSD_HOST,
  port: 8125,
  prefix: 'checkout',
  globalTags: { env: process.env.NODE_ENV, service: 'api' },
  errorHandler(error) {
    console.error('StatsD error', error);
  },
});

Without an explicit host or Datadog environment variables, UDP resolves to the loopback interface. Confirm an agent is actually listening on port 8125.

Increment a tagged countersend-counter

metrics.increment('requests', 1, {
  tags: { route: '/orders', status: '200' },
});

Tags work with DogStatsD and Telegraf, not every classic StatsD server. Avoid user IDs, request IDs and other unbounded tag values.

Record gauges, histograms and timingssend-gauge-histogram

metrics.gauge('queue.depth', 17);
metrics.histogram('payload.bytes', body.length);
metrics.timing('request.duration', elapsedMs);

Histogram semantics vary by receiver. The README lists histogram support for Datadog, Telegraf and the OpenTelemetry Collector, not classic StatsD.

Wrap a promise-returning function with a timertime-async-function

const timedFetch = metrics.asyncTimer(
  async (url, metricContext) => {
    const response = await fetch(url);
    metricContext.addTags({ status: response.status });
    return response.json();
  },
  'upstream.duration',
);

const data = await timedFetch('https://api.example.com/data');

The wrapper appends a metrics context argument to your function. Functions that depend on an exact argument count or use the final argument position need adjustment.

Add subsystem tags with a child clientcreate-child-client

const paymentsMetrics = metrics.childClient({
  prefix: 'payments',
  globalTags: { component: 'payments' },
});

paymentsMetrics.increment('attempts');

Child clients share the parent transport and aggregator. Their distinct global tags also create distinct aggregation contexts.

Sample a high-volume countersample-counter

metrics.increment('cache.lookup', 1, {
  sampleRate: 0.1,
  tags: { result: 'hit' },
});

Sampling is probabilistic and the daemon compensates the count. Do not sample gauges, rare events or values where every individual observation matters.

Aggregate hot metrics before sendingenable-aggregation

const metrics = new StatsD({
  aggregation: {
    flushInterval: 2000,
    maxContexts: 5000,
  },
  errorHandler: console.error,
});

Only counts, gauges and sets are combined. Timings, histograms, distributions, events, checks, timestamped metrics and per-call sampling bypass aggregation.

Send DogStatsD over a Unix socketuse-datadog-socket

const metrics = new StatsD({
  datadog: true,
  protocol: 'uds',
  path: '/var/run/datadog/dsd.socket',
  udsRetryOptions: { retries: 3, retryDelayMs: 100 },
  errorHandler: console.error,
});

UDS relies on the optional unix-dgram native dependency, does not work on Windows and needs the agent socket mounted into the process container.

Use Telegraf's StatsD line protocolconfigure-telegraf

const metrics = new StatsD({
  host: 'telegraf.monitoring.svc',
  port: 8125,
  telegraf: true,
  globalTags: { service: 'checkout' },
});

Telegraf mode changes tag formatting and disables Datadog mode. Datadog-only distributions, events, service checks and timestamps do not carry over.

Emit a Datadog event and service checksend-datadog-event

metrics.event('Deployment finished', 'checkout-api 2.4.0', {
  alert_type: 'success',
  aggregation_key: 'checkout-deploy',
}, ['env:production']);

metrics.check('checkout.health', metrics.CHECKS.OK, {
  message: 'ready',
});

event and check are DogStatsD extensions. They are not portable to classic StatsD, Telegraf or the OpenTelemetry StatsD receiver.

Capture metrics without opening a sockettest-with-mock

const metrics = new StatsD({ mock: true });
metrics.increment('jobs.completed', { queue: 'email' });

expect(metrics.mockBuffer).toContain('jobs.completed:1|c|#queue:email');
metrics.mockBuffer.length = 0;

mockBuffer grows without a limit. Use mock mode only in tests and clear the array between cases.

Flush and close during graceful shutdownclose-on-sigterm

process.once('SIGTERM', () => {
  metrics.increment('app.shutdown', ['signal:SIGTERM']);
  metrics.close((error) => {
    if (error) console.error('Metrics close failed', error);
    process.exit(error ? 1 : 0);
  });
});

Do not send from process exit or uncaughtExceptionMonitor handlers; Node cannot complete asynchronous socket work after the event loop has stopped.

Alternatives

PackageRegistryPick it when
@opentelemetry/sdk-metricsnpmChoose it for vendor-neutral metrics with resource attributes, views and exporters alongside OpenTelemetry traces
prom-clientnpmChoose it when Prometheus will scrape your Node process and pull-based collection fits the deployment model
datadog-metricsnpmChoose it for a Datadog-only process that must submit metrics through the HTTP API rather than a local DogStatsD agent