Logging & Debugging
Overview
Motia provides an out of the box logging and debugging system that works across different runtime environments. The system offers:
- Real-time log streaming in both terminal and Motia Workbench
- Multiple log levels with contextual information
- Local development debugging tools
- Integrated flow monitoring
Log Levels and Usage
Motia supports four standard log levels:
| Log Type | Description |
|---|---|
| info | General information about step execution, flow progress, and successful operations |
| error | Critical issues, exceptions, failed operations, and system errors |
| debug | Detailed debugging information and diagnostic data for troubleshooting |
| warn | Potential issues, edge cases, or situations requiring attention |
Example Usage
<Tabs items={['TS', 'JS', 'Python']}>
// Logging with context
logger.info('Operation completed', {
operationId: input.id,
duration: 1500
})
// Error handling
try {
await riskyOperation()
} catch (error) {
logger.error('Operation failed', {
error: error.message,
stack: error.stack
})
}
// Debug logging
logger.debug('Operation details', {
rawInput: input,
timestamp: Date.now()
})
// Warning logging
if (input.amount > 1000) {
logger.warn('Large operation detected', {
amount: input.amount,
threshold: 1000
})
}
}
```
// Logging with context
logger.info('Operation completed', {
operationId: input.id,
duration: 1500
})
// Error handling
try {
await riskyOperation()
} catch (error) {
logger.error('Operation failed', {
error: error.message,
stack: error.stack
})
}
// Debug logging
logger.debug('Operation details', {
rawInput: input,
timestamp: Date.now()
})
// Warning logging
if (input.amount > 1000) {
logger.warn('Large operation detected', {
amount: input.amount,
threshold: 1000
})
}
}
```
# Logging with context
ctx.logger.info('Operation completed', {
'operation_id': input.get("id"),
'duration': 1500
})
# Error handling
try:
await risky_operation()
except Exception as error:
ctx.logger.error('Operation failed', {
'error': str(error),
'stack': traceback.format_exc()
})
# Debug logging
ctx.logger.debug('Operation details', {
'raw_input': input.__dict__,
'timestamp': time.time()
})
# Warning logging
if input.amount > 1000:
ctx.logger.warn('Large operation detected', {
'amount': input.get("amount"),
'threshold': 1000
})
```
Running and Debugging
1. Navigate to your Motia project root folder
2. Start the development server:
<Tabs items={['npm', 'yarn', 'pnpm', 'bun']}>
<Tab value="yarn">```yarn run dev ```</Tab>
<Tab value="npm">```npm run dev ```</Tab>
<Tab value="pnpm">```pnpm run dev ```</Tab>
<Tab value="bun">```bun run dev ```</Tab>
</Tabs>
3. You can monitor logs in two ways:
- Open [Motia Workbench](http://localhost:3000), select your flow, and expand the logs container
- View logs directly in the terminal where you ran the dev command
You can trigger flows using either the CLI or an [API step](/docs/concepts/steps/api):
<Tabs items={['cli', 'api']}>
<Tab value='cli'>
```bash
npx motia emit --topic <topic> --message '{}'
```
</Tab>
<Tab value='api'>
```bash
curl -X POST http://localhost:3000/<api-step-path> \
-H "Content-Type: application/json" \
-d '{}'
```
</Tab>
</Tabs>
Each log entry automatically includes:
- `timestamp`: When the log was generated
- `traceId`: Unique identifier for the flow execution
- `flows`: Array of flow names this step belongs to
- `file`: Source file generating the log
- `level`: Log level
- `msg`: Log message
Best Practices
Structured Logging
// Good - Structured and searchable
logger.info('Payment processed', {
paymentId: '123',
amount: 100,
status: 'success',
})
// Avoid - Harder to parse and search
logger.info(`Payment ${paymentId} processed: amount=${amount}`)
Performance Monitoring
export const handler: Handlers['StepName'] = async (input, { logger }) => {
const startTime = performance.now()
// Process operation
const result = await processOperation(input)
logger.info('Operation completed', {
duration: performance.now() - startTime,
memoryUsage: process.memoryUsage().heapUsed,
})
}
Debugging Tips
- Add detailed context to error logs:
logger.error('Operation failed', {
error: error.message,
code: error.code,
input: JSON.stringify(input),
stack: error.stack,
})
- Use debug logs for detailed troubleshooting:
logger.debug('Operation details', {
rawInput: input,
timestamp: Date.now(),
state: currentState,
})