Skip to content

Commit 5d41ca0

Browse files
authored
refactor: simplify and improve logging hook (#361)
Signed-off-by: Sahid Velji <sahidvelji@gmail.com>
1 parent 0f6d828 commit 5d41ca0

File tree

2 files changed

+44
-40
lines changed

2 files changed

+44
-40
lines changed

openfeature/hooks/logging_hook.go

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,22 @@ const (
1717
REASON_KEY = "reason"
1818
VARIANT_KEY = "variant"
1919
VALUE_KEY = "value"
20+
STAGE_KEY = "stage"
2021
)
2122

23+
// LoggingHook is a [of.Hook] that logs the flag evaluation lifecycle.
2224
type LoggingHook struct {
2325
includeEvaluationContext bool
2426
logger *slog.Logger
2527
}
2628

29+
// NewLoggingHook returns a new [LoggingHook] with the default logger.
30+
// To provide a custom logger, use [NewCustomLoggingHook].
2731
func NewLoggingHook(includeEvaluationContext bool) (*LoggingHook, error) {
2832
return NewCustomLoggingHook(includeEvaluationContext, slog.Default())
2933
}
3034

35+
// NewCustomLoggingHook returns a new [LoggingHook] with the provided logger.
3136
func NewCustomLoggingHook(includeEvaluationContext bool, logger *slog.Logger) (*LoggingHook, error) {
3237
return &LoggingHook{
3338
logger: logger,
@@ -40,57 +45,53 @@ type MarshaledEvaluationContext struct {
4045
Attributes map[string]any
4146
}
4247

43-
func (l LoggingHook) buildArgs(hookContext of.HookContext) ([]any, error) {
44-
45-
args := []any{
46-
DOMAIN_KEY, hookContext.ClientMetadata().Domain(),
47-
PROVIDER_NAME_KEY, hookContext.ProviderMetadata().Name,
48-
FLAG_KEY_KEY, hookContext.FlagKey(),
49-
DEFAULT_VALUE_KEY, hookContext.DefaultValue(),
48+
func (h *LoggingHook) buildArgs(hookContext of.HookContext) []slog.Attr {
49+
args := []slog.Attr{
50+
slog.String(DOMAIN_KEY, hookContext.ClientMetadata().Domain()),
51+
slog.String(PROVIDER_NAME_KEY, hookContext.ProviderMetadata().Name),
52+
slog.String(FLAG_KEY_KEY, hookContext.FlagKey()),
53+
slog.Any(DEFAULT_VALUE_KEY, hookContext.DefaultValue()),
5054
}
51-
if l.includeEvaluationContext {
55+
if h.includeEvaluationContext {
5256
marshaledEvaluationContext := MarshaledEvaluationContext{
5357
TargetingKey: hookContext.EvaluationContext().TargetingKey(),
5458
Attributes: hookContext.EvaluationContext().Attributes(),
5559
}
56-
args = append(args, EVALUATION_CONTEXT_KEY, marshaledEvaluationContext)
60+
args = append(args, slog.Any(EVALUATION_CONTEXT_KEY, marshaledEvaluationContext))
5761
}
5862

59-
return args, nil
63+
return args
6064
}
6165

62-
func (h *LoggingHook) Before(ctx context.Context, hookContext of.HookContext,
63-
hint of.HookHints) (*of.EvaluationContext, error) {
64-
var args, err = h.buildArgs(hookContext)
65-
if err != nil {
66-
return nil, err
67-
}
68-
h.logger.Debug("Before stage", args...)
66+
func (h *LoggingHook) Before(ctx context.Context, hookContext of.HookContext, hookHints of.HookHints) (*of.EvaluationContext, error) {
67+
args := h.buildArgs(hookContext)
68+
args = append(args, slog.String(STAGE_KEY, "before"))
69+
h.logger.LogAttrs(ctx, slog.LevelDebug, "Before stage", args...)
6970
return nil, nil
7071
}
7172

7273
func (h *LoggingHook) After(ctx context.Context, hookContext of.HookContext,
73-
flagEvaluationDetails of.InterfaceEvaluationDetails, hookHints of.HookHints) error {
74-
var args, err = h.buildArgs(hookContext)
75-
if err != nil {
76-
return err
77-
}
78-
args = append(args, REASON_KEY, flagEvaluationDetails.Reason)
79-
args = append(args, VARIANT_KEY, flagEvaluationDetails.Variant)
80-
args = append(args, VALUE_KEY, flagEvaluationDetails.Value)
81-
h.logger.Debug("After stage", args...)
74+
flagEvaluationDetails of.InterfaceEvaluationDetails, hookHints of.HookHints,
75+
) error {
76+
args := h.buildArgs(hookContext)
77+
args = append(args,
78+
slog.String(REASON_KEY, string(flagEvaluationDetails.Reason)),
79+
slog.String(VARIANT_KEY, flagEvaluationDetails.Variant),
80+
slog.Any(VALUE_KEY, flagEvaluationDetails.Value),
81+
slog.String(STAGE_KEY, "after"),
82+
)
83+
h.logger.LogAttrs(ctx, slog.LevelDebug, "After stage", args...)
8284
return nil
8385
}
8486

85-
func (h *LoggingHook) Error(ctx context.Context, hookContext of.HookContext, err error, hint of.HookHints) {
86-
args, buildArgsErr := h.buildArgs(hookContext)
87-
if buildArgsErr != nil {
88-
slog.Error("Error building args", "error", buildArgsErr)
89-
}
90-
args = append(args, ERROR_MESSAGE_KEY, err)
91-
h.logger.Error("Error stage", args...)
87+
func (h *LoggingHook) Error(ctx context.Context, hookContext of.HookContext, err error, hookHints of.HookHints) {
88+
args := h.buildArgs(hookContext)
89+
args = append(args,
90+
slog.Any(ERROR_MESSAGE_KEY, err),
91+
slog.String(STAGE_KEY, "error"),
92+
)
93+
h.logger.LogAttrs(ctx, slog.LevelError, "Error stage", args...)
9294
}
9395

94-
func (h *LoggingHook) Finally(ctx context.Context, hCtx of.HookContext, flagEvaluationDetails of.InterfaceEvaluationDetails, hint of.HookHints) {
95-
96+
func (h *LoggingHook) Finally(ctx context.Context, hookContext of.HookContext, flagEvaluationDetails of.InterfaceEvaluationDetails, hookHints of.HookHints) {
9697
}

openfeature/hooks/logging_hook_test.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ import (
44
"bytes"
55
"context"
66
"encoding/json"
7+
"log/slog"
78
"os"
89
"testing"
910

10-
"log/slog"
11-
1211
"github.com/open-feature/go-sdk/openfeature"
1312
"github.com/open-feature/go-sdk/openfeature/memprovider"
1413
)
@@ -55,7 +54,7 @@ func TestLoggingHookHandlesNilLoggerGracefully(t *testing.T) {
5554
}
5655

5756
func TestLoggingHookLogsMessagesAsExpected(t *testing.T) {
58-
var buf *bytes.Buffer = new(bytes.Buffer)
57+
buf := new(bytes.Buffer)
5958
handler := slog.NewJSONHandler(buf, &slog.HandlerOptions{Level: slog.LevelDebug})
6059
logger := slog.New(handler)
6160

@@ -128,15 +127,17 @@ func testLoggingHookLogsMessagesAsExpected(hook LoggingHook, logger *slog.Logger
128127

129128
ms := prepareOutput(buf, t)
130129

131-
var expected = map[string]map[string]any{
130+
expected := map[string]map[string]any{
132131
"Before stage": {
133132
"provider_name": "InMemoryProvider",
134133
"domain": "test-app",
134+
"stage": "before",
135135
},
136136
"After stage": {
137137
"provider_name": "InMemoryProvider",
138138
"domain": "test-app",
139139
"flag_key": "boolFlag",
140+
"stage": "after",
140141
},
141142
}
142143

@@ -164,15 +165,17 @@ func testLoggingHookLogsMessagesAsExpected(hook LoggingHook, logger *slog.Logger
164165

165166
ms := prepareOutput(buf, t)
166167

167-
var expected = map[string]map[string]any{
168+
expected := map[string]map[string]any{
168169
"Before stage": {
169170
"provider_name": "InMemoryProvider",
170171
"domain": "test-app",
172+
"stage": "before",
171173
},
172174
"Error stage": {
173175
"provider_name": "InMemoryProvider",
174176
"domain": "test-app",
175177
"flag_key": "non-existing",
178+
"stage": "error",
176179
},
177180
}
178181

0 commit comments

Comments
 (0)