forked from anz-bank/pkg
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tests are cleaned up
- Loading branch information
Showing
13 changed files
with
1,282 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module github.com/anz-bank/pkg | ||
|
||
go 1.13 | ||
|
||
require ( | ||
github.com/marcelocantos/frozen v0.4.0 | ||
github.com/sirupsen/logrus v1.4.2 | ||
github.com/stretchr/testify v1.4.0 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | ||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||
github.com/marcelocantos/frozen v0.4.0 h1:GzYtr+BWZBTGpYeXZvACr3HUDN0wZKDg5tApuKdt59E= | ||
github.com/marcelocantos/frozen v0.4.0/go.mod h1:kMkkLrWmAufGtJqXshM37prrD5O3ovVmb1pvG6mXfvY= | ||
github.com/marcelocantos/hash v0.2.0 h1:pHimAPlPACKciZw0VeMbj8qmca7VmG6w8fAuUOi9gZo= | ||
github.com/marcelocantos/hash v0.2.0/go.mod h1:ZpakDB4Kjclkjg4f6wxrlINDjQ/Wxpky/0bvbwyET7A= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= | ||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= | ||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | ||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= | ||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20191220220014-0732a990476f h1:72l8qCJ1nGxMGH26QVBVIxKd/D34cfGt0OvrPtpemyY= | ||
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= | ||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package log | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/anz-bank/pkg/log/loggers" | ||
) | ||
|
||
type loggerContextKey int | ||
|
||
const loggerKey loggerContextKey = iota | ||
|
||
// WithLogger adds a copy of the logger to the context | ||
func WithLogger(ctx context.Context, logger loggers.Logger) context.Context { | ||
return context.WithValue(ctx, loggerKey, logger.Copy()) | ||
} | ||
|
||
// The fields setup in WithField and WithFields are for context-specific fields | ||
// Fields will be logged alphabetically | ||
|
||
// WithField adds a single field in the scope of the context | ||
func WithField(ctx context.Context, key string, val interface{}) context.Context { | ||
return context.WithValue(ctx, loggerKey, | ||
getCopiedLogger(ctx).PutField(key, val)) | ||
} | ||
|
||
// WithFields adds multiple fields in the scope of the context | ||
func WithFields(ctx context.Context, fields MultipleFields) context.Context { | ||
return context.WithValue(ctx, loggerKey, | ||
getCopiedLogger(ctx).PutFields(fromFields([]Fields{fields}))) | ||
} | ||
|
||
// Logger is a way to access the API of the logger inside the context | ||
func Logger(ctx context.Context, fields ...Fields) loggers.Logger { | ||
if len(fields) == 0 { | ||
return getCopiedLogger(ctx) | ||
} | ||
return getCopiedLogger(ctx).PutFields(fromFields(fields)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
package log | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/anz-bank/pkg/log/loggers" | ||
"github.com/anz-bank/pkg/log/testutil" | ||
"github.com/marcelocantos/frozen" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestWithLogger(t *testing.T) { | ||
t.Parallel() | ||
|
||
logger := loggers.NewMockLogger() | ||
logger.On("Copy").Return(logger).Once() | ||
WithLogger(context.Background(), logger) | ||
|
||
require.True(t, logger.AssertExpectations(t)) | ||
} | ||
|
||
func TestWithField(t *testing.T) { | ||
cases := testutil.GenerateSingleFieldCases() | ||
for _, c := range cases { | ||
c := c | ||
t.Run("TestWithField"+" "+c.Name, func(tt *testing.T) { | ||
tt.Parallel() | ||
|
||
logger := loggers.NewMockLogger() | ||
// this is done so that the mock logger is of the same reference, for testing purposes | ||
// in real use, it will return a different logger | ||
logger.On("Copy").Return(logger) | ||
logger.On("PutField", c.Key, c.Val).Return(logger) | ||
ctx := context.WithValue(context.Background(), loggerKey, logger) | ||
WithField(ctx, c.Key, c.Val) | ||
logger = ctx.Value(loggerKey).(*loggers.MockLogger) | ||
|
||
assert.True(tt, logger.AssertExpectations(tt)) | ||
}) | ||
} | ||
} | ||
|
||
func TestWithFields(t *testing.T) { | ||
cases := testutil.GenerateMultipleFieldsCases() | ||
for _, c := range cases { | ||
c := c | ||
t.Run("TestWithFields"+" "+c.Name, func(tt *testing.T) { | ||
tt.Parallel() | ||
|
||
logger := loggers.NewMockLogger() | ||
setLogSpecificFieldAssertion(logger, c.Fields) | ||
|
||
ctx := context.WithValue(context.Background(), loggerKey, logger) | ||
WithFields(ctx, testutil.ConvertToGoMap(c.Fields)) | ||
logger = ctx.Value(loggerKey).(*loggers.MockLogger) | ||
|
||
assert.True(tt, logger.AssertExpectations(tt)) | ||
}) | ||
} | ||
} | ||
|
||
func TestLogger(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
fields []Fields | ||
}{ | ||
{ | ||
name: "Empty fields", | ||
fields: []Fields{}, | ||
}, | ||
{ | ||
name: "Single fields only", | ||
fields: []Fields{ | ||
NewField("test", 1), | ||
NewField("test again", 2), | ||
NewField("another test", 3), | ||
}, | ||
}, | ||
{ | ||
name: "Multiple fields only", | ||
fields: []Fields{ | ||
FromMap( | ||
map[string]interface{}{ | ||
"test": '1', | ||
"test2": 2, | ||
}, | ||
), | ||
FromMap( | ||
map[string]interface{}{ | ||
"test3": 3, | ||
"test4": 4, | ||
}, | ||
), | ||
}, | ||
}, | ||
{ | ||
name: "Mixed Fields", | ||
fields: []Fields{ | ||
NewField("test", 1), | ||
FromMap( | ||
map[string]interface{}{ | ||
"test3": 3, | ||
"test4": 4, | ||
}, | ||
), | ||
NewField("another test", 2), | ||
}, | ||
}, | ||
} | ||
|
||
for _, ts := range tests { | ||
ts := ts | ||
t.Run(ts.name, func(tt *testing.T) { | ||
tt.Parallel() | ||
|
||
logger := loggers.NewMockLogger() | ||
setLogSpecificFieldAssertion(logger, fromFields(ts.fields)) | ||
|
||
ctx := context.WithValue(context.Background(), loggerKey, logger) | ||
Logger(ctx, ts.fields...) | ||
assert.True(tt, logger.AssertExpectations(tt)) | ||
}) | ||
} | ||
} | ||
|
||
func setLogSpecificFieldAssertion(logger *loggers.MockLogger, fields frozen.Map) { | ||
// set to return the same logger for testing purposes, in real case it will return | ||
// a copied logger | ||
logger.On("Copy").Return(logger) | ||
if fields.Count() != 0 { | ||
logger.On( | ||
"PutFields", | ||
mock.MatchedBy( | ||
func(arg frozen.Map) bool { | ||
return fields.Equal(arg) | ||
}, | ||
), | ||
).Return(logger) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# Examples of Usage | ||
|
||
## Setup | ||
|
||
```go | ||
package main | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/anz-bank/pkg/log" | ||
"github.com/anz-bank/pkg/log/loggers" | ||
) | ||
|
||
func main() { | ||
// User is expected to choose a logger and add it to the context using the library's API | ||
ctx := context.Background() | ||
|
||
// this is a logger based on the logrus standard logger | ||
logger := loggers.NewStandardLogger() | ||
|
||
// WithLogger returns a new context | ||
ctx = log.WithLogger(ctx, logger) | ||
} | ||
``` | ||
|
||
That's all in setup, now logging can be used by using the context. | ||
|
||
## Usage | ||
|
||
```go | ||
import ( | ||
"github.com/anz-bank/pkg/log" | ||
) | ||
|
||
func stuffToLog(ctx context.Context) { | ||
// logging requires the context variable so it must be given to any function that requires it | ||
log.Logger(ctx).Debug("Debug") | ||
log.Logger(ctx).Print("Print") | ||
log.Logger(ctx).Trace("Trace") | ||
log.Logger(ctx).Warn("Warn") | ||
log.Logger(ctx).Error("Error") | ||
log.Logger(ctx).Fatal("Fatal") | ||
log.Logger(ctx).Panic("Panic") | ||
|
||
// Expected to log | ||
// (time in RFC3339Nano Format) (Level) (Message) | ||
// | ||
// Example: | ||
// 2019-12-12T08:23:59.210878+11:00 PRINT Hello There | ||
// | ||
// Each API also has its Format counterpart (Debugf, Printf, Tracef, Warnf, Errorf, Fatalf, Panicf) | ||
} | ||
``` | ||
|
||
Fields are also supported in the logging. There are two kinds of fields, context-level fields and log-level fields. | ||
|
||
```go | ||
import ( | ||
"github.com/anz-bank/pkg/log" | ||
) | ||
|
||
|
||
// With fields, it is expected to log | ||
// (time in RFC3339Nano Format) (Fields) (Level) (Message) | ||
// | ||
// Fields will be logged ALPHABETICALLY. If the same key field is added to the context logger, | ||
// it will replace the existing value that corresponds to that key. | ||
// | ||
// Example: | ||
// 2019-12-12T08:23:59.210878+11:00 random=stuff very=random PRINT Hello There | ||
// | ||
// Each API also has its Format counterpart (Debugf, Printf, Tracef, Warnf, Errorf, Fatalf, Panicf) | ||
|
||
|
||
func logWithField(ctx context.Context) { | ||
// context-level field adds fields to the context and creates a new context | ||
ctx = log.WithField(ctx, "random", "stuff") | ||
ctx = log.WithFields(ctx, map[string]interface{}{ | ||
"just": "stuff", | ||
"stuff": 1 | ||
}) | ||
|
||
// or | ||
ctx = log.WithFields(ctx, MultipleFields{ | ||
"just": "stuff", | ||
"stuff": 1 | ||
}) | ||
|
||
// Any log at this point will have fields and to any function that uses the same context | ||
// just=stuff random=stuff stuff=1 | ||
contextLevelField(ctx) | ||
logLevelField(ctx) | ||
} | ||
|
||
func contextLevelField(ctx context.Context) { | ||
// This is expected to log something like | ||
// 2019-12-12T08:23:59.210878+11:00 just=stuff random=stuff stuff=1 WARN Warn | ||
log.Logger(ctx).Warn("Warn") | ||
} | ||
|
||
func logLevelField(ctx context.Context) { | ||
|
||
// Log level fields are fields that are not stored into the context logger | ||
// Log level fields will add fields on top of the existing context level fields | ||
// If an existing key exists in the stored field, it will replace the value | ||
// This is expected to log something like | ||
// 2019-12-12T08:23:59.210878+11:00 just=stuff more=random stuff random=stuff stuff=1 very=random WARN Warn | ||
|
||
|
||
// You can add multiple fields at once through FromMap API or just use MultipleFields struct | ||
log.Logger(ctx, | ||
FromMap(map[string]interface{}{ | ||
"more": "random stuff", | ||
"very": "random" | ||
} | ||
)).Warn("Warn") | ||
|
||
// or | ||
|
||
log.Logger( | ||
ctx, | ||
MultipleFields{ | ||
"more": "random stuff", | ||
"very": "random" | ||
} | ||
).Warn("Warn") | ||
|
||
// You can also add single field through the API NewField | ||
log.Logger(ctx, | ||
NewField("more", "random stuff"), | ||
NewField("very", "random"), | ||
).Warn("Warn") | ||
|
||
// As long as context logger is not modified, it will log again only the context level fields | ||
contextLevelField(ctx) | ||
} | ||
|
||
``` |
Oops, something went wrong.