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
Unique identifier for the agent
Role of the agent (“root-planner”, “subplanner”, “worker”, or “reconciler”)
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
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
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
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
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
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
Unique identifier for the agent
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
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
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:
| Level | Order | Description | Default Output |
|---|
debug | 0 | Detailed diagnostic information | File only (unless LOG_LEVEL=debug) |
info | 1 | General informational messages | Stdout + File |
warn | 2 | Warning messages | Stdout + File |
error | 3 | Error messages | Stdout + File |
All log levels are always written to the log file. The stdout threshold is controlled by the LOG_LEVEL environment variable or setLogLevel().
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
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);
});