Skip to content

Commit

Permalink
Merge pull request #2 from nelzkiddom/nelz-ctx
Browse files Browse the repository at this point in the history
support underlying context aware client
  • Loading branch information
nelz9999 authored Jun 29, 2024
2 parents 27da972 + 5328af9 commit 9c16530
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 22 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# go-ld-hook
# DEPRECATED!

As of ~2024-Q2, the official SDK now supports hooks.

See https://pkg.go.dev/github.com/launchdarkly/go-server-sdk/v7@v7.3.0/ldhooks

## go-ld-hook
Hooks into Flag Evaluations for the LaunchDarkly Go SDK
9 changes: 7 additions & 2 deletions v6/go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
module github.com/nelz9999/goldhook/v6

go 1.18
go 1.21

toolchain go1.22.1

require (
github.com/launchdarkly/go-sdk-common/v3 v3.0.1
github.com/launchdarkly/go-sdk-common/v3 v3.1.0
github.com/launchdarkly/go-server-sdk/v6 v6.1.0
)

Expand All @@ -15,8 +17,11 @@ require (
github.com/launchdarkly/eventsource v1.6.2 // indirect
github.com/launchdarkly/go-jsonstream/v3 v3.0.0 // indirect
github.com/launchdarkly/go-sdk-events/v2 v2.0.1 // indirect
github.com/launchdarkly/go-sdk-events/v3 v3.3.0 // indirect
github.com/launchdarkly/go-semver v1.0.2 // indirect
github.com/launchdarkly/go-server-sdk-evaluation/v2 v2.0.2 // indirect
github.com/launchdarkly/go-server-sdk-evaluation/v3 v3.0.0 // indirect
github.com/launchdarkly/go-server-sdk/v7 v7.5.0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
golang.org/x/exp v0.0.0-20220823124025-807a23277127 // indirect
Expand Down
8 changes: 8 additions & 0 deletions v6/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,22 @@ github.com/launchdarkly/go-jsonstream/v3 v3.0.0 h1:qJF/WI09EUJ7kSpmP5d1Rhc81NQdY
github.com/launchdarkly/go-jsonstream/v3 v3.0.0/go.mod h1:/1Gyml6fnD309JOvunOSfyysWbZ/ZzcA120gF/cQtC4=
github.com/launchdarkly/go-sdk-common/v3 v3.0.1 h1:rVdLusAIViduNvyjNKy06RA+SPwk0Eq+NocNd1opDhk=
github.com/launchdarkly/go-sdk-common/v3 v3.0.1/go.mod h1:H/zISoCNhviHTTqqBjIKQy2YgSHT8ioL1FtgBKpiEGg=
github.com/launchdarkly/go-sdk-common/v3 v3.1.0 h1:KNCP5rfkOt/25oxGLAVgaU1BgrZnzH9Y/3Z6I8bMwDg=
github.com/launchdarkly/go-sdk-common/v3 v3.1.0/go.mod h1:mXFmDGEh4ydK3QilRhrAyKuf9v44VZQWnINyhqbbOd0=
github.com/launchdarkly/go-sdk-events/v2 v2.0.1 h1:vnUN2Y7og/5wtOCcCZW7wYpmZcS++GAyclasc7gaTIY=
github.com/launchdarkly/go-sdk-events/v2 v2.0.1/go.mod h1:Msqbl6brgFO83RUxmLaJAUx2sYG+WKULcy+Vf3+tKww=
github.com/launchdarkly/go-sdk-events/v3 v3.3.0 h1:OhRZJsj5xkEonGq/inR/fE6HwDRMZMyrRIHiICHijVk=
github.com/launchdarkly/go-sdk-events/v3 v3.3.0/go.mod h1:oepYWQ2RvvjfL2WxkE1uJJIuRsIMOP4WIVgUpXRPcNI=
github.com/launchdarkly/go-semver v1.0.2 h1:sYVRnuKyvxlmQCnCUyDkAhtmzSFRoX6rG2Xa21Mhg+w=
github.com/launchdarkly/go-semver v1.0.2/go.mod h1:xFmMwXba5Mb+3h72Z+VeSs9ahCvKo2QFUTHRNHVqR28=
github.com/launchdarkly/go-server-sdk-evaluation/v2 v2.0.2 h1:PAM0GvE0nIUBeOkjdiymIEKI+8FFLJ+fEsWTupW1yGU=
github.com/launchdarkly/go-server-sdk-evaluation/v2 v2.0.2/go.mod h1:Mztipcz+7ZMatXVun3k/IfPa8IOgUnAqiZawtFh2MRg=
github.com/launchdarkly/go-server-sdk-evaluation/v3 v3.0.0 h1:nQbR1xCpkdU9Z71FI28bWTi5LrmtSVURy0UFcBVD5ZU=
github.com/launchdarkly/go-server-sdk-evaluation/v3 v3.0.0/go.mod h1:cwk7/7SzNB2wZbCZS7w2K66klMLBe3NFM3/qd3xnsRc=
github.com/launchdarkly/go-server-sdk/v6 v6.1.0 h1:pp/VBIon5JNbtSw7ih7I5MXN9mXHfo6T5xikKVy52dI=
github.com/launchdarkly/go-server-sdk/v6 v6.1.0/go.mod h1:3TfS6vNsNksPT4LGeGuGKtT3zTjTbbOsCUK3nrj1neA=
github.com/launchdarkly/go-server-sdk/v7 v7.5.0 h1:SoJR6EAUyY8InbnM9CwD09scWL7f5S1ZHSv1O/SIodk=
github.com/launchdarkly/go-server-sdk/v7 v7.5.0/go.mod h1:tvhDbbMvvsOXOnQIt8fjxaxbcN9n6vP9zbS1ODi4VdU=
github.com/launchdarkly/go-test-helpers/v2 v2.2.0 h1:L3kGILP/6ewikhzhdNkHy1b5y4zs50LueWenVF0sBbs=
github.com/launchdarkly/go-test-helpers/v2 v2.2.0/go.mod h1:L7+th5govYp5oKU9iN7To5PgznBuIjBPn+ejqKR0avw=
github.com/launchdarkly/go-test-helpers/v3 v3.0.2 h1:rh0085g1rVJM5qIukdaQ8z1XTWZztbJ49vRZuveqiuU=
Expand Down
23 changes: 23 additions & 0 deletions v6/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,39 @@ func (fn ObserverFunc) Observe(
type Evaluator interface {
BoolVariation(key string, ldctx ldcontext.Context, defaultVal bool) (bool, error)
BoolVariationDetail(key string, ldctx ldcontext.Context, defaultVal bool) (bool, ldreason.EvaluationDetail, error)

Float64Variation(key string, ldctx ldcontext.Context, defaultVal float64) (float64, error)
Float64VariationDetail(key string, ldctx ldcontext.Context, defaultVal float64) (float64, ldreason.EvaluationDetail, error)

IntVariation(key string, ldctx ldcontext.Context, defaultVal int) (int, error)
IntVariationDetail(key string, ldctx ldcontext.Context, defaultVal int) (int, ldreason.EvaluationDetail, error)

JSONVariation(key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, error)
JSONVariationDetail(key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, ldreason.EvaluationDetail, error)

StringVariation(key string, ldctx ldcontext.Context, defaultVal string) (string, error)
StringVariationDetail(key string, ldctx ldcontext.Context, defaultVal string) (string, ldreason.EvaluationDetail, error)
}

// EvaluatorCtx is the interface that describes the `context.Context`-aware subset of methods on an
// LDClient, which our wrapper invokes to retrieve the value of individual flags.
type EvaluatorCtx interface {
BoolVariationCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal bool) (bool, error)
BoolVariationDetailCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal bool) (bool, ldreason.EvaluationDetail, error)

Float64VariationCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal float64) (float64, error)
Float64VariationDetailCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal float64) (float64, ldreason.EvaluationDetail, error)

IntVariationCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal int) (int, error)
IntVariationDetailCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal int) (int, ldreason.EvaluationDetail, error)

JSONVariationCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, error)
JSONVariationDetailCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, ldreason.EvaluationDetail, error)

StringVariationCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal string) (string, error)
StringVariationDetailCtx(c context.Context, key string, ldctx ldcontext.Context, defaultVal string) (string, ldreason.EvaluationDetail, error)
}

type ContextualEvaluator interface {
Evaluator
WithContext(context.Context) Evaluator
Expand Down
97 changes: 79 additions & 18 deletions v6/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
)

type ObservedEvaluator struct {
client Evaluator
client EvaluatorCtx
hooks []Observer
ctx context.Context
}

func NewEvaluator(ctx context.Context, client Evaluator, subscribers ...Observer) (*ObservedEvaluator, error) {
func NewEvaluator(ctx context.Context, client EvaluatorCtx, subscribers ...Observer) (*ObservedEvaluator, error) {
if client == nil {
return nil, fmt.Errorf("client must not be nil")
}
Expand All @@ -43,6 +43,7 @@ func (oe *ObservedEvaluator) WithContext(c context.Context) Evaluator {
}

func (oe *ObservedEvaluator) notifyHooks(
ctx context.Context,
key string,
ldctx ldcontext.Context,
callsiteDefault ldvalue.Value,
Expand All @@ -51,66 +52,126 @@ func (oe *ObservedEvaluator) notifyHooks(
evalErr error,
) {
for _, h := range oe.hooks {
h.Observe(oe.ctx, key, ldctx, callsiteDefault, elapsed, detail, evalErr)
h.Observe(ctx, key, ldctx, callsiteDefault, elapsed, detail, evalErr)
}
}

/* * * BOOL * * */

func (oe *ObservedEvaluator) BoolVariation(key string, ldctx ldcontext.Context, defaultVal bool) (bool, error) {
_, detail, err := oe.BoolVariationDetail(key, ldctx, defaultVal)
_, detail, err := oe.BoolVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.BoolValue(), err
}

func (oe *ObservedEvaluator) BoolVariationDetail(key string, ldctx ldcontext.Context, defaultVal bool) (bool, ldreason.EvaluationDetail, error) {
_, detail, err := oe.BoolVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.BoolValue(), detail, err
}

func (oe *ObservedEvaluator) BoolVariationCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal bool) (bool, error) {
_, detail, err := oe.BoolVariationDetailCtx(ctx, key, ldctx, defaultVal)
return detail.Value.BoolValue(), err
}

func (oe *ObservedEvaluator) BoolVariationDetailCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal bool) (bool, ldreason.EvaluationDetail, error) {
start := time.Now()
_, detail, err := oe.client.BoolVariationDetail(key, ldctx, defaultVal)
oe.notifyHooks(key, ldctx, ldvalue.Bool(defaultVal), time.Since(start), detail, err)
_, detail, err := oe.client.BoolVariationDetailCtx(ctx, key, ldctx, defaultVal)
oe.notifyHooks(ctx, key, ldctx, ldvalue.Bool(defaultVal), time.Since(start), detail, err)
return detail.Value.BoolValue(), detail, err
}

/* * * FLOAT * * */

func (oe *ObservedEvaluator) Float64Variation(key string, ldctx ldcontext.Context, defaultVal float64) (float64, error) {
_, detail, err := oe.Float64VariationDetail(key, ldctx, defaultVal)
_, detail, err := oe.Float64VariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.Float64Value(), err
}

func (oe *ObservedEvaluator) Float64VariationDetail(key string, ldctx ldcontext.Context, defaultVal float64) (float64, ldreason.EvaluationDetail, error) {
_, detail, err := oe.Float64VariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.Float64Value(), detail, err
}

func (oe *ObservedEvaluator) Float64VariationCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal float64) (float64, error) {
_, detail, err := oe.Float64VariationDetailCtx(ctx, key, ldctx, defaultVal)
return detail.Value.Float64Value(), err
}

