# Logging System Upgrade: Logrus → Zap + Lumberjack

## Overview

The tender management system has been upgraded from Logrus to **Zap** with **Lumberjack** for high-performance structured logging with automatic log rotation.

## 🚀 **Improvements**

### **Performance**
- **10x faster** logging performance with Zap
- Zero-allocation logging in hot paths
- Structured field processing optimized for speed

### **Log Rotation**
- **Automatic log rotation** based on file size, age, and backup count
- **Compression** of rotated log files to save disk space
- **Configurable retention** policies

### **Flexibility**
- **Multi-output** logging (file + stdout simultaneously)
- **Multiple formats** (JSON, console, text)
- **Environment-specific** configuration

## 📁 **Configuration**

### **YAML Configuration**
```yaml
logging:
  level: "info"              # debug, info, warn, error, fatal
  format: "json"             # json, console, text
  output: "file"             # stdout, stderr, file
  file:
    path: "./logs/app.log"   # Path to log file
    max_size: 100            # Max size in MB before rotation
    max_backups: 5           # Number of backup files to keep
    max_age: 30              # Max age in days to keep log files
    compress: true           # Compress rotated files
```

### **Environment Variables**
```bash
export TM_LOGGING_LEVEL="info"
export TM_LOGGING_OUTPUT="file"
export TM_LOGGING_FILE_PATH="./logs/app.log"
export TM_LOGGING_FILE_MAX_SIZE=100
export TM_LOGGING_FILE_MAX_BACKUPS=5
export TM_LOGGING_FILE_MAX_AGE=30
export TM_LOGGING_FILE_COMPRESS=true
```

## 🔧 **Usage**

### **Same Interface**
The logger interface remains the same - **no code changes required** in existing handlers and services:

```go
// All existing code continues to work
log.Info("User logged in", map[string]interface{}{
    "user_id": user.ID.Hex(),
    "email":   user.Email,
})

// Structured logging with fields
logger := log.WithFields(map[string]interface{}{
    "component": "auth",
    "request_id": requestID,
})
logger.Error("Authentication failed", map[string]interface{}{
    "error": err.Error(),
})
```

### **New Features**
```go
// Flush logs before shutdown
logger.Sync()

// Or use the global function
import "tm/pkg/logger"
logger.Sync()
```

## 📊 **Log Rotation Behavior**

### **File Naming Pattern**
```
logs/
├── app.log              # Current log file
├── app.log.1            # Most recent backup
├── app.log.2            # Older backup
├── app.log.3.gz         # Compressed older backup
├── app.log.4.gz         # Compressed older backup
└── app.log.5.gz         # Oldest backup (will be deleted on next rotation)
```

### **Rotation Triggers**
- **Size-based**: When `app.log` reaches 100MB
- **Time-based**: Daily rotation (if configured)
- **Manual**: Can be triggered programmatically

### **Cleanup**
- Keeps maximum 5 backup files
- Deletes files older than 30 days
- Compresses old files to save space

## 🛠️ **Development Commands**

### **Log Management**
```bash
# View live logs
make logs

# Follow logs in real-time
make logs-live

# Clean all log files
make logs-clean

# Clean everything including logs
make clean-all
```

### **Log File Locations**
- **Development**: `./logs/app.log`
- **Docker**: `/logs/app.log` (mounted volume)
- **Production**: Configurable via environment variables

## 🐳 **Docker Integration**

### **Volume Mounting**
```yaml
# docker-compose.yml
volumes:
  - ./logs:/logs  # Host logs directory mounted to container
```

### **Log Persistence**
- Logs persist on the host machine
- Rotation works across container restarts
- Easy log analysis and monitoring

## 🔍 **Log Format Examples**

### **JSON Format (Default)**
```json
{
  "timestamp": "2024-01-15T10:30:45.123Z",
  "level": "info",
  "caller": "handler/auth_handler.go:45",
  "msg": "User logged in successfully",
  "user_id": "123e4567-e89b-12d3-a456-426614174000",
  "email": "user@example.com",
  "request_id": "req_abc123"
}
```

### **Console Format (Development)**
```
2024-01-15T10:30:45.123Z  INFO  handler/auth_handler.go:45  User logged in successfully
  user_id=123e4567-e89b-12d3-a456-426614174000
  email=user@example.com
  request_id=req_abc123
```

## 🚨 **Migration Notes**

### **Breaking Changes**
- **None** - The logger interface remains compatible

### **Dependencies Updated**
```go
// Removed
github.com/sirupsen/logrus v1.9.3

// Added
go.uber.org/zap v1.26.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
```

### **Configuration Changes**
- Added `file` section to logging configuration
- `output: "file"` now enables file logging with rotation

## 📈 **Performance Comparison**

| Metric | Logrus | Zap | Improvement |
|--------|--------|-----|-------------|
| **Throughput** | ~100k/sec | ~1M+/sec | **10x faster** |
| **Allocations** | High | Zero (hot path) | **Much lower memory** |
| **CPU Usage** | Higher | Lower | **Better efficiency** |
| **Structured Fields** | Reflection-based | Type-safe | **Faster processing** |

## 🔧 **Advanced Configuration**

### **Custom Log Levels**
```go
// Set different levels for different components
config := &infrastructure.LoggingConfig{
    Level: "debug",  // Global level
    // Component-specific levels can be added later
}
```

### **Multiple Outputs**
```go
// Logs go to both file and stdout when output is "file"
// Perfect for development - see logs in terminal AND save to file
```

### **Programmatic Control**
```go
// Flush logs before application shutdown
defer logger.Cleanup()

// Or manually sync
if err := logger.Sync(); err != nil {
    // Handle sync error
}
```

## 🎯 **Best Practices**

1. **Use structured fields** for better log analysis
2. **Set appropriate log levels** (info for production, debug for development)
3. **Monitor log file sizes** in production
4. **Use log aggregation** tools like ELK stack for production
5. **Flush logs** before application shutdown

## 📚 **Resources**

- [Zap Documentation](https://pkg.go.dev/go.uber.org/zap)
- [Lumberjack Documentation](https://pkg.go.dev/gopkg.in/natefinch/lumberjack.v2)
- [Go Logging Best Practices](https://dave.cheney.net/2015/11/05/lets-talk-about-logging) 