-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
295 additions
and
2 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
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 @@ | ||
* @yuseferi |
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,38 @@ | ||
# This workflow will build a golang project | ||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go | ||
name: Check & Build | ||
on: | ||
push: | ||
branches: [ "master" ] | ||
pull_request: | ||
branches: [ "master" ] | ||
|
||
jobs: | ||
qa: | ||
name: Quality check | ||
timeout-minutes: 10 | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
- name: Setup Go | ||
uses: actions/setup-go@v4 | ||
- name: Linter | ||
uses: golangci/golangci-lint-action@v3 | ||
with: | ||
version: v1.53.2 | ||
- name: Tests | ||
run: go mod download; go test -race ./... | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v3 | ||
with: | ||
fetch-depth: 0 | ||
- name: Set up Go | ||
uses: actions/setup-go@v4 | ||
- name: Build | ||
run: go mod download; go build -v ./... |
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 |
---|---|---|
|
@@ -19,3 +19,5 @@ | |
|
||
# Go workspace file | ||
go.work | ||
.vs/ | ||
.idea/ |
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 |
---|---|---|
@@ -1,2 +1,61 @@ | ||
# zax | ||
Zap logger with context | ||
# Zax (zap with context) | ||
|
||
Basically this adds context to [Zap Logger](https://github.com/uber-go/zap), and make it easier to for the Gophers to do not generate logger boiler plates. | ||
Passing logger as a parameter to function increase parameters functionalities and worse than couple lots of methods with a explicit dependency. | ||
|
||
|
||
### Installation | ||
|
||
```shell | ||
go get -u github.com/yuseferi/zax | ||
``` | ||
|
||
### Usage: | ||
when you add something to context and would like to carry with context , you just need to add it to context with calling `zap.Set` | ||
|
||
ctx = zax.Set(ctx, logger, []zap.Field{zap.String("trace_id", "my-trace-id")}) | ||
|
||
and when you want to log context fields, just use | ||
|
||
zax.Get(ctx) | ||
|
||
|
||
|
||
##### example: | ||
you want to generate a tracer on entry point of your system and want to keep it until the process finished. | ||
|
||
```Go | ||
func main() { | ||
logger, _ := zap.NewProduction() | ||
ctx := context.Background() | ||
s := NewServiceA(logger) | ||
ctx = zax.Set(ctx, logger, []zap.Field{zap.String("trace_id", "my-trace-id")}) | ||
s.funcA(ctx) | ||
} | ||
|
||
type ServiceA struct { | ||
logger *zap.Logger | ||
} | ||
|
||
func NewServiceA(logger *zap.Logger) *ServiceA { | ||
return &ServiceA{ | ||
logger: logger, | ||
} | ||
} | ||
|
||
func (s *ServiceA) funcA(ctx context.Context) { | ||
s.logger.Info("func A") // it does not contain trace_id, you need to add it manually | ||
zax.Get(ctx).Info("func A") // it will logged with "trace_id" = "my-trace-id" | ||
} | ||
|
||
``` | ||
|
||
### Contributing | ||
I strongly believe in open-source :), feel free to make it better with raising issues and PRs. | ||
|
||
|
||
Released under the [GNU GENERAL PUBLIC LICENSE](LICENSE). | ||
|
||
|
||
|
||
|
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,16 @@ | ||
module zax | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/stretchr/testify v1.8.0 | ||
go.uber.org/zap v1.24.0 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
go.uber.org/atomic v1.7.0 // indirect | ||
go.uber.org/multierr v1.6.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
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,25 @@ | ||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= | ||
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/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | ||
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= | ||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= | ||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= | ||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= | ||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= | ||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= | ||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= | ||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
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,29 @@ | ||
// Package zax provides contextual field logging around the uber-zap logger. | ||
|
||
package zax | ||
|
||
import ( | ||
"context" | ||
"go.uber.org/zap" | ||
) | ||
|
||
type Key string | ||
|
||
// Key name which used for save logger in context | ||
const loggerKey = Key("zax") | ||
|
||
// Set Add passed fields to logger and store zap.Logger as variable in context | ||
func Set(ctx context.Context, logger *zap.Logger, fields []zap.Field) context.Context { | ||
if len(fields) > 0 { | ||
logger = logger.With(fields...) | ||
} | ||
return context.WithValue(ctx, loggerKey, logger) | ||
} | ||
|
||
// Get zap.Logger from context | ||
func Get(ctx context.Context) *zap.Logger { | ||
if logger, ok := ctx.Value(loggerKey).(*zap.Logger); ok { | ||
return logger | ||
} | ||
return zap.L() | ||
} |
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,123 @@ | ||
package zax | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"go.uber.org/zap" | ||
"go.uber.org/zap/zapcore" | ||
"go.uber.org/zap/zaptest/observer" | ||
) | ||
|
||
type Logger struct { | ||
logger *zap.Logger | ||
recorded *observer.ObservedLogs | ||
t *testing.T | ||
} | ||
|
||
func NewLogger(t *testing.T) *Logger { | ||
core, recorded := observer.New(zapcore.DebugLevel) | ||
logger := &Logger{ | ||
logger: zap.New(core), | ||
recorded: recorded, | ||
t: t, | ||
} | ||
return logger | ||
} | ||
|
||
func (l *Logger) GetZapLogger() *zap.Logger { | ||
return l.logger | ||
} | ||
|
||
func (l *Logger) GetRecordedLogs() []observer.LoggedEntry { | ||
return l.recorded.All() | ||
} | ||
|
||
func (l *Logger) AssertLogEntryExist(t assert.TestingT, key, value string) bool { | ||
for _, log := range l.recorded.All() { | ||
for _, r := range log.Context { | ||
if r.Key == key && r.String == value { | ||
return true | ||
} | ||
} | ||
} | ||
return assert.Fail(t, fmt.Sprintf("log entry does not exist with, %s = %s", key, value)) | ||
} | ||
|
||
func (l *Logger) AssertLogEntryKeyExist(t assert.TestingT, key string) bool { | ||
for _, log := range l.recorded.All() { | ||
for _, r := range log.Context { | ||
if r.Key == key { | ||
return true | ||
} | ||
} | ||
} | ||
return assert.Fail(t, fmt.Sprintf("log entry does not exist with key = %s ", key)) | ||
} | ||
|
||
const traceIDKey = "trace_id" | ||
|
||
func TestSet(t *testing.T) { | ||
testLog := NewLogger(t) | ||
testTraceID := "test-trace-id-3333" | ||
testTraceID2 := "test-trace-id-new" | ||
ctx := context.Background() | ||
tests := map[string]struct { | ||
context context.Context | ||
expectedLoggerKey string | ||
expectedLoggerValue string | ||
}{ | ||
"context with trace-id": { | ||
context: Set(ctx, testLog.logger, []zap.Field{zap.String(traceIDKey, testTraceID)}), | ||
expectedLoggerKey: traceIDKey, | ||
expectedLoggerValue: testTraceID, | ||
}, | ||
"context with trace-id with new value(to check it will be updated)": { | ||
context: Set(ctx, testLog.logger, []zap.Field{zap.String(traceIDKey, testTraceID2)}), | ||
expectedLoggerKey: traceIDKey, | ||
expectedLoggerValue: testTraceID2, | ||
}, | ||
} | ||
|
||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
ctx := tc.context | ||
logger := ctx.Value(loggerKey).(*zap.Logger) | ||
logger.Info("just a test record") | ||
assert.NotNil(t, logger) | ||
testLog.AssertLogEntryExist(t, tc.expectedLoggerKey, tc.expectedLoggerValue) | ||
}) | ||
} | ||
} | ||
|
||
func TestGet(t *testing.T) { | ||
testLog := NewLogger(t) | ||
testTraceID := "test-trace-id-3333" | ||
traceIDKey := traceIDKey | ||
ctx := context.Background() | ||
tests := map[string]struct { | ||
context context.Context | ||
expectedLoggerKey *string | ||
}{ | ||
"context with trace-id": { | ||
context: context.TODO(), | ||
expectedLoggerKey: nil, | ||
}, | ||
"context with trace-id with new value(to check it will be updated)": { | ||
context: Set(ctx, testLog.logger, []zap.Field{zap.String(traceIDKey, testTraceID)}), | ||
expectedLoggerKey: &traceIDKey, | ||
}, | ||
} | ||
|
||
for name, tc := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
ctx := tc.context | ||
Get(ctx).Info("just a test record") | ||
if tc.expectedLoggerKey != nil { | ||
testLog.AssertLogEntryKeyExist(t, *tc.expectedLoggerKey) | ||
} | ||
}) | ||
} | ||
} |