# What Logging Is Used for Non-TTY CloddsBot Runs: Pino-Based JSON Strategy

> Discover how CloddsBot uses Pino-based JSON logging for non-TTY runs, ensuring machine-readable records for daemons CI pipelines and Docker containers.

- Repository: [AL/CloddsBot](https://github.com/alsk1992/CloddsBot)
- Tags: how-to-guide
- Published: 2026-09-13

---

**CloddsBot uses a structured Pino logger that automatically writes JSON-formatted logs to `~/.clodds/logs/clodds.log` when running without a TTY, falling back from pretty-printed console output to ensure machine-readable records for daemons, CI pipelines, and Docker containers.**

The `alsk1992/CloddsBot` repository implements a robust logging strategy specifically designed to handle non-interactive execution environments. When the process detects it is not attached to an interactive terminal, the system switches from human-readable formatting to structured JSON output, ensuring that log aggregation systems can parse entries without interference from ANSI color codes or multi-line formatting.

## Core Logger Architecture in [`src/utils/logger.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/logger.ts)

The foundation of CloddsBot’s logging system resides in [`src/utils/logger.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/logger.ts), where the root Pino logger is instantiated using `pino({ level }, transport)`. The module exports a `defaultLogger` instance and a `createLogger(name)` factory function that returns **child loggers** inheriting the root configuration.

The transport configuration dynamically selects between `pino-pretty` for development environments and raw JSON streams for production or non-TTY scenarios. This automatic selection ensures that CI/CD pipelines and containerized deployments receive parseable structured data without manual configuration changes.

## Environment-Driven Configuration

CloddsBot’s logger behavior is controlled through three primary environment variables:

- **`LOG_LEVEL`** – Sets the minimum severity threshold (default: `info`). Accepts standard Pino levels: `trace`, `debug`, `info`, `warn`, `error`, `fatal`.

- **`LOG_FILE`** – Controls file output persistence. Set to `"false"` to disable file logging entirely; otherwise, logs write to the default path.

- **`LOG_JSON`** – Forces JSON output mode when set to `"true"`, overriding the automatic TTY detection.

When `LOG_FILE` is not explicitly disabled, the logger maintains a persistent stream to `~/.clodds/logs/clodds.log`, ensuring that log history survives container restarts and daemon detachments.

## Non-TTY Detection and Output Modes

The system distinguishes between interactive and non-interactive execution through TTY detection logic embedded in the transport configuration. The behavior follows this decision tree:

1. **TTY attached + `LOG_JSON` ≠ `"true"`** – Uses `pino-pretty` transport with colorized, indented formatting for human readability.
2. **Non-TTY OR `LOG_JSON` = `"true"`** – Falls back to raw JSON output with newline-delimited objects, suitable for log shippers like Fluentd, Logstash, or AWS CloudWatch.

This approach prevents pretty-printed logs from corrupting JSON-RPC communication streams and ensures that automated log parsers can extract fields like `level`, `msg`, `time`, and custom child properties without regex manipulation.

## File Rotation and Retention Policies

For long-running non-TTY processes such as trading bots or persistent agents, [`src/utils/logger.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/logger.ts) implements automatic log rotation to prevent disk exhaustion:

- **`maxFileSize`** – Rotates files when they exceed 10 MiB (default).
- **`maxFiles`** – Retains the 5 most recent rotated log files (default).

The rotation mechanism archives older logs with numeric suffixes (e.g., `clodds.log.1`, `clodds.log.2`) while maintaining the active write stream to the primary file. This configuration balances historical debugging capability against storage constraints in production environments.

## Practical Implementation Examples

Import the default logger for standard operational logging:

```typescript
import { defaultLogger as logger } from './utils/logger';

// Writes JSON to file and stdout when non-TTY
logger.info('Bot started', { pid: process.pid, version: '1.2.0' });

// Create component-specific child logger
const tradeLogger = logger.child({ name: 'trade-engine' });
tradeLogger.debug('Order execution initiated', { 
  symbol: 'BTC/USD', 
  size: 0.5,
  orderId: 'abc123'
});

```

When executed without a TTY (e.g., `docker run alsk1992/cloddsbot` or systemd service), the output in `~/.clodds/logs/clodds.log` appears as:

```json
{"level":"info","msg":"Bot started","time":"2024-09-13T12:34:56.789Z","pid":12345,"version":"1.2.0"}
{"level":"debug","msg":"Order execution initiated","time":"2024-09-13T12:35:00.123Z","name":"trade-engine","symbol":"BTC/USD","size":0.5,"orderId":"abc123"}

```

For handler-specific logging, [`src/agents/handlers/predictfun.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/agents/handlers/predictfun.ts) demonstrates the `createLogger()` pattern, while [`src/utils/config.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/config.ts) shows configuration-time logger initialization.

## Summary

- **Non-TTY logging** in CloddsBot relies on a Pino-based implementation in [`src/utils/logger.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/logger.ts) that automatically switches from pretty-printed to JSON output when stdout is not a terminal.
- **Structured JSON logs** write to `~/.clodds/logs/clodds.log` by default, with automatic rotation at 10 MiB and retention of 5 historical files.
- **Environment variables** (`LOG_LEVEL`, `LOG_JSON`, `LOG_FILE`) control severity filtering, output format coercion, and file persistence without code changes.
- **Child loggers** created via `createLogger(name)` inherit root configuration while adding component-specific context for traceability in distributed systems.

## Frequently Asked Questions

### How do I change the default log file location?

Set the `LOG_FILE` environment variable to your desired absolute path before starting the bot. If the directory does not exist, the logger will attempt to create it on initialization. Setting `LOG_FILE="false"` disables file output entirely, sending logs only to stdout.

### Why does my Docker container output JSON instead of formatted text?

When Docker runs containers without a pseudo-TTY (`docker run` without `-t` flag), `process.stdout.isTTY` evaluates to `undefined`, triggering the non-TTY code path. To force pretty printing in Docker for debugging, either attach a TTY with `docker run -t` or set `LOG_JSON="false"` explicitly.

### Can I disable log rotation or adjust the retention count?

The rotation settings (`maxFileSize` and `maxFiles`) are currently hardcoded to 10 MiB and 5 files respectively in [`src/utils/logger.ts`](https://github.com/alsk1992/CloddsBot/blob/main/src/utils/logger.ts). To customize these values, you must modify the Pino transport configuration in the source file and rebuild the application.

### What is the difference between `defaultLogger` and `createLogger()`?

`defaultLogger` is the singleton root instance used for general application logging, while `createLogger(name)` is a factory function that returns a child logger with a bound `name` property. Child loggers automatically include their component name in every log entry, making them ideal for correlating logs across different subsystems like trade engines or prediction handlers.