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

@edakzin/mapi

v1.1.3

Published

Real-time performance and network monitoring module for Next.js / Node.js on Linux.

Readme

@edakzin/mapi

Real-time system performance and network monitoring module for Node.js and Next.js. The native collector is written in Rust with NAPI-RS, and the package exposes a typed TypeScript wrapper for structured snapshots or continuous logging.

What It Measures

  • CPU usage: global usage and per-core usage.
  • Memory: used RAM, total RAM, used swap, total swap, and percentages.
  • System state: uptime, load average, process count, and timestamp.
  • TCP connections: established TCP/TCP6 connections owned by the current process, grouped by local port.
  • Listening ports: listening ports detected for the current process on Linux.

Requirements

  • Node.js 20 or newer is recommended.
  • Linux is required for real TCP connection sampling because the native collector reads /proc/self/fd, /proc/net/tcp, and /proc/net/tcp6.
  • macOS and Windows can load the package, but connection sampling remains degraded and returns an empty breakdown with a non-fatal error message in the snapshot.

Installation

npm install @edakzin/mapi

Automatic Startup

Node.js does not execute dependencies just because they are installed. A production app must load mapi once at startup. Professional monitoring packages usually document this as one of these setup paths:

  • Framework hook: use the startup hook provided by the framework.
  • Preload hook: use NODE_OPTIONS=--require ... so Node loads the package before the app entrypoint.
  • Manual API: import the package and call the starter yourself.

Next.js

Create instrumentation.ts in the root of your Next.js project:

export async function register() {
  if (process.env.NEXT_RUNTIME === 'nodejs') {
    await import('@edakzin/mapi/auto');
  }
}

This starts mapi with defaults when the Next.js server starts:

  • enabled: true
  • intervalMs: 180000
  • port: 'auto'
  • logPath: ./logs/mapi-performance.log
  • logRetentionDays: 14

Node.js Preload

Use this when you want mapi to start without adding imports to your app code:

NODE_OPTIONS="--require @edakzin/mapi/auto" node server.js

For npm scripts:

{
  "scripts": {
    "start": "NODE_OPTIONS=\"--require @edakzin/mapi/auto\" node server.js"
  }
}

On Windows PowerShell:

$env:NODE_OPTIONS="--require @edakzin/mapi/auto"; npm start

Automatic Configuration

@edakzin/mapi/auto reads these environment variables:

| Variable | Default | Description | | --- | --- | --- | | MAPI_ENABLED | true | Use false, 0, no, or off to disable automatic startup. | | MAPI_INTERVAL_MS | 180000 | Interval between reports in milliseconds. | | MAPI_PORT | auto | Use auto, one port, or a comma-separated list such as 3000,8080. | | MAPI_LOG_PATH | ./logs/mapi-performance.log | Base path used to derive daily files such as ./logs/mapi-performance-2026-06-10.log. | | MAPI_LOG_RETENTION_DAYS | 14 | Days a rotated file can stay before it becomes eligible for cleanup. Cleanup runs once per day and only removes files older than this value. Use false, 0, no, or off to disable cleanup. |

If a previous version already wrote a monolithic file at MAPI_LOG_PATH, mapi archives that legacy file on the next start and redistributes its reports into the daily files using each report timestamp.

How Automatic Port Detection Works

When port: 'auto' is enabled, Rust discovers ports from the live process state instead of reading framework config:

  1. It scans /proc/self/fd and extracts the socket inodes owned by the current Node.js process.
  2. A native background thread reads /proc/net/tcp and /proc/net/tcp6 every 200ms.
  3. It keeps only rows whose inode belongs to the current process.
  4. Sockets in LISTEN state become detectedListeningPorts.
  5. Sockets in ESTABLISHED state increment totalEstablished and are grouped by local port in byLocalPort.

This is why auto can discover ports such as 3000 and 3001 without the user declaring them first. Declared ports remain a presentation hint for the plain-text report.

Direct Report Usage

Use this mode when you want to decide when metrics are collected.

import { getTelemetrySnapshot, getMetricsReport } from '@edakzin/mapi';

const snapshot = getTelemetrySnapshot();
console.log(snapshot.connections.totalEstablished);

const report = getMetricsReport('auto');
console.log(report);

initTracker() is still available if you want to start the native sampler eagerly, but the TypeScript wrapper now initializes it automatically on first use.

