mirror of
https://github.com/go-vikunja/vikunja.git
synced 2025-12-05 19:16:51 -06:00
feat: move to slog for logging
This commit is contained in:
@@ -395,6 +395,11 @@
|
||||
"default_value": "INFO",
|
||||
"comment": "Change the log level. Possible values (case-insensitive) are CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG."
|
||||
},
|
||||
{
|
||||
"key": "format",
|
||||
"default_value": "text",
|
||||
"comment": "Logging format. Can be either `text` or `structured` to output JSON."
|
||||
},
|
||||
{
|
||||
"key": "database",
|
||||
"default_value": "off",
|
||||
|
||||
3
go.mod
3
go.mod
@@ -55,7 +55,6 @@ require (
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/olekukonko/tablewriter v1.0.8
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
github.com/pquerna/otp v1.5.0
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/redis/go-redis/v9 v9.11.0
|
||||
@@ -115,8 +114,6 @@ require (
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/huandu/go-clone v1.7.3 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
|
||||
43
go.sum
43
go.sum
@@ -17,8 +17,6 @@ github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||
github.com/ThreeDotsLabs/watermill v1.4.6 h1:rWoXlxdBgUyg/bZ3OO0pON+nESVd9r6tnLTgkZ6CYrU=
|
||||
github.com/ThreeDotsLabs/watermill v1.4.6/go.mod h1:lBnrLbxOjeMRgcJbv+UiZr8Ylz8RkJ4m6i/VN/Nk+to=
|
||||
github.com/ThreeDotsLabs/watermill v1.4.7 h1:LiF4wMP400/psRTdHL/IcV1YIv9htHYFggbe2d6cLeI=
|
||||
github.com/ThreeDotsLabs/watermill v1.4.7/go.mod h1:Ks20MyglVnqjpha1qq0kjaQ+J9ay7bdnjszQ4cW9FMU=
|
||||
github.com/adlio/trello v1.12.0 h1:JqOE2GFHQ9YtEviRRRSnicSxPbt4WFOxhqXzjMOw8lw=
|
||||
@@ -98,12 +96,8 @@ github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBv
|
||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
|
||||
github.com/getsentry/sentry-go v0.34.0 h1:1FCHBVp8TfSc8L10zqSwXUZNiOSF+10qw4czjarTiY4=
|
||||
github.com/getsentry/sentry-go v0.34.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE=
|
||||
github.com/getsentry/sentry-go v0.34.1 h1:HSjc1C/OsnZttohEPrrqKH42Iud0HuLCXpv8cU1pWcw=
|
||||
github.com/getsentry/sentry-go v0.34.1/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE=
|
||||
github.com/getsentry/sentry-go/echo v0.34.0 h1:qjEOup0MJ4qyNKEc/H1XUooIQndka0HOGDMFbLR3x8E=
|
||||
github.com/getsentry/sentry-go/echo v0.34.0/go.mod h1:kCjZ3/HnI340yMESlyRRYoL/7stfCkuxakhFkrR2nxk=
|
||||
github.com/getsentry/sentry-go/echo v0.34.1 h1:QmRs8A6SK7YYbc6Dtuyh2RTFd4Fe9v9VH8Ty4h8wC8s=
|
||||
github.com/getsentry/sentry-go/echo v0.34.1/go.mod h1:4kdQH/69jXiWE7Ve5nwkWa9U4A38FK/Eu/zSQ4tcaHc=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
@@ -136,8 +130,6 @@ github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1
|
||||
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.16.0 h1:bSjH1206tTSXSQZLtUjLvy6sbSrSXO8lGtcB454QP8Q=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.16.0/go.mod h1:fH6IT/2lM5yV5cuTkPkuQv3f6JW+AE9tMUovxUhWUhE=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.17.0 h1:oaWVDAOl13JszPM1jQZ2iS6bIBhy43WY3gpTeQEq/IU=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.17.0/go.mod h1:HCIVT6p9uKXaCv898IT1iS0My5TF8kF785H4n+6049U=
|
||||
github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk=
|
||||
@@ -147,13 +139,9 @@ github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a/go.mod h1:5YoVOkjYA
|
||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-yaml v1.17.1 h1:LI34wktB2xEE3ONG/2Ar54+/HJVBriAGJ55PHls4YuY=
|
||||
github.com/goccy/go-yaml v1.17.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
@@ -194,11 +182,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
|
||||
@@ -256,8 +239,6 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f
|
||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
github.com/jaswdr/faker/v2 v2.5.0 h1:KUYfnleIZMSHNp/q+rDk7XEuqUUL5FhfT19iTTFqF5o=
|
||||
github.com/jaswdr/faker/v2 v2.5.0/go.mod h1:ROK8xwQV0hYOLDUtxCQgHGcl10jbVzIvqHxcIDdwY2Q=
|
||||
github.com/jaswdr/faker/v2 v2.6.0 h1:19MkwsI6I2vrJhYZqsJpspzRb/fDlax2q1iBhPMxGy0=
|
||||
github.com/jaswdr/faker/v2 v2.6.0/go.mod h1:jZq+qzNQr8/P+5fHd9t3txe2GNPnthrTfohtnJ7B+68=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
@@ -367,8 +348,6 @@ github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 h1:r3FaAI0NZK3hS
|
||||
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.8 h1:sbGZ1Fx4QxJXEqL/6IG8GEFnYojUSQ45dJVwN2FH2fc=
|
||||
github.com/olekukonko/ll v0.0.8/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
||||
github.com/olekukonko/tablewriter v1.0.7 h1:HCC2e3MM+2g72M81ZcJU11uciw6z/p82aEnm4/ySDGw=
|
||||
github.com/olekukonko/tablewriter v1.0.7/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs=
|
||||
github.com/olekukonko/tablewriter v1.0.8 h1:f6wJzHg4QUtJdvrVPKco4QTrAylgaU0+b9br/lJxEiQ=
|
||||
github.com/olekukonko/tablewriter v1.0.8/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@@ -381,8 +360,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
|
||||
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
@@ -465,8 +442,6 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
|
||||
github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
|
||||
github.com/swaggo/swag v1.16.5 h1:nMf2fEV1TetMTJb4XzD0Lz7jFfKJmJKGTygEey8NSxM=
|
||||
github.com/swaggo/swag v1.16.5/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
@@ -529,13 +504,9 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE=
|
||||
golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY=
|
||||
golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas=
|
||||
golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@@ -567,8 +538,6 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
@@ -582,8 +551,6 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -618,8 +585,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
@@ -632,8 +597,6 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -648,13 +611,9 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -673,8 +632,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -137,6 +137,7 @@ const (
|
||||
LogEnabled Key = `log.enabled`
|
||||
LogStandard Key = `log.standard`
|
||||
LogLevel Key = `log.level`
|
||||
LogFormat Key = `log.format`
|
||||
LogDatabase Key = `log.database`
|
||||
LogDatabaseLevel Key = `log.databaselevel`
|
||||
LogHTTP Key = `log.http`
|
||||
@@ -400,6 +401,7 @@ func InitDefaultConfig() {
|
||||
LogEnabled.setDefault(true)
|
||||
LogStandard.setDefault("stdout")
|
||||
LogLevel.setDefault("INFO")
|
||||
LogFormat.setDefault("text")
|
||||
LogDatabase.setDefault("off")
|
||||
LogDatabaseLevel.setDefault("WARNING")
|
||||
LogHTTP.setDefault("stdout")
|
||||
@@ -537,7 +539,7 @@ func InitConfig() {
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
|
||||
viper.AutomaticEnv()
|
||||
|
||||
log.ConfigureLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString())
|
||||
log.ConfigureStandardLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString(), LogFormat.GetString())
|
||||
|
||||
// Load the config file
|
||||
viper.AddConfigPath(ServiceRootpath.GetString())
|
||||
@@ -562,7 +564,7 @@ func InitConfig() {
|
||||
log.Warning(err.Error())
|
||||
log.Warning("Using default config.")
|
||||
} else {
|
||||
log.ConfigureLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString())
|
||||
log.ConfigureStandardLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString(), LogFormat.GetString())
|
||||
}
|
||||
} else {
|
||||
log.Info("No config file found, using default or config from environment variables.")
|
||||
|
||||
@@ -87,7 +87,7 @@ func CreateDBEngine() (engine *xorm.Engine, err error) {
|
||||
}
|
||||
engine.SetTZDatabase(loc)
|
||||
engine.SetMapper(names.GonicMapper{})
|
||||
logger := log.NewXormLogger(config.LogEnabled.GetBool(), config.LogDatabase.GetString(), config.LogDatabaseLevel.GetString())
|
||||
logger := log.NewXormLogger(config.LogEnabled.GetBool(), config.LogDatabase.GetString(), config.LogDatabaseLevel.GetString(), config.LogFormat.GetString())
|
||||
engine.SetLogger(logger)
|
||||
|
||||
x = engine
|
||||
|
||||
@@ -53,7 +53,7 @@ func CreateTestEngine() (engine *xorm.Engine, err error) {
|
||||
}
|
||||
|
||||
engine.SetMapper(names.GonicMapper{})
|
||||
logger := log.NewXormLogger(config.LogEnabled.GetBool(), config.LogDatabase.GetString(), "DEBUG")
|
||||
logger := log.NewXormLogger(config.LogEnabled.GetBool(), config.LogDatabase.GetString(), "DEBUG", config.LogFormat.GetString())
|
||||
logger.ShowSQL(os.Getenv("TESTS_VERBOSE") == "1")
|
||||
engine.SetLogger(logger)
|
||||
engine.SetTZLocation(config.GetTimeZone())
|
||||
|
||||
@@ -51,7 +51,7 @@ func (m *messageHandleFailedError) Error() string {
|
||||
|
||||
// InitEvents sets up everything needed to work with events
|
||||
func InitEvents() (err error) {
|
||||
logger := log.NewWatermillLogger(config.LogEnabled.GetBool(), config.LogEvents.GetString(), config.LogEventsLevel.GetString())
|
||||
logger := log.NewWatermillLogger(config.LogEnabled.GetBool(), config.LogEvents.GetString(), config.LogEventsLevel.GetString(), config.LogFormat.GetString())
|
||||
|
||||
router, err := message.NewRouter(
|
||||
message.RouterConfig{},
|
||||
|
||||
@@ -143,7 +143,7 @@ func (f *File) Delete(s *xorm.Session) (err error) {
|
||||
var perr *os.PathError
|
||||
if errors.As(err, &perr) {
|
||||
// Don't fail when removing the file failed
|
||||
log.Errorf("Error deleting file %d: %w", f.ID, err)
|
||||
log.Errorf("Error deleting file %d: %s", f.ID, err)
|
||||
return s.Commit()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,10 +19,15 @@ package files
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
InitTests()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
186
pkg/log/echo_logger.go
Normal file
186
pkg/log/echo_logger.go
Normal file
@@ -0,0 +1,186 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/gommon/log"
|
||||
)
|
||||
|
||||
type EchoLogger struct {
|
||||
logger *slog.Logger
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
// NewEchoLogger creates and initializes a new echo logger
|
||||
func NewEchoLogger(configLogEnabled bool, configLogEcho string, configLogFormat string) echo.Logger {
|
||||
handler, writer := makeLogHandler(configLogEnabled, configLogEcho, "DEBUG", configLogFormat)
|
||||
|
||||
echoLogger := &EchoLogger{
|
||||
logger: slog.New(handler).With("component", "http"),
|
||||
writer: writer,
|
||||
}
|
||||
|
||||
return echoLogger
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Output() io.Writer {
|
||||
return e.writer
|
||||
}
|
||||
|
||||
func (e *EchoLogger) SetOutput(_ io.Writer) {
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Prefix() string {
|
||||
return "http"
|
||||
}
|
||||
|
||||
func (e *EchoLogger) SetPrefix(_ string) {
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Level() log.Lvl {
|
||||
return log.DEBUG
|
||||
}
|
||||
|
||||
func (e *EchoLogger) SetLevel(_ log.Lvl) {
|
||||
}
|
||||
|
||||
func (e *EchoLogger) SetHeader(_ string) {
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Print(i ...interface{}) {
|
||||
e.logger.Info(fmt.Sprint(i...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Printf(format string, args ...interface{}) {
|
||||
e.logger.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Printj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
e.logger.Info(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Debug(i ...interface{}) {
|
||||
e.logger.Debug(fmt.Sprint(i...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Debugf(format string, args ...interface{}) {
|
||||
e.logger.Debug(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Debugj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
e.logger.Debug(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Info(i ...interface{}) {
|
||||
e.logger.Info(fmt.Sprint(i...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Infof(format string, args ...interface{}) {
|
||||
e.logger.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Infoj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
e.logger.Info(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Warn(i ...interface{}) {
|
||||
e.logger.Warn(fmt.Sprint(i...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Warnf(format string, args ...interface{}) {
|
||||
e.logger.Warn(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Warnj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
e.logger.Warn(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Error(i ...interface{}) {
|
||||
e.logger.Error(fmt.Sprint(i...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Errorf(format string, args ...interface{}) {
|
||||
e.logger.Error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Errorj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
e.logger.Error(string(b))
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Fatal(i ...interface{}) {
|
||||
e.logger.Error(fmt.Sprint(i...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Fatalj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
e.logger.Error(string(b))
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Fatalf(format string, args ...interface{}) {
|
||||
e.logger.Error(fmt.Sprintf(format, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Panic(i ...interface{}) {
|
||||
msg := fmt.Sprint(i...)
|
||||
e.logger.Error(msg)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Panicj(j log.JSON) {
|
||||
if b, err := json.Marshal(j); err == nil {
|
||||
msg := string(b)
|
||||
e.logger.Error(msg)
|
||||
panic(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EchoLogger) Panicf(format string, args ...interface{}) {
|
||||
msg := fmt.Sprintf(format, args...)
|
||||
e.logger.Error(msg)
|
||||
panic(msg)
|
||||
}
|
||||
|
||||
// EnableColor enables color output
|
||||
func (e *EchoLogger) EnableColor() {
|
||||
// This is a no-op for our slog implementation
|
||||
}
|
||||
|
||||
// DisableColor disables color output
|
||||
func (e *EchoLogger) DisableColor() {
|
||||
// This is a no-op for our slog implementation
|
||||
}
|
||||
@@ -17,27 +17,15 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/op/go-logging"
|
||||
)
|
||||
|
||||
// ErrFmt holds the format for all the console logging
|
||||
const ErrFmt = `${time_rfc3339}: ${level} ` + "\t" + `▶ ${prefix} ${short_file}:${line}`
|
||||
|
||||
// WebFmt holds the format for all logging related to web requests
|
||||
const WebFmt = `${time_rfc3339}: WEB ` + "\t" + `▶ ${remote_ip} ${id} ${method} ${status} ${uri} ${latency_human} - ${user_agent}`
|
||||
|
||||
// Fmt is the general log format
|
||||
const Fmt = `%{color}%{time:` + time.RFC3339 + `}: %{level}` + "\t" + `▶ %{id:03x}%{color:reset} %{message}`
|
||||
|
||||
const logModule = `vikunja`
|
||||
|
||||
// loginstance is the instance of the logger which is used under the hood to log
|
||||
var logInstance = logging.MustGetLogger(logModule)
|
||||
// logInstance is the instance of the logger which is used under the hood to log
|
||||
var logInstance *slog.Logger
|
||||
|
||||
// logpath is the path in which log files will be written.
|
||||
// This value is a mere fallback for other modules that could but shouldn't be used before calling ConfigureLogger
|
||||
@@ -45,45 +33,74 @@ var logPath = "."
|
||||
|
||||
// InitLogger initializes the global log handler
|
||||
func InitLogger() {
|
||||
// This show correct caller functions
|
||||
logInstance.ExtraCalldepth = 1
|
||||
|
||||
// Init with stdout and INFO as default format and level
|
||||
logBackend := logging.NewLogBackend(os.Stdout, "", 0)
|
||||
backend := logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(Fmt+"\n"))
|
||||
|
||||
backendLeveled := logging.AddModuleLevel(backend)
|
||||
backendLeveled.SetLevel(logging.INFO, logModule)
|
||||
|
||||
logInstance.SetBackend(backendLeveled)
|
||||
handler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo})
|
||||
logInstance = slog.New(handler)
|
||||
}
|
||||
|
||||
// ConfigureLogger configures the global log handler
|
||||
func ConfigureLogger(configLogEnabled bool, configLogStandard string, configLogPath string, configLogLevel string) {
|
||||
lvl := strings.ToUpper(configLogLevel)
|
||||
level, err := logging.LogLevel(lvl)
|
||||
if err != nil {
|
||||
Fatalf("Error setting standard log level %s: %s", lvl, err.Error())
|
||||
func makeLogHandler(enabled bool, output string, level string, format string) (slog.Handler, io.Writer) {
|
||||
var slogLevel slog.Level
|
||||
switch strings.ToUpper(level) {
|
||||
case "CRITICAL", "ERROR":
|
||||
slogLevel = slog.LevelError
|
||||
case "WARNING":
|
||||
slogLevel = slog.LevelWarn
|
||||
case "NOTICE", "INFO":
|
||||
slogLevel = slog.LevelInfo
|
||||
case "DEBUG":
|
||||
slogLevel = slog.LevelDebug
|
||||
default:
|
||||
slogLevel = slog.LevelInfo
|
||||
}
|
||||
|
||||
logPath = configLogPath
|
||||
|
||||
// The backend is the part which actually handles logging the log entries somewhere.
|
||||
var backend logging.Backend
|
||||
backend = &NoopBackend{}
|
||||
if configLogEnabled && configLogStandard != "off" {
|
||||
logBackend := logging.NewLogBackend(GetLogWriter(configLogStandard, "standard"), "", 0)
|
||||
backend = logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(Fmt+"\n"))
|
||||
format = strings.ToLower(format)
|
||||
if format == "" {
|
||||
format = "text"
|
||||
}
|
||||
if format != "text" && format != "structured" {
|
||||
Fatalf("invalid log format %s", format)
|
||||
}
|
||||
|
||||
backendLeveled := logging.AddModuleLevel(backend)
|
||||
backendLeveled.SetLevel(level, logModule)
|
||||
writer := io.Discard
|
||||
if enabled && output != "off" {
|
||||
writer = getLogWriter(output, "standard")
|
||||
}
|
||||
|
||||
logInstance.SetBackend(backendLeveled)
|
||||
return createHandler(writer, slogLevel, format), writer
|
||||
}
|
||||
|
||||
// createHandler creates a consistent slog handler for all loggers
|
||||
func createHandler(writer io.Writer, level slog.Level, format string) slog.Handler {
|
||||
handlerOpts := &slog.HandlerOptions{Level: level}
|
||||
if strings.ToLower(format) == "structured" {
|
||||
return slog.NewJSONHandler(writer, handlerOpts)
|
||||
}
|
||||
|
||||
return slog.NewTextHandler(writer, handlerOpts)
|
||||
}
|
||||
|
||||
// NewHTTPLogger creates and initializes a new HTTP logger
|
||||
func NewHTTPLogger(enabled bool, output string, format string) *slog.Logger {
|
||||
handler, _ := makeLogHandler(enabled, output, "DEBUG", format)
|
||||
|
||||
return slog.New(handler).With("component", "http")
|
||||
}
|
||||
|
||||
// ConfigureStandardLogger configures the global log handler
|
||||
func ConfigureStandardLogger(enabled bool, output string, path string, level string, format string) {
|
||||
handler, _ := makeLogHandler(enabled, output, level, format)
|
||||
logInstance = slog.New(handler)
|
||||
logPath = path
|
||||
}
|
||||
|
||||
// wrapLogger is used for libraries requiring a Debugf method.
|
||||
type wrapLogger struct{}
|
||||
|
||||
func (wrapLogger) Debugf(format string, args ...interface{}) {
|
||||
logInstance.Debug(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// GetLogWriter returns the writer to where the normal log goes, depending on the config
|
||||
func GetLogWriter(logfmt string, logfile string) (writer io.Writer) {
|
||||
func getLogWriter(logfmt string, logfile string) (writer io.Writer) {
|
||||
writer = os.Stdout // Set the default case to prevent nil pointer panics
|
||||
switch logfmt {
|
||||
case "file":
|
||||
@@ -106,68 +123,72 @@ func GetLogWriter(logfmt string, logfile string) (writer io.Writer) {
|
||||
}
|
||||
|
||||
// GetLogger returns the logging instance. DO NOT USE THIS TO LOG STUFF.
|
||||
func GetLogger() *logging.Logger {
|
||||
return logInstance
|
||||
// GetLogger returns a logger which can be used by external libraries expecting a Debugf method.
|
||||
// It only implements Debugf and forwards to the global logger.
|
||||
func GetLogger() interface{ Debugf(string, ...interface{}) } {
|
||||
return wrapLogger{}
|
||||
}
|
||||
|
||||
// The following functions are to be used as an "eye-candy", so one can just write log.Error() instead of log.Log.Error()
|
||||
|
||||
// Debug is for debug messages
|
||||
func Debug(args ...interface{}) {
|
||||
logInstance.Debug(args...)
|
||||
logInstance.Debug(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Debugf is for debug messages
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
logInstance.Debugf(format, args...)
|
||||
logInstance.Debug(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Info is for info messages
|
||||
func Info(args ...interface{}) {
|
||||
logInstance.Info(args...)
|
||||
logInstance.Info(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Infof is for info messages
|
||||
func Infof(format string, args ...interface{}) {
|
||||
logInstance.Infof(format, args...)
|
||||
logInstance.Info(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Error is for error messages
|
||||
func Error(args ...interface{}) {
|
||||
logInstance.Error(args...)
|
||||
logInstance.Error(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Errorf is for error messages
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
logInstance.Errorf(format, args...)
|
||||
logInstance.Error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Warning is for warning messages
|
||||
func Warning(args ...interface{}) {
|
||||
logInstance.Warning(args...)
|
||||
logInstance.Warn(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Warningf is for warning messages
|
||||
func Warningf(format string, args ...interface{}) {
|
||||
logInstance.Warningf(format, args...)
|
||||
logInstance.Warn(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Critical is for critical messages
|
||||
func Critical(args ...interface{}) {
|
||||
logInstance.Critical(args...)
|
||||
logInstance.Error(fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Criticalf is for critical messages
|
||||
func Criticalf(format string, args ...interface{}) {
|
||||
logInstance.Criticalf(format, args...)
|
||||
logInstance.Error(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Fatal is for fatal messages
|
||||
func Fatal(args ...interface{}) {
|
||||
logInstance.Fatal(args...)
|
||||
logInstance.Error(fmt.Sprint(args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatalf is for fatal messages
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
logInstance.Fatalf(format, args...)
|
||||
logInstance.Error(fmt.Sprintf(format, args...))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -17,75 +17,39 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/op/go-logging"
|
||||
"github.com/wneessen/go-mail/log"
|
||||
maillog "github.com/wneessen/go-mail/log"
|
||||
)
|
||||
|
||||
type MailLogger struct {
|
||||
logger *logging.Logger
|
||||
level log.Level
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
const mailFormat = `%{color}%{time:` + time.RFC3339Nano + `}: %{level}` + "\t" + `▶ [MAIL] %{id:03x}%{color:reset} %{message}`
|
||||
const mailLogModule = `vikunja_mail`
|
||||
|
||||
// NewMailLogger creates and initializes a new mail logger
|
||||
func NewMailLogger(configLogEnabled bool, configLogMail string, configLogMailLevel string) log.Logger {
|
||||
lvl := strings.ToUpper(configLogMailLevel)
|
||||
level, err := logging.LogLevel(lvl)
|
||||
if err != nil {
|
||||
Criticalf("Error setting mail log level %s: %s", lvl, err.Error())
|
||||
}
|
||||
func NewMailLogger(configLogEnabled bool, configLogMail string, configLogMailLevel string, configLogFormat string) maillog.Logger {
|
||||
handler, _ := makeLogHandler(configLogEnabled, configLogMail, configLogMailLevel, configLogFormat)
|
||||
|
||||
mailLogger := &MailLogger{
|
||||
logger: logging.MustGetLogger(mailLogModule),
|
||||
}
|
||||
|
||||
var backend logging.Backend
|
||||
backend = &NoopBackend{}
|
||||
if configLogEnabled && configLogMail != "off" {
|
||||
logBackend := logging.NewLogBackend(GetLogWriter(configLogMail, "mail"), "", 0)
|
||||
backend = logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(mailFormat+"\n"))
|
||||
}
|
||||
|
||||
backendLeveled := logging.AddModuleLevel(backend)
|
||||
backendLeveled.SetLevel(level, mailLogModule)
|
||||
|
||||
mailLogger.logger.SetBackend(backendLeveled)
|
||||
|
||||
switch level {
|
||||
case logging.CRITICAL:
|
||||
case logging.ERROR:
|
||||
mailLogger.level = log.LevelError
|
||||
case logging.WARNING:
|
||||
mailLogger.level = log.LevelWarn
|
||||
case logging.NOTICE:
|
||||
case logging.INFO:
|
||||
mailLogger.level = log.LevelInfo
|
||||
case logging.DEBUG:
|
||||
mailLogger.level = log.LevelDebug
|
||||
default:
|
||||
mailLogger.level = 0
|
||||
logger: slog.New(handler).With("component", "mail"),
|
||||
}
|
||||
|
||||
return mailLogger
|
||||
}
|
||||
|
||||
func (m *MailLogger) Debugf(l log.Log) {
|
||||
m.logger.Debugf(l.Format, l.Messages...)
|
||||
func (m *MailLogger) Debugf(l maillog.Log) {
|
||||
m.logger.Debug(fmt.Sprintf(l.Format, l.Messages...))
|
||||
}
|
||||
|
||||
func (m *MailLogger) Infof(l log.Log) {
|
||||
m.logger.Infof(l.Format, l.Messages...)
|
||||
func (m *MailLogger) Infof(l maillog.Log) {
|
||||
m.logger.Info(fmt.Sprintf(l.Format, l.Messages...))
|
||||
}
|
||||
|
||||
func (m *MailLogger) Warnf(l log.Log) {
|
||||
m.logger.Warningf(l.Format, l.Messages...)
|
||||
func (m *MailLogger) Warnf(l maillog.Log) {
|
||||
m.logger.Warn(fmt.Sprintf(l.Format, l.Messages...))
|
||||
}
|
||||
|
||||
func (m *MailLogger) Errorf(l log.Log) {
|
||||
m.logger.Errorf(l.Format, l.Messages...)
|
||||
func (m *MailLogger) Errorf(l maillog.Log) {
|
||||
m.logger.Error(fmt.Sprintf(l.Format, l.Messages...))
|
||||
}
|
||||
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/op/go-logging"
|
||||
)
|
||||
import "log/slog"
|
||||
|
||||
// NoopBackend doesn't log anything. Used in cases where we want to disable logging completely.
|
||||
type NoopBackend struct{}
|
||||
|
||||
func (n *NoopBackend) Log(_ logging.Level, _ int, _ *logging.Record) error {
|
||||
func (n *NoopBackend) Log(_ slog.Level, _ int, _ *slog.Record) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,45 +18,23 @@ package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
"log/slog"
|
||||
|
||||
"github.com/ThreeDotsLabs/watermill"
|
||||
"github.com/op/go-logging"
|
||||
)
|
||||
|
||||
const watermillFmt = `%{color}%{time:` + time.RFC3339Nano + `}: %{level}` + "\t" + `▶ [EVENTS] %{id:03x}%{color:reset} %{message}`
|
||||
|
||||
const watermillLogModule = `vikunja_events`
|
||||
|
||||
type WatermillLogger struct {
|
||||
logger *logging.Logger
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// NewXormLogger creates and initializes a new watermill logger
|
||||
func NewWatermillLogger(configLogEnabled bool, configLogEvents string, configLogEventsLevel string) *WatermillLogger {
|
||||
lvl := strings.ToUpper(configLogEventsLevel)
|
||||
level, err := logging.LogLevel(lvl)
|
||||
if err != nil {
|
||||
Criticalf("Error setting events log level %s: %s", lvl, err.Error())
|
||||
}
|
||||
// NewWatermillLogger creates and initializes a new watermill logger
|
||||
func NewWatermillLogger(configLogEnabled bool, configLogEvents string, configLogEventsLevel string, configLogFormat string) *WatermillLogger {
|
||||
handler, _ := makeLogHandler(configLogEnabled, configLogEvents, configLogEventsLevel, configLogFormat)
|
||||
|
||||
watermillLogger := &WatermillLogger{
|
||||
logger: logging.MustGetLogger(watermillLogModule),
|
||||
logger: slog.New(handler).With("component", "events"),
|
||||
}
|
||||
|
||||
var backend logging.Backend
|
||||
backend = &NoopBackend{}
|
||||
if configLogEnabled && configLogEvents != "off" {
|
||||
logBackend := logging.NewLogBackend(GetLogWriter(configLogEvents, "events"), "", 0)
|
||||
backend = logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(watermillFmt+"\n"))
|
||||
}
|
||||
|
||||
backendLeveled := logging.AddModuleLevel(backend)
|
||||
backendLeveled.SetLevel(level, watermillLogModule)
|
||||
|
||||
watermillLogger.logger.SetBackend(backendLeveled)
|
||||
|
||||
return watermillLogger
|
||||
}
|
||||
|
||||
@@ -75,19 +53,19 @@ func concatFields(fields watermill.LogFields) string {
|
||||
}
|
||||
|
||||
func (w *WatermillLogger) Error(msg string, err error, fields watermill.LogFields) {
|
||||
w.logger.Errorf("%s: %s, %s", msg, err, concatFields(fields))
|
||||
w.logger.Error(fmt.Sprintf("%s: %s, %s", msg, err, concatFields(fields)))
|
||||
}
|
||||
|
||||
func (w *WatermillLogger) Info(msg string, fields watermill.LogFields) {
|
||||
w.logger.Infof("%s, %s", msg, concatFields(fields))
|
||||
w.logger.Info(fmt.Sprintf("%s, %s", msg, concatFields(fields)))
|
||||
}
|
||||
|
||||
func (w *WatermillLogger) Debug(msg string, fields watermill.LogFields) {
|
||||
w.logger.Debugf("%s, %s", msg, concatFields(fields))
|
||||
w.logger.Debug(fmt.Sprintf("%s, %s", msg, concatFields(fields)))
|
||||
}
|
||||
|
||||
func (w *WatermillLogger) Trace(msg string, fields watermill.LogFields) {
|
||||
w.logger.Debugf("%s, %s", msg, concatFields(fields))
|
||||
w.logger.Debug(fmt.Sprintf("%s, %s", msg, concatFields(fields)))
|
||||
}
|
||||
|
||||
func (w *WatermillLogger) With(_ watermill.LogFields) watermill.LoggerAdapter {
|
||||
|
||||
@@ -17,62 +17,24 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/op/go-logging"
|
||||
"xorm.io/xorm/log"
|
||||
)
|
||||
|
||||
// XormFmt defines the format for xorm logging strings
|
||||
const XormFmt = `%{color}%{time:` + time.RFC3339Nano + `}: %{level}` + "\t" + `▶ [DATABASE] %{id:03x}%{color:reset} %{message}`
|
||||
|
||||
const xormLogModule = `vikunja_database`
|
||||
|
||||
// XormLogger holds an implementation of the xorm logger interface.
|
||||
type XormLogger struct {
|
||||
logger *logging.Logger
|
||||
level log.LogLevel
|
||||
logger *slog.Logger
|
||||
showSQL bool
|
||||
}
|
||||
|
||||
// NewXormLogger creates and initializes a new xorm logger
|
||||
func NewXormLogger(configLogEnabled bool, configLogDatabase string, configLogDatabaseLevel string) *XormLogger {
|
||||
lvl := strings.ToUpper(configLogDatabaseLevel)
|
||||
level, err := logging.LogLevel(lvl)
|
||||
if err != nil {
|
||||
Criticalf("Error setting database log level %s: %s", lvl, err.Error())
|
||||
}
|
||||
func NewXormLogger(configLogEnabled bool, configLogDatabase string, configLogDatabaseLevel string, configLogFormat string) *XormLogger {
|
||||
handler, _ := makeLogHandler(configLogEnabled, configLogDatabase, configLogDatabaseLevel, configLogFormat)
|
||||
|
||||
xormLogger := &XormLogger{
|
||||
logger: logging.MustGetLogger(xormLogModule),
|
||||
}
|
||||
|
||||
var backend logging.Backend
|
||||
backend = &NoopBackend{}
|
||||
if configLogEnabled && configLogDatabase != "off" {
|
||||
logBackend := logging.NewLogBackend(GetLogWriter(configLogDatabase, "database"), "", 0)
|
||||
backend = logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(XormFmt+"\n"))
|
||||
}
|
||||
|
||||
backendLeveled := logging.AddModuleLevel(backend)
|
||||
backendLeveled.SetLevel(level, xormLogModule)
|
||||
|
||||
xormLogger.logger.SetBackend(backendLeveled)
|
||||
|
||||
switch level {
|
||||
case logging.CRITICAL:
|
||||
case logging.ERROR:
|
||||
xormLogger.level = log.LOG_ERR
|
||||
case logging.WARNING:
|
||||
xormLogger.level = log.LOG_WARNING
|
||||
case logging.NOTICE:
|
||||
case logging.INFO:
|
||||
xormLogger.level = log.LOG_INFO
|
||||
case logging.DEBUG:
|
||||
xormLogger.level = log.LOG_DEBUG
|
||||
default:
|
||||
xormLogger.level = log.LOG_OFF
|
||||
logger: slog.New(handler).With("component", "database"),
|
||||
}
|
||||
|
||||
xormLogger.showSQL = true
|
||||
@@ -82,52 +44,51 @@ func NewXormLogger(configLogEnabled bool, configLogDatabase string, configLogDat
|
||||
|
||||
// Debug logs a debug string
|
||||
func (x *XormLogger) Debug(v ...interface{}) {
|
||||
x.logger.Debug(v...)
|
||||
x.logger.Debug(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Debugf logs a debug string
|
||||
func (x *XormLogger) Debugf(format string, v ...interface{}) {
|
||||
x.logger.Debugf(format, v...)
|
||||
x.logger.Debug(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Error logs a debug string
|
||||
func (x *XormLogger) Error(v ...interface{}) {
|
||||
x.logger.Error(v...)
|
||||
x.logger.Error(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Errorf logs a debug string
|
||||
func (x *XormLogger) Errorf(format string, v ...interface{}) {
|
||||
x.logger.Errorf(format, v...)
|
||||
x.logger.Error(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Info logs an info string
|
||||
func (x *XormLogger) Info(v ...interface{}) {
|
||||
x.logger.Info(v...)
|
||||
x.logger.Info(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Infof logs an info string
|
||||
func (x *XormLogger) Infof(format string, v ...interface{}) {
|
||||
x.logger.Infof(format, v...)
|
||||
x.logger.Info(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Warn logs a warning string
|
||||
func (x *XormLogger) Warn(v ...interface{}) {
|
||||
x.logger.Warning(v...)
|
||||
x.logger.Warn(fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Warnf logs a warning string
|
||||
func (x *XormLogger) Warnf(format string, v ...interface{}) {
|
||||
x.logger.Warningf(format, v...)
|
||||
x.logger.Warn(fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
// Level returns the current set log level
|
||||
func (x *XormLogger) Level() log.LogLevel {
|
||||
return x.level
|
||||
return log.LOG_DEBUG
|
||||
}
|
||||
|
||||
// SetLevel sets the log level
|
||||
func (x *XormLogger) SetLevel(l log.LogLevel) {
|
||||
x.level = l
|
||||
func (x *XormLogger) SetLevel(_ log.LogLevel) {
|
||||
}
|
||||
|
||||
// ShowSQL sets whether to show the log level or not
|
||||
|
||||
@@ -56,7 +56,7 @@ func getClient() (*mail.Client, error) {
|
||||
}),
|
||||
mail.WithPort(config.MailerPort.GetInt()),
|
||||
mail.WithTimeout((config.MailerQueueTimeout.GetDuration() + 3) * time.Second), // 3s more for us to close before mail server timeout
|
||||
mail.WithLogger(log.NewMailLogger(config.LogEnabled.GetBool(), config.LogMail.GetString(), config.LogMailLevel.GetString())),
|
||||
mail.WithLogger(log.NewMailLogger(config.LogEnabled.GetBool(), config.LogMail.GetString(), config.LogMailLevel.GetString(), config.LogFormat.GetString())),
|
||||
mail.WithDebugLog(),
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ func getMessage(opts *Opts) *mail.Msg {
|
||||
for name, fs := range opts.EmbedFS {
|
||||
err := m.EmbedFromEmbedFS(name, fs)
|
||||
if err != nil {
|
||||
log.Errorf("Error embedding %s via embed.FS into mail: %v", err)
|
||||
log.Errorf("Error embedding %s via embed.FS into mail: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func initMigration(x *xorm.Engine) *xormigrate.Xormigrate {
|
||||
})
|
||||
|
||||
m := xormigrate.New(x, migrations)
|
||||
logger := log.NewXormLogger(config.LogEnabled.GetBool(), config.LogEvents.GetString(), config.LogEventsLevel.GetString())
|
||||
logger := log.NewXormLogger(config.LogEnabled.GetBool(), config.LogEvents.GetString(), config.LogEventsLevel.GetString(), config.LogFormat.GetString())
|
||||
m.SetLogger(logger)
|
||||
m.InitSchema(initSchema)
|
||||
return m
|
||||
|
||||
@@ -704,7 +704,7 @@ func (l *UpdateTaskInSavedFilterViews) Handle(msg *message.Message) (err error)
|
||||
IsErrInvalidTaskFilterConcatinator(err) ||
|
||||
IsErrInvalidTaskFilterComparator(err) ||
|
||||
IsErrInvalidTaskField(err) {
|
||||
log.Debugf("Invalid filter expression for view %d, expression: %s", view.ID, view.Filter)
|
||||
log.Debugf("Invalid filter expression for view %d, expression: %v", view.ID, view.Filter)
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/i18n"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
@@ -54,6 +55,9 @@ func TestMain(m *testing.M) {
|
||||
|
||||
setupTime()
|
||||
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
// Set default config
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
|
||||
@@ -22,12 +22,16 @@ import (
|
||||
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
user.InitTests()
|
||||
files.InitTests()
|
||||
models.SetupTests()
|
||||
|
||||
@@ -22,12 +22,16 @@ import (
|
||||
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
user.InitTests()
|
||||
files.InitTests()
|
||||
models.SetupTests()
|
||||
|
||||
@@ -24,12 +24,16 @@ import (
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
// Set default config
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
|
||||
32
pkg/modules/migration/microsoft-todo/main_test.go
Normal file
32
pkg/modules/migration/microsoft-todo/main_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package microsofttodo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
32
pkg/modules/migration/todoist/main_test.go
Normal file
32
pkg/modules/migration/todoist/main_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package todoist
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -610,7 +610,7 @@ func (m *Migration) Migrate(u *user.User) (err error) {
|
||||
// we can't show them individually and the api returns a 404.
|
||||
buf := bytes.Buffer{}
|
||||
_, _ = buf.ReadFrom(resp.Body)
|
||||
log.Debugf("[Todoist Migration] Could not retrieve task details for task %d: %s", i.TaskID, buf.String())
|
||||
log.Debugf("[Todoist Migration] Could not retrieve task details for task %s: %s", i.TaskID, buf.String())
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
32
pkg/modules/migration/trello/main_test.go
Normal file
32
pkg/modules/migration/trello/main_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package trello
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -24,12 +24,16 @@ import (
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
// Set default config
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
|
||||
@@ -45,6 +45,9 @@ func SetupTests() {
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
// Set default config
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
|
||||
@@ -53,6 +53,7 @@ package routes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -85,6 +86,30 @@ import (
|
||||
"github.com/ulule/limiter/v3"
|
||||
)
|
||||
|
||||
// slogHTTPMiddleware creates a custom HTTP logging middleware using slog
|
||||
func slogHTTPMiddleware(logger *slog.Logger) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return echo.HandlerFunc(func(c echo.Context) error {
|
||||
start := time.Now()
|
||||
|
||||
err := next(c)
|
||||
|
||||
req := c.Request()
|
||||
res := c.Response()
|
||||
|
||||
logger.InfoContext(c.Request().Context(),
|
||||
req.Method+" "+req.RequestURI,
|
||||
"status", res.Status,
|
||||
"remote_ip", c.RealIP(),
|
||||
"latency", time.Since(start),
|
||||
"user_agent", req.UserAgent(),
|
||||
)
|
||||
|
||||
return err
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// NewEcho registers a new Echo instance
|
||||
func NewEcho() *echo.Echo {
|
||||
e := echo.New()
|
||||
@@ -101,11 +126,9 @@ func NewEcho() *echo.Echo {
|
||||
}
|
||||
|
||||
// Logger
|
||||
if !config.LogEnabled.GetBool() || config.LogHTTP.GetString() != "off" {
|
||||
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
|
||||
Format: log.WebFmt + "\n",
|
||||
Output: log.GetLogWriter(config.LogHTTP.GetString(), "http"),
|
||||
}))
|
||||
if config.LogEnabled.GetBool() && config.LogHTTP.GetString() != "off" {
|
||||
httpLogger := log.NewHTTPLogger(config.LogEnabled.GetBool(), config.LogHTTP.GetString(), config.LogFormat.GetString())
|
||||
e.Use(slogHTTPMiddleware(httpLogger))
|
||||
}
|
||||
|
||||
// panic recover
|
||||
|
||||
@@ -19,10 +19,15 @@ package user
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
)
|
||||
|
||||
// TestMain is the main test function used to bootstrap the test env
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
InitTests()
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ To define the thing which gets the appropriate auth object, you need to call a m
|
||||
|
||||
#### Logging
|
||||
|
||||
You can provide your own instance of `logger.Logger` (using [go-logging](https://github.com/op/go-logging)) to the handler.
|
||||
You can provide your own instance of `slog.Logger` from Go's standard library to the handler.
|
||||
It will use this instance to log errors which are not better specified or things like users trying to do something they're
|
||||
not allowed to do and so on.
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/events"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/modules/auth"
|
||||
"code.vikunja.io/api/pkg/modules/keyvalue"
|
||||
@@ -64,6 +65,10 @@ func setupTestEnv() (e *echo.Echo, err error) {
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
config.ServiceRootpath.Set(os.Getenv("VIKUNJA_SERVICE_ROOTPATH"))
|
||||
|
||||
// Initialize logger for tests
|
||||
log.InitLogger()
|
||||
|
||||
// Some tests use the file engine, so we'll need to initialize that
|
||||
files.InitTests()
|
||||
user.InitTests()
|
||||
|
||||
Reference in New Issue
Block a user