Skip to content

Commit b63b896

Browse files
authored
feat: add configurable structured logging (#67)
Resolves #59.
1 parent 4d237b0 commit b63b896

File tree

8 files changed

+91
-19
lines changed

8 files changed

+91
-19
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ To see all planned features, check the [list of issues with the **enhancement**
1515

1616
The recommended and only supported way for production deployments is to run the backend with [the OCI image](https://github.com/envelope-zero/backend/pkgs/container/backend).
1717

18+
### Configuration
19+
20+
The backend can be configured with the following environment variables
21+
22+
| Name | Values | Default | Description |
23+
| ------------ | ------------------ | ---------------------------------------------------- | ------------------------------------------------------------------------------------ |
24+
| `GIN_MODE` | `release`, `debug` | `release` | The mode that gin runs in. Only set this to `debug` on your development environment! |
25+
| `LOG_FORMAT` | `json`, `human` | `json` if `GIN_MODE` is `release`, otherwise `human` | If log output is written human readable or as JSON. |
26+
1827
### Deployment methods
1928

2029
If you want to deploy with a method not listed here, you are welcome to open a discussion to ask any questions needed so that this documentation can be improved.

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212

1313
require (
1414
github.com/davecgh/go-spew v1.1.1 // indirect
15+
github.com/gin-contrib/logger v0.2.2
1516
github.com/gin-contrib/sse v0.1.0 // indirect
1617
github.com/glebarez/go-sqlite v1.15.1 // indirect
1718
github.com/go-playground/locales v0.14.0 // indirect
@@ -36,6 +37,7 @@ require (
3637
github.com/modern-go/reflect2 v1.0.2 // indirect
3738
github.com/pmezard/go-difflib v1.0.0 // indirect
3839
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
40+
github.com/rs/zerolog v1.26.1
3941
github.com/stretchr/testify v1.7.1
4042
github.com/ugorji/go/codec v1.2.7 // indirect
4143
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect

go.sum

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I
55
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
66
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
77
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
8+
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
89
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
910
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
1011
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1112
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1213
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1314
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
15+
github.com/gin-contrib/logger v0.2.2 h1:xIoUvRdmfID02X09wfq7wuWmevBTdMK1T6TQjbv5r+4=
16+
github.com/gin-contrib/logger v0.2.2/go.mod h1:6uKBteCGZF6VtxSfO1MKWl7aEu1sPSOhwCEAFPFxnnI=
1417
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
1518
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
19+
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
1620
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
1721
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
1822
github.com/glebarez/go-sqlite v1.15.1 h1:1gRIcUp1EFZ9wn7qBVFte332R6elCC6nJl4+YWu7SNI=
@@ -33,6 +37,7 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn
3337
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
3438
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
3539
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
40+
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
3641
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
3742
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
3843
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
@@ -136,8 +141,9 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
136141
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
137142
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
138143
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
139-
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
140144
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
145+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
146+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
141147
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
142148
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
143149
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
@@ -147,8 +153,12 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
147153
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
148154
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
149155
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
156+
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
150157
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
151158
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
159+
github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo=
160+
github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc=
161+
github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
152162
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
153163
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
154164
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
@@ -173,6 +183,7 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
173183
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
174184
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
175185
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
186+
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
176187
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
177188
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
178189
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@@ -195,20 +206,24 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP
195206
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
196207
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
197208
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
209+
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
198210
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE=
199211
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
200212
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
201213
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
202214
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
203215
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
216+
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
204217
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
205218
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
206219
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
207220
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
208221
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
209222
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
223+
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
210224
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
211225
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
226+
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
212227
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
213228
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
214229
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -222,9 +237,12 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
222237
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
223238
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
224239
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
240+
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
241+
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
225242
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
226243
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
227244
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
245+
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
228246
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
229247
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
230248
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs=
@@ -248,6 +266,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn
248266
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
249267
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
250268
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
269+
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
270+
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
251271
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
252272
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
253273
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/controllers/allocation.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package controllers
22

33
import (
4-
"log"
54
"net/http"
65
"strconv"
76
"strings"
87

8+
"github.com/rs/zerolog/log"
9+
910
"github.com/envelope-zero/backend/internal/models"
1011
"github.com/gin-gonic/gin"
1112
)
@@ -50,9 +51,6 @@ func CreateAllocation(c *gin.Context) {
5051
errMessage := "There was an error processing your request, please contact your server administrator"
5152
status := http.StatusInternalServerError
5253

53-
log.Print(result.Error)
54-
log.Print(result.Error.Error())
55-
5654
// Set helpful error messages for known errors
5755
if strings.Contains(result.Error.Error(), "UNIQUE constraint failed: allocations.month, allocations.year") {
5856
errMessage = "You can not create multiple allocations for the same month"
@@ -64,7 +62,7 @@ func CreateAllocation(c *gin.Context) {
6462

6563
// Print the error to the server log if it’s a server error
6664
if status == http.StatusInternalServerError {
67-
log.Println(result.Error)
65+
log.Error().Msgf("%T: %v", result.Error, result.Error.Error())
6866
}
6967

7068
c.JSON(status, gin.H{"error": errMessage})

internal/controllers/helper.go

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

33
import (
44
"errors"
5-
"fmt"
65
"io"
7-
"log"
86
"net/http"
97

8+
"github.com/rs/zerolog/log"
9+
1010
"github.com/gin-gonic/gin"
1111
"gorm.io/gorm"
1212
)
@@ -18,7 +18,7 @@ func bindData(c *gin.Context, data interface{}) (int, error) {
1818
return http.StatusBadRequest, errors.New("request body must not be emtpy")
1919
}
2020

21-
log.Println(err)
21+
log.Error().Msgf("%T: %v", err, err.Error())
2222
return http.StatusBadRequest, errors.New("the body of your request contains invalid or un-parseable data. Please check and try again")
2323
}
2424
return http.StatusOK, nil
@@ -43,7 +43,7 @@ func fetchErrorHandler(c *gin.Context, err error) {
4343
if errors.Is(err, gorm.ErrRecordNotFound) {
4444
c.JSON(http.StatusNotFound, gin.H{"error": "Record not found"})
4545
} else {
46-
log.Println(fmt.Sprintf("%T: %v", err, err))
46+
log.Error().Msgf("%T: %v", err, err.Error())
4747
c.JSON(http.StatusInternalServerError, gin.H{"error": "An error occured on the server during your request, please contact your server administrator."})
4848
}
4949
}

internal/controllers/routing.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,38 @@ package controllers
22

33
import (
44
"fmt"
5+
"io"
56
"net/http"
7+
"time"
68

79
"github.com/envelope-zero/backend/internal/models"
10+
"github.com/gin-contrib/logger"
811
"github.com/gin-gonic/gin"
12+
"github.com/rs/zerolog"
13+
"github.com/rs/zerolog/log"
914
)
1015

1116
// Router controls the routes for the API.
1217
func Router() (*gin.Engine, error) {
13-
r := gin.Default()
18+
// Set up the router and middlewares
19+
r := gin.New()
20+
r.Use(gin.Recovery())
21+
r.Use(logger.SetLogger(
22+
logger.WithDefaultLevel(zerolog.InfoLevel),
23+
logger.WithClientErrorLevel(zerolog.InfoLevel),
24+
logger.WithServerErrorLevel(zerolog.ErrorLevel),
25+
logger.WithLogger(func(c *gin.Context, out io.Writer, latency time.Duration) zerolog.Logger {
26+
return log.Logger.With().
27+
Dur("latency", latency).
28+
Str("method", c.Request.Method).
29+
Str("path", c.Request.URL.Path).
30+
Int("status", c.Writer.Status()).
31+
Int("size", c.Writer.Size()).
32+
Str("userAgent", c.Request.UserAgent()).
33+
Logger()
34+
})))
35+
36+
// 12:47AM INF Request ip=::1 latency=0.711125 method=GET path=/v1/budgets status=200 user_agent=HTTPie/3.1.0
1437

1538
err := models.ConnectDatabase()
1639
if err != nil {

internal/models/database.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ package models
22

33
import (
44
"fmt"
5-
"log"
65
"os"
76
"path/filepath"
87
"time"
98

9+
"github.com/rs/zerolog/log"
10+
1011
"github.com/glebarez/sqlite"
1112
"gorm.io/driver/postgres"
1213
"gorm.io/gorm"
@@ -23,7 +24,7 @@ func ConnectDatabase() error {
2324
// Check with database driver to use. If DB_HOST is set, assume postgresql
2425
_, ok := os.LookupEnv("DB_HOST")
2526
if ok {
26-
log.Println("DB_HOST is set, using postgresql")
27+
log.Debug().Msg("DB_HOST is set, using postgresql")
2728
dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s", os.Getenv("DB_HOST"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"))
2829
db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
2930
// Set generated timestamps in UTC
@@ -32,7 +33,7 @@ func ConnectDatabase() error {
3233
},
3334
})
3435
} else {
35-
log.Println("DB_HOST is not set, using sqlite database")
36+
log.Debug().Msg("DB_HOST is not set, using sqlite database")
3637

3738
dataDir := filepath.Join(".", "data")
3839
err = os.MkdirAll(dataDir, os.ModePerm)

main.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,47 @@
11
package main
22

33
import (
4-
"log"
4+
"io"
55
"os"
66

77
"github.com/gin-gonic/gin"
8+
"github.com/rs/zerolog"
9+
"github.com/rs/zerolog/log"
810

911
"github.com/envelope-zero/backend/internal/controllers"
1012
)
1113

1214
func main() {
1315
// gin uses debug as the default mode, we use release for
1416
// security reasons
15-
ginMode := os.Getenv("GIN_MODE")
16-
if ginMode == "" {
17+
ginMode, ok := os.LookupEnv("GIN_MODE")
18+
if !ok {
1719
gin.SetMode("release")
20+
} else {
21+
gin.SetMode(ginMode)
1822
}
1923

24+
// Log format can be explicitly set.
25+
// If it is not set, it defaults to human readable for development
26+
// and JSON for release
27+
logFormat, ok := os.LookupEnv("LOG_FORMAT")
28+
output := io.Writer(os.Stdout)
29+
if (!ok && gin.IsDebugging()) || (ok && logFormat == "human") {
30+
output = zerolog.ConsoleWriter{Out: os.Stdout}
31+
}
32+
33+
zerolog.SetGlobalLevel(zerolog.InfoLevel)
34+
if gin.IsDebugging() {
35+
zerolog.SetGlobalLevel(zerolog.DebugLevel)
36+
}
37+
log.Logger = log.Output(output).With().Timestamp().Logger()
38+
2039
r, err := controllers.Router()
2140
if err != nil {
22-
log.Fatal(err)
41+
log.Fatal().Msg(err.Error())
2342
}
2443

2544
if err := r.Run(); err != nil {
26-
log.Fatal(err)
45+
log.Fatal().Msg(err.Error())
2746
}
2847
}

0 commit comments

Comments
 (0)