1diff --git a/cmd/server/main.go b/cmd/server/main.go
2index 41b2b4a781170e387e42db4d187b3ff91fbfd7d5..c2160c4890eeba599b53517c8d89246262764350 100644
3--- a/cmd/server/main.go
4+++ b/cmd/server/main.go
5@@ -4,6 +4,7 @@ import (
6 "context"
7 "encoding/base64"
8 "errors"
9+ "log/slog"
10 "net/http"
11 "os"
12 "os/signal"
13@@ -11,7 +12,6 @@ "time"
14
15 "github.com/glebarez/sqlite"
16 "github.com/gorilla/mux"
17- "github.com/sirupsen/logrus"
18 flag "github.com/spf13/pflag"
19 "gorm.io/driver/mysql"
20 "gorm.io/driver/postgres"
21@@ -33,19 +33,20 @@ var (
22 key = flag.String("aes-key", "", "AES key, either 16, 24, or 32 bytes string to select AES-128, AES-192, or AES-256")
23 dbType = flag.String("db-type", "sqlite", "Database to be used. Choose either mysql, psql or sqlite")
24 dbCon = flag.String("db-con", "main.db", "Database string connection for given database type. Ref: https://gorm.io/docs/connecting_to_the_database.html")
25- logLevel = flag.String("log-level", "error", "Log level: Choose either trace, debug, info, warning, error, fatal or panic")
26+ logLevel = flag.String("log-level", "error", "Log level: Choose either debug, info, warning, error")
27 schedulerCount = flag.Uint("scheduler-count", 10, "How many workers are created to process media files")
28 cachePath = flag.String("cache-path", "", "Folder to store thumbnail image")
29 )
30
31 flag.Parse()
32
33- l, err := logrus.ParseLevel(*logLevel)
34- if err != nil {
35- panic("failed to parse log level" + err.Error())
36- }
37- logger := logrus.New()
38- logger.SetLevel(l)
39+ level := parseLogLevel(*logLevel)
40+
41+ handler := slog.NewTextHandler(
42+ os.Stdout,
43+ &slog.HandlerOptions{Level: level},
44+ )
45+ logger := slog.New(handler)
46
47 d, err := OpenDatabase(*dbType, *dbCon)
48 if err != nil {
49@@ -53,7 +54,7 @@ panic("failed to parse database strings" + err.Error())
50 }
51
52 db, err := gorm.Open(d, &gorm.Config{
53- Logger: ext.Wraplog(logger.WithField("context", "sql")),
54+ Logger: ext.Wraplog(logger.With("context", "sql")),
55 })
56 if err != nil {
57 panic("failed to connect database: " + err.Error())
58@@ -85,8 +86,8 @@ )
59
60 // middleware
61 var (
62- authMiddleware = ext.NewAuthMiddleware(baseKey, logger.WithField("context", "auth"), userRepository)
63- logMiddleware = ext.NewLogMiddleare(logger.WithField("context", "http"))
64+ authMiddleware = ext.NewAuthMiddleware(baseKey, logger.With("context", "auth"), userRepository)
65+ logMiddleware = ext.NewLogMiddleare(logger.With("context", "http"))
66 initialMiddleware = ext.NewInitialSetupMiddleware(userRepository)
67 )
68
69@@ -129,22 +130,22 @@ serverTask = worker.NewServerTask(&http.Server{Handler: r, Addr: "0.0.0.0:8080"})
70 fileTask = worker.NewTaskFromChanProcessor[string](
71 fileScanner,
72 scheduler,
73- logrus.WithField("context", "file scanner"),
74+ logger.With("context", "file scanner"),
75 )
76 exifTask = worker.NewTaskFromBatchProcessor[*repository.Media](
77 exifScanner,
78 scheduler,
79- logrus.WithField("context", "exif scanner"),
80+ logger.With("context", "exif scanner"),
81 )
82 thumbnailTask = worker.NewTaskFromBatchProcessor[*repository.Media](
83 thumbnailScanner,
84 scheduler,
85- logrus.WithField("context", "thumbnail scanner"),
86+ logger.With("context", "thumbnail scanner"),
87 )
88 albumTask = worker.NewTaskFromSerialProcessor[*repository.Media](
89 albumScanner,
90 scheduler,
91- logrus.WithField("context", "thumbnail scanner"),
92+ logger.With("context", "thumbnail scanner"),
93 )
94 )
95
96@@ -173,3 +174,18 @@ default:
97 return nil, errors.New("No valid db type given")
98 }
99 }
100+
101+func parseLogLevel(input string) slog.Level {
102+ switch input {
103+ case "debug":
104+ return slog.LevelDebug
105+ case "info":
106+ return slog.LevelInfo
107+ case "warn":
108+ return slog.LevelWarn
109+ case "error":
110+ return slog.LevelError
111+ default:
112+ return slog.LevelWarn
113+ }
114+}
115diff --git a/go.mod b/go.mod
116index 6f8eb28073abaad1cb5b5eb126d07cdc6fe79c3d..b8e4bb7bc9e76aa474179b2fc77cc1842c457451 100644
117--- a/go.mod
118+++ b/go.mod
119@@ -1,6 +1,6 @@
120 module git.sr.ht/~gabrielgio/img
121
122-go 1.19
123+go 1.21
124
125 require (
126 github.com/barasher/go-exiftool v1.10.0
127@@ -8,14 +8,12 @@ github.com/glebarez/sqlite v1.9.0
128 github.com/google/go-cmp v0.5.9
129 github.com/gorilla/mux v1.8.0
130 github.com/h2non/bimg v1.1.9
131- github.com/sirupsen/logrus v1.9.2
132 github.com/spf13/pflag v1.0.5
133 github.com/valyala/quicktemplate v1.7.0
134 golang.org/x/crypto v0.8.0
135 gorm.io/driver/mysql v1.5.1
136 gorm.io/driver/postgres v1.5.2
137 gorm.io/driver/sqlite v1.5.0
138- gorm.io/gen v0.3.22
139 gorm.io/gorm v1.25.2
140 )
141
142@@ -33,13 +31,8 @@ github.com/mattn/go-isatty v0.0.17 // indirect
143 github.com/mattn/go-sqlite3 v1.14.16 // indirect
144 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
145 github.com/valyala/bytebufferpool v1.0.0 // indirect
146- golang.org/x/mod v0.10.0 // indirect
147 golang.org/x/sys v0.8.0 // indirect
148 golang.org/x/text v0.10.0 // indirect
149- golang.org/x/tools v0.9.3 // indirect
150- gorm.io/datatypes v1.2.0 // indirect
151- gorm.io/hints v1.1.2 // indirect
152- gorm.io/plugin/dbresolver v1.4.1 // indirect
153 modernc.org/libc v1.22.5 // indirect
154 modernc.org/mathutil v1.5.0 // indirect
155 modernc.org/memory v1.5.0 // indirect
156diff --git a/go.sum b/go.sum
157index 6f654534983a5797bbba47b3fa8e4ce79145933d..03f8b3e75ff3a728a009724d1556164ca2a4caf2 100644
158--- a/go.sum
159+++ b/go.sum
160@@ -11,16 +11,14 @@ github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
161 github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
162 github.com/glebarez/sqlite v1.9.0 h1:Aj6bPA12ZEx5GbSF6XADmCkYXlljPNUY+Zf1EQxynXs=
163 github.com/glebarez/sqlite v1.9.0/go.mod h1:YBYCoyupOao60lzp1MVBLEjZfgkq0tdB1voAQ09K9zw=
164-github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
165 github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
166 github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
167 github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
168-github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
169-github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
170 github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
171 github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
172 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
173 github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
174+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
175 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
176 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
177 github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
178@@ -35,7 +33,6 @@ github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
179 github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
180 github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
181 github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
182-github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
183 github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
184 github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
185 github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
186@@ -45,20 +42,18 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
187 github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
188 github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
189 github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
190-github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
191 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
192 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
193 github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
194 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
195 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
196-github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
197-github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
198 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
199 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
200 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
201 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
202 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
203 github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
204+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
205 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
206 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
207 github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
208@@ -68,15 +63,11 @@ github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
209 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
210 golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
211 golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
212-golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
213-golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
214 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
215 golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
216-golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
217 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
218 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
219 golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
220-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
221 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
222 golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
223 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
224@@ -86,34 +77,20 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
225 golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
226 golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
227 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
228-golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
229-golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
230 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
231 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
232 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
233-gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco=
234-gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04=
235-gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c=
236+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
237 gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw=
238 gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o=
239 gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0=
240 gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8=
241 gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
242 gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
243-gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
244-gorm.io/gen v0.3.22 h1:K7u5tCyaZfe1cbQFD8N2xrTqUuqximNFSRl7zOFPq+M=
245-gorm.io/gen v0.3.22/go.mod h1:dQcELeF/7Kf82M6AQF+O/rKT5r1sjv49TlGz0cerPn4=
246-gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
247-gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
248 gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
249-gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
250 gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
251 gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho=
252 gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
253-gorm.io/hints v1.1.2 h1:b5j0kwk5p4+3BtDtYqqfY+ATSxjj+6ptPgVveuynn9o=
254-gorm.io/hints v1.1.2/go.mod h1:/ARdpUHAtyEMCh5NNi3tI7FsGh+Cj/MIUlvNxCNCFWg=
255-gorm.io/plugin/dbresolver v1.4.1 h1:Ug4LcoPhrvqq71UhxtF346f+skTYoCa/nEsdjvHwEzk=
256-gorm.io/plugin/dbresolver v1.4.1/go.mod h1:CTbCtMWhsjXSiJqiW2R8POvJ2cq18RVOl4WGyT5nhNc=
257 modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
258 modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
259 modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
260diff --git a/pkg/ext/gorm_logger.go b/pkg/ext/gorm_logger.go
261index bfbbb1ebfc55238016b954ad72f80d07d985311b..f0ab59264e7ff3efdea2fe57e613c52c628af9cf 100644
262--- a/pkg/ext/gorm_logger.go
263+++ b/pkg/ext/gorm_logger.go
264@@ -3,15 +3,15 @@
265 import (
266 "context"
267 "fmt"
268+ "log/slog"
269 "time"
270
271- "github.com/sirupsen/logrus"
272 "gorm.io/gorm/logger"
273 "gorm.io/gorm/utils"
274 )
275
276 type Log struct {
277- logrus *logrus.Entry
278+ logger *slog.Logger
279 }
280
281 func getFullMsg(msg string, data ...interface{}) string {
282@@ -24,35 +24,29 @@ }
283
284 func (self *Log) Info(ctx context.Context, msg string, data ...interface{}) {
285 fullMsg := getFullMsg(msg, data)
286- self.logrus.
287- WithContext(ctx).
288- Info(fullMsg)
289+ self.logger.InfoContext(ctx, fullMsg)
290 }
291
292 func (self *Log) Warn(ctx context.Context, msg string, data ...interface{}) {
293 fullMsg := getFullMsg(msg, data)
294- self.logrus.
295- WithContext(ctx).
296- Warn(fullMsg)
297+ self.logger.
298+ WarnContext(ctx, fullMsg)
299 }
300 func (self *Log) Error(ctx context.Context, msg string, data ...interface{}) {
301 fullMsg := getFullMsg(msg, data)
302- self.logrus.
303- WithContext(ctx).
304- Error(fullMsg)
305+ self.logger.
306+ ErrorContext(ctx, fullMsg)
307 }
308
309 func (self *Log) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), _ error) {
310 elapsed := time.Since(begin)
311 sql, _ := fc()
312- self.logrus.
313- WithContext(ctx).
314- WithField("time", elapsed).
315- Printf(sql)
316+ self.logger.
317+ InfoContext(ctx, sql, slog.Duration("elapsed", elapsed))
318 }
319
320-func Wraplog(log *logrus.Entry) *Log {
321+func Wraplog(log *slog.Logger) *Log {
322 return &Log{
323- logrus: log,
324+ logger: log,
325 }
326 }
327diff --git a/pkg/ext/middleware.go b/pkg/ext/middleware.go
328index 6a94c4f9442ed01ba1a98eb375b3c106aeda81e5..38bacca92dc571629e62545f05d3a89362f9d758 100644
329--- a/pkg/ext/middleware.go
330+++ b/pkg/ext/middleware.go
331@@ -4,10 +4,9 @@ import (
332 "context"
333 "encoding/base64"
334 "errors"
335+ "log/slog"
336 "net/http"
337 "time"
338-
339- "github.com/sirupsen/logrus"
340
341 "git.sr.ht/~gabrielgio/img/pkg/database/repository"
342 "git.sr.ht/~gabrielgio/img/pkg/service"
343@@ -24,7 +23,7 @@ type (
344 User string
345
346 LogMiddleware struct {
347- entry *logrus.Entry
348+ logger *slog.Logger
349 }
350 )
351
352@@ -32,9 +31,9 @@ const (
353 UserKey User = "user"
354 )
355
356-func NewLogMiddleare(log *logrus.Entry) *LogMiddleware {
357+func NewLogMiddleare(log *slog.Logger) *LogMiddleware {
358 return &LogMiddleware{
359- entry: log,
360+ logger: log,
361 }
362 }
363
364@@ -43,27 +42,29 @@ return func(w http.ResponseWriter, r *http.Request) {
365 start := time.Now()
366 next(w, r)
367 elapsed := time.Since(start)
368- l.entry.
369- WithField("time", elapsed).
370- WithField("path", r.URL.Path).
371- Info(r.Method)
372+ l.logger.Info(
373+ r.Method,
374+ slog.Duration("elapsed", elapsed),
375+ slog.String("path", r.URL.Path),
376+ )
377+
378 }
379 }
380
381 type AuthMiddleware struct {
382 key []byte
383- entry *logrus.Entry
384+ logger *slog.Logger
385 userRepository repository.UserRepository
386 }
387
388 func NewAuthMiddleware(
389 key []byte,
390- log *logrus.Entry,
391+ logger *slog.Logger,
392 userRepository repository.UserRepository,
393 ) *AuthMiddleware {
394 return &AuthMiddleware{
395 key: key,
396- entry: log.WithField("context", "auth"),
397+ logger: logger,
398 userRepository: userRepository,
399 }
400 }
401@@ -79,35 +80,37 @@
402 redirectLogin := "/login?redirect=" + path
403 authBase64, err := r.Cookie("auth")
404 if errors.Is(err, http.ErrNoCookie) {
405- a.entry.Info("No auth provided")
406+ a.logger.Info("No auth provided")
407 http.Redirect(w, r, redirectLogin, http.StatusTemporaryRedirect)
408 return
409 }
410
411 auth, err := base64.StdEncoding.DecodeString(authBase64.Value)
412 if err != nil {
413- a.entry.Error(err)
414+ a.logger.Error(err.Error())
415 return
416 }
417
418 token, err := service.ReadToken(auth, a.key)
419 if err != nil {
420- a.entry.Error(err)
421+ a.logger.Error(err.Error())
422 http.Redirect(w, r, redirectLogin, http.StatusTemporaryRedirect)
423 return
424 }
425
426 user, err := a.userRepository.Get(r.Context(), token.UserID)
427 if err != nil {
428- a.entry.Error(err)
429+ a.logger.Error(err.Error())
430 return
431 }
432
433 r = r.WithContext(context.WithValue(r.Context(), UserKey, user))
434- a.entry.
435- WithField("userID", token.UserID).
436- WithField("username", token.Username).
437- Info("user recognized")
438+ a.logger.
439+ Info(
440+ "user recognized",
441+ slog.Uint64("userid", uint64(token.UserID)),
442+ slog.String("username", token.Username),
443+ )
444 next(w, r)
445 }
446 }
447diff --git a/pkg/worker/list_processor.go b/pkg/worker/list_processor.go
448index ea6b45372e607368892aeb2d038c25a09d65e437..c4c37819c2c8542e7d39d30ba753bbc2457b7005 100644
449--- a/pkg/worker/list_processor.go
450+++ b/pkg/worker/list_processor.go
451@@ -3,9 +3,8 @@
452 import (
453 "context"
454 "errors"
455+ "log/slog"
456 "sync"
457-
458- "github.com/sirupsen/logrus"
459 )
460
461 type (
462@@ -27,19 +26,19 @@ }
463
464 chanProcessorTask[T any] struct {
465 chanProcessor ChanProcessor[T]
466- logrus *logrus.Entry
467+ logger *slog.Logger
468 scheduler *Scheduler
469 }
470
471 batchProcessorTask[T any] struct {
472 batchProcessor ListProcessor[T]
473- logrus *logrus.Entry
474+ logger *slog.Logger
475 scheduler *Scheduler
476 }
477
478 serialProcessorTask[T any] struct {
479 batchProcessor ListProcessor[T]
480- logrus *logrus.Entry
481+ logger *slog.Logger
482 scheduler *Scheduler
483 }
484 )
485@@ -47,36 +46,36 @@
486 func NewTaskFromBatchProcessor[T any](
487 batchProcessor ListProcessor[T],
488 scheduler *Scheduler,
489- logrus *logrus.Entry,
490+ logger *slog.Logger,
491 ) Task {
492 return &batchProcessorTask[T]{
493 batchProcessor: batchProcessor,
494 scheduler: scheduler,
495- logrus: logrus,
496+ logger: logger,
497 }
498 }
499
500 func NewTaskFromSerialProcessor[T any](
501 batchProcessor ListProcessor[T],
502 scheduler *Scheduler,
503- logrus *logrus.Entry,
504+ logger *slog.Logger,
505 ) Task {
506 return &serialProcessorTask[T]{
507 batchProcessor: batchProcessor,
508 scheduler: scheduler,
509- logrus: logrus,
510+ logger: logger,
511 }
512 }
513
514 func NewTaskFromChanProcessor[T any](
515 chanProcessor ChanProcessor[T],
516 scheduler *Scheduler,
517- logrus *logrus.Entry,
518+ logger *slog.Logger,
519 ) Task {
520 return &chanProcessorTask[T]{
521 chanProcessor: chanProcessor,
522 scheduler: scheduler,
523- logrus: logrus,
524+ logger: logger,
525 }
526 }
527
528@@ -111,7 +110,10 @@ go func(v T) {
529 defer l.scheduler.Return()
530 defer wg.Done()
531 if err := l.batchProcessor.Process(ctx, v); err != nil && !errors.Is(err, context.Canceled) {
532- l.logrus.WithError(err).Error("Error processing batch")
533+ l.logger.Error(
534+ "Error processing batch",
535+ slog.String("error", err.Error()),
536+ )
537 if failure, ok := l.batchProcessor.(OnFail[T]); ok {
538 failure.OnFail(ctx, v, err)
539 }
540@@ -148,7 +150,10 @@ }
541
542 l.scheduler.Take()
543 if err := l.batchProcessor.Process(ctx, v); err != nil && !errors.Is(err, context.Canceled) {
544- l.logrus.WithError(err).Error("Error processing batch")
545+ l.logger.Error(
546+ "Error processing batch",
547+ slog.String("error", err.Error()),
548+ )
549 if failure, ok := l.batchProcessor.(OnFail[T]); ok {
550 failure.OnFail(ctx, v, err)
551 }
552@@ -177,7 +182,13 @@ l.scheduler.Take()
553 go func(v T) {
554 defer l.scheduler.Return()
555 if err := l.chanProcessor.Process(ctx, v); err != nil {
556- l.logrus.WithError(err).Error("Error processing chan")
557+ l.logger.Error(
558+ "Error processing batch",
559+ slog.String("error", err.Error()),
560+ )
561+ if failure, ok := l.chanProcessor.(OnFail[T]); ok {
562+ failure.OnFail(ctx, v, err)
563+ }
564 }
565 }(v)
566 }
567diff --git a/pkg/worker/list_processor_test.go b/pkg/worker/list_processor_test.go
568index abdb90792f9713c640180c778f8db69e9abfe388..21489e82685e62ed1e6f85d04f5209dbc59d7feb 100644
569--- a/pkg/worker/list_processor_test.go
570+++ b/pkg/worker/list_processor_test.go
571@@ -5,11 +5,10 @@
572 import (
573 "context"
574 "errors"
575+ "log/slog"
576 "math/rand"
577 "sync"
578 "testing"
579-
580- "github.com/sirupsen/logrus"
581
582 "git.sr.ht/~gabrielgio/img/pkg/testkit"
583 )
584@@ -27,12 +26,12 @@ )
585
586 func TestListProcessorLimit(t *testing.T) {
587 var (
588- log = logrus.New()
589+ log = slog.Default()
590 scheduler = NewScheduler(1)
591 mock = &mockCounterListProcessor{countTo: 10000}
592 )
593
594- worker := NewTaskFromBatchProcessor[int](mock, scheduler, log.WithField("context", "testing"))
595+ worker := NewTaskFromBatchProcessor[int](mock, scheduler, log.With("context", "testing"))
596
597 err := worker.Start(context.Background())
598 testkit.TestFatalError(t, "Start", err)
599@@ -42,12 +41,12 @@ }
600
601 func TestListProcessorContextCancelQuery(t *testing.T) {
602 var (
603- log = logrus.New()
604+ log = slog.Default()
605 scheduler = NewScheduler(1)
606 mock = &mockContextListProcessor{}
607 )
608
609- worker := NewTaskFromBatchProcessor[int](mock, scheduler, log.WithField("context", "testing"))
610+ worker := NewTaskFromBatchProcessor[int](mock, scheduler, log.With("context", "testing"))
611
612 ctx, cancel := context.WithCancel(context.Background())
613 var wg sync.WaitGroup