Skip to content

Commit 817c7cf

Browse files
committed
Add zap logger middleware as requested at: kataras/iris#2125
1 parent b568fe9 commit 817c7cf

File tree

13 files changed

+1037
-0
lines changed

13 files changed

+1037
-0
lines changed

.github/dependabot.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,7 @@ updates:
4444
directory: "/tollboothic"
4545
schedule:
4646
interval: "daily"
47+
- package-ecosystem: "gomod"
48+
directory: "/zap"
49+
schedule:
50+
interval: "daily"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Middleware is just a chain handlers which can be executed before or after the ma
4646
| [csrf](csrf)| Cross-Site Request Forgery Protection | [csrf/_example](csrf/_example/main.go) |
4747
| [throttler](throttler)| Rate limiting access to HTTP endpoints | [throttler/_example](throttler/_example/main.go) |
4848
| [expmetric](expmetric)| Expvar for counting requests etc. | [expmetric/_example](expmetric/_example/main.go) |
49+
| [zap](zap)| Provides log handling using zap package | [zap/_examples](zap/_examples/example_1/main.go) |
4950

5051
### Register a middleware
5152

zap/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Compiled Object files, Static and Dynamic libs (Shared Objects)
2+
*.o
3+
*.a
4+
*.so
5+
6+
# Folders
7+
_obj
8+
_test
9+
10+
# Architecture specific extensions/prefixes
11+
*.[568vq]
12+
[568vq].out
13+
14+
*.cgo1.go
15+
*.cgo2.c
16+
_cgo_defun.c
17+
_cgo_gotypes.go
18+
_cgo_export.*
19+
20+
_testmain.go
21+
22+
*.exe
23+
*.test
24+
*.prof

zap/LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Iris Contributors
4+
Copyright (c) 2017 gin-contrib
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.

