# @safaricom-mxl/node-sdk

Server-side OpenTelemetry SDK for Node.js services.

## Install

```bash
npm install @safaricom-mxl/node-sdk
```

## Quick start

```ts
import { initSDK } from '@safaricom-mxl/node-sdk';

initSDK({
  serviceName: 'orders-api',
});
```

## CLI preload

```bash
opentelemetry-instrument ./dist/server.js
```

## Framework helpers

- Express: `setupExpressErrorHandler`
- Koa: `setupKoaErrorHandler`
- Fastify: `setupFastifyErrorHandler`
- Nest: `createNestLogger`

## Logger adapters

- Pino: `getPinoTransport`, `getPinoMixinFunction`
- Winston: `getWinstonTransport`
- evlog (wide events): `createEvlogDrain`, `getEvlogDrain`, `createOtelTraceEnricher`, `createAuditOtelDrain`, `parseEvlogEvent`, `OTelEvlogBridge`

Install the peer when using evlog:

```bash
npm install evlog
```

After `initSDK()`, wire evlog so wide events use the same OTLP log pipeline as Pino/Winston. Use `createOtelTraceEnricher()` so logs pick up the active OpenTelemetry span (not only the `traceparent` header). Use `createAuditOtelDrain()` for audit-only events under instrumentation scope `evlog.audit`.

```ts
import express from 'express';
import { initLogger } from 'evlog';
import { evlog } from 'evlog/express';
import {
  initSDK,
  createEvlogDrain,
  createOtelTraceEnricher,
  createAuditOtelDrain,
} from '@safaricom-mxl/node-sdk';

initSDK({ serviceName: 'orders-api' });
initLogger({ env: { service: 'orders-api' } });

const app = express();
app.use(
  evlog({
    enrich: createOtelTraceEnricher(),
    drain: async (ctx) => {
      await Promise.allSettled([
        createEvlogDrain()(ctx),
        createAuditOtelDrain()(ctx),
      ]);
    },
  }),
);
```

Subpath import (same API):

```ts
import { createEvlogDrain } from '@safaricom-mxl/node-sdk/logger/evlog';
```

Optional: add `createFsDrain()` from `evlog/fs` so events are also written under `.evlog/logs/` for local analysis.

Agent skill workflows that pair well with this setup: `/review-logging-patterns`, `/build-audit-logs`, `/analyze-logs`.

## Environment variables

- `OTEL_SERVICE_NAME`
- `OTEL_EXPORTER_OTLP_ENDPOINT`
- `OTEL_EXPORTER_OTLP_PROTOCOL` (`http/protobuf`, `http/json`, `grpc`)
- `OTEL_EXPORTER_OTLP_HEADERS`
- `OTEL_TRACES_SAMPLER`
- `OTEL_TRACES_SAMPLER_ARG`
- `MXL_NODE_ADVANCED_NETWORK_CAPTURE`
- `MXL_NODE_SENTRY_INTEGRATION_ENABLED`

## Troubleshooting

- Ensure collector protocol matches `OTEL_EXPORTER_OTLP_PROTOCOL`.
- If logs are missing, confirm `OTEL_LOGS_EXPORTER` is not set to `none`.
- For preload mode in bundled apps, verify the preload command runs before app bootstrap.
