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

@middle-monitor/sdk

v0.1.9

Published

TypeScript SDK for Middle-Monitor error reporting with OpenTelemetry

Downloads

106

Readme

Middle-Monitor TypeScript SDK

TypeScript/JavaScript SDK for capturing and reporting errors to Middle-Monitor.

Documentation: middlemonitor.io/docs#sdk

For a browser frontend (React, Vue, Angular, Svelte), use @middle-monitor/web instead: this package pulls @opentelemetry/sdk-node and does not bundle for a browser.

Installation

From GitHub:

npm install git+https://github.com/middle-monitor/sdk-typescript.git

Or from a local path:

npm install

Usage

Basic setup

import { MiddleMonitorClient } from '@middle-monitor/sdk';

const client = new MiddleMonitorClient({
  apiUrl: 'https://api.middlemonitor.io',
  service: 'my-service'
});

try {
  throw new Error('Something went wrong');
} catch (error) {
  await client.reportError(error as Error);
}

Custom error

await client.reportCustomError(
  'DatabaseError',
  'Failed to connect to database',
  '/path/to/db.ts',
  123
);

Function wrapper

const riskyFunction = client.wrapFunction(() => {
  throw new Error('This will be automatically reported');
});

Environment variable setup

import { getClient } from '@middle-monitor/sdk';

// Reads MIDDLE_MONITOR_API_URL, MIDDLE_MONITOR_SERVICE
const client = getClient();

Express middleware

One line to enable automatic capture: one trace per request, error status on 4xx/5xx, and 5xx responses reported to the Errors view.

import { initSimple } from '@middle-monitor/sdk';
import { expressMiddleware } from '@middle-monitor/sdk/expressMiddleware';

initSimple();
app.use(expressMiddleware());

To only report 5xx errors without tracing, use captureExceptionErrors() instead (do not combine both).

Request logs

expressMiddleware() also writes one log line per failed request, so the Logs view carries traffic without the application calling log itself:

GET /api/orders 500

Carried as attributes: http.method, http.route, http.status_code, duration_ms. What gets through is decided by the log sampling rules — the defaults keep 2xx traffic out (that volume is what traces are for) and health probes out of the baseline:

| Response | Level | Logged by default | |---|---|---| | 2xx / 3xx | INFO | No | | 4xx | WARN | Yes | | 5xx | ERROR | Yes | | /health, /metrics, /ready | — | No |

const cfg = newConfig(apiUrl, service, token);
cfg.sampling.logs.levels = [LogLevel.INFO];              // every request
cfg.sampling.logs.alwaysCaptureRoutes = ['/api/pay/*'];  // every hit on a route
init(cfg);

Unlike the Go and Python SDKs, the line carries no cause suffix: Express exposes the response body only to the res.end wrapper of captureExceptionErrors, which runs after this log is emitted. The cause is in the Errors view for the same request.

Caller address

The request log also carries a client.ip attribute, which is what tells a wall of 404s on /wp-login.php apart from a real user hitting a broken page. It is read from CF-Connecting-IP, True-Client-IP, X-Forwarded-For or X-Real-IP before falling back to the socket address, so a service behind Caddy, nginx or Cloudflare records the caller and not the proxy.

An IP address is personal data, so the default keeps the network and drops the host part — 203.0.113.42 is stored as 203.0.113.0, an IPv6 address is cut to its /48. That is enough to recognise a scan, not enough to single out a person.

const cfg = newConfig(apiUrl, service, token);
cfg.clientIp = ClientIpMode.FULL;  // whole address: needs its own legal basis
cfg.clientIp = ClientIpMode.OFF;   // record nothing
init(cfg);

Recording full addresses is a decision about your users' data: give it a legal basis and say so in your privacy policy. An address that does not parse is dropped rather than stored, so a forged header never lands in the attribute.

Correlating with host metrics

Every export is labelled with host.name, which is what lets Middle-Monitor line up a CPU or memory spike on a host with the traffic of the services running on it. Inside a container os.hostname() is the container ID and matches no host, so set the real one:

environment:
  MIDDLE_MONITOR_HOSTNAME: host4   # as the host is named in Middle-Monitor

Environment variables

export MIDDLE_MONITOR_API_URL=https://api.middlemonitor.io
export MIDDLE_MONITOR_SERVICE=my-service
export MIDDLE_MONITOR_TOKEN=your_token
# Host this service runs on, as Middle-Monitor names it. Required in a container,
# where the OS hostname is the container ID and matches no host.
export MIDDLE_MONITOR_HOSTNAME=host4
# Optional: stop the Express middleware from reporting 5xx
export MIDDLE_MONITOR_DISABLE_HTTP_ERROR_REPORTING=true
# Optional: caller address on request logs — anonymized (default), full or off
export MIDDLE_MONITOR_CLIENT_IP=off

MIDDLE_MONITOR_TOKEN also acts as the opt-in switch: with no token set, the SDK does not initialize itself and every entry point is a no-op, so an application that never configured Middle-Monitor never sends anything.

Applications that report their own errors

captureExceptionErrors() submits every 5xx to the Errors view, building the message from the response body. If your application already reports its errors from its own error handler, you get two entries per failure — one with the real cause, one generic. Disable the middleware's half:

const cfg = newConfig(apiUrl, service, token);
cfg.disableHttpErrorReporting = true;
init(cfg);