npm package: @fullstackhouse/nestjs-logger-middleware
Description: A configurable HTTP logger middleware for NestJS applications
Latest version: 1.1.0

# NestJS Logger Middleware

Configurable HTTP request/response logger middleware for NestJS applications.

## Installation

```bash
npm install @fullstackhouse/nestjs-logger-middleware
```

## Usage

### Basic Usage (Module)

Import and configure the module in your `AppModule`:

```typescript
import { Module } from "@nestjs/common";
import { LoggerMiddlewareModule } from "@fullstackhouse/nestjs-logger-middleware";

@Module({
  imports: [LoggerMiddlewareModule.forRoot()],
})
export class AppModule {}
```

### With Configuration

```typescript
import { Module } from "@nestjs/common";
import { LoggerMiddlewareModule } from "@fullstackhouse/nestjs-logger-middleware";

@Module({
  imports: [
    LoggerMiddlewareModule.forRoot({
      routes: "*", // default, can be string or array of strings
      skipPaths: ["/health", /^\/metrics/],
      logHeaders: ["x-user-id", "x-tenant-id"],
      logClientIp: true,
      logUserAgent: true,
      logContext: (req) => ({ userId: req.headers["x-user-id"] }),
    }),
  ],
})
export class AppModule {}
```

### Manual Middleware Application

You can also apply the middleware manually:

```typescript
import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";
import { LoggerMiddleware } from "@fullstackhouse/nestjs-logger-middleware";

@Module({})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes("*");
  }
}
```

## Configuration Options

### Module Options

| Option            | Type                                                                  | Default     | Description                                           |
| ----------------- | --------------------------------------------------------------------- | ----------- | ----------------------------------------------------- |
| `routes`          | `string \| string[]`                                                  | `'*'`       | Routes to apply the middleware to                     |
| `skipPaths`       | `(string \| RegExp)[]`                                                | `[]`        | Paths to skip logging (unless error occurs)           |
| `logRequestBody`  | `boolean`                                                             | `false`     | Include request body in logs                          |
| `logResponseBody` | `boolean`                                                             | `false`     | Include response body in logs                         |
| `logClientIp`     | `boolean`                                                             | `false`     | Extract and log client IP from headers/request        |
| `logUserAgent`    | `boolean`                                                             | `false`     | Extract and log user agent                            |
| `logHeaders`      | `string[]`                                                            | `[]`        | Additional headers to extract and log                 |
| `logTrace`        | `boolean`                                                             | `true`      | Extract and log trace ID from headers or generate one |
| `logContext`      | `(req, res?) => Record<string, unknown>`                              | `undefined` | Function to extract custom context for logs           |
| `skip`            | `(req, res?) => boolean \| { request?: boolean; response?: boolean }` | `undefined` | Dynamic skip function for request/response logs       |

## Logged Information

### Request Logs

- HTTP method
- Request path
- Client IP (if enabled)
- User agent (if enabled)
- Trace ID (from `sentry-trace`, `x-trace-id`, or auto-generated)
- Custom headers (if configured)
- Request body (if enabled)

### Response Logs

- HTTP method
- Request path
- Status code
- Response time
- Query parameters (if present)
- Client IP (if enabled)
- User agent (if enabled)
- Trace ID
- Custom headers (if configured)

## Examples

### Skip Health Checks in Production

```typescript
LoggerMiddlewareModule.forRoot({
  skipPaths:
    process.env.NODE_ENV === "production" ? ["/health", "/metrics"] : [],
});
```

### Extract User Context from Headers

```typescript
LoggerMiddlewareModule.forRoot({
  logHeaders: ["x-user-id", "x-tenant-id", "x-organization-id"],
});
```

### Debug Mode with Request Bodies

```typescript
LoggerMiddlewareModule.forRoot({
  logRequestBody: process.env.NODE_ENV !== "production",
});
```

### Dynamic Logging Context

```typescript
LoggerMiddlewareModule.forRoot({
  logContext: (req, res) => {
    const trace = req.headers["sentry-trace"]?.split("-")[0];
    return {
      trace,
      userId: req.headers["x-user-id"],
      tenant: req.headers["x-tenant-id"],
    };
  },
});
```

### Dynamic Skip Logic

```typescript
LoggerMiddlewareModule.forRoot({
  skip: (req, res) => {
    // Skip both request and response logs for health checks
    if (req.path === "/health") return true;

    // Skip only response logs for successful requests
    if (res && res.statusCode < 400) {
      return { response: true };
    }

    return false;
  },
});
```

### Apply to Specific Routes

```typescript
LoggerMiddlewareModule.forRoot({
  routes: ["/api/*", "/admin/*"],
  logClientIp: true,
  logUserAgent: true,
});
```

## License

MIT