first commit
This commit is contained in:
78
internal/middleware/logger.go
Normal file
78
internal/middleware/logger.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"cardverse/internal/pkg/logger"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Logger mencatat setiap request: method, path, status, durasi, IP, dan body request
|
||||
// (kalau JSON) supaya gampang di-debug. Field sensitif seperti password, token, dsb
|
||||
// OTOMATIS disensor oleh package logger (lihat internal/pkg/logger), jadi aman
|
||||
// dipasang bahkan di endpoint login/register.
|
||||
func Logger() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
|
||||
bodyFields := readBodyForLog(c)
|
||||
|
||||
c.Next()
|
||||
|
||||
duration := time.Since(start)
|
||||
status := c.Writer.Status()
|
||||
|
||||
fields := logger.Fields{
|
||||
"method": c.Request.Method,
|
||||
"path": c.Request.URL.Path,
|
||||
"status": status,
|
||||
"duration": duration.String(),
|
||||
"ip": c.ClientIP(),
|
||||
}
|
||||
if bodyFields != nil {
|
||||
fields["body"] = bodyFields
|
||||
}
|
||||
if len(c.Errors) > 0 {
|
||||
fields["gin_errors"] = c.Errors.String()
|
||||
}
|
||||
|
||||
switch {
|
||||
case status >= 500:
|
||||
logger.Error("request selesai", fields)
|
||||
case status >= 400:
|
||||
logger.Warn("request selesai", fields)
|
||||
default:
|
||||
logger.Info("request selesai", fields)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// readBodyForLog membaca body request (kalau berupa JSON) untuk keperluan log,
|
||||
// lalu mengembalikan body itu ke request supaya handler asli tetap bisa membacanya
|
||||
// seperti biasa. Field sensitif di dalam body (misal "password") akan disensor
|
||||
// otomatis oleh package logger saat log ditulis, bukan di sini.
|
||||
func readBodyForLog(c *gin.Context) map[string]interface{} {
|
||||
if c.Request.Body == nil {
|
||||
return nil
|
||||
}
|
||||
if c.Request.Method != "POST" && c.Request.Method != "PUT" && c.Request.Method != "PATCH" {
|
||||
return nil
|
||||
}
|
||||
|
||||
bodyBytes, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
// kembalikan body supaya bisa dibaca lagi oleh ShouldBindJSON di handler
|
||||
c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
|
||||
|
||||
var parsed map[string]interface{}
|
||||
if err := json.Unmarshal(bodyBytes, &parsed); err != nil {
|
||||
return nil // bukan JSON (atau body kosong), tidak masalah, cukup skip
|
||||
}
|
||||
return parsed
|
||||
}
|
||||
Reference in New Issue
Block a user