# @coralogix/opentelemetry

> Coralogix extensions for the OpenTelemetry Node SDK, including a transaction sampler for Coralogix APM.

Latest version **0.5.0** (published 2026-08-26) · Apache-2.0 license · 0 weekly downloads

## Install

```sh
npm install @coralogix/opentelemetry
pnpm add @coralogix/opentelemetry
yarn add @coralogix/opentelemetry
bun add @coralogix/opentelemetry
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; has provenance; recently updated; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.5.0 |
| Published | 2026-08-26 |
| First published | 2023-11-22 |
| Weekly downloads | 0 |
| License | Apache-2.0 |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 354.5 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 0 |
| Maintainers | coralogixnpm, ashley-hunter-cx, cx-shaharkazaz |

## Links

- npm: https://www.npmjs.com/package/@coralogix/opentelemetry
- Repository: https://github.com/coralogix/coralogix-opentelemetry-js
- Homepage: https://github.com/coralogix/coralogix-opentelemetry-js#readme
- Issues: https://github.com/coralogix/coralogix-opentelemetry-js/issues
- npm.io page: https://npm.io/package/@coralogix/opentelemetry

## Dependencies (1)

- [@opentelemetry/semantic-conventions](https://npm.io/package/@opentelemetry/semantic-conventions.md) ^1.25.1

## Recent versions

- 0.5.0 (latest) — 2026-08-26
- 0.4.0 — 2026-07-08
- 0.3.0 — 2026-07-07
- 0.2.1 — 2026-07-01
- 0.2.0 — 2026-06-30
- 0.1.4 — 2026-06-26
- 0.1.3 — 2024-07-29
- 0.1.2 — 2023-12-04
- 0.1.1 — 2023-11-22
- 0.1.0 — 2023-11-22

## README

# coralogix-opentelemetry-js

[![npm version](https://img.shields.io/npm/v/@coralogix/opentelemetry.svg)](https://www.npmjs.com/package/@coralogix/opentelemetry)
[![License: Apache-2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](./LICENSE)

Coralogix extensions for the [OpenTelemetry Node SDK](https://github.com/open-telemetry/opentelemetry-js). This package adds Coralogix-specific behavior on top of a standard OpenTelemetry tracing setup — transaction tagging via a sampler and/or a `SpanProcessor`, including exclusive self duration on the processor path.

```bash
npm install --save @coralogix/opentelemetry
```

## Requirements

This package relies on your application's existing OpenTelemetry setup. The following are `peerDependencies` and must be installed alongside it:

| Package | Version |
| --- | --- |
| `@opentelemetry/api` | `^1.7.0` |
| `@opentelemetry/sdk-trace-base` | `^2.8.0` |

The examples below also use `@opentelemetry/resources` and `@opentelemetry/semantic-conventions`, which are part of a typical OpenTelemetry Node setup.

> **Note:** This package targets OpenTelemetry JS SDK **2.x**. The resource/provider APIs shown below (`resourceFromAttributes`, `ATTR_SERVICE_NAME`) are the 2.x APIs; if you are still on SDK 1.x, adapt the setup accordingly (`new Resource(...)`, `SemanticResourceAttributes`).

## CoralogixTransactionSampler

`CoralogixTransactionSampler` wraps an existing OpenTelemetry sampler to define, report, and monitor Coralogix [transactions](https://coralogix.com/docs/user-guides/apm/features/transactions/). It sets Coralogix transaction attributes on sampled spans and propagates the transaction identity across the trace.

```js
import { CoralogixTransactionSampler } from "@coralogix/opentelemetry";
import { AlwaysOnSampler } from "@opentelemetry/sdk-trace-base";

// Wrap your existing sampler...
const sampler = new CoralogixTransactionSampler(new AlwaysOnSampler());

// ...or omit the argument to default to a ParentBased(AlwaysOn) sampler.
const defaultSampler = new CoralogixTransactionSampler();
```

Pass the sampler to your tracer provider like any other OpenTelemetry sampler:

```js
import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";

