Audit Logging
Related Topics: Configuration (enable auditing) | Monitoring (observability) | Policies (access control) | Common Tasks (quick setup)
MXCP provides comprehensive audit logging to track all endpoint executions. Audit logs are essential for security, compliance, debugging, and understanding usage patterns.
How It Works
Section titled “How It Works”The audit logger runs in a background thread with an async queue, ensuring zero impact on request latency.
What Gets Logged
Section titled “What Gets Logged”When enabled, MXCP logs every execution with:
| Field | Description | Example |
|---|---|---|
timestamp | UTC timestamp | 2024-01-15T10:30:45.123Z |
caller_type | Request source | http, stdio (see below) |
operation_type | Endpoint type | tool, resource, prompt |
operation_name | Endpoint name | get_user |
input_data | Parameters (redacted) | {"user_id": 123} |
duration_ms | Execution time | 145 |
policy_decision | Policy result | allow, deny, n/a |
policy_reason | Policy reason | "Admin access required" |
operation_status | Execution result | success, error |
error | Error message | "Connection timeout" |
user_id | Authenticated user | "john@example.com" |
session_id | Session identifier | "sess_abc123" |
Caller Types
Section titled “Caller Types”The caller_type field indicates how the endpoint was invoked:
- http: HTTP API request (when running
mxcp servewith default transport) - stdio: Standard I/O protocol (when running
mxcp serve --transport stdio)
Note: Audit logging only occurs through mxcp serve. Direct CLI execution via mxcp run does not generate audit logs.
Configuration
Section titled “Configuration”Enable audit logging in mxcp-site.yml:
profiles: default: audit: enabled: true path: audit/logs.jsonl
production: audit: enabled: true path: /var/log/mxcp/audit.jsonlThe log file is created automatically when the first event is logged.
Storage Format
Section titled “Storage Format”Audit logs use JSONL (JSON Lines) format - one JSON object per line:
{"timestamp":"2024-01-15T10:30:45.123Z","caller_type":"http","operation_type":"tool","operation_name":"get_user","input_data":{"user_id":123},"duration_ms":145,"policy_decision":"allow","operation_status":"success"}{"timestamp":"2024-01-15T10:30:46.456Z","caller_type":"http","operation_type":"tool","operation_name":"update_user","input_data":{"user_id":123},"duration_ms":89,"policy_decision":"deny","policy_reason":"Admin required","operation_status":"error"}JSONL advantages:
- Human-readable
- Streaming-friendly (can be tailed)
- Compatible with many analysis tools
Querying Logs
Section titled “Querying Logs”Use mxcp log to query audit logs:
Basic Queries
Section titled “Basic Queries”# Show recent logsmxcp log
# Show last 50 entriesmxcp log --limit 50Filter by Time
Section titled “Filter by Time”# Last 10 minutesmxcp log --since 10m
# Last 2 hoursmxcp log --since 2h
# Last daymxcp log --since 1dFilter by Endpoint
Section titled “Filter by Endpoint”# Specific toolmxcp log --tool get_user
# All toolsmxcp log --type tool
# All resourcesmxcp log --type resourceFilter by Status
Section titled “Filter by Status”# Only errorsmxcp log --status error
# Only successfulmxcp log --status successFilter by Policy
Section titled “Filter by Policy”# Denied requestsmxcp log --policy deny
# Allowed requestsmxcp log --policy allow
# No policy appliedmxcp log --policy n/aCombine Filters
Section titled “Combine Filters”# Errors in last hourmxcp log --status error --since 1h
# Denied tool calls todaymxcp log --type tool --policy deny --since 1d
# Specific tool errorsmxcp log --tool get_user --status errorOutput Formats
Section titled “Output Formats”Table Format (Default)
Section titled “Table Format (Default)”mxcp logTIMESTAMP TYPE NAME STATUS POLICY DURATION2024-01-15T10:30:45.123Z tool get_user success allow 145ms2024-01-15T10:30:46.456Z tool update error deny 89msJSON Format
Section titled “JSON Format”mxcp log --json[ { "timestamp": "2024-01-15T10:30:45.123Z", "type": "tool", "name": "get_user", "status": "success", "policy_decision": "allow", "duration_ms": 145 }]Export to CSV
Section titled “Export to CSV”mxcp log --export-csv audit.csvExport to DuckDB
Section titled “Export to DuckDB”mxcp log --export-duckdb audit.dbDuckDB Analysis
Section titled “DuckDB Analysis”Export to DuckDB for complex SQL analysis:
mxcp log --export-duckdb audit.dbduckdb audit.dbExample Queries
Section titled “Example Queries”Top 10 most used tools:
SELECT operation_name, COUNT(*) as countFROM logsWHERE operation_type = 'tool'GROUP BY operation_nameORDER BY count DESCLIMIT 10;Error rate by hour:
SELECT DATE_TRUNC('hour', timestamp) as hour, COUNT(CASE WHEN operation_status = 'error' THEN 1 END) as errors, COUNT(*) as total, ROUND(100.0 * COUNT(CASE WHEN operation_status = 'error' THEN 1 END) / COUNT(*), 2) as error_rateFROM logsGROUP BY hourORDER BY hour DESC;Policy violations by endpoint:
SELECT operation_name, COUNT(*) as denials, STRING_AGG(DISTINCT policy_reason, ', ') as reasonsFROM logsWHERE policy_decision = 'deny'GROUP BY operation_nameORDER BY denials DESC;Average response time by tool:
SELECT operation_name, AVG(duration_ms) as avg_ms, MIN(duration_ms) as min_ms, MAX(duration_ms) as max_ms, COUNT(*) as callsFROM logsWHERE operation_type = 'tool' AND operation_status = 'success'GROUP BY operation_nameORDER BY avg_ms DESC;Real-Time Monitoring
Section titled “Real-Time Monitoring”Monitor logs in real-time using standard Unix tools:
# Watch all logstail -f audit/logs.jsonl
# Watch for errorstail -f audit/logs.jsonl | grep '"operation_status":"error"'
# Watch for policy denialstail -f audit/logs.jsonl | grep '"policy_decision":"deny"'
# Pretty-print recent entriestail -n 10 audit/logs.jsonl | jq .Sensitive Data Redaction
Section titled “Sensitive Data Redaction”Fields marked as sensitive: true in your schema are automatically redacted:
Schema:
parameters: - name: username type: string description: User's username - name: api_key type: string sensitive: true description: API key for authentication - name: config type: object properties: host: type: string password: type: string sensitive: trueAudit log entry:
{ "input_data": { "username": "john_doe", "api_key": "[REDACTED]", "config": { "host": "example.com", "password": "[REDACTED]" } }}Redaction applies to:
- Parameters marked sensitive
- Nested fields marked sensitive
- Any field containing
password,secret,token,key(configurable)
Important: Only fields explicitly marked with sensitive: true in the endpoint schema will be redacted. If no schema is provided or fields are not marked as sensitive, they will appear in plain text in the audit logs.
Log Rotation
Section titled “Log Rotation”For production environments, implement log rotation:
Using logrotate (Linux)
Section titled “Using logrotate (Linux)”Create /etc/logrotate.d/mxcp:
/var/log/mxcp/audit.jsonl { daily rotate 30 compress delaycompress missingok notifempty create 0640 mxcp mxcp postrotate systemctl reload mxcp endscript}Manual Rotation
Section titled “Manual Rotation”# Archive current logmv audit/logs.jsonl audit/logs-$(date +%Y%m%d).jsonl
# Compress archived logsgzip audit/logs-*.jsonl
# MXCP creates new file automaticallyIntegration with Log Analysis Tools
Section titled “Integration with Log Analysis Tools”Elasticsearch
Section titled “Elasticsearch”# Import JSONL to Elasticsearchcat audit/logs.jsonl | \ curl -X POST "localhost:9200/mxcp-audit/_bulk" \ -H "Content-Type: application/x-ndjson" \ --data-binary @-Splunk
Section titled “Splunk”Configure Splunk to monitor the JSONL file or use HTTP Event Collector.
jq Analysis
Section titled “jq Analysis”# Count by statuscat audit/logs.jsonl | jq -s 'group_by(.operation_status) | map({status: .[0].operation_status, count: length})'
# Extract error messagescat audit/logs.jsonl | jq 'select(.operation_status == "error") | {name: .operation_name, error}'
# Calculate average durationcat audit/logs.jsonl | jq -s 'map(.duration_ms) | add / length'Miller (mlr)
Section titled “Miller (mlr)”# Convert to CSVmlr --ijson --ocsv cat audit/logs.jsonl > audit.csv
# Aggregate statsmlr --ijson stats1 -a count,mean,min,max -f duration_ms -g name audit/logs.jsonlPerformance
Section titled “Performance”The audit logger is designed for minimal impact:
- Background thread - No impact on request latency
- Async queue - Requests return immediately
- Batch writing - Efficient I/O operations
- Graceful shutdown - Ensures all events are written
Best Practices
Section titled “Best Practices”1. Enable in Production
Section titled “1. Enable in Production”Always enable audit logging in production:
profiles: production: audit: enabled: true2. Set Up Alerts
Section titled “2. Set Up Alerts”Monitor for issues:
# Cron job for error alerts*/5 * * * * mxcp log --status error --since 5m --json | jq -e 'length > 0' && notify-admin3. Define Retention Policy
Section titled “3. Define Retention Policy”Keep logs based on compliance requirements:
- Financial services: Often 7 years
- Healthcare: Often 6 years
- General: 90 days minimum
4. Include in Backups
Section titled “4. Include in Backups”Treat audit logs as critical data.
5. Regular Review
Section titled “5. Regular Review”Schedule periodic log reviews for security analysis.
Troubleshooting
Section titled “Troubleshooting”Logs Not Appearing
Section titled “Logs Not Appearing”-
Check audit is enabled:
audit:enabled: true -
Verify path is writable:
Terminal window touch audit/logs.jsonl -
Check MXCP logs for errors.
Large Log Files
Section titled “Large Log Files”For large files:
- Export to DuckDB for analysis
- Implement log rotation
- Archive old logs
Query Performance
Section titled “Query Performance”For better performance on large datasets:
- Export to DuckDB
- Create indexes for common queries
- Use time-based partitioning
Log Retention and Cleanup
Section titled “Log Retention and Cleanup”MXCP provides automated audit log cleanup to manage storage and comply with data retention policies.
Default Retention
Section titled “Default Retention”MXCP uses a default retention period of 90 days for endpoint execution logs. Records older than this are automatically removed when you run the cleanup command.
Manual Cleanup
Section titled “Manual Cleanup”Run cleanup manually:
# Apply retention policiesmxcp log-cleanup
# Preview what would be deleted (dry run)mxcp log-cleanup --dry-run
# Use specific profilemxcp log-cleanup --profile production
# Output as JSONmxcp log-cleanup --jsonAutomated Cleanup
Section titled “Automated Cleanup”Using Cron:
# Edit crontabcrontab -e
# Add this line (runs daily at 2 AM)0 2 * * * cd /path/to/project && /usr/bin/mxcp log-cleanupUsing systemd:
- Create a timer unit (
/etc/systemd/system/mxcp-audit-cleanup.timer):
[Unit]Description=MXCP Audit Log Cleanup Timer
[Timer]OnCalendar=*-*-* 02:00:00Persistent=true
[Install]WantedBy=timers.target- Create a service unit (
/etc/systemd/system/mxcp-audit-cleanup.service):
[Unit]Description=MXCP Audit Log Cleanup
[Service]Type=oneshotWorkingDirectory=/path/to/projectExecStart=/usr/bin/mxcp log-cleanupUser=mxcp- Enable and start:
sudo systemctl daemon-reloadsudo systemctl enable --now mxcp-audit-cleanup.timerMonitoring Cleanup
Section titled “Monitoring Cleanup”View cleanup results:
# Check systemd logsjournalctl -u mxcp-audit-cleanup.service
# Run with debug outputmxcp log-cleanup --debug
# Get JSON output for monitoringmxcp log-cleanup --json | jqCleanup Output
Section titled “Cleanup Output”Example JSON output:
{ "status": "ok", "result": { "status": "success", "message": "Deleted 1523 records", "deleted_per_schema": { "api_operations:1": 1200, "debug_logs:1": 323 } }}Retention Guidelines
Section titled “Retention Guidelines”| Log Type | Suggested Retention | Reason |
|---|---|---|
| Authentication | 365 days | Regulatory compliance |
| API access | 90 days | Operational analysis |
| Debug | 30 days | Troubleshooting |
| Error | 180 days | Incident investigation |
Best Practices
Section titled “Best Practices”- Test first: Always use
--dry-runbefore automated cleanup - Monitor disk space: Set alerts for audit directory size
- Backup: Archive old logs before deletion
- Gradual rollout: Start conservative, adjust as needed
Security Considerations
Section titled “Security Considerations”- Access Control - Restrict log file access
- Encryption - Consider encrypting logs at rest
- Integrity - Implement log integrity verification
- Retention - Define and enforce retention policies
Next Steps
Section titled “Next Steps”- Policies - Control what gets logged
- Authentication - Track user identity
- Monitoring - Set up observability