[data-reveal]{opacity:1!important;transform:none!important}
Logging
Core

Logging

Overview

Use Logging.Info for a status message, or a named channel when you want to distinguish one part of the application. These calls emit structured events. The runtime's listener decides how to display them; the interface does not itself write a file or send logs to a service.

Write your first message

import { Logging } from "@antelopejs/interface-core/logging";

Logging.Info("Worker started");

const jobs = new Logging.Channel("jobs");
jobs.Info("Job completed", { jobId: "job-42", durationMs: 120 });

The first event uses channel main; the second uses jobs. Both have level INFO (20). Inside an AntelopeJS project, the runtime's logging configuration determines whether they appear in the output. Without a registered listener, events are not retained for later display.

Log identifiers and outcomes rather than credentials, tokens, or complete request bodies. Arguments reach listeners unchanged; this interface does not redact secrets or serialize arbitrary objects for you.

For ordinary application code, the level and channel methods below are enough. Custom listeners are for integrations that need their own output destination or formatting.

Severity levels

The Logging.Level enum defines the available severity levels:

LevelValuePurpose
ERROR40Critical errors that may cause failure
WARN30Issues that do not prevent operation
INFO20General status updates and information
DEBUG10Detailed information for debugging
TRACE0Highly detailed tracing information
NO_PREFIX-1Messages displayed without a level prefix

Log to the main channel

The Logging namespace exposes convenience functions that write to the "main" channel:

import { Logging } from "@antelopejs/interface-core/logging";

Logging.Error("Database connection failed");
Logging.Warn("Retrying database connection");
Logging.Info("Server started on port", 5011);
Logging.Debug("Request completed", { requestId: "req-42", status: 200 });
Logging.Trace("Entering function processItem");

Each function accepts any number of arguments of any type.

Use named channels

For categorized logging, create a Logging.Channel instance with a channel name:

import { Logging } from "@antelopejs/interface-core/logging";

const dbLog = new Logging.Channel("database");
const httpLog = new Logging.Channel("http");

dbLog.Info("Connection established");
dbLog.Error("Query failed", { operation: "listUsers" });

httpLog.Info("GET /api/users", 200);
httpLog.Debug("Response sent", { requestId: "req-42" });

Channels provide the same methods as the main logging functions: Error, Warn, Info, Debug, and Trace.

Write at a custom level

Use the Write function for logs at a custom severity level:

// Static function on the Logging namespace
Logging.Write(25, "custom-channel", "Custom level message");

// Instance method on a channel
const channel = new Logging.Channel("metrics");
channel.Write(15, "Custom level within the metrics channel");

Log entry structure

Each log entry emitted through the event system has the following structure:

interface Log {
  time: number; // Timestamp in milliseconds since epoch
  channel: string; // Channel name (e.g., "main", "database")
  levelId: number; // Numeric severity level
  args: any[]; // The logged values
}

Listen for log events

Register a listener before emitting the messages you want to receive. This example selects warning and error events for console output; it leaves other levels alone.

import { Logging } from "@antelopejs/interface-core/logging";
import eventLog, {
  type Log,
} from "@antelopejs/interface-core/logging/listener";

function writeWarning(log: Log) {
  if (log.levelId < Logging.Level.WARN) return;
  const date = new Date(log.time).toISOString();
  console.warn(`[${date}] [${log.levelId}] [${log.channel}]`, ...log.args);
}

eventLog.register(writeWarning);
Logging.Warn("Retry scheduled");
// When this subscription is no longer needed:
eventLog.unregister(writeWarning);

Keep the same function reference to unsubscribe. The runtime also removes module-owned listeners when their owner is destroyed. A second console listener may duplicate output already written by the runtime.

Listeners run synchronously. A slow listener delays the logging call, and emit does not await promises from asynchronous listeners. Handle asynchronous failures inside your listener. Do not call Logging.* from a log listener: that emits another log event and can recurse indefinitely.

Project logging filters belong to the runtime's output listener. A custom listener receives raw events and must apply its own filtering and redaction. NO_PREFIX is a level convention for formatters, not a bypass for these responsibilities.

Next steps

  • Configuration - Project configuration with logging settings
  • Proxies - Understand the EventProxy that powers the logging transport