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

@kittl/observability-node

v0.1.0

Published

Shared Node.js observability for Kittl services and workers.

Readme

Node Observability

Shared Node.js observability for Kittl services and workers.

@kittl/observability-node provides a single entry point for OpenTelemetry tracing and metrics.

How to use

Create telemetry.ts file and make sure it is imported into your entrypoint:

import { KittlNodeTelemetry } from '@kittl/observability-node';

const telemetry = new KittlNodeTelemetry({
  serviceName: 'api',
  serviceVersion: process.env.RELEASE_SHA,
  owner: 'developers',
});
telemetry.start();

With default parameters this sets up Node auto-instrumentation and exports both metrics and traces. Metrics will be exposed on port 9464 under /metrics path by default. If you use @kittl/logger, logs will be correlated with traces automatically.

It is recommended to shut down the instance gracefully based on SIGTERM signal:

process.on('SIGTERM', () => {
  telemetry
    .shutdown()
    .then(
      () => logger.info('SDK shut down successfully'),
      (err) => logger.error('Error shutting down SDK', err)
    )
    .finally(() => process.exit(0));
});

Node auto-instrumentations can be fine-tuned using nodeAutoInstrumentations parameter:

new KittlNodeTelemetry({
  serviceName: 'api',
  nodeAutoInstrumentations: {
    '@opentelemetry/instrumentation-express': {
      ignoreLayersType: [ExpressLayerType.MIDDLEWARE, ExpressLayerType.ROUTER],
    },
  },
});

NOTE: For each auto instrumentation configuration, only specified parameters will be overridden. Remaining parameters will be set to default values.

Check supported-instrumentations for information on what is included.

Additional instrumentations can be added via additionalInstrumentations parameter:

import { PrismaInstrumentation } from '@prisma/instrumentation';

new KittlNodeTelemetry({
  serviceName: 'api',
  additionalInstrumentations: [new PrismaInstrumentation()],
});

Kubernetes configuration

To make sure that service metrics are collected and traces are exported, following minimal values.yaml configuration is required:

env:
  - name: NODE_IP
    valueFrom:
      fieldRef:
        fieldPath: status.hostIP
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: http://$(NODE_IP):4318
deployment:
  metrics:
    enabled: true
    port: 9464 # change if different port is used
    path: /metrics

In addition following environment variables are recommended to be set via configmap:

OTEL_LOG_LEVEL: warn
# use new stable HTTP conventions
OTEL_SEMCONV_STABILITY_OPT_IN: http

User journeys

This package provides abstraction for tracking user journeys in a standardized way via Journey class. It supports recording step transitions as a counter metric, as well as recording step durations into a histogram.

Steps are particular operations inside the journey. For example, AI generation journey might contain separate steps to charge the user, generate image and refund the user in case of error. Each step has a particular outcome - for example, generation might fail with an error, be successful or it might time out. For more information on this topic see Business Metrics Taxonomy

Here's an example of tracking generation step in ai_generation journey using recordStep method:

import { Journey, ATTR_OUTCOME, ATTR_ERROR_CATEGORY } from '@kittl/observability-node';

const aiGenerationJourney = new Journey('ai_generation');

function generateAiImage(...) {
  try {
    /** some business logic */
  } catch {
    aiGenerationJourney.recordStep('generation', {
      [ATTR_OUTCOME]: 'failure',
      [ATTR_ERROR_CATEGORY]: 'generation_failed',
    });
    return;
  }
  aiGenerationJourney.recordStep('generation', {
    [ATTR_OUTCOME]: 'success',
  });
}

NOTE: Error category is always tracked, but defaults to none when it is not specified.

By default Journey only allows passing built-in ATTR_OUTCOME and ATTR_ERROR_CATEGORY attributes. To include additional attributes, they should be fined as an interface and passed to Journey as a generic type argument:

import { ATTR_PROVIDER } from '@kittl/observability-node';

const ATTR_CONTENT_TYPE = 'content.type';

interface AiGenerationJourneyAttributes {
  [ATTR_PROVIDER]?: 'nano-banana' | 'gemini' | 'stripe';
  [ATTR_CONTENT_TYPE]?: 'image' | 'video';
}

const aiGenerationJourney = new Journey<AiGenerationJourneyAttributes>(
  'ai_generation'
);
aiGenerationJourney.recordStep('generation', {
  [ATTR_OUTCOME]: 'success',
  [ATTR_PROVIDER]: 'nano-banana',
  [ATTR_CONTENT_TYPE]: 'image',
});

In cases where we are also interested in duration of a step, it is possible to also track step duration via recordStepWithDuration method. It does same as what recordStep does, but also records duration measurement in a histogram. Here's an example of tracking a different step in ai_generation journey:

function chargeUserForGeneration(...) {
  const startTime = performance.now();
  /** some business logic */
  aiGenerationJourney.recordStepWithDuration(
    'charge',
    (performance.now() - startTime) / 1000, // convert to seconds
    {
      [ATTR_OUTCOME]: 'success',
      [ATTR_PROVIDER]: 'stripe'
    }
  ),
}

NOTE: This example omits error handling for simplicity, but it is necessary when tracking durations in production code.

As this pattern of tracking start time and subtracting it from current time is so common, Journey class provides a useful createTimer method to simplify it:

const timer = aiGenerationJourney.createTimer();
/** some businees logic */
timer.recordStepWithDuration('charge', {
  [ATTR_OUTCOME]: 'success',
  [ATTR_PROVIDER]: 'stripe',
});