Files
log/doc/troubleshooting.md

10 KiB

Troubleshooting

← Examples | ← Back to README

Common issues and solutions when using the lixenwraith/log package.

Table of Contents

Common Issues

Logger Not Writing to File

Symptoms:

  • No log files created
  • Empty log directory
  • No error messages

Solutions:

  1. Check initialization

    logger := log.NewLogger()
    err := logger.InitWithDefaults()
    if err != nil {
        fmt.Printf("Init failed: %v\n", err)
    }
    
  2. Verify directory permissions

    # Check directory exists and is writable
    ls -la /var/log/myapp
    touch /var/log/myapp/test.log
    
  3. Check if file output is disabled

    // Ensure file output is enabled
    logger.InitWithDefaults(
        "disable_file=false",  // Default, but be explicit
        "directory=/var/log/myapp",
    )
    
  4. Enable console output for debugging

    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

    logger.InitWithDefaults(
        "buffer_size=4096",  // Increase from default 1024
    )
    
  2. Monitor with heartbeats

    logger.InitWithDefaults(
        "heartbeat_level=1",
        "heartbeat_interval_s=60",
    )
    // Watch for: dropped_logs=N
    
  3. Reduce log volume

    // 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

    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

    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

    # 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

    # 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

    // 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

    // Error: "failed to create log directory: permission denied"
    // Solution: Check permissions or use accessible directory
    logger.InitWithDefaults("directory=/tmp/logs")
    
  3. Configuration conflicts

    // 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

// 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

// 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

// 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:

# 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:

// 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:

# 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:

# Check limits
ulimit -n

# Increase if needed
ulimit -n 65536

SELinux Issues:

# 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:

# Ensure log directory ownership
chown appuser:appgroup /var/log/myapp
chmod 755 /var/log/myapp

Jails Configuration:

# Allow log directory access in jail
jail -m jid=1 allow.mount.devfs=1 path=/var/log/myapp

Windows

Path Format:

// 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:

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:

// 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:

// Change directory
logger.InitWithDefaults("directory=/new/path")

Q: How do I completely disable logging?

Several options:

// 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:

// 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:

// 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:

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 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 | ← Back to README