Continuous Logging Usage

Use this mode in a server process when you want mapi to append reports to a daily rotated log file on an interval.

import { startTracker, stopTracker } from '@edakzin/mapi';

startTracker({
  enabled: process.env.NODE_ENV === 'production',
  intervalMs: 180_000,
  port: 'auto',
  logPath: './logs/mapi-performance.log',
  logRetentionDays: 14,
});

process.on('SIGTERM', () => {
  stopTracker();
});

By default, startTracker() only runs in production. Pass enabled: true if you need to force it in another environment. logPath acts as a base path, and mapi writes files like mapi-performance-2026-06-10.log. If a legacy monolithic log already exists at that exact base path, mapi archives it as mapi-performance-legacy-archive.log and migrates its parsed reports to the daily files without discarding the original data.

API

@edakzin/mapi/auto

Starts continuous logging as soon as the module is loaded. It is intended for Next.js instrumentation or Node.js preload setups.

initTracker(): void

Initializes the native system tracker and starts the background connection sampler.

getTelemetrySnapshot(): TelemetrySnapshot

Returns a structured snapshot with CPU, memory, swap, uptime, load average, process count, timestamp, and connection data.

TelemetrySnapshot.connections contains:

  • totalEstablished: total ESTABLISHED sockets owned by the current process.
  • byLocalPort: breakdown by local port, for example [{ port: 3000, established: 4 }].
  • detectedListeningPorts: listening ports detected for the current process.
  • lastScanAt: timestamp of the last successful native scan.
  • stale: whether the connection sampler is degraded or stale.
  • error: a non-fatal error message when connection sampling is not healthy.

getMetricsReport(ports?: number | number[] | 'auto'): string

Returns a formatted text report built from the structured snapshot.

Parameters:

  • ports: optional preferred ports to highlight in the text report. They do not limit native collection.

Important details:

  • On Linux, mapi samples all ESTABLISHED TCP/TCP6 sockets owned by the current process and groups them by local port.
  • In auto mode, listening ports come from live sockets discovered through /proc/self/fd, not from Next.js or Node.js configuration introspection.
  • Declared ports are only a presentation preference for the text report.
  • On Windows and macOS, the connection breakdown stays empty and the snapshot marks the sampler as degraded instead of throwing a fatal error.

startTracker(config?: MapiConfig): void

Starts continuous metric collection and appends each report to a daily rotated log file.

Configuration:

  • enabled?: boolean: enables or disables the tracker. Default: process.env.NODE_ENV === 'production'.
  • intervalMs?: number: interval between reports in milliseconds. Default: 180000.
  • port?: number | number[] | 'auto': preferred ports for report presentation. Default: 3000 in the manual API and auto in @edakzin/mapi/auto.
  • logPath?: string: base path for rotated log files. Relative paths are resolved from the current working directory. Default: ./logs/mapi-performance.log, which produces files such as ./logs/mapi-performance-2026-06-10.log.
  • logRetentionDays?: number | false: number of days a rotated file can stay before it becomes eligible for cleanup. Cleanup runs once per day and only removes files older than this value. Use false to disable cleanup. Default: 14.

Legacy migration details:

  • If a monolithic legacy file still exists at logPath, mapi archives it before writing new daily files.
  • Parsed legacy reports are redistributed by the TIMESTAMP date found inside each report block.
  • The archived legacy copy is preserved so no existing data is discarded during migration.

stopTracker(): void

Stops the active interval created by startTracker() and shuts down the native connection sampler.

Output Example

======================================================================
TIMESTAMP: 2026-05-31 18:42:15.331
UPTIME: 1d 04h 12m 30s
LOAD AVERAGE: 0.15, 0.22, 0.08
TASKS: 142 total
ESTABLISHED CONNECTIONS (Proceso actual): 5
CONFIGURED PORTS: auto
DETECTED LISTENING PORTS: 3000, 3001
LAST CONNECTION SCAN: 2026-05-31 18:42:15.200 (ok)
----------------------------------------------------------------------
CONNECTION BREAKDOWN (Local Port):
  Puerto 3000 : 4
  Puerto 49152: 1
----------------------------------------------------------------------
CPU USAGE:
  Global: 12.45%
MEMORY:
  RAM:  4096 MB / 16384 MB (25.00%)
  SWAP: 1024 MB / 8192 MB (12.50%)
======================================================================

License

MIT