Skip to content

Commit

Permalink
Merge branch 'introduce-slog-logger'
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo82148 committed Jul 31, 2023
2 parents 7b221b3 + c92ed1a commit c426c0a
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 36 deletions.
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ It is similar to "github.com/gorilla/handlers".LoggingHandler, but more flexible

## SYNOPSIS

If you want to write a custom logger:

```go
package main

Expand Down Expand Up @@ -37,6 +39,31 @@ func main() {
}
```

Here is a ready-made logger for [log/slog](https://pkg.go.dev/log/slog):

```go
package main

import (
"fmt"
"log/slog"
"net/http"

"github.com/shogo82148/go-http-logger"
)

func Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World")
}

func main() {
logger := NewSlogLogger(slog.LevelInfo, "message for http access", slog.Default())
h := httplogger.LoggingHandler(logger, http.HandlerFunc(Handler))
http.Handle("/", h)
http.ListenAndServe(":8000", nil)
}
```

## LICENSE

This software is released under the MIT License, see LICENSE.md.
50 changes: 50 additions & 0 deletions examples_slog_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//go:build go1.21
// +build go1.21

package httplogger_test

import (
"fmt"
"log"
"log/slog"
"net/http"
"net/http/httptest"
"os"

httplogger "github.com/shogo82148/go-http-logger"
)

func ExampleLoggingHandler_slog() {
originalHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello World")
})

replace := func(groups []string, a slog.Attr) slog.Attr {
// Remove time.
if a.Key == slog.TimeKey && len(groups) == 0 {
return slog.Attr{}
}
// Remove unstable attributes for testing.
if a.Key == "received_time" || a.Key == "request_time" || a.Key == "vhost" || a.Key == "host" {
return slog.Attr{}
}
return a
}

slogger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ReplaceAttr: replace}))
logger := httplogger.NewSlogLogger(slog.LevelInfo, "test", slogger)
loggingHandler := httplogger.LoggingHandler(logger, originalHandler)

ts := httptest.NewServer(loggingHandler)
defer ts.Close()

resp, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()

// Output:
// level=INFO msg=test forwardedfor="" user="" req="GET / HTTP/1.1" method=GET uri=/ protocol=HTTP/1.1 status=200 sent_bytes=11 received_bytes=0 referer="" ua=Go-http-client/1.1
}
41 changes: 41 additions & 0 deletions examples_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package httplogger_test

import (
"fmt"
"log"
"net/http"
"net/http/httptest"

httplogger "github.com/shogo82148/go-http-logger"
)

func ExampleLoggingHandler() {
originalHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello World")
})

loggingHandler := httplogger.LoggingHandler(httplogger.LoggerFunc(func(l httplogger.Attrs, r *http.Request) {
fmt.Println("size:", l.ResponseSize())
fmt.Println("status:", l.Status())
fmt.Println("method:", r.Method)
fmt.Println("request uri:", r.RequestURI)
fmt.Println("content type:", l.Header().Get("Content-Type"))
}), originalHandler)

ts := httptest.NewServer(loggingHandler)
defer ts.Close()

resp, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()

// Output:
// size: 11
// status: 200
// method: GET
// request uri: /
// content type: text/plain
}
38 changes: 2 additions & 36 deletions handler_test.go
Original file line number Diff line number Diff line change
@@ -1,46 +1,12 @@
package httplogger_test
package httplogger

import (
"fmt"
"log"
"net/http"
"net/http/httptest"
"testing"

httplogger "github.com/shogo82148/go-http-logger"
)

func ExampleLoggingHandler() {
originalHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "Hello World")
})

loggingHandler := httplogger.LoggingHandler(httplogger.LoggerFunc(func(l httplogger.Attrs, r *http.Request) {
fmt.Println("size:", l.ResponseSize())
fmt.Println("status:", l.Status())
fmt.Println("method:", r.Method)
fmt.Println("request uri:", r.RequestURI)
fmt.Println("content type:", l.Header().Get("Content-Type"))
}), originalHandler)

ts := httptest.NewServer(loggingHandler)
defer ts.Close()

resp, err := http.Get(ts.URL)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()

// Output:
// size: 11
// status: 200
// method: GET
// request uri: /
// content type: text/plain
}

func TestHijack(t *testing.T) {
var logged bool
originalHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand All @@ -59,7 +25,7 @@ func TestHijack(t *testing.T) {
}
})

loggingHandler := httplogger.LoggingHandler(httplogger.LoggerFunc(func(l httplogger.Attrs, r *http.Request) {
loggingHandler := LoggingHandler(LoggerFunc(func(l Attrs, r *http.Request) {
if l.Status() != http.StatusSwitchingProtocols {
t.Errorf("unexpected status code: %d", l.Status())
}
Expand Down

0 comments on commit c426c0a

Please sign in to comment.