乐闻世界logo
搜索文章和话题

How to implement logging and monitoring in the Gin framework?

2月21日 15:15

The implementation methods for logging and monitoring in the Gin framework are as follows:

1. Logging overview

The Gin framework has built-in basic logging capabilities and also supports integration with third-party logging libraries such as logrus, zap, zerolog, etc.

2. Using built-in logging

2.1 Basic logging

go
import "github.com/gin-gonic/gin" func main() { // Set Gin mode gin.SetMode(gin.DebugMode) // or gin.ReleaseMode r := gin.Default() // Default includes Logger and Recovery middleware r.GET("/", func(c *gin.Context) { c.String(200, "Hello World") }) r.Run(":8080") }

2.2 Custom log format

go
func main() { r := gin.New() // Custom logging middleware r.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string { return fmt.Sprintf("[%s] %s %s %d %s\n", param.TimeStamp.Format("2006-01-02 15:04:05"), param.Method, param.Path, param.StatusCode, param.Latency, ) })) r.Use(gin.Recovery()) r.GET("/", func(c *gin.Context) { c.String(200, "Hello World") }) r.Run(":8080") }

3. Integrating logrus

3.1 Configuring logrus

go
import ( "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) var log = logrus.New() func init() { log.SetFormatter(&logrus.JSONFormatter{}) log.SetOutput(os.Stdout) log.SetLevel(logrus.InfoLevel) } func logrusMiddleware() gin.HandlerFunc { return func(c *gin.Context) { startTime := time.Now() c.Next() latency := time.Since(startTime) status := c.Writer.Status() entry := log.WithFields(logrus.Fields{ "method": c.Request.Method, "path": c.Request.URL.Path, "status": status, "latency": latency, "ip": c.ClientIP(), "user-agent": c.Request.UserAgent(), }) if status >= 500 { entry.Error("Server error") } else if status >= 400 { entry.Warn("Client error") } else { entry.Info("Request completed") } } }

3.2 Using logrus

go
func main() { r := gin.New() r.Use(logrusMiddleware()) r.Use(gin.Recovery()) r.GET("/", func(c *gin.Context) { log.Info("Processing request") c.String(200, "Hello World") }) r.Run(":8080") }

4. Integrating zap

4.1 Configuring zap

go
import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" ) var logger *zap.Logger func initLogger() { config := zap.NewProductionConfig() config.EncoderConfig.TimeKey = "timestamp" config.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder var err error logger, err = config.Build() if err != nil { panic(err) } } func zapMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() path := c.Request.URL.Path query := c.Request.URL.RawQuery c.Next() latency := time.Since(start) status := c.Writer.Status() logger.Info("Request", zap.String("method", c.Request.Method), zap.String("path", path), zap.String("query", query), zap.Int("status", status), zap.Duration("latency", latency), zap.String("ip", c.ClientIP()), ) } }

5. Request tracing

5.1 Adding request ID

go
import "github.com/google/uuid" func requestIDMiddleware() gin.HandlerFunc { return func(c *gin.Context) { requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() } c.Set("request_id", requestID) c.Header("X-Request-ID", requestID) c.Next() } }

5.2 Distributed tracing

go
import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/trace" ) func tracingMiddleware() gin.HandlerFunc { return func(c *gin.Context) { tracer := otel.Tracer("gin-server") ctx, span := tracer.Start(c.Request.Context(), c.Request.URL.Path) defer span.End() c.Request = c.Request.WithContext(ctx) c.Next() } }

6. Performance monitoring

6.1 Prometheus metrics

go
import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) var ( httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "HTTP request duration in seconds", }, []string{"method", "path", "status"}) httpRequestsTotal = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "path", "status"}) ) func prometheusMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() c.Next() duration := time.Since(start).Seconds() status := strconv.Itoa(c.Writer.Status()) httpDuration.WithLabelValues(c.Request.Method, c.FullPath(), status).Observe(duration) httpRequestsTotal.WithLabelValues(c.Request.Method, c.FullPath(), status).Inc() } }

6.2 Exposing metrics endpoint

go
import "github.com/prometheus/client_golang/prometheus/promhttp" func setupMetrics(r *gin.Engine) { r.GET("/metrics", gin.WrapH(promhttp.Handler())) }

7. Error monitoring

7.1 Sentry integration

go
import "github.com/getsentry/sentry-go" func initSentry() { err := sentry.Init(sentry.ClientOptions{ Dsn: "your-sentry-dsn", }) if err != nil { panic(err) } } func sentryMiddleware() gin.HandlerFunc { return func(c *gin.Context) { hub := sentry.CurrentHub().Clone() hub.Scope().SetRequest(c.Request) c.Set("sentry", hub) defer func() { if err := recover(); err != nil { hub.CaptureException(err.(error)) c.JSON(500, gin.H{"error": "Internal server error"}) c.Abort() } }() c.Next() } }

8. Structured logging

8.1 Using structured fields

go
func logStructured(c *gin.Context) { log.WithFields(logrus.Fields{ "request_id": c.GetString("request_id"), "user_id": c.GetInt("user_id"), "action": "user_login", "ip": c.ClientIP(), }).Info("User logged in") }

8.2 Log level control

go
func logWithLevel(c *gin.Context, err error) { if err == nil { log.Info("Operation successful") return } switch { case errors.Is(err, ErrNotFound): log.WithField("error", err).Warn("Resource not found") case errors.Is(err, ErrUnauthorized): log.WithField("error", err).Warn("Unauthorized access") default: log.WithField("error", err).Error("Internal error") } }

9. Log rotation

9.1 Using lumberjack

go
import "gopkg.in/natefinch/lumberjack.v2" func setupRotatingLogger() { log.SetOutput(&lumberjack.Logger{ Filename: "app.log", MaxSize: 100, // MB MaxBackups: 3, MaxAge: 28, // days Compress: true, }) }

10. Best practices

  1. Log content

    • Record request ID for tracing
    • Include timestamp, method, path, status code
    • Record key business operations
    • Avoid logging sensitive information
  2. Log levels

    • Debug: Development debugging information
    • Info: Normal business flow
    • Warn: Potential issues
    • Error: Errors but recoverable
    • Fatal: Fatal errors
  3. Performance considerations

    • Use asynchronous logging
    • Avoid logging detailed information in hot paths
    • Use structured logging for easy parsing
    • Reasonably set log levels
  4. Monitoring metrics

    • Request latency distribution
    • Request success rate
    • Error rate
    • Concurrent connections
    • Memory and CPU usage
  5. Alert configuration

    • Set error rate thresholds
    • Configure latency alerts
    • Monitor resource usage
    • Set log anomaly detection

Through the above methods, you can implement a comprehensive logging and monitoring system in the Gin framework.

标签:Gin