461 lines
10 KiB
Markdown
461 lines
10 KiB
Markdown
# Troubleshooting
|
|
|
|
[← Examples](examples.md) | [← Back to README](../README.md)
|
|
|
|
Common issues and solutions when using the lixenwraith/log package.
|
|
|
|
## Table of Contents
|
|
|
|
- [Common Issues](#common-issues)
|
|
- [Diagnostic Tools](#diagnostic-tools)
|
|
- [Error Messages](#error-messages)
|
|
- [Performance Issues](#performance-issues)
|
|
- [Platform-Specific Issues](#platform-specific-issues)
|
|
- [FAQ](#faq)
|
|
|
|
## Common Issues
|
|
|
|
### Logger Not Writing to File
|
|
|
|
**Symptoms:**
|
|
- No log files created
|
|
- Empty log directory
|
|
- No error messages
|
|
|
|
**Solutions:**
|
|
|
|
1. **Check initialization**
|
|
```go
|
|
logger := log.NewLogger()
|
|
err := logger.InitWithDefaults()
|
|
if err != nil {
|
|
fmt.Printf("Init failed: %v\n", err)
|
|
}
|
|
```
|
|
|
|
2. **Verify directory permissions**
|
|
```bash
|
|
# Check directory exists and is writable
|
|
ls -la /var/log/myapp
|
|
touch /var/log/myapp/test.log
|
|
```
|
|
|
|
3. **Check if file output is disabled**
|
|
```go
|
|
// Ensure file output is enabled
|
|
logger.InitWithDefaults(
|
|
"disable_file=false", // Default, but be explicit
|
|
"directory=/var/log/myapp",
|
|
)
|
|
```
|
|
|
|
4. **Enable console output for debugging**
|
|
```go
|
|
logger.InitWithDefaults(
|
|
"enable_stdout=true",
|
|
"level=-4", // Debug level
|
|
)
|
|
```
|
|
|
|
### Logs Being Dropped
|
|
|
|
**Symptoms:**
|
|
- "Logs were dropped" messages
|
|
- Missing log entries
|
|
- `dropped_logs` count in heartbeats
|
|
|
|
**Solutions:**
|
|
|
|
1. **Increase buffer size**
|
|
```go
|
|
logger.InitWithDefaults(
|
|
"buffer_size=4096", // Increase from default 1024
|
|
)
|
|
```
|
|
|
|
2. **Monitor with heartbeats**
|
|
```go
|
|
logger.InitWithDefaults(
|
|
"heartbeat_level=1",
|
|
"heartbeat_interval_s=60",
|
|
)
|
|
// Watch for: dropped_logs=N
|
|
```
|
|
|
|
3. **Reduce log volume**
|
|
```go
|
|
// Increase log level
|
|
logger.InitWithDefaults("level=0") // Info and above only
|
|
|
|
// Or batch operations
|
|
logger.Info("Batch processed", "count", 1000) // Not 1000 individual logs
|
|
```
|
|
|
|
4. **Optimize flush interval**
|
|
```go
|
|
logger.InitWithDefaults(
|
|
"flush_interval_ms=500", // Less frequent flushes
|
|
)
|
|
```
|
|
|
|
### Disk Full Errors
|
|
|
|
**Symptoms:**
|
|
- "Log directory full or disk space low" messages
|
|
- `disk_status_ok=false` in heartbeats
|
|
- No new logs being written
|
|
|
|
**Solutions:**
|
|
|
|
1. **Configure automatic cleanup**
|
|
```go
|
|
logger.InitWithDefaults(
|
|
"max_total_size_mb=1000", // 1GB total limit
|
|
"min_disk_free_mb=500", // 500MB free required
|
|
"retention_period_hrs=24", // Keep only 24 hours
|
|
)
|
|
```
|
|
|
|
2. **Manual cleanup**
|
|
```bash
|
|
# Find and remove old logs
|
|
find /var/log/myapp -name "*.log" -mtime +7 -delete
|
|
|
|
# Or keep only recent files
|
|
ls -t /var/log/myapp/*.log | tail -n +11 | xargs rm
|
|
```
|
|
|
|
3. **Monitor disk usage**
|
|
```bash
|
|
# Set up monitoring
|
|
df -h /var/log
|
|
du -sh /var/log/myapp
|
|
```
|
|
|
|
### Logger Initialization Failures
|
|
|
|
**Symptoms:**
|
|
- Init returns error
|
|
- "logger previously failed to initialize" errors
|
|
- Application won't start
|
|
|
|
**Common Errors and Solutions:**
|
|
|
|
1. **Invalid configuration**
|
|
```go
|
|
// Error: "invalid format: 'xml' (use txt or json)"
|
|
logger.InitWithDefaults("format=json") // Use valid format
|
|
|
|
// Error: "buffer_size must be positive"
|
|
logger.InitWithDefaults("buffer_size=1024") // Use positive value
|
|
```
|
|
|
|
2. **Directory creation failure**
|
|
```go
|
|
// Error: "failed to create log directory: permission denied"
|
|
// Solution: Check permissions or use accessible directory
|
|
logger.InitWithDefaults("directory=/tmp/logs")
|
|
```
|
|
|
|
3. **Configuration conflicts**
|
|
```go
|
|
// Error: "min_check_interval > max_check_interval"
|
|
logger.InitWithDefaults(
|
|
"min_check_interval_ms=100",
|
|
"max_check_interval_ms=60000", // Max must be >= min
|
|
)
|
|
```
|
|
|
|
## Diagnostic Tools
|
|
|
|
### Enable Debug Logging
|
|
|
|
```go
|
|
// Temporary debug configuration
|
|
logger.InitWithDefaults(
|
|
"level=-4", // Debug everything
|
|
"enable_stdout=true", // See logs immediately
|
|
"trace_depth=3", // Include call stacks
|
|
"heartbeat_level=3", // All statistics
|
|
"heartbeat_interval_s=10", // Frequent updates
|
|
)
|
|
```
|
|
|
|
### Check Logger State
|
|
|
|
```go
|
|
// Add diagnostic helper
|
|
func diagnoseLogger(logger *log.Logger) {
|
|
// Try logging at all levels
|
|
logger.Debug("Debug test")
|
|
logger.Info("Info test")
|
|
logger.Warn("Warn test")
|
|
logger.Error("Error test")
|
|
|
|
// Force flush
|
|
if err := logger.Flush(1 * time.Second); err != nil {
|
|
fmt.Printf("Flush failed: %v\n", err)
|
|
}
|
|
|
|
// Check for output
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
```
|
|
|
|
### Monitor Resource Usage
|
|
|
|
```go
|
|
// Add resource monitoring
|
|
func monitorResources(logger *log.Logger) {
|
|
ticker := time.NewTicker(10 * time.Second)
|
|
defer ticker.Stop()
|
|
|
|
for range ticker.C {
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
|
|
logger.Info("Resource usage",
|
|
"goroutines", runtime.NumGoroutine(),
|
|
"memory_mb", m.Alloc/1024/1024,
|
|
"gc_runs", m.NumGC,
|
|
)
|
|
}
|
|
}
|
|
```
|
|
|
|
## Error Messages
|
|
|
|
### Configuration Errors
|
|
|
|
| Error | Cause | Solution |
|
|
|-------|-------|----------|
|
|
| `log name cannot be empty` | Empty name parameter | Provide valid name or use default |
|
|
| `invalid format: 'X' (use txt or json)` | Invalid format value | Use "txt" or "json" |
|
|
| `extension should not start with dot` | Extension has leading dot | Use "log" not ".log" |
|
|
| `buffer_size must be positive` | Zero or negative buffer | Use positive value (default: 1024) |
|
|
| `trace_depth must be between 0 and 10` | Invalid trace depth | Use 0-10 range |
|
|
|
|
### Runtime Errors
|
|
|
|
| Error | Cause | Solution |
|
|
|-------|-------|----------|
|
|
| `logger not initialized or already shut down` | Using closed logger | Check initialization order |
|
|
| `timeout waiting for flush confirmation` | Flush timeout | Increase timeout or check I/O |
|
|
| `failed to create log file: permission denied` | Directory permissions | Check directory access rights |
|
|
| `failed to write to log file: no space left` | Disk full | Free space or configure cleanup |
|
|
|
|
### Recovery Errors
|
|
|
|
| Error | Cause | Solution |
|
|
|-------|-------|----------|
|
|
| `no old logs available to delete` | Can't free space | Manual intervention needed |
|
|
| `could not free enough space` | Cleanup insufficient | Reduce limits or add storage |
|
|
| `disk check failed` | Can't check disk space | Check filesystem health |
|
|
|
|
## Performance Issues
|
|
|
|
### High CPU Usage
|
|
|
|
**Diagnosis:**
|
|
```bash
|
|
# Check process CPU
|
|
top -p $(pgrep yourapp)
|
|
|
|
# Profile application
|
|
go tool pprof http://localhost:6060/debug/pprof/profile
|
|
```
|
|
|
|
**Solutions:**
|
|
1. Increase flush interval
|
|
2. Disable periodic sync
|
|
3. Reduce heartbeat level
|
|
4. Use text format instead of JSON
|
|
|
|
### Memory Growth
|
|
|
|
**Diagnosis:**
|
|
```go
|
|
// Add to application
|
|
import _ "net/http/pprof"
|
|
go http.ListenAndServe("localhost:6060", nil)
|
|
|
|
// Check heap
|
|
go tool pprof http://localhost:6060/debug/pprof/heap
|
|
```
|
|
|
|
**Solutions:**
|
|
1. Check for logger reference leaks
|
|
2. Verify reasonable buffer size
|
|
3. Look for logging loops
|
|
|
|
### Slow Disk I/O
|
|
|
|
**Diagnosis:**
|
|
```bash
|
|
# Check disk latency
|
|
iostat -x 1
|
|
ioping -c 10 /var/log
|
|
```
|
|
|
|
**Solutions:**
|
|
1. Use SSD storage
|
|
2. Increase flush interval
|
|
3. Disable periodic sync
|
|
4. Use separate log volume
|
|
|
|
## Platform-Specific Issues
|
|
|
|
### Linux
|
|
|
|
**File Handle Limits:**
|
|
```bash
|
|
# Check limits
|
|
ulimit -n
|
|
|
|
# Increase if needed
|
|
ulimit -n 65536
|
|
```
|
|
|
|
**SELinux Issues:**
|
|
```bash
|
|
# Check SELinux denials
|
|
ausearch -m avc -ts recent
|
|
|
|
# Set context for log directory
|
|
semanage fcontext -a -t var_log_t "/var/log/myapp(/.*)?"
|
|
restorecon -R /var/log/myapp
|
|
```
|
|
|
|
### FreeBSD
|
|
|
|
**Directory Permissions:**
|
|
```bash
|
|
# Ensure log directory ownership
|
|
chown appuser:appgroup /var/log/myapp
|
|
chmod 755 /var/log/myapp
|
|
```
|
|
|
|
**Jails Configuration:**
|
|
```bash
|
|
# Allow log directory access in jail
|
|
jail -m jid=1 allow.mount.devfs=1 path=/var/log/myapp
|
|
```
|
|
|
|
### Windows
|
|
|
|
**Path Format:**
|
|
```go
|
|
// Use proper Windows paths
|
|
logger.InitWithDefaults(
|
|
"directory=C:\\Logs\\MyApp", // Escaped backslashes
|
|
// or
|
|
"directory=C:/Logs/MyApp", // Forward slashes work too
|
|
)
|
|
```
|
|
|
|
**Permissions:**
|
|
- Run as Administrator for system directories
|
|
- Use user-writable locations like `%APPDATA%`
|
|
|
|
## FAQ
|
|
|
|
### Q: Can I use the logger before initialization?
|
|
|
|
No, always initialize first:
|
|
```go
|
|
logger := log.NewLogger()
|
|
logger.InitWithDefaults() // Must call before logging
|
|
logger.Info("Now safe to log")
|
|
```
|
|
|
|
### Q: How do I rotate logs manually?
|
|
|
|
The logger handles rotation automatically. To force rotation:
|
|
```go
|
|
// Set small size limit temporarily
|
|
logger.InitWithDefaults("max_size_mb=0.001")
|
|
logger.Info("This will trigger rotation")
|
|
```
|
|
|
|
### Q: Can I change log directory at runtime?
|
|
|
|
Yes, through reconfiguration:
|
|
```go
|
|
// Change directory
|
|
logger.InitWithDefaults("directory=/new/path")
|
|
```
|
|
|
|
### Q: How do I completely disable logging?
|
|
|
|
Several options:
|
|
```go
|
|
// Option 1: Disable file output, no console
|
|
logger.InitWithDefaults(
|
|
"disable_file=true",
|
|
"enable_stdout=false",
|
|
)
|
|
|
|
// Option 2: Set very high log level
|
|
logger.InitWithDefaults("level=100") // Nothing will log
|
|
|
|
// Option 3: Don't initialize (logs are dropped)
|
|
logger := log.NewLogger() // Don't call Init
|
|
```
|
|
|
|
### Q: Why are my logs not appearing immediately?
|
|
|
|
Logs are buffered for performance:
|
|
```go
|
|
// For immediate output
|
|
logger.InitWithDefaults(
|
|
"flush_interval_ms=10", // Quick flushes
|
|
"enable_stdout=true", // Also to console
|
|
)
|
|
|
|
// Or force flush
|
|
logger.Flush(1 * time.Second)
|
|
```
|
|
|
|
### Q: Can multiple processes write to the same log file?
|
|
|
|
No, each process should use its own log file:
|
|
```go
|
|
// Include process ID in name
|
|
logger.InitWithDefaults(
|
|
fmt.Sprintf("name=myapp_%d", os.Getpid()),
|
|
)
|
|
```
|
|
|
|
### Q: How do I parse JSON logs?
|
|
|
|
Use any JSON parser:
|
|
```go
|
|
type LogEntry struct {
|
|
Time string `json:"time"`
|
|
Level string `json:"level"`
|
|
Fields []interface{} `json:"fields"`
|
|
}
|
|
|
|
// Parse line
|
|
var entry LogEntry
|
|
json.Unmarshal([]byte(logLine), &entry)
|
|
```
|
|
|
|
### Getting Help
|
|
|
|
If you encounter issues not covered here:
|
|
|
|
1. Check the [examples](examples.md) for working code
|
|
2. Enable debug logging and heartbeats
|
|
3. Review error messages carefully
|
|
4. Check system logs for permission/disk issues
|
|
5. File an issue with:
|
|
- Go version
|
|
- OS/Platform
|
|
- Minimal reproduction code
|
|
- Error messages
|
|
- Heartbeat output if available
|
|
|
|
---
|
|
|
|
[← Examples](examples.md) | [← Back to README](../README.md) |