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

@semiont/observability

v0.5.2

Published

OpenTelemetry-based tracing for Semiont — Tier 2 of OBSERVABILITY.md. Process-init helpers (Node + Web), withSpan helper, W3C traceparent inject/extract for bus payloads. No-op when no exporter is configured.

Readme

@semiont/observability

Tests codecov npm version npm downloads License

OpenTelemetry-based tracing and metrics for Semiont. Tier 2 of the Semiont observability stack: process-init helpers (Node + Web), a thin withSpan wrapper, W3C trace-context propagation across the bus, and a small set of metric recorders for the platform's hot paths.

Off by default. With no OTEL_EXPORTER_OTLP_ENDPOINT (or OTEL_CONSOLE_EXPORTER=true) set, every API in this package becomes a no-op via the @opentelemetry/api no-op tracer. You pay nothing in production unless you opt in.

Architecture context

Semiont's observability is layered:

  • Tier 1 — busLog (in @semiont/core): a 5-op grep-friendly timeline at the ITransport contract layer (EMIT, RECV, SSE, PUT, GET). Always on, always free.
  • Tier 2 — this package: real OpenTelemetry traces + metrics, with W3C trace-context propagation across the bus's HTTP and SSE legs so a single user action produces one trace spanning frontend → backend → worker → smelter.
  • Tier 3 — log correlation and dashboards.

This package does not implement any platform domain logic; it provides the spanning helpers and metric recorders the rest of the codebase calls.

Installation

npm install @semiont/observability

Quick start (Node)

Initialize once at the process entry point, before any spanning code runs:

// worker-main.ts (or backend index.ts, etc.)
import { initObservabilityNode } from '@semiont/observability/node';

initObservabilityNode({ serviceName: 'semiont-worker' });

// ...rest of process startup

Then use the universal API anywhere:

import { withSpan } from '@semiont/observability';

await withSpan('handle-request', async (span) => {
  span.setAttribute('user.id', userId);
  return await doWork();
});

Configuration is via the standard OTEL_* env vars:

| Variable | Purpose | |---|---| | OTEL_EXPORTER_OTLP_ENDPOINT | Collector HTTP endpoint (e.g. http://jaeger:4318) | | OTEL_SERVICE_NAME | Overrides the serviceName passed to init | | OTEL_TRACES_SAMPLER | Sampler (default: parentbased_always_on) | | OTEL_TRACES_SAMPLER_ARG | Sampler ratio (default: 1.0) | | OTEL_METRIC_EXPORT_INTERVAL | Metric export interval ms (default: 30000) | | OTEL_CONSOLE_EXPORTER=true | Dev-only: emit spans + metrics to stderr | | OTEL_SDK_DISABLED=true | Skip initialization entirely |

Process logger (Node)

For long-lived Node entry points (backend, workers, smelter), the package exposes a winston-based structured logger that auto-correlates each line with the active span:

// worker-main.ts (or smelter-main.ts, etc.)
import { createProcessLogger } from '@semiont/observability/process-logger';

const logger = createProcessLogger('worker');
logger.info('Started', { config });

Reads LOG_LEVEL (default info) and LOG_FORMAT (json default, simple for dev). When an OTel SDK is initialized and a span is active at log time, every emitted line gets trace_id / span_id fields — Tier 3 correlation between grep-the-stdout and the trace UI. Lives on its own subpath so consumers that don't want winston in their bundle can ignore it.

Quick start (Web)

// SPA entry point (main.tsx)
import { initObservabilityWeb } from '@semiont/observability/web';

initObservabilityWeb({ serviceName: 'semiont-frontend' });

Web init wires up the same universal API plus browser-appropriate context propagation. Spans created in the SPA propagate to the backend via the bus's _trace payload field.

Universal API

Everything below is from the main @semiont/observability import — works identically in Node and the browser.

Spans

import { withSpan, withActorSpan, SpanKind } from '@semiont/observability';

// Generic async wrapper
await withSpan('parse-document', () => parser.parse(buf));

// With kind + attributes
await withSpan(
  'job:reference-annotation',
  () => runJob(job),
  { kind: SpanKind.CONSUMER, attrs: { 'job.id': job.id } },
);

// Actor handler wrapper — used by the bus dispatcher to standardize
// span names across state units (StowerStateUnit, BrowserStateUnit, GathererStateUnit, MatcherStateUnit, SmelterStateUnit).
await withActorSpan('stower', 'mark:create', () => handler(payload));

Trace-context propagation

W3C traceparent propagation is automatic for HTTP requests routed through the bus. For payloads that cross SSE (or any non-HTTP channel), use the explicit helpers:

import {
  injectTraceparent,
  extractTraceparent,
  withTraceparent,
  getActiveTraceparent,
} from '@semiont/observability';

// Sender side: stamp the active trace onto the bus payload.
const wirePayload = injectTraceparent(payload);

// Receiver side: extract and continue the trace.
const traceparent = extractTraceparent(incoming);
await withTraceparent(traceparent, () =>
  withSpan('handle-incoming', () => process(incoming)),
);

Log correlation

Add the active trace-id and span-id to every log line so log search and the trace UI link up:

import { getLogTraceContext } from '@semiont/observability';

logger.info({ ...getLogTraceContext(), msg: 'job started' });
// → { trace_id: '4e3...', span_id: 'a1b...', msg: 'job started' }

Metrics

Hot-path metric recorders. The names and label conventions are picked to match Tier 3 dashboards:

import {
  recordBusEmit,
  recordHandlerDuration,
  recordJobOutcome,
  recordSubscriberConnect,
  recordSubscriberDisconnect,
  recordInferenceUsage,
} from '@semiont/observability';

recordBusEmit('mark:create', 'browse');
recordHandlerDuration('stower', 'mark:create', durationMs);
recordJobOutcome('reference-annotation', 'completed', durationMs);
recordSubscriberConnect();
recordInferenceUsage({ model: 'gemma3:27b', inputTokens: 412, outputTokens: 87 });

Provider registration

Long-lived snapshots (job queue depth, vector index size) are gauges, registered via callback so the SDK can pull at metric-export time:

import {
  registerJobQueueProvider,
  registerVectorIndexSizeProvider,
} from '@semiont/observability';

registerJobQueueProvider(() => ({
  pending: jobs.pending.size,
  running: jobs.running.size,
}));

registerVectorIndexSizeProvider(() => qdrant.getCollectionInfo());

Implementation notes

This package wires BasicTracerProvider and MeterProvider (stable @opentelemetry/sdk-trace-base 2.x line) directly, plus AsyncLocalStorageContextManager for Node async-context propagation. It deliberately avoids @opentelemetry/sdk-node because that package's experimental 0.x versions cross-depend on older 2.0.x SDK lines, forcing npm to nest duplicate copies of the stable packages and bloating consumer bundles.

initObservabilityNode is idempotent — calling twice is a no-op and returns false on the second call. Both providers shut down cleanly on SIGTERM / SIGINT.

License

Apache-2.0 — see LICENSE.

Related packages

  • @semiont/core — Tier 1 busLog, domain types
  • @semiont/sdk — high-level Semiont client, the primary consumer of this package's spanning helpers
  • @semiont/api-client — HTTP transport, propagates traceparent on every request