func (oe *ObservedEvaluator) Float64VariationDetailCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal float64) (float64, ldreason.EvaluationDetail, error) {
start := time.Now()
_, detail, err := oe.client.Float64VariationDetail(key, ldctx, defaultVal)
oe.notifyHooks(key, ldctx, ldvalue.Float64(defaultVal), time.Since(start), detail, err)
_, detail, err := oe.client.Float64VariationDetailCtx(ctx, key, ldctx, defaultVal)
oe.notifyHooks(ctx, key, ldctx, ldvalue.Float64(defaultVal), time.Since(start), detail, err)
return detail.Value.Float64Value(), detail, err
}

/* * * INT * * */

func (oe *ObservedEvaluator) IntVariation(key string, ldctx ldcontext.Context, defaultVal int) (int, error) {
_, detail, err := oe.IntVariationDetail(key, ldctx, defaultVal)
_, detail, err := oe.IntVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.IntValue(), err
}

func (oe *ObservedEvaluator) IntVariationDetail(key string, ldctx ldcontext.Context, defaultVal int) (int, ldreason.EvaluationDetail, error) {
_, detail, err := oe.IntVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.IntValue(), detail, err
}

func (oe *ObservedEvaluator) IntVariationCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal int) (int, error) {
_, detail, err := oe.IntVariationDetailCtx(ctx, key, ldctx, defaultVal)
return detail.Value.IntValue(), err
}

