Documentation Index Fetch the complete documentation index at: https://mintlify.com/mastra-ai/mastra/llms.txt
Use this file to discover all available pages before exploring further.
Mastra provides structured logging with automatic correlation to traces and spans, making it easy to debug issues and understand system behavior.
Overview
Mastra’s logging system:
Automatically correlates logs with traces and spans
Supports multiple log levels (debug, info, warn, error, fatal)
Captures structured data with each log message
Works with any logger that implements the LoggerContext interface
Basic Usage
Default Logger
Mastra includes a console logger by default:
import { Mastra } from '@mastra/core' ;
const mastra = new Mastra ({
agents: { /* ... */ },
});
// Get the logger
const logger = mastra . getLogger ();
// Log messages
logger . info ( 'Processing request' , { userId: '123' });
logger . error ( 'Failed to connect' , { service: 'database' , error: 'timeout' });
Log Levels
Available log levels in order of severity:
logger . debug ( 'Debug info' , { data: { ... } }); // Lowest
logger . info ( 'Info message' , { status: 'ok' });
logger . warn ( 'Warning' , { threshold: 0.8 });
logger . error ( 'Error occurred' , { error: err });
logger . fatal ( 'Critical failure' , { service: 'auth' }); // Highest
Structured Logging
Adding Context
Include structured data with log messages:
logger . info ( 'User login' , {
userId: 'user-123' ,
email: 'user@example.com' ,
ipAddress: '192.168.1.1' ,
timestamp: new Date (),
});
logger . error ( 'Database query failed' , {
query: 'SELECT * FROM users' ,
database: 'production' ,
duration: 5000 ,
error: {
message: 'Connection timeout' ,
code: 'ETIMEDOUT' ,
},
});
Automatic Trace Correlation
Logs automatically include trace and span IDs when logged within a traced operation:
const result = await agent . generate ({
messages: [{ role: 'user' , content: 'Hello' }],
onStepStart : () => {
// This log will include traceId and spanId automatically
logger . info ( 'Agent step started' );
},
onStepFinish : ({ result }) => {
logger . info ( 'Agent step completed' , {
finishReason: result . finishReason ,
});
// Log entry:
// {
// level: 'info',
// message: 'Agent step completed',
// data: { finishReason: 'stop' },
// traceId: 'a1b2c3d4...',
// spanId: 'e5f67890...',
// timestamp: Date(...)
// }
},
});
Custom Logger
Implementing LoggerContext
Create a custom logger by implementing the LoggerContext interface:
import { LoggerContext } from '@mastra/core/observability' ;
class CustomLogger implements LoggerContext {
debug ( message : string , data ?: Record < string , unknown >) : void {
console . log ( '[DEBUG]' , message , data );
}
info ( message : string , data ?: Record < string , unknown >) : void {
console . log ( '[INFO]' , message , data );
}
warn ( message : string , data ?: Record < string , unknown >) : void {
console . warn ( '[WARN]' , message , data );
}
error ( message : string , data ?: Record < string , unknown >) : void {
console . error ( '[ERROR]' , message , data );
}
fatal ( message : string , data ?: Record < string , unknown >) : void {
console . error ( '[FATAL]' , message , data );
}
}
// Use custom logger
const mastra = new Mastra ({
logger: new CustomLogger (),
agents: { /* ... */ },
});
Winston Integration
Integrate with Winston logger:
import winston from 'winston' ;
import { LoggerContext , LogLevel } from '@mastra/core/observability' ;
class WinstonLogger implements LoggerContext {
private logger : winston . Logger ;
constructor () {
this . logger = winston . createLogger ({
level: 'info' ,
format: winston . format . combine (
winston . format . timestamp (),
winston . format . json ()
),
transports: [
new winston . transports . Console (),
new winston . transports . File ({ filename: 'mastra.log' }),
],
});
}
private log ( level : LogLevel , message : string , data ?: Record < string , unknown >) {
this . logger . log ( level , message , data );
}
debug ( message : string , data ?: Record < string , unknown >) : void {
this . log ( 'debug' , message , data );
}
info ( message : string , data ?: Record < string , unknown >) : void {
this . log ( 'info' , message , data );
}
warn ( message : string , data ?: Record < string , unknown >) : void {
this . log ( 'warn' , message , data );
}
error ( message : string , data ?: Record < string , unknown >) : void {
this . log ( 'error' , message , data );
}
fatal ( message : string , data ?: Record < string , unknown >) : void {
this . log ( 'error' , message , { ... data , fatal: true });
}
}
const mastra = new Mastra ({
logger: new WinstonLogger (),
agents: { /* ... */ },
});
Pino Integration
Integrate with Pino logger:
import pino from 'pino' ;
import { LoggerContext } from '@mastra/core/observability' ;
class PinoLogger implements LoggerContext {
private logger : pino . Logger ;
constructor () {
this . logger = pino ({
level: 'debug' ,
transport: {
target: 'pino-pretty' ,
options: { colorize: true },
},
});
}
debug ( message : string , data ?: Record < string , unknown >) : void {
this . logger . debug ( data , message );
}
info ( message : string , data ?: Record < string , unknown >) : void {
this . logger . info ( data , message );
}
warn ( message : string , data ?: Record < string , unknown >) : void {
this . logger . warn ( data , message );
}
error ( message : string , data ?: Record < string , unknown >) : void {
this . logger . error ( data , message );
}
fatal ( message : string , data ?: Record < string , unknown >) : void {
this . logger . fatal ( data , message );
}
}
const mastra = new Mastra ({
logger: new PinoLogger (),
agents: { /* ... */ },
});
ExportedLog Structure
Logs are exported with this structure:
interface ExportedLog {
timestamp : Date ; // When log was emitted
level : LogLevel ; // Log severity level
message : string ; // Human-readable message
data ?: Record < string , unknown >; // Structured data
traceId ?: string ; // Correlated trace ID
spanId ?: string ; // Correlated span ID
tags ?: string []; // Optional tags
metadata ?: Record < string , unknown >; // Additional metadata
}
Example Log Entry
{
"timestamp" : "2024-01-15T10:30:00.000Z" ,
"level" : "info" ,
"message" : "Agent generation completed" ,
"data" : {
"agentId" : "myAgent" ,
"duration" : 1250 ,
"tokenUsage" : {
"input" : 150 ,
"output" : 75
}
},
"traceId" : "a1b2c3d4e5f67890a1b2c3d4e5f67890" ,
"spanId" : "e5f67890a1b2c3d4" ,
"tags" : [ "production" ],
"metadata" : {
"userId" : "user-123" ,
"sessionId" : "session-abc"
}
}
Best Practices
Use Appropriate Log Levels
// DEBUG - Detailed information for troubleshooting
logger . debug ( 'Processing message' , { messageId: '123' , content: 'Hello' });
// INFO - General informational messages
logger . info ( 'Request processed successfully' , { userId: '123' , duration: 250 });
// WARN - Warning messages that don't prevent operation
logger . warn ( 'Rate limit approaching' , { current: 95 , limit: 100 });
// ERROR - Error conditions that should be investigated
logger . error ( 'Failed to call external API' , { api: 'weather' , error: 'timeout' });
// FATAL - Critical errors that require immediate attention
logger . fatal ( 'Database connection lost' , { database: 'production' });
Include Relevant Context
// Good: Includes context for debugging
logger . error ( 'Tool execution failed' , {
toolName: 'calculator' ,
input: { operation: 'divide' , a: 10 , b: 0 },
error: 'Division by zero' ,
userId: 'user-123' ,
});
// Bad: Missing context
logger . error ( 'Tool failed' );
Structure Complex Data
logger . info ( 'Model response received' , {
model: 'gpt-4' ,
usage: {
prompt: 150 ,
completion: 75 ,
total: 225 ,
},
timing: {
ttft: 250 , // Time to first token
total: 1200 ,
},
finishReason: 'stop' ,
});
Avoid Logging Sensitive Data
// Good: Redact sensitive information
logger . info ( 'User authenticated' , {
userId: user . id ,
email: user . email . replace ( / ( . {2} ) . * ( @ . * ) / , '$1***$2' ), // Redact email
});
// Bad: Logging sensitive data
logger . info ( 'User authenticated' , {
userId: user . id ,
password: user . password , // Never log passwords!
apiKey: user . apiKey , // Never log API keys!
});
Querying Logs
If using an observability platform, query logs via the HTTP API:
# Query logs with filters
curl "http://localhost:3000/api/logs?level=error&limit=100"
# Query logs for specific trace
curl "http://localhost:3000/api/logs?traceId=a1b2c3d4e5f67890a1b2c3d4e5f67890"
Next Steps
Tracing Learn about OpenTelemetry tracing
Server API Explore server routes and handlers