Skip to main content

Logger API

The Logger provides structured logging with dual output to both stdout and file, with configurable log levels and per-agent context tagging.

Logger Class

The main Logger class provides level-based logging methods with automatic context tagging.
class Logger {
  constructor(agentId: string, agentRole: AgentRole, taskId?: string);
  withTask(taskId: string): Logger;
  debug(message: string, data?: Record<string, unknown>): void;
  info(message: string, data?: Record<string, unknown>): void;
  warn(message: string, data?: Record<string, unknown>): void;
  error(message: string, data?: Record<string, unknown>): void;
}

Constructor

agentId
string
required
Unique identifier for the agent
agentRole
AgentRole
required
Role of the agent (“root-planner”, “subplanner”, “worker”, or “reconciler”)
taskId
string
Optional task ID to associate with all log entries

Methods

withTask

Create a new Logger instance with an associated task ID.
withTask(taskId: string): Logger
taskId
string
required
Task ID to associate with the new logger instance
Returns: A new Logger instance with the same agent context but with the specified task ID. Example:
const logger = createLogger("agent-1", "worker");
const taskLogger = logger.withTask("task-123");
taskLogger.info("Starting task execution");

debug

Log a debug-level message. Only written to stdout if LOG_LEVEL=debug.
debug(message: string, data?: Record<string, unknown>): void
message
string
required
Log message
data
Record<string, unknown>
Optional structured data to include
Example:
logger.debug("Processing file", { file: "src/index.ts", lines: 150 });

info

Log an info-level message.
info(message: string, data?: Record<string, unknown>): void
message
string
required
Log message
data
Record<string, unknown>
Optional structured data to include
Example:
logger.info("Task completed successfully", { duration: 5000, filesChanged: 3 });

warn

Log a warning-level message.
warn(message: string, data?: Record<string, unknown>): void
message
string
required
Log message
data
Record<string, unknown>
Optional structured data to include
Example:
logger.warn("High token usage detected", { tokensUsed: 50000, limit: 100000 });

error

Log an error-level message.
error(message: string, data?: Record<string, unknown>): void
message
string
required
Log message
data
Record<string, unknown>
Optional structured data to include
Example:
logger.error("Build failed", { exitCode: 1, stderr: "Type error in src/index.ts" });

Functions

createLogger

Factory function to create a new Logger instance.
function createLogger(agentId: string, role: AgentRole, taskId?: string): Logger
agentId
string
required
Unique identifier for the agent
role
AgentRole
required
Agent role type
taskId
string
Optional task ID to associate with log entries
Returns: A new Logger instance. Example:
import { createLogger } from "@longshot/core";

const logger = createLogger("worker-1", "worker", "task-123");
logger.info("Worker initialized");

enableFileLogging

Enable file logging for all Logger instances. Creates a timestamped NDJSON log file in <projectRoot>/logs/.
function enableFileLogging(projectRoot: string): string
projectRoot
string
required
Absolute path to the project root directory
Returns: Absolute path to the created log file. Example:
import { enableFileLogging } from "@longshot/core";

const logFilePath = enableFileLogging("/path/to/project");
console.log(`Logs will be written to: ${logFilePath}`);
// Output: Logs will be written to: /path/to/project/logs/run-2026-03-03T10-30-45.ndjson
Call this function once at startup from your main entry point. Subsequent calls are no-ops and return the existing log file path.

closeFileLogging

Close the log file stream. Call on graceful shutdown.
function closeFileLogging(): void
Example:
import { closeFileLogging } from "@longshot/core";

process.on("SIGTERM", () => {
  closeFileLogging();
  process.exit(0);
});

setLogLevel

Programmatically set the minimum log level for stdout output.
function setLogLevel(level: "debug" | "info" | "warn" | "error"): void
level
string
required
Minimum log level: “debug”, “info”, “warn”, or “error”
Example:
import { setLogLevel } from "@longshot/core";

setLogLevel("debug"); // Show debug messages on stdout
The default log level is info, which can be overridden by setting the LOG_LEVEL environment variable. Use setLogLevel() to override both the default and the environment variable.

getLogLevel

Get the current stdout log level.
function getLogLevel(): "debug" | "info" | "warn" | "error"
Returns: Current minimum log level for stdout output. Example:
import { getLogLevel } from "@longshot/core";

console.log(`Current log level: ${getLogLevel()}`);
// Output: Current log level: info

Log Levels

Log levels are ordered by severity:
LevelOrderDescriptionDefault Output
debug0Detailed diagnostic informationFile only (unless LOG_LEVEL=debug)
info1General informational messagesStdout + File
warn2Warning messagesStdout + File
error3Error messagesStdout + File
All log levels are always written to the log file. The stdout threshold is controlled by the LOG_LEVEL environment variable or setLogLevel().

Log Format

Logs are written as NDJSON (newline-delimited JSON) with the following structure:
{
  "timestamp": 1709467845000,
  "level": "info",
  "agentId": "worker-1",
  "agentRole": "worker",
  "taskId": "task-123",
  "message": "Task completed successfully",
  "data": {
    "duration": 5000,
    "filesChanged": 3
  }
}

Environment Variables

LOG_LEVEL
string
default:"info"
Minimum log level for stdout output. Valid values: debug, info, warn, error
Example:
LOG_LEVEL=debug node dist/main.js

Complete Example

import { createLogger, enableFileLogging, closeFileLogging } from "@longshot/core";

// Initialize file logging at startup
const logFile = enableFileLogging("/path/to/project");
console.log(`Logging to: ${logFile}`);

// Create a logger for a worker agent
const logger = createLogger("worker-1", "worker");

// Log general messages
logger.info("Worker started");
logger.debug("Internal state", { queue: [], ready: true });

// Create task-specific logger
const taskLogger = logger.withTask("task-123");
taskLogger.info("Starting task execution");

try {
  // Do work...
  taskLogger.info("Task completed", { duration: 5000 });
} catch (err) {
  taskLogger.error("Task failed", { error: String(err) });
}

// Cleanup on shutdown
process.on("SIGTERM", () => {
  logger.info("Shutting down");
  closeFileLogging();
  process.exit(0);
});

Build docs developers (and LLMs) love