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

@m4ike1/ion-telemetry

v0.1.1

Published

Vendor-neutral telemetry contracts and typed schema utilities for ion

Readme

@m4ike1/ion-telemetry

Vendor-neutral telemetry contracts and typed schema utilities for ion.

This package defines how ion code records telemetry without depending on a backend. It provides:

  • an explicit, callback-based TelemetryContext / TelemetrySpan contract;
  • W3C traceparent propagation across process and service boundaries;
  • a shared NOOP_TELEMETRY_CONTEXT;
  • a reference InMemoryTelemetryContext implementation with injectable timing;
  • serializable schema definitions with inferred TypeScript types and sensitive-attribute enforcement;
  • an adapter conformance suite under @m4ike1/ion-telemetry/testing.

It provides no exporter, no ambient current-span state, and no backend dependency. Applications pass a context explicitly and bridge it to OpenTelemetry, Sentry, logs, or another backend with an adapter.

Installation

npm install @m4ike1/ion-telemetry

Requires Node >=22.19. The root entrypoint is runtime-neutral (no Node APIs); only the /testing subpath uses node:assert/strict.

Quick start

Accept a context parameter defaulting to no-op, and start a span around the work:

import {
  NOOP_TELEMETRY_CONTEXT,
  type TelemetryContext,
} from '@m4ike1/ion-telemetry';

async function loadAccount(
  accountId: string,
  telemetryContext: TelemetryContext = NOOP_TELEMETRY_CONTEXT,
) {
  return telemetryContext.startSpan(
    {
      name: 'example.account.load',
      attributes: { 'example.account.id': accountId },
    },
    async (span) => {
      const account = await readAccount(accountId);
      span.setAttributes({ 'example.account.found': account !== undefined });
      return account;
    },
  );
}

Nest by starting child spans from the callback span:

return telemetryContext.startSpan({ name: 'example.parent' }, async (parentSpan) => {
  return parentSpan.startSpan({ name: 'example.child' }, async (childSpan) => {
    childSpan.addEvent('example.cache.lookup', { 'example.cache.hit': true });
    return performWork();
  });
});

startSpan() returns a synchronous callback result directly and returns a promise only when the callback returns a promise or throws. Existing await call sites work for both forms.

Propagate a W3C traceparent when work crosses an RPC, subagent, lane, or service boundary:

const outgoing = await telemetry.startSpan({ name: 'example.parent' }, async (span) => {
  const headers = { traceparent: telemetry.inject(span) };
  await callRemoteService(headers);
});

const remoteTelemetry = telemetry.extract(incomingHeaders.traceparent);
await remoteTelemetry.startSpan({ name: 'example.remote' }, runRemoteWork);

extract() never throws for malformed input: an invalid or missing traceparent produces a new root trace. Future traceparent versions with a valid W3C prefix are accepted and emitted as version 00; only the sampled flag is propagated. inject() returns undefined for a span the context does not own.

Capture spans in tests with the in-memory reference adapter:

import { InMemoryTelemetryContext } from '@m4ike1/ion-telemetry';

const telemetry = new InMemoryTelemetryContext();
await loadAccount('123', telemetry);
console.log(telemetry.getSpans());

Constrain names and attributes at compile time with a typed schema:

import {
  createTypedSpanStarter,
  defineTelemetrySchema,
} from '@m4ike1/ion-telemetry';

const schema = defineTelemetrySchema({
  version: 1,
  spans: {
    'example.read': {
      description: 'Read one resource',
      parents: { kind: 'any' },
      startAttributes: {
        'example.resource': { type: 'string', required: true, description: 'Resource kind' },
      },
      endAttributes: {
        'example.item_count': { type: 'number', description: 'Items returned' },
      },
      status: { default: 'ok', errorWhen: 'The read throws' },
    },
  },
} as const);

const startSpan = createTypedSpanStarter(telemetryContext, [schema]);
await startSpan('example.read', { 'example.resource': 'account' }, async (span) => {
  const accounts = await readAccounts();
  span.setAttributes({ 'example.item_count': accounts.length });
  return accounts;
});

The typed starter also supplies the matching span definition to the adapter at runtime. Attributes declared sensitive: true must be omitted, hashed, or truncated before recording. The in-memory adapter uses the shared redactAttributes() helper from @m4ike1/ion-telemetry, which omits those values from start, end, and event attributes.

Docs

Development

From this package directory:

npm test
npm run build

Repository-wide checks run with npm run check from the repo root.

License

MIT