Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switched to goji2 #2

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 34 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,58 @@ glogrus provides structured logging via logrus for Goji.

## Example


**Simple logging**
```go

package main

import(
"github.com/zenazn/goji"
"github.com/zenazn/goji/web/middleware"
"github.com/goji/glogrus"
"github.com/Sirupsen/logrus"
"goji.io"
"net/http"
"github.com/Sirupsen/logrus"
)

func main() {
goji.Abandon(middleware.Logger)

router := goji.NewMux()
logr := logrus.New()
logr.Formatter = new(logrus.JSONFormatter)
goji.Use(glogrus.NewGlogrus(logr, "my-app-name"))

goji.Get("/ping", yourHandler)
goji.Serve()
log.Fatal(http.ListenAndServe(":8080", router))
}

```

- - -
**Logging with custom request id from http Context**
```go

package main

import(
"github.com/goji/glogrus"
"goji.io"
"golang.org/x/net/context"
"net/http"
"github.com/Sirupsen/logrus"
)

func main() {
router := goji.NewMux()
logr := logrus.New()
logr.Formatter = new(logrus.JSONFormatter)
router.UseC(glogrus.NewGlogrusWithReqId(historian.Weblog, "my-app-name", IdFromContext))

log.Fatal(http.ListenAndServe(":8080", router))
}

func IdFromContext(ctx context.Context) string {
return ctx.Value("requestIdKey")
}
```
- - -
#### Need something to put requestId in your Context?
[gojiid can help you with that](https://github.com/atlassian/gojiid)

#### Looking for hierarchical structured logging?
[slog](https://github.com/zenazn/slog) and [lunk](https://github.com/codahale/lunk) looks interesting.
122 changes: 75 additions & 47 deletions glogrus.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,65 +4,26 @@ import (
"fmt"
"net/http"
"time"

"github.com/Sirupsen/logrus"
"github.com/zenazn/goji/web"
"github.com/zenazn/goji/web/middleware"
"goji.io"
"golang.org/x/net/context"
)

// glogrus is a middleware handler that logs the
// request and response in a structured way
type glogrus struct {
h http.Handler
c *web.C
l *logrus.Logger
name string
}

func (glogr glogrus) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
start := time.Now()
reqID := middleware.GetReqID(*glogr.c)
glogr.l.WithFields(logrus.Fields{
"req_id": reqID,
"uri": req.RequestURI,
"method": req.Method,
"remote": req.RemoteAddr,
}).Info("req_start")
lresp := wrapWriter(resp)

glogr.h.ServeHTTP(lresp, req)
lresp.maybeWriteHeader()

latency := float64(time.Since(start)) / float64(time.Millisecond)

glogr.l.WithFields(logrus.Fields{
"req_id": reqID,
"status": lresp.status(),
"method": req.Method,
"uri": req.RequestURI,
"remote": req.RemoteAddr,
"latency": fmt.Sprintf("%6.4f ms", latency),
"app": glogr.name,
}).Info("req_served")
}

// NewGlogrus allows you to configure a goji middleware that logs all requests and responses
// using the structured logger logrus. It takes the logrus instance and the name of the app
// as the parameters and returns a middleware of type "func(c *web.C, http.Handler) http.Handler"
// as the parameters and returns a middleware of type "func(goji.Handler) goji.Handler"
//
// Example:
//
// package main
//
// import(
// "github.com/zenazn/goji"
// "github.com/zenazn/goji/web/middleware"
// ""goji.io"
// "github.com/goji/glogrus"
// "github.com/Sirupsen/logrus"
// )
//
// func main() {
// goji.Abandon(middleware.Logger)
//
// logr := logrus.New()
// logr.Formatter = new(logrus.JSONFormatter)
Expand All @@ -72,9 +33,76 @@ func (glogr glogrus) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
// goji.Serve()
// }
//
func NewGlogrus(l *logrus.Logger, name string) func(*web.C, http.Handler) http.Handler {
fn := func(c *web.C, h http.Handler) http.Handler {
return glogrus{h: h, c: c, l: l, name: name}
func NewGlogrus(l *logrus.Logger, name string) func(goji.Handler) goji.Handler {
return NewGlogrusWithReqId(l, name, emptyRequestId)
}

// NewGlogrusWithReqId allows you to configure a goji middleware that logs all requests and responses
// using the structured logger logrus. It takes the logrus instance, the name of the app and a function
// that can retrieve a requestId from the Context "func(context.Context) string"
// as the parameters and returns a middleware of type "func(goji.Handler) goji.Handler"
//
// Passing in the function that returns a requestId allows you to "plug in" other middleware that may set the request id
//
// Example:
//
// package main
//
// import(
// ""goji.io"
// "github.com/goji/glogrus"
// "github.com/Sirupsen/logrus"
// )
//
// func main() {
//
// logr := logrus.New()
// logr.Formatter = new(logrus.JSONFormatter)
// goji.Use(glogrus.NewGlogrusWithReqId(logr, "my-app-name", GetRequestId))
//
// goji.Get("/ping", yourHandler)
// goji.Serve()
// }
//
// func GetRequestId(ctx context.Context) string {
// return ctx.Value("requestIdKey")
// }
//
func NewGlogrusWithReqId(l *logrus.Logger, name string, reqidf func(context.Context) string) func(goji.Handler) goji.Handler {
return func(h goji.Handler) goji.Handler {
fn := func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
start := time.Now()

reqID := reqidf(ctx)

l.WithFields(logrus.Fields{
"req_id": reqID,
"uri": r.RequestURI,
"method": r.Method,
"remote": r.RemoteAddr,
}).Info("req_start")
lresp := wrapWriter(w)

h.ServeHTTPC(ctx, lresp, r)
lresp.maybeWriteHeader()

latency := float64(time.Since(start)) / float64(time.Millisecond)

l.WithFields(logrus.Fields{
"req_id": reqID,
"status": lresp.status(),
"method": r.Method,
"uri": r.RequestURI,
"remote": r.RemoteAddr,
"latency": fmt.Sprintf("%6.4f ms", latency),
"app": name,
}).Info("req_served")
}
return goji.HandlerFunc(fn)
}
return fn

}

func emptyRequestId(ctx context.Context) string {
return ""
}