Professional Logging
Astreus includes a professional logging system with structured output, color-coded messages, and consistent formatting. The logging system provides comprehensive visibility into agent operations, component interactions, and system events.
Logging Architecture
The Astreus logging system features:
- Structured Format: Consistent "Astreus [AgentName] Component → Message" format
- Color-coded Output: Different colors for different log levels
- Professional Appearance: Clean, readable logs without emojis
- Configurable Levels: Set LOG_LEVEL environment variable
- Component Tracking: Track specific components and operations
- Agent-specific Logs: Associate logs with specific agents
Basic Logging Usage
import { logger } from '@astreus-ai/astreus';
// Professional logging with consistent format
logger.info("MyAgent", "Database", "Connected to database successfully");
logger.debug("MyAgent", "Memory", "Storing conversation context");
logger.success("MyAgent", "Task", "Task completed successfully");
logger.warn("MyAgent", "Provider", "Rate limit approaching");
logger.error("MyAgent", "Plugin", "Plugin initialization failed");
Output format:
Astreus [MyAgent] Database → Connected to database successfully
Astreus [MyAgent] Memory → Storing conversation context
Astreus [MyAgent] Task → Task completed successfully
Astreus [MyAgent] Provider → Rate limit approaching
Astreus [MyAgent] Plugin → Plugin initialization failed
Log Levels
Astreus supports multiple log levels with color coding:
Available Log Levels
debug
(Gray): Detailed debugging informationinfo
(Blue): General information messagessuccess
(Green): Success confirmationswarn
(Yellow): Warning messageserror
(Red): Error messages
Setting Log Level
# Environment variable
LOG_LEVEL=debug node your-app.js
LOG_LEVEL=info node your-app.js
LOG_LEVEL=warn node your-app.js
LOG_LEVEL=error node your-app.js
// In your application
process.env.LOG_LEVEL = 'debug';
import { logger } from '@astreus-ai/astreus';
// These will all be displayed when LOG_LEVEL=debug
logger.debug("Agent", "Memory", "Searching for similar embeddings");
logger.info("Agent", "Chat", "Processing user message");
logger.success("Agent", "Response", "Generated response successfully");
logger.warn("Agent", "Provider", "Token usage is high");
logger.error("Agent", "Database", "Connection failed");
Component-Specific Logging
Track different components of your Astreus application:
Database Operations
import { createDatabase, logger } from '@astreus-ai/astreus';
async function setupDatabase() {
try {
logger.info("System", "Database", "Initializing database connection");
const db = await createDatabase();
logger.success("System", "Database", "Database connected successfully");
return db;
} catch (error) {
logger.error("System", "Database", `Connection failed: ${error.message}`);
throw error;
}
}
Memory Operations
import { createMemory, logger } from '@astreus-ai/astreus';
async function setupMemory(database) {
logger.info("System", "Memory", "Creating memory instance");
const memory = await createMemory({
database: database,
tableName: "conversations",
maxEntries: 1000,
enableEmbeddings: true
});
logger.success("System", "Memory", "Memory system initialized with embeddings");
logger.debug("System", "Memory", `Table: conversations, Max entries: 1000`);
return memory;
}
Agent Operations
import { createAgent, logger } from '@astreus-ai/astreus';
async function createAgentWithLogging(config) {
const agentName = config.name || 'DefaultAgent';
logger.info(agentName, "Initialization", "Creating agent instance");
try {
const agent = await createAgent(config);
logger.success(agentName, "Initialization", "Agent created successfully");
// Log available capabilities
const tools = agent.getAvailableTools();
logger.info(agentName, "Tools", `${tools.length} tools available: ${tools.join(', ')}`);
return agent;
} catch (error) {
logger.error(agentName, "Initialization", `Failed to create agent: ${error.message}`);
throw error;
}
}
Chat Operations
async function chatWithLogging(agent, message, sessionId) {
const agentName = agent.name || 'Agent';
logger.info(agentName, "Chat", `Processing message for session: ${sessionId}`);
logger.debug(agentName, "Chat", `Message length: ${message.length} characters`);
try {
const startTime = Date.now();
const response = await agent.chat({
message,
sessionId,
stream: false
});
const duration = Date.now() - startTime;
logger.success(agentName, "Chat", `Response generated in ${duration}ms`);
logger.debug(agentName, "Chat", `Response length: ${response.length} characters`);
return response;
} catch (error) {
logger.error(agentName, "Chat", `Failed to generate response: ${error.message}`);
throw error;
}
}
Streaming Chat Logging
Log streaming operations with real-time feedback:
async function streamingChatWithLogging(agent, message, sessionId) {
const agentName = agent.name || 'Agent';
logger.info(agentName, "Stream", `Starting streaming chat for session: ${sessionId}`);
let chunkCount = 0;
let totalChars = 0;
const startTime = Date.now();
try {
await agent.chat({
message,
sessionId,
stream: true,
onChunk: (chunk) => {
chunkCount++;
totalChars += chunk.length;
// Log every 10th chunk to avoid spam
if (chunkCount % 10 === 0) {
logger.debug(agentName, "Stream", `Chunk ${chunkCount}: ${totalChars} chars total`);
}
}
});
const duration = Date.now() - startTime;
logger.success(agentName, "Stream",
`Streaming completed: ${chunkCount} chunks, ${totalChars} chars in ${duration}ms`);
} catch (error) {
logger.error(agentName, "Stream", `Streaming failed: ${error.message}`);
throw error;
}
}
Plugin and Tool Logging
Track plugin operations and tool executions:
// Plugin initialization logging
async function initializePluginWithLogging(pluginClass, config) {
const pluginName = pluginClass.name || 'Plugin';
logger.info("System", "Plugin", `Initializing ${pluginName}`);
try {
const plugin = new pluginClass(config);
await plugin.init();
const tools = plugin.getTools ? plugin.getTools() : [];
logger.success("System", "Plugin",
`${pluginName} initialized with ${tools.length} tools`);
tools.forEach(tool => {
logger.debug("System", "Plugin", `Tool available: ${tool.name}`);
});
return plugin;
} catch (error) {
logger.error("System", "Plugin", `${pluginName} initialization failed: ${error.message}`);
throw error;
}
}
// Tool execution logging
async function executeToolWithLogging(tool, params, agentName = 'Agent') {
logger.info(agentName, "Tool", `Executing ${tool.name}`);
logger.debug(agentName, "Tool", `Parameters: ${JSON.stringify(params)}`);
try {
const startTime = Date.now();
const result = await tool.execute(params);
const duration = Date.now() - startTime;
logger.success(agentName, "Tool", `${tool.name} completed in ${duration}ms`);
logger.debug(agentName, "Tool", `Result type: ${typeof result}`);
return result;
} catch (error) {
logger.error(agentName, "Tool", `${tool.name} failed: ${error.message}`);
throw error;
}
}
RAG Operations Logging
Track document processing and search operations:
import { createRAG, parsePDF, logger } from '@astreus-ai/astreus';
async function setupRAGWithLogging(config) {
logger.info("System", "RAG", "Initializing RAG system");
try {
const rag = await createRAG(config);
logger.success("System", "RAG", `RAG system created (type: ${config.type})`);
return rag;
} catch (error) {
logger.error("System", "RAG", `RAG initialization failed: ${error.message}`);
throw error;
}
}
async function addDocumentWithLogging(rag, filePath) {
logger.info("System", "RAG", `Processing document: ${filePath}`);
try {
const document = await parsePDF(filePath);
logger.debug("System", "RAG", `Parsed ${document.documents.length} chunks`);
for (let i = 0; i < document.documents.length; i++) {
await rag.addDocument(document.documents[i]);
if ((i + 1) % 10 === 0) {
logger.debug("System", "RAG", `Added ${i + 1}/${document.documents.length} chunks`);
}
}
logger.success("System", "RAG", `Document added: ${document.documents.length} chunks`);
} catch (error) {
logger.error("System", "RAG", `Document processing failed: ${error.message}`);
throw error;
}
}
async function searchWithLogging(rag, query, agentName = 'Agent') {
logger.info(agentName, "RAG", `Searching for: "${query}"`);
try {
const startTime = Date.now();
const results = await rag.search(query, 5);
const duration = Date.now() - startTime;
logger.success(agentName, "RAG", `Found ${results.length} results in ${duration}ms`);
results.forEach((result, index) => {
logger.debug(agentName, "RAG",
`Result ${index + 1}: score ${result.score?.toFixed(3) || 'N/A'}`);
});
return results;
} catch (error) {
logger.error(agentName, "RAG", `Search failed: ${error.message}`);
throw error;
}
}
Task System Logging
Track task execution and dependencies:
async function runTasksWithLogging(agent, taskIds) {
const agentName = agent.name || 'Agent';
logger.info(agentName, "Task", `Starting execution of ${taskIds.length} tasks`);
try {
const startTime = Date.now();
const results = await agent.runTasks(taskIds);
const duration = Date.now() - startTime;
let successCount = 0;
let failureCount = 0;
results.forEach((result, taskId) => {
if (result.success) {
successCount++;
logger.success(agentName, "Task", `Task ${taskId} completed successfully`);
} else {
failureCount++;
logger.error(agentName, "Task", `Task ${taskId} failed: ${result.output?.error || 'Unknown error'}`);
}
});
logger.info(agentName, "Task",
`Execution completed in ${duration}ms: ${successCount} success, ${failureCount} failed`);
return results;
} catch (error) {
logger.error(agentName, "Task", `Task execution failed: ${error.message}`);
throw error;
}
}
Performance Monitoring
Use logging for performance monitoring and optimization:
// Memory usage monitoring
function logMemoryUsage(component = "System") {
const usage = process.memoryUsage();
const mb = (bytes) => Math.round(bytes / 1024 / 1024 * 100) / 100;
logger.debug(component, "Memory",
`RSS: ${mb(usage.rss)}MB, Heap: ${mb(usage.heapUsed)}/${mb(usage.heapTotal)}MB`);
}
// Performance timing
class PerformanceLogger {
private timers = new Map();
start(operation, component = "System") {
this.timers.set(operation, Date.now());
logger.debug(component, "Performance", `Started: ${operation}`);
}
end(operation, component = "System") {
const startTime = this.timers.get(operation);
if (startTime) {
const duration = Date.now() - startTime;
logger.debug(component, "Performance", `Completed: ${operation} (${duration}ms)`);
this.timers.delete(operation);
return duration;
}
return 0;
}
}
// Usage example
const perfLogger = new PerformanceLogger();
async function processWithPerformanceLogging() {
perfLogger.start("agent_creation", "Setup");
const agent = await createAgent(config);
perfLogger.end("agent_creation", "Setup");
perfLogger.start("conversation", agent.name);
const response = await agent.chat({ message: "Hello", sessionId: "test" });
perfLogger.end("conversation", agent.name);
logMemoryUsage("Setup");
}
Structured Logging for Analysis
Export logs in structured format for analysis:
// JSON logging for structured analysis
class StructuredLogger {
static logEvent(agentName, component, event, data = {}) {
const logEntry = {
timestamp: new Date().toISOString(),
agent: agentName,
component: component,
event: event,
data: data,
level: 'info'
};
// Log to console in Astreus format
logger.info(agentName, component, event);
// Also log as JSON for analysis (optional)
if (process.env.STRUCTURED_LOGS === 'true') {
console.log(JSON.stringify(logEntry));
}
}
static logError(agentName, component, error, context = {}) {
const logEntry = {
timestamp: new Date().toISOString(),
agent: agentName,
component: component,
event: 'error',
error: {
message: error.message,
stack: error.stack,
name: error.name
},
context: context,
level: 'error'
};
logger.error(agentName, component, error.message);
if (process.env.STRUCTURED_LOGS === 'true') {
console.log(JSON.stringify(logEntry));
}
}
}
// Usage
StructuredLogger.logEvent("ChatBot", "Conversation", "Message processed", {
messageLength: 150,
responseTime: 1200,
sessionId: "abc123"
});
StructuredLogger.logError("ChatBot", "Database", new Error("Connection timeout"), {
connectionString: "postgresql://...",
retryAttempt: 3
});
Best Practices
1. Use Consistent Component Names
// ✅ Good: Consistent component naming
logger.info("CustomerAgent", "Database", "Connection established");
logger.info("CustomerAgent", "Memory", "Loading conversation history");
logger.info("CustomerAgent", "Chat", "Processing user message");
logger.info("CustomerAgent", "Provider", "Calling OpenAI API");
2. Include Relevant Context
// ✅ Good: Include relevant context
logger.info("Agent", "Chat", `Processing message for session ${sessionId}`);
logger.success("Agent", "Task", `Completed task ${taskId} in ${duration}ms`);
logger.warn("Agent", "Provider", `Rate limit: ${remaining} requests remaining`);
3. Use Appropriate Log Levels
// ✅ Good: Appropriate log levels
logger.debug("Agent", "Memory", "Searching embeddings"); // Internal details
logger.info("Agent", "Chat", "Message received"); // General flow
logger.success("Agent", "Task", "Task completed"); // Positive outcomes
logger.warn("Agent", "Provider", "High token usage"); // Potential issues
logger.error("Agent", "Database", "Connection failed"); // Actual errors
4. Avoid Logging Sensitive Information
// ❌ Bad: Logging sensitive data
logger.info("Agent", "Auth", `API key: ${apiKey}`);
// ✅ Good: Log without sensitive data
logger.info("Agent", "Auth", "API key configured");
logger.debug("Agent", "Auth", `API key length: ${apiKey.length}`);
Configuration
Configure logging behavior through environment variables:
# Set log level
LOG_LEVEL=debug # Show all logs
LOG_LEVEL=info # Show info, success, warn, error
LOG_LEVEL=warn # Show warn and error only
LOG_LEVEL=error # Show error only
# Enable structured JSON logs
STRUCTURED_LOGS=true
# Disable colors (for file output)
NO_COLOR=true
Next Steps
- Learn about Agents for comprehensive agent logging
- Explore Database for database operation logging
- Check out Chat for chat system logging
- See Tasks for task execution logging
- Review Providers for provider interaction logging
How is this guide?