summaryrefslogtreecommitdiff
path: root/shrine/middleware/logger.go
blob: 500c2ac838846c2794bfb6ed4f573db673be4d26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package middleware

import (
	"fmt"
	"shrine/utils/logger"
	"strconv"
	"strings"
	"time"

	"github.com/gofiber/fiber/v2"
)

func httpLogger() fiber.Handler {
	return func(context *fiber.Ctx) error {
		start := time.Now()

		err := context.Next()

		duration := time.Since(start)
		status := context.Response().StatusCode()
		method := context.Method()
		path := context.Path()
		ip := context.IP()

		// Pad method for alignment
		paddedMethod := method
		if len(method) < 7 {
			paddedMethod = method + strings.Repeat(" ", 7-len(method))
		}

		message := fmt.Sprintf(
			"%s %-3d %-15s %-10s %s",
			paddedMethod,
			status,
			"IP: "+ip,
			"TTR: "+formatDuration(duration),
			"Path: "+path,
		)

		logByStatus(status, "HTTP", message)

		return err
	}
}

func logByStatus(status int, prefix, message string) {
	switch {
	case status >= 500:
		logger.Errorf(prefix, "%s", message)
	case status >= 400:
		logger.Warnf(prefix, "%s", message)
	case status >= 300:
		logger.Infof(prefix, "%s", message)
	case status >= 200:
		logger.Successf(prefix, "%s", message)
	default:
		logger.Infof(prefix, "%s", message)
	}
}

func formatDuration(d time.Duration) string {
	if d < time.Microsecond {
		return strconv.FormatInt(d.Nanoseconds(), 10) + "ns"
	}
	if d < time.Millisecond {
		return strconv.FormatInt(d.Nanoseconds()/1_000, 10) + "µs"
	}
	if d < time.Second {
		return strconv.FormatFloat(
			float64(d.Nanoseconds())/float64(time.Millisecond),
			'f',
			3,
			64,
		) + "ms"
	}
	return strconv.FormatFloat(
		float64(d.Nanoseconds())/float64(time.Second),
		'f',
		3,
		64,
	) + "s"
}