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

@thesharks/analytics

v0.0.0

Published

Opinionated Sentry-on-OpenTelemetry telemetry bootstrap for Sapphire Discord bots: traces, metrics and logs over OTLP, with a Sapphire logger bridge

Readme

@thesharks/analytics

Full documentation: https://wildbeast.guide/analytics/overview/

Using a coding assistant? Give it the docs as one Markdown file: https://wildbeast.guide/_llms-txt/analytics.txt

OpenTelemetry-first analytics helpers for WildBeast. This package provides:

  • initOpenTelemetry bootstrap for traces/metrics/logs
  • Sapphire logger bridge (AnalyticsLogger)
  • OpenTelemetry API re-exports (metrics, logs, trace)

OpenTelemetry bootstrap

The shared bootstrap configures traces, metrics, and logs via OTLP HTTP or gRPC exporters. The bootstrap automatically configures exporters for all signals when an OTLP endpoint is provided. If no endpoint is set, exporters remain disabled unless enableExport is explicitly set to true. The bootstrap enables the pg, undici, ioredis and runtime-node auto-instrumentations by default (disable via config or environment variables).

Common config knobs in initOpenTelemetry:

  • serviceName, serviceVersion, namespace, environment, instanceId, shardId
  • enableExport to force exporters on/off
  • shutdownTimeoutMillis to bound telemetry flushing on shutdown (default 10s)
  • exporters to override OTLP endpoints/headers/protocol/timeout/compression per signal
  • instrumentations to toggle pg, undici, ioredis, fs and runtimeNode
  • sentry to override dsn, tracesSampleRate, tracesSampler, environment, release

Local metric inspection

Pass an additional reader when initializing telemetry to inspect metrics without an OTLP collector. LocalMetricReader collects cumulative snapshots that can be sent through worker IPC; collecting them does not drain other metric readers.

import { initOpenTelemetry, LocalMetricReader } from '@thesharks/analytics'

const reader = new LocalMetricReader()
const telemetry = initOpenTelemetry({ metricReaders: [reader] })
// After application instruments have emitted data:
const snapshot = await reader.snapshot()
// snapshot.points contains labels, units, counters, gauges, and histogram summaries.
await telemetry.shutdown()

Register the reader before starting application work. Collection has a one-second observable callback timeout, a 200-series cardinality limit per instrument, and a 2,000-point snapshot cap. Check errors and truncated for partial results.

Exporter configuration

