npm package: @oneiriq/stoat-logger
Description: Stoat Logger is a simple and modular logging framework with support for multiple transports for Deno and NodeJS.
Author: oneiriq
Latest version: 1.1.1

# Stoat Logger 🐹

[![Build Status](https://img.shields.io/badge/Build-passing-brightgreen.svg)](https://github.com/oneiriq/stoat-logger) [![Deno Version](https://img.shields.io/badge/Deno-v2.4.1-green)](https://deno.land/) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![JSR](https://jsr.io/badges/@oneiriq/stoat-logger)](https://jsr.io/@oneiriq/stoat-logger)

Stoat is a simple and modular logging framework with support for multiple transports.

---

## Features

Originally developed as a structured logging framework, the Stoat Logger now supports a suite of common logging functionalities to support various logging needs such as FS integration, child loggers, observability/tracing, and custom serialization.

## Additional Features

### Performance

Stoat offers memory-efficient logging with zero-allocation paths for simple log entries, making it ideal for low-footprint applications.

- **Dynamic Log Levels**: Custom log levels with advanced management
- **Modular Transport Systems**: Console, file, HTTP, WebSocket, and custom transports for integration
- **Safe Fallbacks**: Fallbacks for sync logging under memory pressure

### **Security & Reliability**

A strong emphasis on security, reliability, and best practices went into ensuring safe logging in production environments.

- **Input Sanitization** with configurable redaction policies
- **Data Classification** (sensitive data marking and handling)
- **Error-Safe Design** (never throws, graceful fallbacks)

### **Observability & Tracing**

It also easily integrates with OpenTelemetry for distributed tracing, making it suitable for microservices and complex architectures.

- **OpenTelemetry Integration** (trace/span correlation)
- **Rich Context Propagation** for logging within microservices
- **Request Correlation** across distributed systems
- **Performance Timing** with built-in operation tracking

---

## Quick Start

### Basic Usage

```typescript
import { stoat } from '@oneiriq/stoat-logger'

const logger = stoat.create({
  level: 'info',
  prettyPrint: true
})

logger.trace('This is a trace message')
logger.info('Application started')
logger.warn('High process count', { process: 'app.exe', usage: 73 })
logger.error('Order execution failed', { orderId: 'ORD-123', error: 'timeout' })
```

### Example Output

```shell
2025-07-25T21:13:50.918Z INFO  [session:7fe340ff module:basic-stoat-examples_fileLogger] This goes to both console and file
2025-07-25T21:13:50.919Z ERROR [session:7fe340ff module:basic-stoat-examples_fileLogger] Error logged to file | {"error":"database_error"}
```

### Advanced Logging with `LogEntry`

```typescript
import {
  stoat,
  StructuredLogger,
  createAsyncLogger,
  ASYNC_CONFIGS
} from '@oneiriq/stoat-logger'

const structuredLogger = new StructuredLogger({
  pretty: true,
  maxDepth: 15,
  includeStackTrace: true,
  timestampFormat: 'iso'
})

const logEntry = structuredLogger.createLogEntry({
  level: 'info',
  message: 'Trade executed successfully',
  data: {
    orderId: 'ORD-123',
    symbol: 'NVDA',
    quantity: 100,
    price: 150.25,
    venue: 'NYSE'
  },
  context: {
    traceId: 'trace-abc-123',
    spanId: 'span-def-456',
    requestId: 'req-789',
    strategy: 'momentum',
    agentId: 'agent-001'
  }
})

const jsonOutput = structuredLogger.serialize(logEntry)
console.log(jsonOutput)
```

---

## Feature Overview

### Async Logging

```typescript
// async loggers
const asyncLogger = createAsyncLogger(
  ASYNC_CONFIGS.trading,
  (entry) => {
    console.log(JSON.stringify(entry))
  }
)

// Log thousands of entries without blocking
for (let i = 0; i < 10000; i++) {
  await asyncLogger.log({
    timestamp: new Date().toISOString(),
    level: 'info',
    levelValue: 30,
    message: `Low-footprint entry ${i}`,
    data: { tickId: i, latency: performance.now() }
  })
}

// Flush as required (or just allow auto-flush)
await asyncLogger.flush()
```

### Supports Multiple Transports

```typescript
const logger = stoat.create({
  transports: [
    createConsoleTransport({
      format: 'json',
      minLevel: 'debug'
    }),
    createFileTransport({
      path: './logs/app.log',
      format: 'text',
      minLevel: 'info',
      async: true,
      bufferSize: 1000
    }),
    createHttpTransport({
      endpoint: 'https://logs.company.com/ingest',
      minLevel: 'warn',
      batchSize: 100
    })
  ]
})
```

### Custom Serializers

```typescript
const serializer = createSerializer({
  maxDepth: 10,
  maxStringLength: 5000,
  enableCircularDetection: true,
  fastPaths: true,
  customSerializers: {
    'BigNumber': (value) => ({
      __type: 'bignumber',
      value: value.toString(),
      precision: value.decimalPlaces()
    }),
    'OrderId': (value) => ({
      __type: 'orderId',
      value: String(value)
    })
  }
})

const result = serializer.serialize(complexTradingObject)
console.log(`Serialized in ${result.serializationTime}ms`)
```

---

## Stoat Example

```typescript
import { stoat } from '@oneiriq/stoat-logger'

// Rich development logger with pretty-printing
const devLogger = stoat.create({
  level: 'trace',
  prettyPrint: true,
  structured: true,
  transports: [{
    type: 'console',
    format: 'json'
  }],
  serializer: {
    maxDepth: 20,
    includeStackTrace: true,
    includeNonEnumerable: true
  }
})

// Debug complex objects with full detail
const complexObject = {
  user: { id: 123, profile: { /* deep nesting */ } },
  orders: [/* large arrays */],
  metadata: new Map(),
  customTypes: new BigNumber('123.456')
}

devLogger.debug('Complex object analysis', complexObject)

// Performance debugging
const perfLogger = devLogger.child({
  component: 'performance-analysis'
})

const start = performance.now()
// ... some operation
perfLogger.trace('Operation timing', {
  operation: 'data-processing',
  duration: performance.now() - start,
  memoryBefore: process.memoryUsage(),
  memoryAfter: process.memoryUsage()
})
```

For more, see the **examples/** directory.

---

## Security Features

### Data Sanitization & Redaction

```typescript
import { createSanitizer } from '@oneiriq/stoat/security'

const logger = stoat.create({
  security: {
    enableSanitization: true,
    sanitizer: createSanitizer({
      redactFields: ['password', 'apiKey', 'ssn', 'creditCard'],
      redactRegexes: [
        /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g, // Credit cards
        /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g // Emails
      ],
      maxLogSize: 1024 * 1024, // 1MB limit
      enableTruncation: true
    })
  }
})

// Automatically redacts sensitive data
logger.info('User login', {
  userId: 123,
  email: 'user@example.com', // Will be redacted
  password: 'secret123',     // Will be redacted
  apiKey: 'key-abc-123'      // Will be redacted
})

// Output: { userId: 123, email: '[REDACTED]', password: '[REDACTED]', apiKey: '[REDACTED]' }
```

### Type-Safe Security Classification

```typescript
import { markSensitive, createSanitized } from '@oneiriq/stoat/types'

// Compile-time security classification
const customerData = markSensitive({
  ssn: '123-45-6789',
  creditScore: 750,
  income: 75000
})

const sanitizedInput = createSanitized(userInput) // Validated input

logger.info('Customer profile updated', {
  customerId: 123,
  data: customerData,    // Automatically handled as sensitive
  source: sanitizedInput // Marked as safe
})
```

## Development

```bash
# Clone repository
git clone https://github.com/oneiriq/stoat.git
cd stoat

# Run tests
deno task test

# Run benchmarks
deno task bench

# Format code
deno task fmt

# Lint code
deno task lint
```

---

## License

MIT License - see [LICENSE](LICENSE) file for details.