Skip to content

Commit

Permalink
report tags from context
Browse files Browse the repository at this point in the history
  • Loading branch information
henrod committed Sep 11, 2018
1 parent af50924 commit 5bcf279
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 23 deletions.
9 changes: 9 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,15 @@ func GetDefaultLoggerFromCtx(ctx context.Context) logger.Logger {
return ctx.Value(constants.LoggerCtxKey).(logger.Logger)
}

// AddMetricTagsToPropagateCtx adds a key and metric tags that will
// be propagated through RPC calls
func AddMetricTagsToPropagateCtx(
ctx context.Context,
tags map[string]string,
) context.Context {
return pcontext.AddToPropagateCtx(ctx, constants.MetricTagsKey, tags)
}

// AddToPropagateCtx adds a key and value that will be propagated through RPC calls
func AddToPropagateCtx(ctx context.Context, key string, val interface{}) context.Context {
return pcontext.AddToPropagateCtx(ctx, key, val)
Expand Down
12 changes: 12 additions & 0 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,18 @@ func TestGetSessionFromCtx(t *testing.T) {
assert.Equal(t, ss, s)
}

func TestAddMetricTagsToPropagateCtx(t *testing.T) {
ctx := AddMetricTagsToPropagateCtx(context.Background(), map[string]string{
"key": "value",
})
val := ctx.Value(constants.PropagateCtxKey)
assert.Equal(t, map[string]interface{}{
constants.MetricTagsKey: map[string]string{
"key": "value",
},
}, val)
}

func TestAddToPropagateCtx(t *testing.T) {
ctx := AddToPropagateCtx(context.Background(), "key", "val")
val := ctx.Value(constants.PropagateCtxKey)
Expand Down
4 changes: 4 additions & 0 deletions constants/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,7 @@ var StartTimeKey = "req-start-time"

// RouteKey is the key holding the request route to be sent over the context
var RouteKey = "req-route"

// MetricTagsKey is the key holding request tags to be sent over the context
// to be reported
var MetricTagsKey = "metric-tags"
30 changes: 26 additions & 4 deletions metrics/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ func ReportTimingFromCtx(ctx context.Context, reporters []Reporter, typ string,
startTime := pcontext.GetFromPropagateCtx(ctx, constants.StartTimeKey)
route := pcontext.GetFromPropagateCtx(ctx, constants.RouteKey)
elapsed := time.Since(time.Unix(0, startTime.(int64)))
tags := map[string]string{
tags := getTags(ctx, map[string]string{
"route": route.(string),
"status": status,
"type": typ,
}
})
for _, r := range reporters {
r.ReportSummary(ResponseTime, tags, float64(elapsed.Nanoseconds()))
}
Expand All @@ -56,10 +56,10 @@ func ReportMessageProcessDelayFromCtx(ctx context.Context, reporters []Reporter,
startTime := pcontext.GetFromPropagateCtx(ctx, constants.StartTimeKey)
elapsed := time.Since(time.Unix(0, startTime.(int64)))
route := pcontext.GetFromPropagateCtx(ctx, constants.RouteKey)
tags := map[string]string{
tags := getTags(ctx, map[string]string{
"route": route.(string),
"type": typ,
}
})
for _, r := range reporters {
r.ReportSummary(ProcessDelay, tags, float64(elapsed.Nanoseconds()))
}
Expand Down Expand Up @@ -89,3 +89,25 @@ func ReportSysMetrics(reporters []Reporter, period time.Duration) {
time.Sleep(period)
}
}

func tagsFromContext(ctx context.Context) map[string]string {
val := pcontext.GetFromPropagateCtx(ctx, constants.MetricTagsKey)
if val == nil {
return map[string]string{}
}

tags, ok := val.(map[string]string)
if !ok {
return map[string]string{}
}

return tags
}

func getTags(ctx context.Context, tags map[string]string) map[string]string {
for k, v := range tagsFromContext(ctx) {
tags[k] = v
}

return tags
}
118 changes: 99 additions & 19 deletions metrics/report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,103 @@ import (
)

func TestReportTimingFromCtx(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsReporter := mocks.NewMockReporter(ctrl)

originalTs := time.Now().UnixNano()
expectedRoute := uuid.New().String()
expectedType := uuid.New().String()
expectedErrored := true
ctx := pcontext.AddToPropagateCtx(context.Background(), constants.StartTimeKey, originalTs)
ctx = pcontext.AddToPropagateCtx(ctx, constants.RouteKey, expectedRoute)

time.Sleep(200 * time.Millisecond) // to test duration report
mockMetricsReporter.EXPECT().ReportSummary(ResponseTime, gomock.Any(), gomock.Any()).Do(
func(metric string, tags map[string]string, duration float64) {
assert.InDelta(t, duration, time.Now().UnixNano()-originalTs, 10e6)
},
)

ReportTimingFromCtx(ctx, []Reporter{mockMetricsReporter}, expectedType, expectedErrored)
t.Run("test-duration", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsReporter := mocks.NewMockReporter(ctrl)

originalTs := time.Now().UnixNano()
expectedRoute := uuid.New().String()
expectedType := uuid.New().String()
expectedErrored := true
ctx := pcontext.AddToPropagateCtx(context.Background(), constants.StartTimeKey, originalTs)
ctx = pcontext.AddToPropagateCtx(ctx, constants.RouteKey, expectedRoute)

time.Sleep(200 * time.Millisecond) // to test duration report
mockMetricsReporter.EXPECT().ReportSummary(ResponseTime, gomock.Any(), gomock.Any()).Do(
func(metric string, tags map[string]string, duration float64) {
assert.InDelta(t, duration, time.Now().UnixNano()-originalTs, 10e6)
},
)

ReportTimingFromCtx(ctx, []Reporter{mockMetricsReporter}, expectedType, expectedErrored)
})

t.Run("test-tags", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsReporter := mocks.NewMockReporter(ctrl)

originalTs := time.Now().UnixNano()
expectedRoute := uuid.New().String()
expectedType := uuid.New().String()
expectedErrored := false
ctx := pcontext.AddToPropagateCtx(context.Background(), constants.StartTimeKey, originalTs)
ctx = pcontext.AddToPropagateCtx(ctx, constants.RouteKey, expectedRoute)
ctx = pcontext.AddToPropagateCtx(ctx, constants.MetricTagsKey, map[string]string{
"key": "value",
})

expectedTags := map[string]string{
"route": expectedRoute,
"status": "ok",
"type": expectedType,
"key": "value",
}

mockMetricsReporter.EXPECT().ReportSummary(ResponseTime, expectedTags, gomock.Any())

ReportTimingFromCtx(ctx, []Reporter{mockMetricsReporter}, expectedType, expectedErrored)
})

t.Run("test-tags-not-correct-type", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsReporter := mocks.NewMockReporter(ctrl)

originalTs := time.Now().UnixNano()
expectedRoute := uuid.New().String()
expectedType := uuid.New().String()
expectedErrored := false
ctx := pcontext.AddToPropagateCtx(context.Background(), constants.StartTimeKey, originalTs)
ctx = pcontext.AddToPropagateCtx(ctx, constants.RouteKey, expectedRoute)
ctx = pcontext.AddToPropagateCtx(ctx, constants.MetricTagsKey, "not-map")

expectedTags := map[string]string{
"route": expectedRoute,
"status": "ok",
"type": expectedType,
}

mockMetricsReporter.EXPECT().ReportSummary(ResponseTime, expectedTags, gomock.Any())

ReportTimingFromCtx(ctx, []Reporter{mockMetricsReporter}, expectedType, expectedErrored)
})
}

func TestReportMessageProcessDelayFromCtx(t *testing.T) {
t.Run("test-tags", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockMetricsReporter := mocks.NewMockReporter(ctrl)

originalTs := time.Now().UnixNano()
expectedRoute := uuid.New().String()
expectedType := uuid.New().String()
ctx := pcontext.AddToPropagateCtx(context.Background(), constants.StartTimeKey, originalTs)
ctx = pcontext.AddToPropagateCtx(ctx, constants.RouteKey, expectedRoute)
ctx = pcontext.AddToPropagateCtx(ctx, constants.MetricTagsKey, map[string]string{
"key": "value",
})

expectedTags := map[string]string{
"route": expectedRoute,
"type": expectedType,
"key": "value",
}

mockMetricsReporter.EXPECT().ReportSummary(ProcessDelay, expectedTags, gomock.Any())

ReportMessageProcessDelayFromCtx(ctx, []Reporter{mockMetricsReporter}, expectedType)
})
}

0 comments on commit 5bcf279

Please sign in to comment.