396 lines
11 KiB
Markdown
396 lines
11 KiB
Markdown
# Logging System Usage Examples
|
|
|
|
This document provides comprehensive examples and documentation for using the new structured logging system in the ACC Server Manager.
|
|
|
|
## Overview
|
|
|
|
The logging system has been refactored to provide:
|
|
- **Structured logging** with separate files for each log level
|
|
- **Base logger** providing core functionality
|
|
- **Centralized error handling** for controllers
|
|
- **Backward compatibility** with existing code
|
|
|
|
## Architecture
|
|
|
|
```
|
|
logging/
|
|
├── base.go # Base logger with core functionality
|
|
├── error.go # Error-specific logging
|
|
├── warn.go # Warning-specific logging
|
|
├── info.go # Info-specific logging
|
|
├── debug.go # Debug-specific logging
|
|
└── logger.go # Main logger for backward compatibility
|
|
```
|
|
|
|
## Basic Usage
|
|
|
|
### Simple Logging (Backward Compatible)
|
|
|
|
```go
|
|
import "acc-server-manager/local/utl/logging"
|
|
|
|
// These work exactly as before
|
|
logging.Info("Server started on port %d", 8080)
|
|
logging.Error("Failed to connect to database: %v", err)
|
|
logging.Warn("Configuration value missing, using default")
|
|
logging.Debug("Processing request with ID: %s", requestID)
|
|
```
|
|
|
|
### Enhanced Logging with Context
|
|
|
|
```go
|
|
// Error logging with context
|
|
logging.ErrorWithContext("DATABASE", "Connection failed: %v", err)
|
|
logging.ErrorWithContext("AUTH", "Invalid credentials for user: %s", username)
|
|
|
|
// Info logging with context
|
|
logging.InfoWithContext("STARTUP", "Service initialized: %s", serviceName)
|
|
logging.InfoWithContext("SHUTDOWN", "Gracefully shutting down service: %s", serviceName)
|
|
|
|
// Warning with context
|
|
logging.WarnWithContext("CONFIG", "Missing configuration key: %s", configKey)
|
|
|
|
// Debug with context
|
|
logging.DebugWithContext("REQUEST", "Processing API call: %s", endpoint)
|
|
```
|
|
|
|
### Specialized Logging Functions
|
|
|
|
```go
|
|
// Application lifecycle
|
|
logging.LogStartup("DATABASE", "Connection pool initialized")
|
|
logging.LogShutdown("API_SERVER", "HTTP server stopped")
|
|
|
|
// Operations tracking
|
|
logging.LogOperation("USER_CREATE", "Created user with ID: " + userID.String())
|
|
logging.LogOperation("SERVER_START", "Started ACC server: " + serverName)
|
|
|
|
// HTTP request/response logging
|
|
logging.LogRequest("GET", "/api/v1/servers", "Mozilla/5.0...")
|
|
logging.LogResponse("GET", "/api/v1/servers", 200, "15ms")
|
|
|
|
// Error object logging
|
|
logging.LogError(err, "Failed to parse configuration file")
|
|
|
|
// Performance and debugging
|
|
logging.LogSQL("SELECT * FROM servers WHERE active = ?", true)
|
|
logging.LogMemory() // Logs current memory usage
|
|
logging.LogTiming("database_query", duration)
|
|
```
|
|
|
|
### Direct Logger Instances
|
|
|
|
```go
|
|
// Get specific logger instances for advanced usage
|
|
errorLogger := logging.GetErrorLogger()
|
|
infoLogger := logging.GetInfoLogger()
|
|
debugLogger := logging.GetDebugLogger()
|
|
warnLogger := logging.GetWarnLogger()
|
|
|
|
// Use specific logger methods
|
|
errorLogger.LogWithStackTrace("Critical system error occurred")
|
|
debugLogger.LogVariable("userConfig", userConfigObject)
|
|
debugLogger.LogState("cache", cacheState)
|
|
warnLogger.LogDeprecation("OldFunction", "NewFunction")
|
|
```
|
|
|
|
## Controller Error Handling
|
|
|
|
### Using the Centralized Error Handler
|
|
|
|
```go
|
|
package controller
|
|
|
|
import (
|
|
"acc-server-manager/local/utl/error_handler"
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
type MyController struct {
|
|
service *MyService
|
|
errorHandler *error_handler.ControllerErrorHandler
|
|
}
|
|
|
|
func NewMyController(service *MyService) *MyController {
|
|
return &MyController{
|
|
service: service,
|
|
errorHandler: error_handler.NewControllerErrorHandler(),
|
|
}
|
|
}
|
|
|
|
func (mc *MyController) GetUser(c *fiber.Ctx) error {
|
|
userID, err := uuid.Parse(c.Params("id"))
|
|
if err != nil {
|
|
// Automatically logs error and returns standardized response
|
|
return mc.errorHandler.HandleUUIDError(c, "user ID")
|
|
}
|
|
|
|
user, err := mc.service.GetUser(userID)
|
|
if err != nil {
|
|
// Logs error with context and returns appropriate HTTP status
|
|
return mc.errorHandler.HandleServiceError(c, err)
|
|
}
|
|
|
|
return c.JSON(user)
|
|
}
|
|
|
|
func (mc *MyController) CreateUser(c *fiber.Ctx) error {
|
|
var user User
|
|
if err := c.BodyParser(&user); err != nil {
|
|
return mc.errorHandler.HandleParsingError(c, err)
|
|
}
|
|
|
|
if err := mc.service.CreateUser(&user); err != nil {
|
|
return mc.errorHandler.HandleServiceError(c, err)
|
|
}
|
|
|
|
return c.JSON(user)
|
|
}
|
|
```
|
|
|
|
### Available Error Handler Methods
|
|
|
|
```go
|
|
// Generic error handling
|
|
HandleError(c *fiber.Ctx, err error, statusCode int, context ...string)
|
|
|
|
// Specific error types
|
|
HandleValidationError(c *fiber.Ctx, err error, field string)
|
|
HandleDatabaseError(c *fiber.Ctx, err error)
|
|
HandleAuthError(c *fiber.Ctx, err error)
|
|
HandleNotFoundError(c *fiber.Ctx, resource string)
|
|
HandleBusinessLogicError(c *fiber.Ctx, err error)
|
|
HandleServiceError(c *fiber.Ctx, err error)
|
|
HandleParsingError(c *fiber.Ctx, err error)
|
|
HandleUUIDError(c *fiber.Ctx, field string)
|
|
```
|
|
|
|
### Global Error Handler Functions
|
|
|
|
```go
|
|
import "acc-server-manager/local/utl/error_handler"
|
|
|
|
// Use global error handler functions for convenience
|
|
func (mc *MyController) SomeEndpoint(c *fiber.Ctx) error {
|
|
if err := someOperation(); err != nil {
|
|
return error_handler.HandleServiceError(c, err)
|
|
}
|
|
return c.JSON(result)
|
|
}
|
|
```
|
|
|
|
## Request Logging Middleware
|
|
|
|
### Setup Request Logging
|
|
|
|
```go
|
|
import (
|
|
middlewareLogging "acc-server-manager/local/middleware/logging"
|
|
)
|
|
|
|
func setupRoutes(app *fiber.App) {
|
|
// Add request logging middleware
|
|
app.Use(middlewareLogging.Handler())
|
|
|
|
// Your routes here...
|
|
}
|
|
```
|
|
|
|
This will automatically log:
|
|
- Incoming requests with method, URL, and user agent
|
|
- Outgoing responses with status code and duration
|
|
- Any errors that occur during request processing
|
|
|
|
## Advanced Usage Examples
|
|
|
|
### Custom Logger with Specific Configuration
|
|
|
|
```go
|
|
// Create a custom base logger instance
|
|
baseLogger, err := logging.InitializeBase()
|
|
if err != nil {
|
|
log.Fatal("Failed to initialize logger")
|
|
}
|
|
|
|
// Create specialized loggers
|
|
errorLogger := logging.NewErrorLogger()
|
|
debugLogger := logging.NewDebugLogger()
|
|
|
|
// Use them directly
|
|
errorLogger.LogWithStackTrace("Critical error in payment processing")
|
|
debugLogger.LogMemory()
|
|
debugLogger.LogGoroutines()
|
|
```
|
|
|
|
### Panic Recovery and Logging
|
|
|
|
```go
|
|
func dangerousOperation() {
|
|
defer logging.RecoverAndLog()
|
|
|
|
// Your potentially panicking code here
|
|
// If panic occurs, it will be logged with full stack trace
|
|
}
|
|
```
|
|
|
|
### Performance Monitoring
|
|
|
|
```go
|
|
func processRequest() {
|
|
start := time.Now()
|
|
defer func() {
|
|
duration := time.Since(start)
|
|
logging.LogTiming("request_processing", duration)
|
|
}()
|
|
|
|
// Log memory usage periodically
|
|
logging.LogMemory()
|
|
|
|
// Your processing logic here
|
|
}
|
|
```
|
|
|
|
### Database Query Logging
|
|
|
|
```go
|
|
func (r *Repository) GetUser(id uuid.UUID) (*User, error) {
|
|
query := "SELECT * FROM users WHERE id = ?"
|
|
logging.LogSQL(query, id)
|
|
|
|
var user User
|
|
err := r.db.Get(&user, query, id)
|
|
if err != nil {
|
|
logging.ErrorWithContext("DATABASE", "Failed to get user %s: %v", id, err)
|
|
return nil, err
|
|
}
|
|
|
|
return &user, nil
|
|
}
|
|
```
|
|
|
|
## Migration Guide
|
|
|
|
### For Existing Code
|
|
|
|
Your existing logging calls will continue to work:
|
|
|
|
```go
|
|
// These still work exactly as before
|
|
logging.Info("Message")
|
|
logging.Error("Error: %v", err)
|
|
logging.Warn("Warning message")
|
|
logging.Debug("Debug info")
|
|
```
|
|
|
|
### Upgrading to New Features
|
|
|
|
Consider upgrading to new features gradually:
|
|
|
|
```go
|
|
// Instead of:
|
|
logging.Error("Database error: %v", err)
|
|
|
|
// Use:
|
|
logging.ErrorWithContext("DATABASE", "Connection failed: %v", err)
|
|
// or
|
|
logging.LogError(err, "Database connection failed")
|
|
```
|
|
|
|
### Controller Updates
|
|
|
|
Replace manual error handling:
|
|
|
|
```go
|
|
// Old way:
|
|
if err != nil {
|
|
logging.Error("Service error: %v", err)
|
|
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
|
}
|
|
|
|
// New way:
|
|
if err != nil {
|
|
return mc.errorHandler.HandleServiceError(c, err)
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Log Levels
|
|
|
|
The system automatically handles different log levels. All logs are written to the same file but with different level indicators:
|
|
|
|
```
|
|
[2024-01-15 10:30:45.123] [INFO] [server.go:45] Server started successfully
|
|
[2024-01-15 10:30:46.456] [ERROR] [database.go:12] Connection failed: timeout
|
|
[2024-01-15 10:30:47.789] [WARN] [config.go:67] Using default configuration
|
|
[2024-01-15 10:30:48.012] [DEBUG] [handler.go:23] Processing request ID: 12345
|
|
```
|
|
|
|
### File Organization
|
|
|
|
Logs are automatically organized by date in the `logs/` directory:
|
|
- `logs/acc-server-2024-01-15.log`
|
|
- `logs/acc-server-2024-01-16.log`
|
|
|
|
### Output Destinations
|
|
|
|
All logs are written to both:
|
|
- Console (stdout) for development
|
|
- Log files for persistence
|
|
|
|
## Best Practices
|
|
|
|
1. **Use contextual logging** for better debugging
|
|
2. **Use appropriate log levels** (DEBUG for development, INFO for operations, WARN for issues, ERROR for failures)
|
|
3. **Use the error handler** in controllers for consistent error responses
|
|
4. **Include relevant information** in log messages (IDs, timestamps, etc.)
|
|
5. **Avoid logging sensitive information** (passwords, tokens, etc.)
|
|
6. **Use structured fields** when possible for better parsing
|
|
|
|
## Examples by Use Case
|
|
|
|
### API Controller Logging
|
|
|
|
```go
|
|
func (ac *APIController) CreateServer(c *fiber.Ctx) error {
|
|
var server Server
|
|
if err := c.BodyParser(&server); err != nil {
|
|
return ac.errorHandler.HandleParsingError(c, err)
|
|
}
|
|
|
|
logging.InfoOperation("SERVER_CREATE", fmt.Sprintf("Creating server: %s", server.Name))
|
|
|
|
if err := ac.service.CreateServer(&server); err != nil {
|
|
return ac.errorHandler.HandleServiceError(c, err)
|
|
}
|
|
|
|
logging.InfoOperation("SERVER_CREATE", fmt.Sprintf("Successfully created server: %s (ID: %s)", server.Name, server.ID))
|
|
return c.JSON(server)
|
|
}
|
|
```
|
|
|
|
### Service Layer Logging
|
|
|
|
```go
|
|
func (s *ServerService) StartServer(serverID uuid.UUID) error {
|
|
logging.InfoWithContext("SERVER_SERVICE", "Starting server %s", serverID)
|
|
|
|
server, err := s.repository.GetServer(serverID)
|
|
if err != nil {
|
|
logging.ErrorWithContext("SERVER_SERVICE", "Failed to get server %s: %v", serverID, err)
|
|
return err
|
|
}
|
|
|
|
logging.DebugState("server_config", server)
|
|
|
|
if err := s.processManager.Start(server); err != nil {
|
|
logging.ErrorWithContext("SERVER_SERVICE", "Failed to start server %s: %v", serverID, err)
|
|
return err
|
|
}
|
|
|
|
logging.InfoOperation("SERVER_START", fmt.Sprintf("Server %s started successfully", server.Name))
|
|
return nil
|
|
}
|
|
```
|
|
|
|
This new logging system provides comprehensive error handling and logging capabilities while maintaining backward compatibility with existing code. |