const tracerProvider = new BasicTracerProvider({
    resource: resourceFromAttributes({
        [ATTR_SERVICE_NAME]: "<your-service-name>",
    }),
    sampler: new CoralogixTransactionSampler(),
});
```

### Supported instrumentation

It works with [individual auto-instrumentation](https://coralogix.com/docs/opentelemetry/instrumentation-options/nodejs-opentelemetry-instrumentation/#individual-auto-instrumentation) and [manual instrumentation](https://coralogix.com/docs/opentelemetry/instrumentation-options/nodejs-opentelemetry-instrumentation/#manual-instrumentation). The bundled auto-instrumentation method is **not** supported.

### Emitted attributes

When a span starts a transaction, the sampler adds the following attributes:

| Attribute | Description |
| --- | --- |
| `cgx.transaction` | The transaction name (e.g. `GET /users/:id`). |
| `cgx.transaction.distributed` | The distributed transaction name propagated across services. |
| `cgx.transaction.root` | Whether this span is the root of the transaction. |

## TransactionSpanProcessor

`TransactionSpanProcessor` wraps a `SpanExporter` to tag Coralogix transactions, stamp exclusive self duration (`cgx.transaction.self_duration`, seconds) on completed local traces, and record the matching histogram (unit `s`). It works with any sampler.

### How naming works

Transaction **membership** (new vs inherit, and `cgx.transaction.root`) is decided on span start. The display name `cgx.transaction` is stamped only when a completed local trace is finalized for export, using `overrideName ?? rootSpan.name`. That matters for Express: the HTTP span often starts as `GET` and is later renamed to `GET /myroute` by middleware — the exported transaction name is the final root span name.

### Harvest defaults (data loss)

By default the processor keeps only the **slowest** completed local trace(s) for each harvest window:

| Behavior | Default |
| --- | --- |
| Spans kept per local trace | `maxNodes: 256` (slowest first; transaction roots always kept) |
| Traces kept until harvest | `maxRegularTraces: 1` |
| Harvest period | `harvestPeriodMillis: 60_000` (60s) |

**Data-loss implication:** with `maxRegularTraces: 1`, every completed local trace that is *not* the slowest in the current harvest window is **not** exported as a full waterfall. Losers are reduced to **root-only stubs** (APM presence) and dropped from the detailed export. Self-duration **metrics** are still recorded for every completed local trace, including losers.

Set `maxRegularTraces: 0` to export every completed trimmed trace immediately (no harvest competition). Setting `harvestPeriodMillis: 0` also disables the heap and exports immediately.

```js
import { BasicTracerProvider, ConsoleSpanExporter } from "@opentelemetry/sdk-trace-base";
import { TransactionSpanProcessor } from "@coralogix/opentelemetry";

const tracerProvider = new BasicTracerProvider({
    spanProcessors: [
        new TransactionSpanProcessor(new ConsoleSpanExporter(), {
            // Optional MeterProvider for the self-duration histogram; defaults to the global one.
            // maxRegularTraces: 0, // export all completed traces (tests / debugging)
        }),
    ],
});
```

### Options

Constructor options win over environment variables. Invalid env values fall back to the default.

| Option | Type | Default | Env var | Meaning |
| --- | --- | --- | --- | --- |
| `maxNodes` | `number` | `256` | `OTEL_CX_TRANSACTION_MAX_NODES` | Max spans kept per completed local trace (slowest first; roots always kept). |
| `maxRegularTraces` | `number` | `1` | `OTEL_CX_TRANSACTION_MAX_REGULAR_TRACES` | Max full traces retained until harvest (slowest-N). `0` = export every completed trimmed trace immediately. Losers become root stubs. |
| `harvestPeriodMillis` | `number` | `60000` | `OTEL_CX_TRANSACTION_HARVEST_PERIOD_MILLIS` | Harvest flush interval. `<= 0` exports every completed trace immediately (no heap). |
| `completionHoldbackMillis` | `number` | `100` | `OTEL_CX_TRANSACTION_COMPLETION_HOLDBACK_MILLIS` | After the last live span ends, wait this long before finalize so late siblings can join. `0` = finalize immediately. |
| `shutdownIdleWaitMillis` | `number` | `30000` | — | How long shutdown waits for in-flight spans. |
| `meterProvider` | `MeterProvider` | global | — | MeterProvider for the self-duration histogram. |

## Transactions with Express

To resolve stable, low-cardinality transaction names for Express routes (e.g. `GET /users/:id` instead of a per-request path), call `setExpressApp` so the sampler can learn your app's routes and endpoints.

> **Important:** Call `setExpressApp` **after all routes and routers have been registered**. The sampler reads the Express router stack at the moment you call it, so any routes added afterwards will not be resolved.

```javascript
import { BasicTracerProvider } from "@opentelemetry/sdk-trace-base";
import { resourceFromAttributes } from "@opentelemetry/resources";
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
import { CoralogixTransactionSampler } from "@coralogix/opentelemetry";
import express from "express";
import router from "./router";

const sampler = new CoralogixTransactionSampler();

const tracerProvider = new BasicTracerProvider({
    resource: resourceFromAttributes({
        [ATTR_SERVICE_NAME]: "<your-service-name>",
    }),
    sampler,
});

const app = express();
app.use("/", router);

// Register routes first, then hand the app to the sampler.
sampler.setExpressApp(app);

app.listen(3000, () => {
    console.log("Server is running");
});
```

### Prefixed and nested routers

`setExpressApp` resolves the **full** route template, including mount prefixes and arbitrarily nested routers. For example, given:

```javascript
const orders = express.Router();
orders.get("/orders/:oid", handler);

const api = express.Router();
api.use("/deep", orders);

app.use("/api", api);
```

a request to `/api/deep/orders/9` resolves to the transaction `GET /api/deep/orders/:oid`.

### Express version support

Both **Express 4** and **Express 5** are supported.

Parameters are templatized correctly on both versions, including a parameter used in a *mount prefix* (`app.use("/v/:ver", router)`): a request to `/v/2/things/abc` resolves to `GET /v/:ver/things/:t`.

## Changelog

See [CHANGELOG.md](./CHANGELOG.md) for release notes. Note that route-template resolution for prefixed and nested routers is a **breaking output change**: transaction names for affected apps change, so update any dashboards, alerts, or saved views keyed on the previous names.

## License

Licensed under the [Apache License 2.0](./LICENSE).

---
_Source: https://npm.io/package/@coralogix/opentelemetry · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
