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

@foam-ai/cliengo-kori

v2.0.0

Published

Foam observability toolkit for Cliengo kori (Fastify 5 + Pino + optional New Relic).

Downloads

2,688

Readme

@foam-ai/cliengo-kori

Foam observability for kori — Fastify 5, Pino, and optional New Relic bridge.

Exports traces, logs, and metrics to Foam's OTLP endpoint. Injects trace context into Pino logs, propagates traces across SNS/SQS boundaries, and optionally bridges New Relic so both systems share the same traceId.

Quick start

// src/foam.ts — import before anything else
import { init } from '@foam-ai/cliengo-kori';

init('kori', {});
// Reads FOAM_OTEL_TOKEN from env automatically.
// Or pass it explicitly: init('kori', { token: '...' })
// src/server.ts
import { getFoam, createFastifyLoggerConfig } from '@foam-ai/cliengo-kori';

const foam = getFoam()!;
const fastify = Fastify({
  logger: createFastifyLoggerConfig({ level: 'info' }),
});
await fastify.register(foam.createFastifyPlugin());
// Shutdown — call in your SIGTERM handler
await getFoam()?.shutdown();

init(serviceName, options)

Initializes Foam and returns a KoriInstance. Call once at startup, before creating the Fastify server. In non-production environments (without forceExport), returns an inert no-op instance — no providers, no patches, no network calls.

| Option | Type | Default | Description | |--------|------|---------|-------------| | token | string | process.env.FOAM_OTEL_TOKEN | Foam OTLP bearer token. Falls back to FOAM_OTEL_TOKEN env var. If missing when exporting, logs a warning and returns an inert instance. | | newrelic | boolean | false | true loads New Relic via require('newrelic'). false or omitted skips the NR bridge — everything works through OTel alone. | | forceExport | boolean | false | Export telemetry even outside production (NODE_ENV !== 'production'). Useful for staging. |

KoriInstance methods

createFastifyPlugin()

Returns a Fastify plugin that creates one OTel span per HTTP request. Register it on your Fastify instance:

await fastify.register(foam.createFastifyPlugin());

The plugin hooks into onRequest, onError, and onResponse to manage span lifecycle, record exceptions, and capture request context (params, query, body, headers — with automatic redaction of sensitive fields).

createFastifyLoggerConfig(opts?)

Returns a Pino configuration object for Fastify's logger constructor option. Includes the trace-context mixin and an OTLP log destination automatically.

Fastify({ logger: createFastifyLoggerConfig({ level: 'info' }) });

Pass streams to replace the default stdout output (e.g., pino-pretty in development):

foam.createFastifyLoggerConfig({
  level: 'debug',
  streams: [{ stream: pinoPretty() }],
});

wrapSqsConsumer(spanName, msg, fn)

Wraps an SQS message handler with an OTel span and optional NR background transaction. Extracts the traceparent from the message attributes to continue the upstream trace.

await foam.wrapSqsConsumer('automation-events', msg, async () => {
  // process the message
});

Supports both RawMessageDelivery=true (traceparent in msg.MessageAttributes) and RawMessageDelivery=false (traceparent inside the SNS envelope in msg.Body).

injectSnsAttributes(attrs)

Adds a traceparent attribute to SNS MessageAttributes so downstream SQS consumers can continue the trace.

const params = {
  Message: JSON.stringify(payload),
  TopicArn: topicArn,
  MessageAttributes: foam.injectSnsAttributes({
    triggerType: { DataType: 'String', StringValue: 'chat' },
  }),
};
await sns.publish(params);

getTraceContext()

Returns the current { traceId, spanId, traceparent } from the active OTel span, NR transaction, or generates fresh IDs. Useful for propagating trace context to outgoing HTTP calls or other systems.

buildTraceparent()

Returns a W3C traceparent string from the active trace context, or generates a fresh one.

shutdown()

Flushes all pending traces, logs, and metrics, then shuts down the OTel providers. Call this in your SIGTERM handler:

process.on('SIGTERM', async () => {
  await getFoam()?.shutdown();
  await fastify.close();
  process.exit(0);
});

getFoam(serviceName?)

Retrieves the KoriInstance created by init(). If only one instance exists, serviceName can be omitted.

createFastifyLoggerConfig(opts?)

Standalone version of foam.createFastifyLoggerConfig() — looks up the Foam instance internally via getFoam(). Convenient when you don't want to pass the instance around:

import { createFastifyLoggerConfig } from '@foam-ai/cliengo-kori';
Fastify({ logger: createFastifyLoggerConfig({ level: 'info' }) });

Trace propagation

Traces propagate across service boundaries via W3C traceparent:

SNS publish (combee)          SQS consumer (kori)
───────────────────           ──────────────────
injectSnsAttributes() ──────> wrapSqsConsumer()
adds traceparent to           extracts traceparent,
MessageAttributes             creates child span

The Fastify plugin creates a shadow OTel span per HTTP request, inheriting the traceId from New Relic (if bridged) or generating a fresh one. All Pino logs within the request carry the same traceId for log-to-trace correlation.

Design philosophy

This package is a toolkit, not an agent. It never:

  • Registers process handlers (uncaughtException, unhandledRejection)
  • Sets global tracer providers
  • Monkey-patches runtime modules (http, mongodb, redis, etc.)

The consumer owns process lifecycle, shutdown, and any additional instrumentation (e.g., @opentelemetry/instrumentation-http).