Skip to content

Commit

Permalink
feat: impl callGetEvaluationAPI and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
S-H1129 authored and mura-s committed Apr 22, 2021
1 parent 0373abd commit cfcc6e2
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 76 deletions.
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
Expand All @@ -31,8 +32,8 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -58,7 +59,6 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
Expand All @@ -68,11 +68,9 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
25 changes: 16 additions & 9 deletions pkg/bucketeer/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,23 @@ import (
"go.opencensus.io/tag"
)


var (
registerOnce sync.Once
latencyMs = stats.Int64("bucketeer_latency_distribution", "bucketeer api latency in milliseconds", stats.UnitMilliseconds)
counter = stats.Int64("bucketeer_call_count", "bucketeer api call count", stats.UnitDimensionless)
latencyMs = stats.Int64(
"bucketeer_go_server_sdk_get_evaluation_latency_distribution",
"Get evaluation latency in milliseconds",
stats.UnitMilliseconds,
)
counter = stats.Int64(
"bucketeer_go_server_sdk_get_evaluation_call_count",
"Get evaluation call count",
stats.UnitDimensionless,
)
)

var (
KeyFeatureID = tag.MustNewKey("featureID")
KeyStatus = tag.MustNewKey("status")
keyFeatureID = tag.MustNewKey("featureID")
keyStatus = tag.MustNewKey("status")
)

func RegisterMetrics() error {
Expand All @@ -28,14 +35,14 @@ func RegisterMetrics() error {
Name: latencyMs.Name(),
Measure: latencyMs,
Description: latencyMs.Description(),
TagKeys: []tag.Key{KeyFeatureID, KeyStatus},
TagKeys: []tag.Key{keyFeatureID, keyStatus},
Aggregation: newLatencyDistribution(),
},
{
Name: counter.Name(),
Measure: counter,
Description: counter.Description(),
TagKeys: []tag.Key{KeyFeatureID, KeyStatus},
TagKeys: []tag.Key{keyFeatureID, keyStatus},
Aggregation: view.Count(),
},
}
Expand All @@ -54,10 +61,10 @@ func count(ctx context.Context) {
stats.Record(ctx, counter.M(1))
}

func NewContext(ctx context.Context, featureID string) (context.Context, error) {
func newMetricsContext(ctx context.Context, mutators []tag.Mutator) (context.Context, error) {
return tag.New(
ctx,
tag.Insert(KeyFeatureID, featureID),
mutators...,
)
}

Expand Down
32 changes: 32 additions & 0 deletions pkg/bucketeer/metrics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package bucketeer

import (
"context"
"github.com/stretchr/testify/assert"
"go.opencensus.io/stats/view"
"go.opencensus.io/tag"
"testing"
)

func TestRegisterMetrics(t *testing.T) {
assert.NoError(t, RegisterMetrics())
}

func TestNewMetricsContext(t *testing.T) {
expectedCtx, err := tag.New(context.Background(), tag.Insert(keyFeatureID, sdkFeatureID))
assert.NoError(t, err)

ctx := context.Background()
mutators := []tag.Mutator{
tag.Insert(keyFeatureID, sdkFeatureID),
}
ctx, err = newMetricsContext(ctx, mutators)
assert.NoError(t, err)

assert.Equal(t, expectedCtx, ctx)
}

func TestNewLatencyDistribution(t *testing.T){
expected := view.Distribution(25, 50, 100, 200, 400, 800, 1600, 3200, 6400).Buckets
assert.Equal(t, expected, newLatencyDistribution().Buckets)
}
48 changes: 31 additions & 17 deletions pkg/bucketeer/sdk.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,32 +219,49 @@ func (s *sdk) JSONVariation(ctx context.Context, user *User, featureID string, d
}

func (s *sdk) getEvaluation(ctx context.Context, user *User, featureID string) (*protofeature.Evaluation, error) {
ctx, err := NewContext(ctx, featureID)
if !user.Valid() {
return nil, fmt.Errorf("invalid user: %v", user)
}
req := &protogateway.GetEvaluationRequest{
Tag: s.tag,
User: user.User,
FeatureId: featureID,
}
res, err := s.callGetEvaluationAPI(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to generate new context: %w", err)
return nil, fmt.Errorf("failed to call get evaluation api: %w", err)
}
if err := s.validateGetEvaluationResponse(res, featureID); err != nil {
return nil, fmt.Errorf("invalid get evaluation response: %w", err)
}
return res.Evaluation, nil
}

func (s *sdk) callGetEvaluationAPI(
ctx context.Context,
req *protogateway.GetEvaluationRequest,
) (*protogateway.GetEvaluationResponse, error) {
var gserr error
reqStart := time.Now()
defer func() {
state := status.Code(err).String()
ctx, err := tag.New(ctx, tag.Insert(KeyStatus, state))
state := status.Code(gserr).String()
mutators := []tag.Mutator{
tag.Insert(keyFeatureID, req.FeatureId),
tag.Insert(keyStatus, state),
}
ctx, err := newMetricsContext(ctx, mutators)
if err != nil {
return
}

count(ctx)
measure(ctx, time.Since(reqStart))
}()
if !user.Valid() {
return nil, fmt.Errorf("invalid user: %v", user)
}
req := &protogateway.GetEvaluationRequest{
Tag: s.tag,
User: user.User,
FeatureId: featureID,
}

res, err := s.apiClient.GetEvaluation(ctx, req)
if err != nil || res == nil {
if status.Code(err) == codes.DeadlineExceeded {
gserr = err // set gRPC status error
if status.Code(gserr) == codes.DeadlineExceeded {
s.eventProcessor.PushTimeoutErrorCountMetricsEvent(ctx, s.tag)
} else {
s.eventProcessor.PushInternalErrorCountMetricsEvent(ctx, s.tag)
Expand All @@ -253,10 +270,7 @@ func (s *sdk) getEvaluation(ctx context.Context, user *User, featureID string) (
}
s.eventProcessor.PushGetEvaluationLatencyMetricsEvent(ctx, time.Since(reqStart), s.tag)
s.eventProcessor.PushGetEvaluationSizeMetricsEvent(ctx, proto.Size(res), s.tag)
if err := s.validateGetEvaluationResponse(res, featureID); err != nil {
return nil, fmt.Errorf("invalid get evaluation response: %w", err)
}
return res.Evaluation, nil
return res, nil
}

// Require res is not nil.
Expand Down
Loading

0 comments on commit cfcc6e2

Please sign in to comment.