• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rm-hull / gps-routes-api / 14010529033

22 Mar 2025 04:50PM UTC coverage: 0.0%. Remained the same
14010529033

Pull #15

github

web-flow
Merge 62cb318f1 into 7f5e60cab
Pull Request #15: Convert to structured JSON logging

0 of 20 new or added lines in 1 file covered. (0.0%)

3 existing lines in 1 file now uncovered.

0 of 886 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cmds/http_server.go
1
package cmds
2

3
import (
4
        "context"
5
        "log"
6
        "log/slog"
7
        "os"
8
        "time"
9

10
        "github.com/Depado/ginprom"
11
        ratelimit "github.com/JGLTechnologies/gin-rate-limit"
12
        "github.com/aurowora/compress"
13
        "github.com/earthboundkid/versioninfo/v2"
14
        "github.com/gin-contrib/cors"
15
        limits "github.com/gin-contrib/size"
16
        "github.com/gin-gonic/gin"
17
        "github.com/jackc/pgx/v5/stdlib"
18
        sloggin "github.com/samber/slog-gin"
19
        healthcheck "github.com/tavsec/gin-healthcheck"
20
        "github.com/tavsec/gin-healthcheck/checks"
21
        hc_config "github.com/tavsec/gin-healthcheck/config"
22
        cachecontrol "go.eigsys.de/gin-cachecontrol/v2"
23

24
        "github.com/rm-hull/gps-routes-api/db"
25
        "github.com/rm-hull/gps-routes-api/middlewares"
26
        "github.com/rm-hull/gps-routes-api/repositories"
27
        "github.com/rm-hull/gps-routes-api/routes"
28
        "github.com/rm-hull/gps-routes-api/services"
29
)
30

UNCOV
31
func NewHttpServer() {
×
32

×
33
        // Connect to Postgres
×
34
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
×
35
        defer cancel()
×
36

×
NEW
37
        dbConfig := db.ConfigFromEnv()
×
NEW
38
        pool, err := db.NewDBPool(ctx, dbConfig)
×
39
        if err != nil {
×
40
                log.Fatalf("failed to create database pool: %v", err)
×
41
        }
×
42
        defer pool.Close()
×
43

×
44
        engine := gin.New()
×
NEW
45
        logger := createLogger()
×
NEW
46

×
47
        prometheus := ginprom.New(
×
48
                ginprom.Engine(engine),
×
49
                ginprom.Namespace("gps_routes"),
×
50
                ginprom.Subsystem("api"),
×
51
        )
×
52

×
53
        rlStore := ratelimit.InMemoryStore(&ratelimit.InMemoryOptions{
×
54
                Rate:  time.Second,
×
55
                Limit: 5,
×
56
        })
×
57
        rateLimiter := ratelimit.RateLimiter(rlStore, &ratelimit.Options{
×
58
                ErrorHandler: func(c *gin.Context, info ratelimit.Info) {
×
59
                        c.JSON(429, gin.H{
×
60
                                "error":   "Too many requests",
×
61
                                "message": "Try again in " + time.Until(info.ResetTime).String(),
×
62
                        })
×
63
                },
×
64
                KeyFunc: func(c *gin.Context) string {
×
65
                        return c.ClientIP()
×
66
                },
×
67
        })
68

UNCOV
69
        engine.Use(
×
NEW
70
                sloggin.NewWithConfig(logger, sloggin.Config{
×
NEW
71
                        WithSpanID:  true,
×
NEW
72
                        WithTraceID: true,
×
NEW
73
                        Filters: []sloggin.Filter{
×
NEW
74
                                sloggin.IgnorePath("/healthz", "/metrics"),
×
NEW
75
                        }}),
×
76
                gin.Recovery(),
×
77
                cors.Default(),
×
78
                middlewares.ErrorHandler(),
×
79
                compress.Compress(),
×
80
                limits.RequestSizeLimiter(10*1024),
×
81
                cachecontrol.New(cachecontrol.CacheAssetsForeverPreset),
×
82
                prometheus.Instrument(),
×
83
                rateLimiter,
×
84
        )
×
85

×
86
        db := stdlib.OpenDB(*pool.Config().ConnConfig)
×
87
        defer db.Close()
×
88
        err = healthcheck.New(engine, hc_config.DefaultConfig(), []checks.Check{
×
89
                checks.SqlCheck{Sql: db},
×
90
        })
×
91
        if err != nil {
×
92
                log.Fatalf("failed to initialize healthcheck: %v", err)
×
93
        }
×
94

NEW
UNCOV
95
        pg := repositories.NewPostgresRouteRepository(pool, dbConfig.Schema)
×
96
        repo := repositories.NewCachedRepository(prometheus, pg)
×
97
        service := services.NewRoutesService(repo)
×
98

×
99
        router := routes.NewRouterWithGinEngine(engine, routes.ApiHandleFunctions{
×
100
                RoutesAPI: routes.RoutesAPI{
×
101
                        Service: service,
×
102
                },
×
103
        })
×
104

×
NEW
105
        logger.With("version", versioninfo.Short()).Info("Server started")
×
NEW
106

×
NEW
107
        err = router.Run(":8080")
×
NEW
108
        logger.With("error", err).Error("Unhandled/unexpected crash")
×
109
}
110

NEW
111
func createLogger() *slog.Logger {
×
NEW
112
        if gin.IsDebugging() {
×
NEW
113
                return slog.New(slog.NewTextHandler(os.Stdout, nil))
×
NEW
114
        }
×
115

NEW
116
        return slog.New(slog.NewJSONHandler(os.Stdout, nil))
×
117
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc