Skip to content

Log Analysis

This guide covers log locations, formats, and analysis techniques for License Monitor and License Server Detail.

Log TypeDefault LocationConfiguration
Application/var/log/license-monitor/license_monitor.log[daemon] log_file
Systemdjournalctl -u license-monitor-
Stdout (debug)Console--debug flag
Log TypeLocationNotes
ApplicationConsole/stdoutNext.js output
PM2 logs~/.pm2/logs/If using PM2
Docker logsdocker logs containerIf containerized
2024-01-15T10:30:45.123Z INFO [license_monitor::api] Request completed
request_id=req-abc123 method=GET path=/api/health status=200 duration_ms=45

Components:

  • Timestamp (ISO 8601)
  • Level (ERROR, WARN, INFO, DEBUG, TRACE)
  • Module path
  • Message
  • Structured fields

When log_format = "json":

{
"timestamp": "2024-01-15T10:30:45.123Z",
"level": "INFO",
"module": "license_monitor::api",
"message": "Request completed",
"request_id": "req-abc123",
"method": "GET",
"path": "/api/health",
"status": 200,
"duration_ms": 45
}
LevelUseExamples
ERRORCritical failuresConnection failures, crashes
WARNPotential issuesHigh latency, deprecated features
INFONormal operationsRequests, status changes
DEBUGTroubleshootingDetailed flow, variable values
TRACEDeep debuggingAll function calls, data dumps
2024-01-15T10:30:45.123Z INFO [license_monitor::api] Request started
request_id=req-abc123 method=GET path=/api/licenses
2024-01-15T10:30:45.200Z INFO [license_monitor::api] Request completed
request_id=req-abc123 status=200 duration_ms=77
2024-01-15T10:30:45.123Z WARN [license_monitor::auth] Authentication failed
request_id=req-abc123 reason=invalid_api_key ip=192.168.1.100
2024-01-15T10:30:45.123Z ERROR [license_monitor::license] License query failed
server=flexlm-01 error="Connection refused" attempt=3
2024-01-15T10:30:45.123Z WARN [license_monitor::rate_limit] Rate limit exceeded
ip=192.168.1.100 limit=100 window=60s
Terminal window
# View recent logs
tail -f /var/log/license-monitor/license_monitor.log
# Filter by level
grep "ERROR\|WARN" /var/log/license-monitor/license_monitor.log
# Filter by date
grep "2024-01-15" /var/log/license-monitor/license_monitor.log
# Filter by request ID
grep "req-abc123" /var/log/license-monitor/license_monitor.log
Terminal window
# Count errors by type
grep "ERROR" /var/log/license-monitor/license_monitor.log | \
awk '{print $4}' | sort | uniq -c | sort -rn
# Count requests by status
grep "Request completed" /var/log/license-monitor/license_monitor.log | \
grep -oP 'status=\d+' | sort | uniq -c
# Average response time
grep "duration_ms" /var/log/license-monitor/license_monitor.log | \
grep -oP 'duration_ms=\d+' | \
awk -F= '{sum+=$2; count++} END {print "Average:", sum/count, "ms"}'
Terminal window
# Requests per minute
grep "Request completed" /var/log/license-monitor/license_monitor.log | \
cut -d'T' -f2 | cut -d':' -f1,2 | sort | uniq -c
# Errors in last hour
awk -v date="$(date -d '1 hour ago' '+%Y-%m-%dT%H')" '$0 ~ date' \
/var/log/license-monitor/license_monitor.log | grep ERROR
Terminal window
# Parse JSON logs
cat /var/log/license-monitor/license_monitor.json | jq '.'
# Filter errors
cat /var/log/license-monitor/license_monitor.json | \
jq 'select(.level == "ERROR")'
# Extract specific fields
cat /var/log/license-monitor/license_monitor.json | \
jq '{timestamp, level, message}'
# Count by level
cat /var/log/license-monitor/license_monitor.json | \
jq -s 'group_by(.level) | map({level: .[0].level, count: length})'
Terminal window
# Real-time JSON log viewing
tail -f /var/log/license-monitor/license_monitor.json | jq '.'
# Real-time error filtering
tail -f /var/log/license-monitor/license_monitor.json | \
jq 'select(.level == "ERROR") | {timestamp, message}'
/etc/logrotate.d/license-monitor
/var/log/license-monitor/*.log {
daily
rotate 14
compress
delaycompress
missingok
notifempty
create 0640 license-monitor license-monitor
postrotate
systemctl reload license-monitor > /dev/null 2>&1 || true
endscript
}
Terminal window
# Rotate logs manually
logrotate -f /etc/logrotate.d/license-monitor
# Check rotation status
cat /var/lib/logrotate/status | grep license-monitor
config.toml
[daemon]
log_output = "syslog"
syslog_facility = "local0"
/etc/filebeat/filebeat.yml
# Using Filebeat
filebeat.inputs:
- type: log
paths:
- /var/log/license-monitor/*.log
json.keys_under_root: true
json.add_error_key: true
output.elasticsearch:
hosts: ["localhost:9200"]
index: "license-monitor-%{+yyyy.MM.dd}"
Terminal window
# Requests over 1 second
grep "duration_ms" /var/log/license-monitor/license_monitor.log | \
awk -F'duration_ms=' '{if ($2 > 1000) print}' | \
tail -20
Terminal window
# Failed requests (non-2xx status)
grep "Request completed" /var/log/license-monitor/license_monitor.log | \
grep -v "status=2"
Terminal window
# Find all logs for a specific request
REQUEST_ID="req-abc123"
grep "$REQUEST_ID" /var/log/license-monitor/license_monitor.log | \
sort | less