Astreus - Docs

Professional Logging

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 information
  • info (Blue): General information messages
  • success (Green): Success confirmations
  • warn (Yellow): Warning messages
  • error (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?