zap/README.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# zap
2+
3+
Alternative logging through [zap](https://github.com/uber-go/zap) after the [#2125 feature request](https://github.com/kataras/iris/issues/2125). A clone of https://github.com/gin-contrib/zap.
4+
5+
## Usage
6+
7+
### Start using it
8+
9+
Download and install it:
10+
11+
```sh
12+
go get github.com/iris-contrib/middleware/zap@master
13+
```
14+
15+
Import it in your code:
16+
17+
```go
18+
import "github.com/iris-contrib/middleware/zap"
19+
```
20+
21+
## Example
22+
23+
See the [example](_examples/example_1main.go).
24+
25+
```go
26+
package main
27+
28+
import (
29+
"fmt"
30+
"time"
31+
32+
iriszap "github.com/iris-contrib/middleware/zap"
33+
"github.com/kataras/iris/v12"
34+
"go.uber.org/zap"
35+
)
36+
37+
func main() {
38+
app := iris.New()
39+
40+
logger, _ := zap.NewProduction()
41+
42+
// Add a iriszap middleware, which:
43+
// - Logs all requests, like a combined access and error log.
44+
// - Logs to stdout.
45+
// - RFC3339 with UTC time format.
46+
app.Use(iriszap.New(logger, time.RFC3339, true))
47+
48+
// Logs all panic to error log
49+
// - stack means whether output the stack info.
50+
app.Use(iriszap.RecoveryWithZap(logger, true))
51+
52+
// Example ping request.
53+
app.Get("/ping", func(ctx iris.Context) {
54+
ctx.Text("pong " + fmt.Sprint(time.Now().Unix()))
55+
})
56+
57+
// Example when panic happen.
58+
app.Get("/panic", func(ctx iris.Context) {
59+
panic("An unexpected error happen!")
60+
})
61+
62+
// Listen and Server in 0.0.0.0:8080
63+
app.Listen(":8080")
64+
}
65+
```
66+
67+
## Skip logging
68+
69+
When you want to skip logging for specific path,
70+
please use `NewWithConfig`
71+
72+
```go
73+
74+
app.Use(NewWithConfig(utcLogger, &Config{
75+
TimeFormat: time.RFC3339,
76+
UTC: true,
77+
SkipPaths: []string{"/no_log"},
78+
}))
79+
```
80+
81+
## Custom Zap fields
82+
83+
Example for custom log request body, response request ID or log [Open Telemetry](https://opentelemetry.io/) TraceID.
84+
85+
```go
86+
func main() {
87+
app := iris.New()
88+
89+
logger, _ := zap.NewProduction()
90+
91+
app.Use(iriszap.NewWithConfig(logger, &iriszap.Config{
92+
UTC: true,
93+
TimeFormat: time.RFC3339,
94+
Context: iriszap.Fn(func(ctx iris.Context) []zapcore.Field {
95+
req := ctx.Request()
96+
97+
fields := []zapcore.Field{}
98+
// log request ID
99+
if requestID := ctx.ResponseWriter().Header().Get("X-Request-Id"); requestID != "" {
100+
fields = append(fields, zap.String("request_id", requestID))
101+
}
102+
103+
// log trace and span ID
104+
if trace.SpanFromContext(req.Context()).SpanContext().IsValid() {
105+
fields = append(fields, zap.String("trace_id", trace.SpanFromContext(req.Context()).SpanContext().TraceID().String()))
106+
fields = append(fields, zap.String("span_id", trace.SpanFromContext(req.Context()).SpanContext().SpanID().String()))
107+
}
108+
109+
// log request body
110+
var body []byte
111+
var buf bytes.Buffer
112+
tee := io.TeeReader(req.Body, &buf)
113+
body, _ = io.ReadAll(tee)
114+
req.Body = io.NopCloser(&buf)
115+
fields = append(fields, zap.String("body", string(body)))
116+
117+
return fields
118+
}),
119+
}))
120+
121+
// Example ping request.
122+
app.Get("/ping", func(ctx iris.Context) {
123+
ctx.Header("X-Request-Id", "1234-5678-9012")
124+
ctx.Text("pong " + fmt.Sprint(time.Now().Unix()))
125+
})
126+
127+
app.Post("/ping", func(ctx iris.Context) {
128+
ctx.Header("X-Request-Id", "9012-5678-1234")
129+
ctx.Text("pong " + fmt.Sprint(time.Now().Unix()))
130+
})
131+
132+
// Listen and Server in 0.0.0.0:8080
133+
app.Listen(":8080")
134+
}
135+
```

zap/_examples/example_1/main.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"time"
6+
7+
iriszap "github.com/iris-contrib/middleware/zap"
8+
"github.com/kataras/iris/v12"
9+
"go.uber.org/zap"
10+
)
11+
12+
func main() {
13+
app := iris.New()
14+
15+
logger, _ := zap.NewProduction()
16+
17+
// Add a iriszap middleware, which:
18+
// - Logs all requests, like a combined access and error log.
19+
// - Logs to stdout.
20+
// - RFC3339 with UTC time format.
21+
app.Use(iriszap.New(logger, time.RFC3339, true))
22+
23+
// Logs all panic to error log
24+
// - stack means whether output the stack info.
25+
app.Use(iriszap.RecoveryWithZap(logger, true))
26+
27+
// Example ping request.
28+
app.Get("/ping", func(ctx iris.Context) {
29+
ctx.Text("pong " + fmt.Sprint(time.Now().Unix()))
30+
})
31+
32+
// Example when panic happen.
33+
app.Get("/panic", func(ctx iris.Context) {
34+
panic("An unexpected error happen!")
35+
})
36+
37+
// Listen and Server in 0.0.0.0:8080
38+
app.Listen(":8080")
39+
}

zap/_examples/example_2/go.mod

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
module example_2
2+
3+
go 1.20
4+
5+
replace github.com/iris-contrib/middleware/zap => ../../
6+
7+
require (
8+
github.com/iris-contrib/middleware/zap v0.0.0-00010101000000-000000000000
9+
github.com/kataras/iris/v12 v12.2.0
10+
go.opentelemetry.io/otel/trace v1.14.0
11+
go.uber.org/zap v1.24.0
12+
)
13+
14+
require (
15+
github.com/BurntSushi/toml v1.2.1 // indirect
16+
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
17+
github.com/CloudyKit/jet/v6 v6.2.0 // indirect
18+
github.com/Joker/jade v1.1.3 // indirect
19+
github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
20+
github.com/andybalholm/brotli v1.0.5 // indirect
21+
github.com/aymerick/douceur v0.2.0 // indirect
22+
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect
23+
github.com/fatih/structs v1.1.0 // indirect
24+
github.com/flosch/pongo2/v4 v4.0.2 // indirect
25+
github.com/golang/snappy v0.0.4 // indirect
26+
github.com/google/uuid v1.3.0 // indirect
27+
github.com/gorilla/css v1.0.0 // indirect
28+
github.com/iris-contrib/schema v0.0.6 // indirect
29+
github.com/josharian/intern v1.0.0 // indirect
30+
github.com/kataras/blocks v0.0.7 // indirect
31+
github.com/kataras/golog v0.1.8 // indirect
32+
github.com/kataras/pio v0.0.11 // indirect
33+
github.com/kataras/sitemap v0.0.6 // indirect
34+
github.com/kataras/tunnel v0.0.4 // indirect
35+
github.com/klauspost/compress v1.16.0 // indirect
36+
github.com/mailgun/raymond/v2 v2.0.48 // indirect
37+
github.com/mailru/easyjson v0.7.7 // indirect
38+
github.com/microcosm-cc/bluemonday v1.0.23 // indirect
39+
github.com/russross/blackfriday/v2 v2.1.0 // indirect
40+
github.com/schollz/closestmatch v2.1.0+incompatible // indirect
41+
github.com/sirupsen/logrus v1.8.1 // indirect
42+
github.com/tdewolff/minify/v2 v2.12.4 // indirect
43+
github.com/tdewolff/parse/v2 v2.6.4 // indirect
44+
github.com/valyala/bytebufferpool v1.0.0 // indirect
45+
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
46+
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
47+
github.com/yosssi/ace v0.0.5 // indirect
48+
go.opentelemetry.io/otel v1.14.0 // indirect
49+
go.uber.org/atomic v1.7.0 // indirect
50+
go.uber.org/multierr v1.6.0 // indirect
51+
golang.org/x/crypto v0.7.0 // indirect
52+
golang.org/x/net v0.8.0 // indirect
53+
golang.org/x/sys v0.6.0 // indirect
54+
golang.org/x/text v0.8.0 // indirect
55+
golang.org/x/time v0.3.0 // indirect
56+
google.golang.org/protobuf v1.29.0 // indirect
57+
gopkg.in/ini.v1 v1.67.0 // indirect
58+
gopkg.in/yaml.v3 v3.0.1 // indirect
59+
)

0 commit comments

Comments
 (0)