Skip to content

Commit 9a0f255

Browse files
committed
feat: ✨ add slog for logger with source
add slog for logger with source
1 parent 19797f9 commit 9a0f255

File tree

8 files changed

+201
-30
lines changed

8 files changed

+201
-30
lines changed

cmd/main.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,28 @@ package main
22

33
import (
44
"context"
5-
"log"
5+
"log/slog"
66
"os"
77
"os/signal"
88
"syscall"
99

1010
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/application"
1111
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/config"
12+
mlog "github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/logger"
1213
)
1314

1415
func main() {
15-
app := application.New(config.AppConfig)
16-
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
16+
logger := slog.New(slog.NewJSONHandler(
17+
os.Stdout, &slog.HandlerOptions{
18+
AddSource: true,
19+
},
20+
))
21+
rootContext := context.WithValue(context.Background(), mlog.CtxKey{}, logger)
22+
app := application.New(config.AppConfig, rootContext)
23+
ctx, cancel := signal.NotifyContext(rootContext, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
1724
defer cancel()
1825
err := app.Start(ctx)
1926
if err != nil {
20-
log.Fatalf("failed to start app: %v", err)
27+
logger.Error("failed to start app", "error", err)
2128
}
2229
}

go.mod

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,34 @@ go 1.22.4
55
require github.com/spf13/viper v1.19.0
66

77
require (
8-
github.com/bytedance/sonic v1.11.6 // indirect
8+
github.com/bytedance/sonic v1.11.9 // indirect
99
github.com/bytedance/sonic/loader v0.1.1 // indirect
1010
github.com/cloudwego/base64x v0.1.4 // indirect
1111
github.com/cloudwego/iasm v0.2.0 // indirect
1212
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
13-
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
13+
github.com/gabriel-vasile/mimetype v1.4.4 // indirect
1414
github.com/gin-contrib/sse v0.1.0 // indirect
1515
github.com/go-playground/locales v0.14.1 // indirect
1616
github.com/go-playground/universal-translator v0.18.1 // indirect
17-
github.com/go-playground/validator/v10 v10.20.0 // indirect
18-
github.com/goccy/go-json v0.10.2 // indirect
17+
github.com/go-playground/validator/v10 v10.22.0 // indirect
18+
github.com/goccy/go-json v0.10.3 // indirect
19+
github.com/google/uuid v1.6.0 // indirect
1920
github.com/json-iterator/go v1.1.12 // indirect
20-
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
21+
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
2122
github.com/leodido/go-urn v1.4.0 // indirect
2223
github.com/mattn/go-isatty v0.0.20 // indirect
2324
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
2425
github.com/modern-go/reflect2 v1.0.2 // indirect
2526
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
27+
github.com/samber/slog-gin v1.13.6 // indirect
2628
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
2729
github.com/ugorji/go/codec v1.2.12 // indirect
30+
go.opentelemetry.io/otel v1.29.0 // indirect
31+
go.opentelemetry.io/otel/trace v1.29.0 // indirect
2832
golang.org/x/arch v0.8.0 // indirect
29-
golang.org/x/crypto v0.23.0 // indirect
30-
golang.org/x/net v0.25.0 // indirect
31-
google.golang.org/protobuf v1.34.1 // indirect
33+
golang.org/x/crypto v0.24.0 // indirect
34+
golang.org/x/net v0.26.0 // indirect
35+
google.golang.org/protobuf v1.34.2 // indirect
3236
)
3337

3438
require (
@@ -49,8 +53,8 @@ require (
4953
go.uber.org/atomic v1.9.0 // indirect
5054
go.uber.org/multierr v1.9.0 // indirect
5155
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
52-
golang.org/x/sys v0.20.0 // indirect
53-
golang.org/x/text v0.15.0 // indirect
56+
golang.org/x/sys v0.21.0 // indirect
57+
golang.org/x/text v0.16.0 // indirect
5458
gopkg.in/ini.v1 v1.67.0 // indirect
5559
gopkg.in/yaml.v3 v3.0.1 // indirect
5660
)

go.sum

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
22
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
3+
github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5zg=
4+
github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
35
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
46
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
57
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
@@ -14,6 +16,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
1416
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
1517
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
1618
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
19+
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
20+
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
1721
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
1822
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
1923
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
@@ -24,16 +28,24 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
2428
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
2529
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
2630
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
31+
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
32+
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
2733
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
2834
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
35+
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
36+
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
2937
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
38+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
39+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
3040
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
3141
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
3242
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
3343
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
3444
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
3545
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
3646
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
47+
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
48+
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
3749
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
3850
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
3951
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
@@ -57,6 +69,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke
5769
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
5870
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
5971
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
72+
github.com/samber/slog-gin v1.13.6 h1:clWpgtdL/3KM1eGkUMUHTLNM1fG4nA3bHC1Pt7v0z44=
73+
github.com/samber/slog-gin v1.13.6/go.mod h1:iicbXYT1DozbzsbLfpRdXkAal3zmzIjayQCV5YR+A6M=
6074
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
6175
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
6276
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
@@ -85,6 +99,10 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
8599
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
86100
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
87101
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
102+
go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
103+
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
104+
go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
105+
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
88106
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
89107
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
90108
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
@@ -94,22 +112,32 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
94112
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
95113
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
96114
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
115+
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
116+
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
97117
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
98118
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
99119
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
100120
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
121+
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
122+
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
101123
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
102124
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
103125
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
104126
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
105127
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
106128
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
129+
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
130+
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
107131
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
108132
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
109133
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
110134
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
135+
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
136+
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
111137
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
112138
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
139+
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
140+
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
113141
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
114142
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
115143
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=

interanl/application/app.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ package application
33
import (
44
"context"
55
"fmt"
6-
"log"
76
"net/http"
87
"time"
98

109
"github.com/gin-gonic/gin"
1110
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/config"
11+
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/logger"
1212
)
1313

1414
// define app dependency
@@ -17,20 +17,21 @@ type App struct {
1717
config *config.Config
1818
}
1919

20-
func New(config *config.Config) *App {
20+
func New(config *config.Config, ctx context.Context) *App {
2121
app := &App{
2222
config: config,
2323
}
24-
app.SetupRoutes()
24+
app.SetupRoutes(ctx)
2525
return app
2626
}
2727

2828
func (app *App) Start(ctx context.Context) error {
29+
logger := logger.FromContext(ctx)
2930
server := &http.Server{
3031
Addr: fmt.Sprintf(":%s", app.config.Port),
3132
Handler: app.Router,
3233
}
33-
log.Printf("Starting server on %s", app.config.Port)
34+
logger.Info(fmt.Sprintf("Starting server on %s", app.config.Port))
3435
errCh := make(chan error, 1)
3536
go func() {
3637
err := server.ListenAndServe()
@@ -44,7 +45,7 @@ func (app *App) Start(ctx context.Context) error {
4445
case err := <-errCh:
4546
return err
4647
case <-ctx.Done():
47-
log.Println("server cancel")
48+
logger.Info("server cancel")
4849
timeout, cancel := context.WithTimeout(context.Background(), time.Second*10)
4950
defer cancel()
5051
return server.Shutdown(timeout)

interanl/application/route.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
package application
22

33
import (
4+
"context"
45
"net/http"
56

67
"github.com/gin-gonic/gin"
8+
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/logger"
79
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/services/news"
10+
sloggin "github.com/samber/slog-gin"
811
)
912

1013
// define route
11-
func (app *App) SetupRoutes() {
14+
func (app *App) SetupRoutes(ctx context.Context) {
1215
gin.SetMode(app.config.GinMode)
1316
router := gin.New()
1417
// recovery middleward
18+
router.Use(sloggin.New(logger.FromContext(ctx)))
1519
router.Use(gin.Recovery())
1620
router.GET("/", func(ctx *gin.Context) {
1721
ctx.JSON(http.StatusOK, map[string]string{"message": "ok"})

interanl/logger/log.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package logger
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
"os"
7+
)
8+
9+
type CtxKey struct{}
10+
11+
func CtxWithLogger(ctx context.Context, logger *slog.Logger) context.Context {
12+
if logger == nil {
13+
return ctx
14+
}
15+
if ctxLog, ok := ctx.Value(CtxKey{}).(*slog.Logger); ok && ctxLog == logger {
16+
return ctx
17+
}
18+
return context.WithValue(ctx, CtxKey{}, logger)
19+
}
20+
21+
func FromContext(ctx context.Context) *slog.Logger {
22+
if logger, ok := ctx.Value(CtxKey{}).(*slog.Logger); ok {
23+
return logger
24+
}
25+
26+
return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
27+
AddSource: true,
28+
}))
29+
}

interanl/logger/log_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package logger_test
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
"os"
7+
"testing"
8+
9+
"github.com/leetcode-golang-classroom/golang-rest-api-sample/interanl/logger"
10+
)
11+
12+
func Test_CtxWithLogger(t *testing.T) {
13+
testCases := []struct {
14+
name string
15+
ctx context.Context
16+
logger *slog.Logger
17+
exists bool
18+
}{
19+
{
20+
name: "returns context without logger",
21+
ctx: context.Background(),
22+
},
23+
{
24+
name: "return ctx as it is",
25+
ctx: context.WithValue(context.Background(), logger.CtxKey{}, slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
26+
AddSource: true,
27+
}))),
28+
exists: true,
29+
},
30+
{
31+
name: "inject logger",
32+
ctx: context.Background(),
33+
logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
34+
AddSource: true,
35+
})),
36+
exists: true,
37+
},
38+
}
39+
for _, tc := range testCases {
40+
t.Run(tc.name, func(t *testing.T) {
41+
ctx := logger.CtxWithLogger(tc.ctx, tc.logger)
42+
43+
_, ok := ctx.Value(logger.CtxKey{}).(*slog.Logger)
44+
if tc.exists != ok {
45+
t.Errorf("expected :%v got: %v", tc.exists, ok)
46+
}
47+
})
48+
}
49+
}
50+
51+
func Test_FromContext(t *testing.T) {
52+
testCases := []struct {
53+
name string
54+
ctx context.Context
55+
expected bool
56+
}{
57+
{
58+
name: "logger exists",
59+
ctx: context.WithValue(context.Background(), logger.CtxKey{}, slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
60+
AddSource: true,
61+
}))),
62+
expected: true,
63+
},
64+
{
65+
name: "new loggger returned",
66+
ctx: context.Background(),
67+
expected: true,
68+
},
69+
}
70+
for _, tc := range testCases {
71+
t.Run(tc.name, func(t *testing.T) {
72+
logger := logger.FromContext(tc.ctx)
73+
74+
if tc.expected && logger == nil {
75+
t.Errorf("expected: %v, got: %v", tc.expected, logger)
76+
}
77+
})
78+
}
79+
}

0 commit comments

Comments
 (0)