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

@molecule/api-logger-axiom

v1.0.2

Published

Axiom logger provider for molecule.dev — mirrors log lines with structured fields into an Axiom dataset while still printing them locally.

Readme

@molecule/api-logger-axiom

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

Axiom logger provider for molecule.dev.

Every log call is written to an inner logger (the console by default) exactly as before, and lines at or above a level are also queued as structured events in an Axiom dataset. Sending is batched and asynchronous through the same ingest client as @molecule/api-analytics-axiom, so a log call never waits on the network.

Quick Start

import { logger, setLogger } from '@molecule/api-logger'
import { createLogger } from '@molecule/api-logger-axiom'

const axiomLogger = createLogger({
  // token / dataset default to AXIOM_TOKEN / AXIOM_DATASET
  level: 'warn', // mirror warn + error only; everything still prints locally
  service: 'my-api',
})
setLogger(axiomLogger)

logger.warn('Payment webhook retried', { provider: 'stripe', attempt: 2 })
// Axiom event: { _time, kind: 'log', level: 'warn',
//   message: 'Payment webhook retried',
//   fields: '{"provider":"stripe","attempt":2}', service: 'my-api', env }

await axiomLogger.shutdown() // before exit

Type

provider

Installation

npm install @molecule/api-logger-axiom @molecule/api-analytics-axiom @molecule/api-logger

API

Interfaces

AxiomLogger

A logger that mirrors into Axiom, with its ingester's lifecycle exposed.

interface AxiomLogger extends Logger {
  /** Whether a token and dataset are configured. When false lines only reach `inner`. */
  readonly enabled: boolean
  /** Send every queued line now. */
  flush(): Promise<void>
  /** Stop the flush timer and send what is left within `deadlineMs` (default 5000). */
  shutdown(options?: AxiomShutdownOptions): Promise<void>
}

AxiomLoggerOptions

Options for {@link createLogger}. Ingest fields fall back to the AXIOM_* env vars.

interface AxiomLoggerOptions extends AxiomIngesterOptions {
  /** Where every line is ALSO written, unchanged. Defaults to the console. Pass `null` to send to Axiom only. */
  inner?: Logger | null
  /** Lowest level mirrored to Axiom (default `'info'`). Lines below it still reach `inner`. */
  level?: Exclude<LogLevel, 'silent'>
  /**
   * `'json'` (default) stores a line's fields as one JSON string field, `fields`, so arbitrary
   * keys never add dataset columns (query with `parse_json(fields)`); `'object'` stores them as a
   * nested object, one column per key.
   */
  fieldsMode?: AxiomLogFieldsMode
  /** Stamped as `service` on every line. */
  service?: string
  /** Stamped as `env`. Defaults to `$NODE_ENV`. */
  env?: string
  /** Stamped as `region`. */
  region?: string
  /** Stamped as `version`. */
  version?: string
}

Types

AxiomLogFieldsMode

How a log line's structured fields are stored in Axiom.

type AxiomLogFieldsMode = 'json' | 'object'

Functions

createLogger(options)

Creates an Axiom logger.

function createLogger(options?: AxiomLoggerOptions): AxiomLogger
  • options — Ingest settings, the inner logger, the mirrored level and stamped fields.

Returns: The logger. Without a token and dataset it only writes to inner.

splitLogArgs(args)

Splits logger arguments into a message and structured fields: strings, numbers and booleans join into message; plain objects merge into fields; an Error becomes fields.error (or fields.errors for several); anything else is kept in fields.args.

function splitLogArgs(args: unknown[]): { message: string; fields: Record<string, unknown> }
  • args — The arguments passed to a log call.

Returns: The message and fields.

Constants

provider

The default logger: console output plus an Axiom mirror configured from AXIOM_TOKEN / AXIOM_DATASET / AXIOM_ORG_ID / AXIOM_EDGE_URL. Created on first use, so env loaded after import still applies.

const provider: AxiomLogger

Core Interface

Implements @molecule/api-logger interface.

Bond Wiring

Setup function to register this provider with the core interface:

import { setLogger } from '@molecule/api-logger'
import { provider } from '@molecule/api-logger-axiom'

export function setupLoggerAxiom(): void {
  setLogger(provider)
}

Injection Notes

Requirements

Peer dependencies:

  • @molecule/api-logger ^1.0.1

Environment Variables

  • AXIOM_TOKEN (optional) — Axiom API token
  • AXIOM_DATASET (optional) — Axiom dataset
    • Setup: Name of the Axiom dataset events are sent to. Unset disables sending.
    • Example: my-app-prod
  • AXIOM_ORG_ID (optional) — Axiom org id
    • Setup: Only needed with a personal token; API tokens carry their org.
  • AXIOM_EDGE_URL (optional) — Axiom edge URL
    • Setup: Edge deployment base URL for region-local ingest; unset uses https://api.axiom.co.
    • Example: https://eu-central-1.aws.edge.axiom.co

Runtime Dependencies

  • @molecule/api-analytics-axiom

  • @molecule/api-logger

  • No token or no dataset → console only. enabled is false and nothing is queued; the inner logger still gets every line. Same env vars as @molecule/api-analytics-axiom: AXIOM_TOKEN, AXIOM_DATASET, AXIOM_ORG_ID, AXIOM_EDGE_URL. Pass dataset to send logs to a different dataset than your events.

  • Two level gates apply in order: the logger CORE's (LOG_LEVEL, default info) drops lines before this provider sees them; then level (default info) decides which of the remaining lines are mirrored to Axiom.

  • Arguments are split into message (strings, numbers, booleans joined by spaces) and fields (plain objects merged; an Error becomes error: { name, message, stack }). With fieldsMode: 'json' (the default) fields are ONE string field, so arbitrary log keys never add columns to the dataset — Axiom caps fields per dataset (256 on the free plan) — and you query them with parse_json(fields). fieldsMode: 'object' stores one column per key.

  • inner: null sends to Axiom only. The default inner logger writes to the console; pass another provider (pino, winston) to keep its formatting.

  • Ingest failures warn through console.warn at most once a minute per kind and never through this logger, so an unreachable Axiom cannot loop.

  • Short-lived processes: await logger.shutdown() (or flush()) before exit. shutdown({ deadlineMs }) bounds the final drain (default 5000 ms; raise it if your host waits longer before killing the process): at the deadline every send still running stops, including one already in flight, and unsent lines are counted as dropped with one warning.

  • Memory is bounded twice: at most maxQueueEvents (10 000) lines and maxQueueBytes (32 MB) wait in memory; past either, NEW lines are dropped (the inner logger still gets them), and a single line larger than maxBatchBytes (1 MB) is never queued.