Each signal (traces, metrics, logs) can be configured with:

  • endpoint: OTLP endpoint URL (for example http://localhost:4317 or grpc://localhost:4317)
  • headers: Custom headers for the exporter
  • protocol: Explicitly set 'http' or 'grpc' (optional, auto-detected from endpoint URL)
  • timeout: Request timeout in milliseconds (optional)
  • compression: Compression setting ('gzip' or 'none', optional)

Protocol selection

Protocol is determined by precedence:

  1. Config field: protocol: 'http' | 'grpc'
  2. Signal-specific env var: OTEL_EXPORTER_OTLP_{SIGNAL}_PROTOCOL
  3. Global env var: OTEL_EXPORTER_OTLP_PROTOCOL
  4. URL scheme detection: grpc:// or grpcs:// → gRPC, otherwise HTTP

Multiple exporters

Each signal can have multiple exporters configured as an array:

exporters: {
  traces: [
    { endpoint: "http://primary:4317", headers: { "X-Primary": "true" } },
    { endpoint: "http://secondary:4317", headers: { "X-Secondary": "true" } },
  ]
}

Example exporter override:

const telemetry = initOpenTelemetry({
  enableExport: true,
  exporters: {
    otlp: { 
      endpoint: "http://localhost:4317",
      headers: { "Authorization": "Bearer token" },
    },
    traces: { 
      endpoint: "grpc://localhost:4317",
      timeout: 30000,
      compression: "gzip",
    },
  },
});
import { initOpenTelemetry } from "@thesharks/analytics";

const telemetry = initOpenTelemetry({
  serviceName: "@thesharks/discord",
  namespace: "@thesharks",
  shardId: process.env.SHARD_ID,
  instrumentations: {
    pg: true,
    undici: true,
  },
});

process.once("SIGINT", () => telemetry.shutdown());
process.once("SIGTERM", () => telemetry.shutdown());

API overview

This package exports the OpenTelemetry API for creating metrics, logs, and traces. Use metrics.getMeter, logs.getLogger, and trace.getTracer to instrument your application.

OTel API usage

import { metrics, logs, trace } from "@thesharks/analytics";

const meter = metrics.getMeter("@thesharks/discord");
const logger = logs.getLogger("@thesharks/discord");
const tracer = trace.getTracer("@thesharks/discord");

const guildGauge = meter.createObservableGauge("discord_guilds_total", {
  description: "Total number of Discord guilds the bot is in",
});

logger.emit({
  severityText: "info",
  body: "Telemetry initialized",
});

Sapphire logger bridge

The AnalyticsLogger extends Sapphire's logger to automatically send logs to both OpenTelemetry and Sentry:

import { AnalyticsLogger } from "@thesharks/analytics";

const client = new SapphireClient({
  logger: {
    instance: new AnalyticsLogger(),
  },
});

The AnalyticsLogger sends all Sapphire logs to three destinations:

  1. Console (standard behavior)
  2. OpenTelemetry as log records
  3. Sentry using the Logs API (trace, debug, info, warn, error, fatal)

Sentry Logs integration is enabled by default and requires @sentry/node v9.41.0 or later.

Environment variables

OpenTelemetry

Required for export

  • OTEL_EXPORTER_OTLP_ENDPOINT: Base OTLP endpoint (for example http://localhost:4317 or grpc://localhost:4317)

Endpoints (optional)

  • OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: Overrides traces endpoint
  • OTEL_EXPORTER_OTLP_METRICS_ENDPOINT: Overrides metrics endpoint
  • OTEL_EXPORTER_OTLP_LOGS_ENDPOINT: Overrides logs endpoint

Headers (optional)

Format: Comma-separated key=value pairs (for example Authorization=Bearer token,X-Custom-Header=value)

  • OTEL_EXPORTER_OTLP_HEADERS: Global headers for all OTLP exporters
  • OTEL_EXPORTER_OTLP_TRACES_HEADERS: Traces-specific headers
  • OTEL_EXPORTER_OTLP_METRICS_HEADERS: Metrics-specific headers
  • OTEL_EXPORTER_OTLP_LOGS_HEADERS: Logs-specific headers

Protocol (optional)

  • OTEL_EXPORTER_OTLP_PROTOCOL: Global protocol: http/protobuf or grpc
  • OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: Traces-specific protocol
  • OTEL_EXPORTER_OTLP_METRICS_PROTOCOL: Metrics-specific protocol
  • OTEL_EXPORTER_OTLP_LOGS_PROTOCOL: Logs-specific protocol

Timeout (optional)

  • OTEL_EXPORTER_OTLP_TIMEOUT: Request timeout in milliseconds

Compression (optional)

  • OTEL_EXPORTER_OTLP_COMPRESSION: Compression setting: gzip or none

Service configuration (optional)

  • OTEL_SERVICE_NAME: Overrides service name
  • OTEL_DIAGNOSTIC_LOG_LEVEL: Set to verbose to enable OTEL diagnostics
  • OTEL_INSTRUMENTATION_PG_ENABLED: Set to false to disable pg instrumentation
  • OTEL_INSTRUMENTATION_UNDICI_ENABLED: Set to false to disable undici instrumentation

Sentry

  • SENTRY_DSN: Sentry DSN for error tracing
  • SENTRY_VALIDATE_OTEL_SETUP: Set to true to validate OTEL setup on boot (throws if validation fails)

End-to-end testing

test/collector.e2e.test.ts verifies the full pipeline against a real OpenTelemetry collector (both OTLP/HTTP and OTLP/gRPC). The easiest way to run it is the repo-wide integration runner, which provisions the collector (and Redis) in docker automatically:

pnpm test:integration # from the repo root

To run it manually instead, it is skipped unless OTEL_E2E_OUTPUT is set:

mkdir -p /tmp/otel-e2e && chmod 777 /tmp/otel-e2e
docker run --rm -d --name otel-e2e \
  -p 14317:4317 -p 14318:4318 \
  -v $PWD/test/fixtures/otel-collector.yaml:/etc/otelcol-contrib/config.yaml \
  -v /tmp/otel-e2e:/out \
  otel/opentelemetry-collector-contrib:latest
pnpm build # scenarios boot the real pipeline from dist
OTEL_E2E_OUTPUT=/tmp/otel-e2e/telemetry.json pnpm test
docker rm -f otel-e2e