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

@graphorin/observability

v0.8.0

Published

Observability primitives for the Graphorin framework: typed AISpan tracer over OpenTelemetry, mandatory withValidation wrapper for every exporter, sensitivity-aware RedactionValidator with built-in PII / secret patterns, GenAI Semantic Conventions conform

Readme

@graphorin/observability

Observability primitives for the Graphorin framework.

@graphorin/observability ships every cross-cutting tracing, redaction, replay, cost, and structured-logging primitive every other @graphorin/* package builds on. The package is intentionally opinionated: every exporter must be wrapped through withValidation(...) before it can ship a single span, the validator defaults to default-deny non-public, and the framework makes zero outbound network calls without an explicit user action.

Highlights

  • Typed AISpan<T> tracer. createTracer({...}) returns a GraphorinTracer that emits AISpan<SpanType> records compatible with OpenTelemetry. Sampling rules + per-event sampling cover noisy span kinds (memory.embed, tool.execute.partial, …).

  • Mandatory withValidation(...) wrapper. Every exporter passed to createTracer({ exporters }) is wrapped through the configured RedactionValidator. Registering a raw exporter while validation: 'off' triggers UnvalidatedExporterError at startup - there is no silent path.

  • RedactionValidator with 14 built-in patterns. API key / JWT / PEM private key / GitHub PAT / AWS access key / Graphorin token / bearer header / basic-auth header / email / credit card / US SSN / E.164 phone / IBAN - all on by default. Three additional patterns (IPv4, IPv6, GCP service account) are opt-in.

  • OpenTelemetry GenAI semantic-conventions conformance. emitGenAIAttributes(span, {...}), emitGenAIMessageEvents(span, [...]), and deriveGenAISystem(...) ship the canonical gen_ai.* attribute family alongside the existing graphorin.* attributes - additive, never replacing. Span names follow the semconv {operation} {target} shape (chat <model>, execute_tool <tool>, invoke_agent <agent>) via the exported spanNameFor(type, attrs) helper, applied by the tracer automatically.

  • OpenInference span-kind layer. emitOpenInferenceKind(span) emits the openinference.span.kind attribute via the canonical per-SpanType mapping (agent.*AGENT, provider.*LLM, tool.executeTOOL, memory.*RETRIEVER / EMBEDDING, workflow.*CHAIN, agent.evaluator.iterationEVALUATOR).

  • ConsoleExporter, JSONLExporter, OTLPHttpExporter. The built-in exporters cover dev (console), replay (append-only JSONL with 0700 directories + 0600 files), and remote OTLP collectors (fetch-based reference implementation, swappable fetchImpl).

  • Sanitized-by-default Replay. createReplay({...}) exposes a run(...) async iterator that yields replay.start / replay.event / replay.skipped / replay.end markers. Raw mode requires the canReadRaw callback to return true and emits an audit-bridge entry on every invocation.

  • Hierarchical CostTracker. createCostTracker({...}) rolls up tokens + cost (including the prompt-cache read/write legs) across parent-child spans and supports per-run / per-session / per-agent / per-user budgets with an onExceed callback. Internal maps are bounded by default (retention: { maxSpanEntries, maxScopeEntries }, 10k each; oldest-first eviction with an onEviction observer - usage() for an evicted id reports zero; pass retention: false for the old unbounded behaviour). Feed it from the provider middleware with the shipped bridge:

    import { costTrackerUsageDelegate, createCostTracker } from '@graphorin/observability';
    import { withCostTracking } from '@graphorin/provider';
    
    const tracker = createCostTracker({ budgets: { perSession: 5 } });
    const provider = withCostTracking(base, {
      priceLookup: () => ({ inputPerMtok: 3, outputPerMtok: 15 }),
      onUsage: costTrackerUsageDelegate(tracker, () => ({
        spanId: currentSpanId(),
        sessionId: currentSessionId(),
      })),
    });
    // Later: tracker.usage('session', sessionId).cost
  • Structured logger. createLogger({...}) writes JSON or pretty records, automatically correlates with the current span via withCurrentSpan(...), and pipes every field through the validator.

  • Zero-default telemetry. getTelemetryStatus() and announceTelemetryPosture() expose the v0.1 promise: the framework performs zero outbound network calls, no version pings, no crash reports, no auto-updates. The GRAPHORIN_TELEMETRY and GRAPHORIN_NO_PHONE_HOME environment variables are reserved for forward compatibility and are acknowledged at startup.

Installation

pnpm add @graphorin/observability
# Optional peer deps for OTLP export - install only when you need them:
pnpm add @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http

Quick start

import {
  createTracer,
  createConsoleExporter,
  createJSONLExporter,
  withValidation,
} from '@graphorin/observability';

const tracer = createTracer({
  serviceName: 'my-assistant',
  exporters: [
    // Auto-wrapped via the tracer-managed validator.
    createConsoleExporter({ pretty: true }),
    // Manually wrapped - useful when each exporter needs its own policy.
    withValidation(createJSONLExporter({ path: './traces' }), {
      minTier: 'internal',
    }),
  ],
  validation: { minTier: 'public', failOnUnredactedSensitive: false },
  sampling: {
    rate: 1.0,
    rules: [{ type: 'memory.embed', rate: 0.1 }],
  },
});

await tracer.span(
  { type: 'agent.run', attrs: { 'graphorin.agent.id': 'support-bot' } },
  async (span) => {
    span.setAttributes({ 'graphorin.session.id': 'session-123' });
    return runAgent();
  },
);

await tracer.shutdown();

License

MIT © 2026 Oleksiy Stepurenko.


Project Graphorin · v0.8.0 · MIT License · © 2026 Oleksiy Stepurenko · https://github.com/o-stepper/graphorin