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

@tokenbooks/zenstack-otel

v0.1.1

Published

OpenTelemetry runtime plugin for ZenStack ORM query and Kysely hooks

Readme

@tokenbooks/zenstack-otel

OpenTelemetry runtime plugin for ZenStack ORM.

This package wraps ZenStack's runtime plugin hooks and emits spans for:

  • ORM query operations via onQuery
  • Kysely query execution via onKyselyQuery

It is a runtime plugin for ZenStack ORM, not a zen generate CLI plugin.

Install

pnpm add @tokenbooks/zenstack-otel @opentelemetry/api @zenstackhq/orm

Usage

Install the plugin either through the client constructor's plugins option or by calling $use.

import { Pool } from 'pg';
import { ZenStackClient } from '@zenstackhq/orm';
import { PostgresDialect } from '@zenstackhq/orm/dialects/postgres';
import { createZenStackOtelPlugin } from '@tokenbooks/zenstack-otel';
import { schema } from './schema';

const db = new ZenStackClient(schema, {
  dialect: new PostgresDialect({
    pool: new Pool({
      connectionString: process.env.DATABASE_URL,
    }),
  }),
  plugins: [
    createZenStackOtelPlugin({
      tracerName: 'api-db',
    }),
  ],
});

Or:

const tracedDb = db.$use(createZenStackOtelPlugin());

Emitted spans

createZenStackOtelPlugin() creates spans with these names:

  • zenstack.<Model>.<operation> for ORM query hooks
  • zenstack.kysely.query for Kysely query hooks

It sets these attributes when available:

  • db.orm=zenstack
  • db.zenstack.model
  • db.zenstack.operation
  • db.zenstack.kysely.kind
  • db.statement when captureStatement is enabled
  • db.zenstack.kysely.parameter_count when captureStatement is enabled
  • db.zenstack.kysely.parameters when both captureStatement and captureParameters are enabled

API

createZenStackOtelPlugin(options?)

Creates a ZenStack runtime plugin instance.

Options:

  • pluginId?: string overrides the default plugin id (zenstack-otel)
  • tracerName?: string overrides the tracer name passed to trace.getTracer
  • captureStatement?: boolean attaches the compiled Kysely SQL text with placeholders to Kysely spans
  • captureParameters?: boolean also attaches compiled bind parameters as JSON; requires captureStatement: true
  • spanLifecycle?: SpanLifecycle injects a custom span runner, useful for tests or custom wrappers

new ZenStackOtelPlugin(options).create()

Class-based API for callers who prefer explicit construction over the factory function.

getDefaultZenStackOtelPlugin()

Returns a lazily cached default plugin instance.

SQL capture

By default, the plugin records logical ZenStack attributes only. If you enable captureStatement, the Kysely hook recompiles the operation node to recover dialect-specific SQL text with placeholders. If you also enable captureParameters, it serializes the compiled bind parameters into a separate span attribute.

Example:

createZenStackOtelPlugin({
  tracerName: 'api-db',
  captureStatement: true,
  captureParameters: true,
});

That produces Kysely span attributes like:

  • db.statement = select * from "User" where "id" = $1
  • db.zenstack.kysely.parameter_count = 1
  • db.zenstack.kysely.parameters = ["user-1"]

captureParameters requires captureStatement: true.

This extra compilation work can add overhead on hot paths. ZenStack's current onKyselyQuery hook exposes the Kysely operation node, not ZenStack's already-compiled query object, so there is no stable public hook payload to reuse instead of recompiling.

Development notes

ZenStack's plugin API is currently documented as a preview feature, so this package tracks the ZenStack v3 runtime plugin surface described here:

  • https://zenstack.dev/docs/orm/plugins
  • https://zenstack.dev/docs/orm/plugins/kysely-query-hooks
  • https://zenstack.dev/docs/recipe/plugin-dev

Release

pnpm release:patch
pnpm release:minor
pnpm release:major

The release script runs lint, tests, and build, bumps package.json, tags vX.Y.Z, and pushes to main. GitHub Actions publishes to npm from the tag.