Skip to content

Commit 2f1b231

Browse files
authored
Merge pull request #42 from hashicorp/f-context
{From,With}Context for storing a logger in a context.Context
2 parents d2f17ae + ea9db1c commit 2f1b231

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

context.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package hclog
2+
3+
import (
4+
"context"
5+
)
6+
7+
// WithContext inserts a logger into the context and is retrievable
8+
// with FromContext. The optional args can be set with the same syntax as
9+
// Logger.With to set fields on the inserted logger. This will not modify
10+
// the logger argument in-place.
11+
func WithContext(ctx context.Context, logger Logger, args ...interface{}) context.Context {
12+
// While we could call logger.With even with zero args, we have this
13+
// check to avoid unnecessary allocations around creating a copy of a
14+
// logger.
15+
if len(args) > 0 {
16+
logger = logger.With(args...)
17+
}
18+
19+
return context.WithValue(ctx, contextKey, logger)
20+
}
21+
22+
// FromContext returns a logger from the context. This will return L()
23+
// (the default logger) if no logger is found in the context. Therefore,
24+
// this will never return a nil value.
25+
func FromContext(ctx context.Context) Logger {
26+
logger, _ := ctx.Value(contextKey).(Logger)
27+
if logger == nil {
28+
return L()
29+
}
30+
31+
return logger
32+
}
33+
34+
// Unexported new type so that our context key never collides with another.
35+
type contextKeyType struct{}
36+
37+
// contextKey is the key used for the context to store the logger.
38+
var contextKey = contextKeyType{}

context_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package hclog
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestContext_simpleLogger(t *testing.T) {
12+
l := L()
13+
ctx := WithContext(context.Background(), l)
14+
require.Equal(t, l, FromContext(ctx))
15+
}
16+
17+
func TestContext_empty(t *testing.T) {
18+
require.Equal(t, L(), FromContext(context.Background()))
19+
}
20+
21+
func TestContext_fields(t *testing.T) {
22+
var buf bytes.Buffer
23+
l := New(&LoggerOptions{
24+
Level: Debug,
25+
Output: &buf,
26+
})
27+
28+
// Insert the logger with fields
29+
ctx := WithContext(context.Background(), l, "hello", "world")
30+
l = FromContext(ctx)
31+
require.NotNil(t, l)
32+
33+
// Log something so we can test the output that the field is there
34+
l.Debug("test")
35+
require.Contains(t, buf.String(), "hello")
36+
}

0 commit comments

Comments
 (0)