Skip to content

Commit

Permalink
Use slog for structured, standardised logs
Browse files Browse the repository at this point in the history
Mostly just switching out methods, but also use more appropriate log levels in a few places

For CTC-138 #patch
  • Loading branch information
gregtyler committed Mar 6, 2024
1 parent f4791c8 commit 1079e5a
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 121 deletions.
29 changes: 21 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/leodido/go-urn v1.4.0
github.com/ministryofjustice/opg-go-common v0.0.0-20240223111039-066f4e682b9b
github.com/ministryofjustice/opg-go-common v0.0.0-20240227144553-d506200e53d5
github.com/stretchr/testify v1.9.0
)

Expand All @@ -40,22 +40,35 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/brunoscheufler/aws-ecs-metadata-go v0.0.0-20220812150832-b6b31c6eeeaf // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.50.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/sys v0.14.0 // indirect
go.opentelemetry.io/contrib/detectors/aws/ecs v1.24.0 // indirect
go.opentelemetry.io/contrib/propagators/aws v1.24.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/grpc v1.62.0 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
114 changes: 49 additions & 65 deletions go.sum

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion internal/shared/problem.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package shared
import (
"encoding/json"
"fmt"
"log/slog"
"os"
"strings"
"time"
Expand All @@ -23,8 +24,10 @@ type Problem struct {
}

type LogEvent struct {
Timestamp time.Time `json:"time"`
Level string `json:"level"`
Message string `json:"msg"`
ServiceName string `json:"service_name"`
Timestamp time.Time `json:"timestamp"`
Status int `json:"status"`
Problem Problem `json:"problem"`
ErrorString string `json:"error_string,omitempty"`
Expand Down Expand Up @@ -62,6 +65,8 @@ func (problem Problem) Respond() (events.APIGatewayProxyResponse, error) {

_ = json.NewEncoder(os.Stdout).Encode(LogEvent{
ServiceName: "opg-data-lpa-store",
Level: slog.LevelInfo.String(),
Message: problem.Detail,
Timestamp: time.Now(),
Status: problem.StatusCode,
Problem: problem,
Expand Down
27 changes: 15 additions & 12 deletions lambda/create/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"log/slog"
"os"
"time"

Expand All @@ -15,15 +16,17 @@ import (
"github.com/ministryofjustice/opg-data-lpa-store/internal/event"
"github.com/ministryofjustice/opg-data-lpa-store/internal/objectstore"
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared"
"github.com/ministryofjustice/opg-go-common/logging"
"github.com/ministryofjustice/opg-go-common/telemetry"
)

type EventClient interface {
SendLpaUpdated(ctx context.Context, event event.LpaUpdated) error
}

type Logger interface {
Print(...interface{})
Error(string, ...any)
Info(string, ...any)
Debug(string, ...any)
}

type Store interface {
Expand All @@ -50,11 +53,11 @@ type Lambda struct {
func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
_, err := l.verifier.VerifyHeader(req)
if err != nil {
l.logger.Print("Unable to verify JWT from header")
l.logger.Info("Unable to verify JWT from header")
return shared.ProblemUnauthorisedRequest.Respond()
}

l.logger.Print("Successfully parsed JWT from event header")
l.logger.Debug("Successfully parsed JWT from event header")

var input shared.LpaInit
uid := req.PathParameters["uid"]
Expand All @@ -68,7 +71,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ
var existingLpa shared.Lpa
existingLpa, err = l.store.Get(ctx, uid)
if err != nil {
l.logger.Print(err)
l.logger.Error("error fetching LPA", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

Expand All @@ -80,7 +83,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ

err = json.Unmarshal([]byte(req.Body), &input)
if err != nil {
l.logger.Print(err)
l.logger.Error("error unmarshalling request", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

Expand All @@ -99,15 +102,15 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ

// save
if err = l.store.Put(ctx, data); err != nil {
l.logger.Print(err)
l.logger.Error("error saving LPA", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

// save to static storage as JSON
objectKey := fmt.Sprintf("%s/donor-executed-lpa.json", data.Uid)

if err = l.staticLpaStorage.Put(ctx, objectKey, data); err != nil {
l.logger.Print(err)
l.logger.Error("error saving static record", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

Expand All @@ -118,7 +121,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ
})

if err != nil {
l.logger.Print(err)
l.logger.Error("unexpected error occurred", slog.Any("err", err))
}

// respond
Expand All @@ -129,7 +132,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ
}

func main() {
logger := logging.New(os.Stdout, "opg-data-lpa-store")
logger := telemetry.NewLogger("opg-data-lpa-store/create")

// set endpoint to "" outside dev to use default AWS resolver
endpointURL := os.Getenv("AWS_S3_ENDPOINT")
Expand All @@ -147,7 +150,7 @@ func main() {

eventClientConfig, err := config.LoadDefaultConfig(ctx)
if err != nil {
logger.Print("Failed to load event client configuration:", err)
logger.Error("Failed to load event client configuration", slog.Any("err", err))
}

s3Config, err := config.LoadDefaultConfig(
Expand All @@ -158,7 +161,7 @@ func main() {
},
)
if err != nil {
logger.Print("Failed to load S3 configuration:", err)
logger.Error("Failed to load S3 configuration", slog.Any("err", err))
}

l := &Lambda{
Expand Down
19 changes: 11 additions & 8 deletions lambda/get/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ package main
import (
"context"
"encoding/json"
"log/slog"
"os"

"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
"github.com/ministryofjustice/opg-data-lpa-store/internal/ddb"
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared"
"github.com/ministryofjustice/opg-go-common/logging"
"github.com/ministryofjustice/opg-go-common/telemetry"
)

type Logger interface {
Print(...interface{})
Error(string, ...any)
Info(string, ...any)
Debug(string, ...any)
}

type Store interface {
Expand All @@ -33,11 +36,11 @@ type Lambda struct {
func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
_, err := l.verifier.VerifyHeader(event)
if err != nil {
l.logger.Print("Unable to verify JWT from header")
l.logger.Info("Unable to verify JWT from header")
return shared.ProblemUnauthorisedRequest.Respond()
}

l.logger.Print("Successfully parsed JWT from event header")
l.logger.Debug("Successfully parsed JWT from event header")

response := events.APIGatewayProxyResponse{
StatusCode: 500,
Expand All @@ -49,19 +52,19 @@ func (l *Lambda) HandleEvent(ctx context.Context, event events.APIGatewayProxyRe
// If item can't be found in DynamoDB then it returns empty object hence 404 error returned if
// empty object returned
if lpa.Uid == "" {
l.logger.Print("Uid not found")
l.logger.Debug("Uid not found")
return shared.ProblemNotFoundRequest.Respond()
}

if err != nil {
l.logger.Print(err)
l.logger.Error("error fetching LPA", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

body, err := json.Marshal(lpa)

if err != nil {
l.logger.Print(err)
l.logger.Error("error marshalling LPA", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

Expand All @@ -79,7 +82,7 @@ func main() {
os.Getenv("DDB_TABLE_NAME_CHANGES"),
),
verifier: shared.NewJWTVerifier(),
logger: logging.New(os.Stdout, "opg-data-lpa-store"),
logger: telemetry.NewLogger("opg-data-lpa-store/get"),
}

lambda.Start(l.HandleEvent)
Expand Down
27 changes: 15 additions & 12 deletions lambda/update/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"encoding/json"
"log/slog"
"os"
"time"

Expand All @@ -13,15 +14,17 @@ import (
"github.com/ministryofjustice/opg-data-lpa-store/internal/ddb"
"github.com/ministryofjustice/opg-data-lpa-store/internal/event"
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared"
"github.com/ministryofjustice/opg-go-common/logging"
"github.com/ministryofjustice/opg-go-common/telemetry"
)

type EventClient interface {
SendLpaUpdated(ctx context.Context, event event.LpaUpdated) error
}

type Logger interface {
Print(...interface{})
Error(string, ...any)
Info(string, ...any)
Debug(string, ...any)
}

type Store interface {
Expand All @@ -43,11 +46,11 @@ type Lambda struct {
func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
claims, err := l.verifier.VerifyHeader(req)
if err != nil {
l.logger.Print("Unable to verify JWT from header")
l.logger.Info("Unable to verify JWT from header")
return shared.ProblemUnauthorisedRequest.Respond()
}

l.logger.Print("Successfully parsed JWT from event header")
l.logger.Debug("Successfully parsed JWT from event header")

response := events.APIGatewayProxyResponse{
StatusCode: 500,
Expand All @@ -56,17 +59,17 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ

var update shared.Update
if err = json.Unmarshal([]byte(req.Body), &update); err != nil {
l.logger.Print(err)
l.logger.Error("error unmarshalling request", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

lpa, err := l.store.Get(ctx, req.PathParameters["uid"])
if err != nil {
l.logger.Print(err)
l.logger.Error("error fetching LPA", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}
if lpa.Uid == "" {
l.logger.Print("Uid not found")
l.logger.Debug("Uid not found")
return shared.ProblemNotFoundRequest.Respond()
}

Expand All @@ -91,13 +94,13 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ
update.Author, _ = claims.GetSubject()

if err := l.store.PutChanges(ctx, lpa, update); err != nil {
l.logger.Print(err)
l.logger.Error("error saving changes", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

body, err := json.Marshal(lpa)
if err != nil {
l.logger.Print(err)
l.logger.Error("error marshalling LPA", slog.Any("err", err))
return shared.ProblemInternalServerError.Respond()
}

Expand All @@ -108,7 +111,7 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ
})

if err != nil {
l.logger.Print(err)
l.logger.Error("unexpected error occurred", slog.Any("err", err))
}

response.StatusCode = 201
Expand All @@ -118,11 +121,11 @@ func (l *Lambda) HandleEvent(ctx context.Context, req events.APIGatewayProxyRequ
}

func main() {
logger := logging.New(os.Stdout, "opg-data-lpa-store")
logger := telemetry.NewLogger("opg-data-lpa-store/update")
ctx := context.Background()
awsConfig, err := config.LoadDefaultConfig(ctx)
if err != nil {
logger.Print("Failed to load configuration:", err)
logger.Error("Failed to load configuration", slog.Any("err", err))
}

l := &Lambda{
Expand Down
Loading

0 comments on commit 1079e5a

Please sign in to comment.