Skip to content

Commit

Permalink
Feature/log mdc (#24)
Browse files Browse the repository at this point in the history
* feat: adds custom logger package
* feat: adds request headers as logging fields in slog
* feat: replaces log with slog in api request flow

---------

Signed-off-by: Amit Singh <[email protected]>
  • Loading branch information
semmet95 authored Feb 15, 2025
1 parent 2bd31e6 commit 7c1d10c
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 18 deletions.
7 changes: 6 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
issues:
exclude:
- (.*)_test\.go$
- (.*)_test\.go$

linters-settings:
errcheck:
exclude-functions:
- (*Logger).Sync
4 changes: 2 additions & 2 deletions acceptance/acceptance_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ func TestSourceScore(t *testing.T) {
log.Fatalf("application not running on port: %s", serverPort)
}

baseUrl = "http://" + helpers.LOCALHOST + ":" + serverPort
baseUrl = "http://" + helpers.Localhost + ":" + serverPort

RegisterFailHandler(Fail)
RunSpecs(t, "SourceScore Acceptance Test Suite")
}

func isLocalPortOpen(port string) bool {
address := net.JoinHostPort(helpers.LOCALHOST, port)
address := net.JoinHostPort(helpers.Localhost, port)
conn, err := net.DialTimeout("tcp", address, 2*time.Second)
if err != nil {
return false
Expand Down
31 changes: 28 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,48 @@ package main

import (
"log"
"log/slog"
"os"

"github.com/gin-gonic/gin"

"source-score/pkg/api"
"source-score/pkg/conf"
"source-score/pkg/helpers"
"source-score/pkg/logger"
)

func main() {
// initialize the config
conf.LoadConfig()

// initialize the logger
slog.SetDefault(
slog.New(&logger.ContextHandler{
Handler: slog.NewJSONHandler(os.Stdout, nil),
}),
)

// initialize the server
loggerOpts := api.GinServerOptions{
Middlewares: []api.MiddlewareFunc{
// function to add request headers to log fields
func(c *gin.Context) {
for _, fieldKey := range helpers.ApiReqLogFields {
fieldVal := c.Request.Header.Get(fieldKey)
logger.AppendGinCtx(c, slog.String(fieldKey, fieldVal))
}
},
},
}

server := gin.Default()
api.RegisterHandlers(server, api.NewRouter())
api.RegisterHandlersWithOptions(server, api.NewRouter(), loggerOpts)

err := server.Run()
if err != nil {
log.Fatalf("failed to start the server: %s\n", err)
log.Fatalf("failed to start the server : %s\n", err.Error())
} else {
log.Println("Server is up and running!")
}
}
}
12 changes: 6 additions & 6 deletions pkg/api/router.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package api

import (
"log"
"log/slog"
"net/http"
"source-score/pkg/handlers"

Expand All @@ -26,23 +26,23 @@ func (r *router) CreateSource(ctx *gin.Context) {
_ = ctx.AbortWithError(http.StatusBadRequest, err)
return
}
log.Println("unimplemented")
slog.InfoContext(ctx, "unimplemented")
}

func (r *router) DeleteSource(ctx *gin.Context, uriDigest string) {
log.Println("unimplemented")
slog.InfoContext(ctx, "unimplemented")
}

func (r *router) GetSource(ctx *gin.Context, uriDigest string) {
log.Println("unimplemented")
slog.InfoContext(ctx, "unimplemented")
}

func (r *router) UpdateSource(ctx *gin.Context, uriDigest string) {
log.Println("unimplemented")
slog.InfoContext(ctx, "unimplemented")
}

func (r *router) GetPing(ctx *gin.Context) {
message := r.pingHandler.GetPing()
message := r.pingHandler.GetPing(ctx)

ctx.JSON(http.StatusOK, gin.H{"data": message})
}
18 changes: 14 additions & 4 deletions pkg/domain/source/source_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"log"
"fmt"
"log/slog"

"source-score/pkg/api"
"source-score/pkg/db/cnpg"
Expand All @@ -22,7 +23,10 @@ func NewSourceRepository(ctx context.Context, client *cnpg.Client) *SourceReposi

func (sr *SourceRepository) DeleteSourceByUriDigest(ctx context.Context, source *api.Source) error {
result := sr.client.Delete(ctx, source)
log.Printf("%d rows affected\n", result.RowsAffected)
slog.InfoContext(
ctx,
fmt.Sprintf("%d rows affected\n", result.RowsAffected),
)

return result.Error
}
Expand Down Expand Up @@ -56,7 +60,10 @@ func (sr *SourceRepository) PutSource(ctx context.Context, sourceInput *api.Sour
}

result := sr.client.Create(ctx, source)
log.Printf("%d rows affected\n", result.RowsAffected)
slog.InfoContext(
ctx,
fmt.Sprintf("%d rows affected\n", result.RowsAffected),
)

return result.Error
}
Expand All @@ -76,7 +83,10 @@ func (sr *SourceRepository) UpdateSourceByUriDigest(ctx context.Context, sourceI
source.Tags = sourceInput.Tags

result = sr.client.Update(ctx, source)
log.Printf("%d rows affected\n", result.RowsAffected)
slog.InfoContext(
ctx,
fmt.Sprintf("%d rows affected\n", result.RowsAffected),
)

return result.Error
}
6 changes: 5 additions & 1 deletion pkg/handlers/ping.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package handlers

import (
"context"
)

type PingHandler struct {
message string
}
Expand All @@ -10,6 +14,6 @@ func NewPingHandler() *PingHandler {
}
}

func (ph PingHandler) GetPing() string {
func (ph PingHandler) GetPing(ctx context.Context) string {
return ph.message
}
9 changes: 8 additions & 1 deletion pkg/helpers/constants.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
package helpers

const (
LOCALHOST = "127.0.0.1"
Localhost = "127.0.0.1"
RequestIdHeader = "X-Request-ID"
)

var (
ApiReqLogFields = []string {
RequestIdHeader,
}
)
40 changes: 40 additions & 0 deletions pkg/logger/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package logger

import (
"context"
"log/slog"

"github.com/gin-gonic/gin"
)

const (
slogFields = "slog_fields"
)

type ContextHandler struct {
slog.Handler
}

// Handle adds contextual attributes to the Record before calling the underlying handler
func (h ContextHandler) Handle(ctx context.Context, r slog.Record) error {
if attrs, ok := ctx.Value(slogFields).([]slog.Attr); ok {
for _, v := range attrs {
r.AddAttrs(v)
}
}

return h.Handler.Handle(ctx, r)
}

// AppendGinCtx adds an slog attribute to the provided context so that it will be included
// in any Record created with such context
func AppendGinCtx(parent *gin.Context, attr slog.Attr) {
if v, ok := parent.Value(slogFields).([]slog.Attr); ok {
v = append(v, attr)
parent.Set(slogFields, v)
}

v := []slog.Attr{}
v = append(v, attr)
parent.Set(slogFields, v)
}

0 comments on commit 7c1d10c

Please sign in to comment.