npm package: @inso_web/els-express
Description: Express middleware для @inso_web/els-client с request-scoped логированием (req.log) и error handler. Drop-in замена pino-http и morgan + winston.
Author: INSOWEB
Latest version: 0.3.0

# @inso_web/els-express

[![npm version](https://img.shields.io/npm/v/@inso_web/els-express.svg)](https://www.npmjs.com/package/@inso_web/els-express)
[![npm downloads](https://img.shields.io/npm/dm/@inso_web/els-express.svg)](https://www.npmjs.com/package/@inso_web/els-express)
[![bundle size](https://img.shields.io/bundlephobia/minzip/@inso_web/els-express)](https://bundlephobia.com/package/@inso_web/els-express)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![TypeScript](https://img.shields.io/badge/TypeScript-strict-blue)](https://www.typescriptlang.org/)

Express middleware и error handler для централизованного логирования через [`@inso_web/els-client`](https://www.npmjs.com/package/@inso_web/els-client). Drop-in замена для `pino-http`, `morgan + winston`, `express-pino-logger`.

## Что внутри

- **`createELSExpressLogger`** — middleware, добавляет `req.log` (child-logger с request id) и `req.id`, авто-логирует завершённые запросы (`info` для 2xx/3xx, `warn` для 4xx, `error` для 5xx)
- **`createELSErrorHandler`** — error handler middleware, ловит throw, шлёт в ELS, отвечает 500
- **Re-export `ELSClient`** — чтобы можно было ставить только этот пакет, без отдельного `@inso_web/els-client`

## Quick Start

```bash
npm i @inso_web/els-express express
```

```ts
import express from "express";
import {
  ELSClient,
  createELSExpressLogger,
  createELSErrorHandler,
} from "@inso_web/els-express";

// 1. Создаём клиент-логгер один раз при старте приложения
const log = new ELSClient({
  endpoint: "https://api.insoweb.ru/els",
  apiKey: process.env.ELS_API_KEY!,
  appSlug: "my-api",
  serviceName: "api-server",
  deploymentEnv: "PRODUCTION",
  minLevel: "info",
});

const app = express();

// 2. Middleware — добавляет req.log и авто-логирует request finish
app.use(createELSExpressLogger({ client: log }));

app.get("/users/:id", (req, res) => {
  // Используем req.log как обычный логгер — у него уже есть requestId, method, url
  req.log.info({ userId: req.params.id }, "Fetching user");
  res.json({ id: req.params.id });
});

// 3. Error handler — последним
app.use(createELSErrorHandler(log));

app.listen(3000);
```

## Migration from pino-http

```diff
- import pinoHttp from 'pino-http';
- app.use(pinoHttp());
+ import { ELSClient, createELSExpressLogger } from '@inso_web/els-express';
+ const log = new ELSClient({ endpoint, apiKey, appSlug });
+ app.use(createELSExpressLogger({ client: log }));

// В handler ничего менять не нужно:
req.log.info('msg');  // ← работает как раньше, только шлёт в ELS
```

## Migration from morgan + winston

```diff
- import morgan from 'morgan';
- import winston from 'winston';
- const winstonLog = winston.createLogger({ level: 'info', transports: [...] });
- app.use(morgan('combined'));
+ import { ELSClient, createELSExpressLogger } from '@inso_web/els-express';
+ const log = new ELSClient({ endpoint, apiKey, appSlug });
+ app.use(createELSExpressLogger({ client: log }));

// morgan заменяется на autoLogRequests: true (default)
// winston заменяется на ELSClient — те же методы .info/.warn/.error
```

## Migration from express-pino-logger

```diff
- import expressPinoLogger from 'express-pino-logger';
- app.use(expressPinoLogger());
+ import { ELSClient, createELSExpressLogger } from '@inso_web/els-express';
+ const log = new ELSClient({ endpoint, apiKey, appSlug });
+ app.use(createELSExpressLogger({ client: log }));
```

## Configuration

```ts
createELSExpressLogger({
  client,                           // ELSClient инстанс — обязательно
  reqIdHeader: "x-request-id",      // имя HTTP заголовка для request id
  genReqId: (req) => req.headers["my-trace-id"] as string,  // кастомный генератор
  autoLogRequests: true,            // авто-лог завершённых запросов
  ignorePaths: ["/health", /\/metrics/],  // не логировать эти пути
});
```

## API

### `req.log`
Child-logger с биндингами `{ requestId, method, url, ip }`. Полный Pino-совместимый API: `info`, `warn`, `error`, `debug`, `trace`, `fatal`, `child`.

### `req.id`
Request ID для текущего запроса. Берётся из заголовка `x-request-id` если есть, иначе генерируется UUID v4.

## FAQ

**Можно ли использовать без авто-логирования?** Да: `createELSExpressLogger({ client, autoLogRequests: false })`. Тогда middleware только добавит `req.log` и `req.id`.

**Что с пропуском health-чеков?** Используй `ignorePaths: ['/health', '/ready']` — middleware будет пропускать эти пути целиком.

**Совместимо с TypeScript?** Да, типы `Express.Request` augmented автоматически — `req.log` и `req.id` появятся в IntelliSense.

## Examples

См. `./examples/` — рабочие примеры Express серверов.

## License

MIT