func (oe *ObservedEvaluator) IntVariationDetailCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal int) (int, ldreason.EvaluationDetail, error) {
start := time.Now()
_, detail, err := oe.client.IntVariationDetail(key, ldctx, defaultVal)
oe.notifyHooks(key, ldctx, ldvalue.Int(defaultVal), time.Since(start), detail, err)
_, detail, err := oe.client.IntVariationDetailCtx(ctx, key, ldctx, defaultVal)
oe.notifyHooks(ctx, key, ldctx, ldvalue.Int(defaultVal), time.Since(start), detail, err)
return detail.Value.IntValue(), detail, err
}

/* * * JSON * * */

func (oe *ObservedEvaluator) JSONVariation(key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, error) {
_, detail, err := oe.JSONVariationDetail(key, ldctx, defaultVal)
_, detail, err := oe.JSONVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value, err
}

func (oe *ObservedEvaluator) JSONVariationDetail(key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, ldreason.EvaluationDetail, error) {
_, detail, err := oe.JSONVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value, detail, err
}

func (oe *ObservedEvaluator) JSONVariationCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, error) {
_, detail, err := oe.JSONVariationDetailCtx(ctx, key, ldctx, defaultVal)
return detail.Value, err
}

func (oe *ObservedEvaluator) JSONVariationDetailCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal ldvalue.Value) (ldvalue.Value, ldreason.EvaluationDetail, error) {
start := time.Now()
_, detail, err := oe.client.JSONVariationDetail(key, ldctx, defaultVal)
oe.notifyHooks(key, ldctx, defaultVal, time.Since(start), detail, err)
_, detail, err := oe.client.JSONVariationDetailCtx(ctx, key, ldctx, defaultVal)
oe.notifyHooks(ctx, key, ldctx, defaultVal, time.Since(start), detail, err)
return detail.Value, detail, err
}

/* * * STRING * * */

func (oe *ObservedEvaluator) StringVariation(key string, ldctx ldcontext.Context, defaultVal string) (string, error) {
_, detail, err := oe.StringVariationDetail(key, ldctx, defaultVal)
_, detail, err := oe.StringVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.StringValue(), err
}

func (oe *ObservedEvaluator) StringVariationDetail(key string, ldctx ldcontext.Context, defaultVal string) (string, ldreason.EvaluationDetail, error) {
_, detail, err := oe.StringVariationDetailCtx(oe.ctx, key, ldctx, defaultVal)
return detail.Value.StringValue(), detail, err
}

func (oe *ObservedEvaluator) StringVariationCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal string) (string, error) {
_, detail, err := oe.StringVariationDetailCtx(ctx, key, ldctx, defaultVal)
return detail.Value.StringValue(), err
}

func (oe *ObservedEvaluator) StringVariationDetailCtx(ctx context.Context, key string, ldctx ldcontext.Context, defaultVal string) (string, ldreason.EvaluationDetail, error) {
start := time.Now()
_, detail, err := oe.client.StringVariationDetail(key, ldctx, defaultVal)
oe.notifyHooks(key, ldctx, ldvalue.String(defaultVal), time.Since(start), detail, err)
_, detail, err := oe.client.StringVariationDetailCtx(ctx, key, ldctx, defaultVal)
oe.notifyHooks(ctx, key, ldctx, ldvalue.String(defaultVal), time.Since(start), detail, err)
return detail.Value.StringValue(), detail, err
}
2 changes: 1 addition & 1 deletion v6/wrapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"github.com/launchdarkly/go-sdk-common/v3/ldreason"
"github.com/launchdarkly/go-sdk-common/v3/lduser"
"github.com/launchdarkly/go-sdk-common/v3/ldvalue"
ld "github.com/launchdarkly/go-server-sdk/v6"
ld "github.com/launchdarkly/go-server-sdk/v7"

"github.com/nelz9999/goldhook/v6"
)
Expand Down

0 comments on commit 9c16530

Please sign in to comment.