Skip to content

Commit

Permalink
add PrioritizedLogger interface for prioritized logging events
Browse files Browse the repository at this point in the history
  • Loading branch information
lufia committed Jun 3, 2019
1 parent 3a2ef8d commit fa77a80
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 11 deletions.
46 changes: 35 additions & 11 deletions mackerel.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ const (
apiRequestTimeout = 30 * time.Second
)

// PrioritizedLogger is the interface that groups prioritized logging methods.
type PrioritizedLogger interface {
Tracef(format string, v ...interface{})
Debugf(format string, v ...interface{})
Infof(format string, v ...interface{})
Warningf(format string, v ...interface{})
Errorf(format string, v ...interface{})
}

// Client api client for mackerel
type Client struct {
BaseURL *url.URL
Expand All @@ -25,9 +34,10 @@ type Client struct {
AdditionalHeaders http.Header
HTTPClient *http.Client

// Logger specifies an optional logger.
// If nil, logging is done via the log package's standard logger.
Logger *log.Logger
// Client will send logging events to both Logger and PrioritizedLogger.
// When neither Logger or PrioritizedLogger is set, the log package's standard logger will be used.
Logger *log.Logger
PrioritizedLogger PrioritizedLogger
}

// NewClient returns new mackerel.Client
Expand All @@ -44,7 +54,14 @@ func NewClientWithOptions(apikey string, rawurl string, verbose bool) (*Client,
}
client := &http.Client{}
client.Timeout = apiRequestTimeout
return &Client{u, apikey, verbose, defaultUserAgent, http.Header{}, client, nil}, nil
return &Client{
BaseURL: u,
APIKey: apikey,
Verbose: verbose,
UserAgent: defaultUserAgent,
AdditionalHeaders: http.Header{},
HTTPClient: client,
}, nil
}

func (c *Client) urlFor(path string) *url.URL {
Expand All @@ -69,19 +86,26 @@ func (c *Client) buildReq(req *http.Request) *http.Request {
return req
}

func (c *Client) tracef(format string, v ...interface{}) {
if c.PrioritizedLogger != nil {
c.PrioritizedLogger.Tracef(format, v...)
}
if c.Logger != nil {
c.Logger.Printf(format, v...)
}
if c.PrioritizedLogger == nil && c.Logger == nil {
log.Printf(format, v...)
}
}

// Request request to mackerel and receive response
func (c *Client) Request(req *http.Request) (resp *http.Response, err error) {
req = c.buildReq(req)

logPrintf := log.Printf
if c.Logger != nil {
logPrintf = c.Logger.Printf
}

if c.Verbose {
dump, err := httputil.DumpRequest(req, true)
if err == nil {
logPrintf("%s", dump)
c.tracef("%s", dump)
}
}

Expand All @@ -92,7 +116,7 @@ func (c *Client) Request(req *http.Request) (resp *http.Response, err error) {
if c.Verbose {
dump, err := httputil.DumpResponse(resp, true)
if err == nil {
logPrintf("%s", dump)
c.tracef("%s", dump)
}
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {
Expand Down
99 changes: 99 additions & 0 deletions mackerel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package mackerel

import (
"bytes"
"fmt"
"io"
"log"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"
)
Expand Down Expand Up @@ -77,3 +80,99 @@ func TestLogger(t *testing.T) {
t.Errorf("verbose log should match /<api>.*OK/; but %s", s)
}
}

type fakePrinter struct {
w io.Writer
}

func (p *fakePrinter) Tracef(format string, v ...interface{}) {
fmt.Fprintf(p.w, format, v...)
}
func (p *fakePrinter) Debugf(format string, v ...interface{}) {}
func (p *fakePrinter) Infof(format string, v ...interface{}) {}
func (p *fakePrinter) Warningf(format string, v ...interface{}) {}
func (p *fakePrinter) Errorf(format string, v ...interface{}) {}
func (p *fakePrinter) Criticalf(format string, v ...interface{}) {}

func TestPrivateTracef(t *testing.T) {
var (
stdbuf bytes.Buffer
logbuf bytes.Buffer
pbuf bytes.Buffer
)
log.SetOutput(&stdbuf)
defer log.SetOutput(os.Stderr)
oflags := log.Flags()
defer log.SetFlags(oflags)
log.SetFlags(0)

msg := "test\n"
t.Run("Logger+PrioritizedLogger", func(t *testing.T) {
var c Client
c.Logger = log.New(&logbuf, "", 0)
c.PrioritizedLogger = &fakePrinter{w: &pbuf}
c.tracef(msg)
if s := stdbuf.String(); s != "" {
t.Errorf("tracef(%q): log.Printf(%q); want %q", msg, s, "")
}
if s := logbuf.String(); s != msg {
t.Errorf("tracef(%q): Logger.Printf(%q); want %q", msg, s, msg)
}
if s := pbuf.String(); s != msg {
t.Errorf("tracef(%q): PrioritizedLogger.Tracef(%q); want %q", msg, s, msg)
}
})

stdbuf.Reset()
logbuf.Reset()
pbuf.Reset()
t.Run("Logger", func(t *testing.T) {
var c Client
c.Logger = log.New(&logbuf, "", 0)
c.tracef(msg)
if s := stdbuf.String(); s != "" {
t.Errorf("tracef(%q): log.Printf(%q); want %q", msg, s, "")
}
if s := logbuf.String(); s != msg {
t.Errorf("tracef(%q): Logger.Printf(%q); want %q", msg, s, msg)
}
if s := pbuf.String(); s != "" {
t.Errorf("tracef(%q): PrioritizedLogger.Tracef(%q); want %q", msg, s, "")
}
})

stdbuf.Reset()
logbuf.Reset()
pbuf.Reset()
t.Run("PrioritizedLogger", func(t *testing.T) {
var c Client
c.PrioritizedLogger = &fakePrinter{w: &pbuf}
c.tracef(msg)
if s := stdbuf.String(); s != "" {
t.Errorf("tracef(%q): log.Printf(%q); want %q", msg, s, "")
}
if s := logbuf.String(); s != "" {
t.Errorf("tracef(%q): Logger.Printf(%q); want %q", msg, s, "")
}
if s := pbuf.String(); s != msg {
t.Errorf("tracef(%q): PrioritizedLogger.Tracef(%q); want %q", msg, s, msg)
}
})

stdbuf.Reset()
logbuf.Reset()
pbuf.Reset()
t.Run("default", func(t *testing.T) {
var c Client
c.tracef(msg)
if s := stdbuf.String(); s != msg {
t.Errorf("tracef(%q): log.Printf(%q); want %q", msg, s, msg)
}
if s := logbuf.String(); s != "" {
t.Errorf("tracef(%q): Logger.Printf(%q); want %q", msg, s, "")
}
if s := pbuf.String(); s != "" {
t.Errorf("tracef(%q): PrioritizedLogger.Tracef(%q); want %q", msg, s, "")
}
})
}

0 comments on commit fa77a80

Please sign in to comment.