From 48ac237560d304d49202d8bb6a77a081d8a0ce67 Mon Sep 17 00:00:00 2001 From: James DeFelice Date: Wed, 14 Jun 2017 13:40:57 +0000 Subject: [PATCH] rule/metrics: optimize default metric labels for events and calls --- api/v1/cmd/example-scheduler/app/app.go | 4 +- api/v1/lib/extras/executor/callrules/gen.go | 2 +- .../executor/callrules/metrics_generated.go | 32 +++++++++++-- .../callrules/metrics_generated_test.go | 4 +- api/v1/lib/extras/executor/eventrules/gen.go | 2 +- .../executor/eventrules/metrics_generated.go | 32 +++++++++++-- .../eventrules/metrics_generated_test.go | 4 +- api/v1/lib/extras/gen/rule_metrics.go | 45 ++++++++++++++++--- api/v1/lib/extras/scheduler/callrules/gen.go | 2 +- .../scheduler/callrules/metrics_generated.go | 32 +++++++++++-- .../callrules/metrics_generated_test.go | 4 +- api/v1/lib/extras/scheduler/eventrules/gen.go | 2 +- .../scheduler/eventrules/metrics_generated.go | 32 +++++++++++-- .../eventrules/metrics_generated_test.go | 4 +- 14 files changed, 165 insertions(+), 36 deletions(-) diff --git a/api/v1/cmd/example-scheduler/app/app.go b/api/v1/cmd/example-scheduler/app/app.go index a2332fdf..d4b29926 100644 --- a/api/v1/cmd/example-scheduler/app/app.go +++ b/api/v1/cmd/example-scheduler/app/app.go @@ -287,7 +287,7 @@ func eventMetrics(metricsAPI *metricsAPI, clock func() time.Time, timingMetrics timed = nil } harness := xmetrics.NewHarness(metricsAPI.eventReceivedCount, metricsAPI.eventErrorCount, timed, clock) - return eventrules.Metrics(harness) + return eventrules.Metrics(harness, nil) } // callMetrics logs metrics for every outgoing Mesos call @@ -297,7 +297,7 @@ func callMetrics(metricsAPI *metricsAPI, clock func() time.Time, timingMetrics b timed = nil } harness := xmetrics.NewHarness(metricsAPI.callCount, metricsAPI.callErrorCount, timed, clock) - return callrules.Metrics(harness) + return callrules.Metrics(harness, nil) } // logCalls logs a specific message string when a particular call-type is observed diff --git a/api/v1/lib/extras/executor/callrules/gen.go b/api/v1/lib/extras/executor/callrules/gen.go index fc6ee423..521598a8 100644 --- a/api/v1/lib/extras/executor/callrules/gen.go +++ b/api/v1/lib/extras/executor/callrules/gen.go @@ -4,4 +4,4 @@ package callrules //go:generate go run ../../gen/rule_callers.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/executor -import github.com/mesos/mesos-go/api/v1/lib/executor/calls -type E:*executor.Call -type C:calls.Caller -type CF:calls.CallerFunc -output callers_generated.go -//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Call:&executor.Call{} -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go +//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Call:&executor.Call{} -type ET:executor.Call_Type -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go diff --git a/api/v1/lib/extras/executor/callrules/metrics_generated.go b/api/v1/lib/extras/executor/callrules/metrics_generated.go index 642b6ab8..7e716804 100644 --- a/api/v1/lib/extras/executor/callrules/metrics_generated.go +++ b/api/v1/lib/extras/executor/callrules/metrics_generated.go @@ -1,10 +1,11 @@ package callrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Call:&executor.Call{} -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Call:&executor.Call{} -type ET:executor.Call_Type -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( "context" + "strings" "github.com/mesos/mesos-go/api/v1/lib/extras/metrics" @@ -13,13 +14,36 @@ import ( "github.com/mesos/mesos-go/api/v1/lib/executor" ) -func Metrics(harness metrics.Harness) Rule { +// Labeler generates a set of strings that should be associated with metrics that are generated for the given event. +type Labeler func(ctx context.Context, e *executor.Call) []string + +var defaultLabels = func() map[executor.Call_Type][]string { + m := make(map[executor.Call_Type][]string) + for k, v := range executor.Call_Type_name { + m[executor.Call_Type(k)] = []string{strings.ToLower(v)} + } + return m +}() + +func defaultLabeler(ctx context.Context, e *executor.Call) []string { + return defaultLabels[e.GetType()] +} + +// Metrics generates a Rule that invokes the given harness for each event, using the labels generated by the Labeler. +// Panics if harness or labeler is nil. +func Metrics(harness metrics.Harness, labeler Labeler) Rule { + if harness == nil { + panic("harness is a required parameter") + } + if labeler == nil { + labeler = defaultLabeler + } return func(ctx context.Context, e *executor.Call, z mesos.Response, err error, ch Chain) (context.Context, *executor.Call, mesos.Response, error) { - typename := strings.ToLower(e.GetType().String()) + labels := labeler(ctx, e) harness(func() error { ctx, e, z, err = ch(ctx, e, z, err) return err - }, typename) + }, labels...) return ctx, e, z, err } } diff --git a/api/v1/lib/extras/executor/callrules/metrics_generated_test.go b/api/v1/lib/extras/executor/callrules/metrics_generated_test.go index 8a19f930..04d41bc2 100644 --- a/api/v1/lib/extras/executor/callrules/metrics_generated_test.go +++ b/api/v1/lib/extras/executor/callrules/metrics_generated_test.go @@ -1,6 +1,6 @@ package callrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Call:&executor.Call{} -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Call:&executor.Call{} -type ET:executor.Call_Type -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( @@ -23,7 +23,7 @@ func TestMetrics(t *testing.T) { i++ return f() } - r = Metrics(h) + r = Metrics(h, func(_ context.Context, _ *executor.Call) []string { return nil }) ) var zp = &mesos.ResponseWrapper{} for ti, tc := range []struct { diff --git a/api/v1/lib/extras/executor/eventrules/gen.go b/api/v1/lib/extras/executor/eventrules/gen.go index 25b0086b..d17240e1 100644 --- a/api/v1/lib/extras/executor/eventrules/gen.go +++ b/api/v1/lib/extras/executor/eventrules/gen.go @@ -4,4 +4,4 @@ package eventrules //go:generate go run ../../gen/rule_handlers.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/executor -import github.com/mesos/mesos-go/api/v1/lib/executor/events -type E:*executor.Event -type H:events.Handler -type HF:events.HandlerFunc -output handlers_generated.go -//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Event:&executor.Event{} -output metrics_generated.go +//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Event:&executor.Event{} -type ET:executor.Event_Type -output metrics_generated.go diff --git a/api/v1/lib/extras/executor/eventrules/metrics_generated.go b/api/v1/lib/extras/executor/eventrules/metrics_generated.go index 921b08b2..d85f4f57 100644 --- a/api/v1/lib/extras/executor/eventrules/metrics_generated.go +++ b/api/v1/lib/extras/executor/eventrules/metrics_generated.go @@ -1,10 +1,11 @@ package eventrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Event:&executor.Event{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Event:&executor.Event{} -type ET:executor.Event_Type -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( "context" + "strings" "github.com/mesos/mesos-go/api/v1/lib/extras/metrics" @@ -12,13 +13,36 @@ import ( "github.com/mesos/mesos-go/api/v1/lib/executor" ) -func Metrics(harness metrics.Harness) Rule { +// Labeler generates a set of strings that should be associated with metrics that are generated for the given event. +type Labeler func(ctx context.Context, e *executor.Event) []string + +var defaultLabels = func() map[executor.Event_Type][]string { + m := make(map[executor.Event_Type][]string) + for k, v := range executor.Event_Type_name { + m[executor.Event_Type(k)] = []string{strings.ToLower(v)} + } + return m +}() + +func defaultLabeler(ctx context.Context, e *executor.Event) []string { + return defaultLabels[e.GetType()] +} + +// Metrics generates a Rule that invokes the given harness for each event, using the labels generated by the Labeler. +// Panics if harness or labeler is nil. +func Metrics(harness metrics.Harness, labeler Labeler) Rule { + if harness == nil { + panic("harness is a required parameter") + } + if labeler == nil { + labeler = defaultLabeler + } return func(ctx context.Context, e *executor.Event, err error, ch Chain) (context.Context, *executor.Event, error) { - typename := strings.ToLower(e.GetType().String()) + labels := labeler(ctx, e) harness(func() error { ctx, e, err = ch(ctx, e, err) return err - }, typename) + }, labels...) return ctx, e, err } } diff --git a/api/v1/lib/extras/executor/eventrules/metrics_generated_test.go b/api/v1/lib/extras/executor/eventrules/metrics_generated_test.go index 6bd01c8c..b51fd90f 100644 --- a/api/v1/lib/extras/executor/eventrules/metrics_generated_test.go +++ b/api/v1/lib/extras/executor/eventrules/metrics_generated_test.go @@ -1,6 +1,6 @@ package eventrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Event:&executor.Event{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib/executor -type E:*executor.Event:&executor.Event{} -type ET:executor.Event_Type -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( @@ -22,7 +22,7 @@ func TestMetrics(t *testing.T) { i++ return f() } - r = Metrics(h) + r = Metrics(h, func(_ context.Context, _ *executor.Event) []string { return nil }) ) for ti, tc := range []struct { ctx context.Context diff --git a/api/v1/lib/extras/gen/rule_metrics.go b/api/v1/lib/extras/gen/rule_metrics.go index 316b4c53..dafc66e1 100644 --- a/api/v1/lib/extras/gen/rule_metrics.go +++ b/api/v1/lib/extras/gen/rule_metrics.go @@ -18,22 +18,55 @@ var metricsTemplate = template.Must(template.New("").Parse(`package {{.Package}} import ( "context" +{{if .Type "ET"}} "strings" - +{{end}} "github.com/mesos/mesos-go/api/v1/lib/extras/metrics" {{range .Imports}} {{ printf "%q" . -}} {{end}} ) -{{.RequireType "E" -}}{{/* type E should have a GetType() func that returns an object w/ a String() func */ -}} -func Metrics(harness metrics.Harness) Rule { +{{.RequireType "E" -}} + +// Labeler generates a set of strings that should be associated with metrics that are generated for the given event. +type Labeler func(ctx context.Context, e {{.Type "E"}}) []string + +{{if .Type "ET" -}} +var defaultLabels = func() map[{{.Type "ET"}}][]string { + m := make(map[{{.Type "ET"}}][]string) + for k, v := range {{.Type "ET"}}_name { + m[{{.Type "ET"}}(k)] = []string{strings.ToLower(v)} + } + return m +}() + +func defaultLabeler(ctx context.Context, e {{.Type "E"}}) []string { + return defaultLabels[e.GetType()] +} + +{{end -}} +// Metrics generates a Rule that invokes the given harness for each event, using the labels generated by the Labeler. +// Panics if harness {{if .Type "ET"}}or labeler {{end}}is nil. +func Metrics(harness metrics.Harness, labeler Labeler) Rule { + if harness == nil { + panic("harness is a required parameter") + } + {{if .Type "ET" -}} + if labeler == nil { + labeler = defaultLabeler + } + {{else -}} + if labeler == nil { + panic("labeler is a required parameter") + } + {{end -}} return func(ctx context.Context, e {{.Type "E"}}, {{.Arg "Z" "z," -}} err error, ch Chain) (context.Context, {{.Type "E"}}, {{.Arg "Z" "," -}} error) { - typename := strings.ToLower(e.GetType().String()) + labels := labeler(ctx, e) harness(func() error { ctx, e, {{.Ref "Z" "z," -}} err = ch(ctx, e, {{.Ref "Z" "z," -}} err) return err - }, typename) + }, labels...) return ctx, e, {{.Ref "Z" "z," -}} err } } @@ -67,7 +100,7 @@ func TestMetrics(t *testing.T) { i++ return f() } - r = Metrics(h) + r = Metrics(h, func(_ context.Context, _ {{.Type "E"}}) []string { return nil }) ) {{if .Type "Z" -}} var zp = {{.Prototype "Z"}} diff --git a/api/v1/lib/extras/scheduler/callrules/gen.go b/api/v1/lib/extras/scheduler/callrules/gen.go index 844b927a..da4fde28 100644 --- a/api/v1/lib/extras/scheduler/callrules/gen.go +++ b/api/v1/lib/extras/scheduler/callrules/gen.go @@ -4,4 +4,4 @@ package callrules //go:generate go run ../../gen/rule_callers.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/scheduler -import github.com/mesos/mesos-go/api/v1/lib/scheduler/calls -type E:*scheduler.Call -type C:calls.Caller -type CF:calls.CallerFunc -output callers_generated.go -//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Call:&scheduler.Call{} -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go +//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Call:&scheduler.Call{} -type ET:scheduler.Call_Type -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go diff --git a/api/v1/lib/extras/scheduler/callrules/metrics_generated.go b/api/v1/lib/extras/scheduler/callrules/metrics_generated.go index 7010022c..df31d228 100644 --- a/api/v1/lib/extras/scheduler/callrules/metrics_generated.go +++ b/api/v1/lib/extras/scheduler/callrules/metrics_generated.go @@ -1,10 +1,11 @@ package callrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Call:&scheduler.Call{} -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Call:&scheduler.Call{} -type ET:scheduler.Call_Type -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( "context" + "strings" "github.com/mesos/mesos-go/api/v1/lib/extras/metrics" @@ -13,13 +14,36 @@ import ( "github.com/mesos/mesos-go/api/v1/lib/scheduler" ) -func Metrics(harness metrics.Harness) Rule { +// Labeler generates a set of strings that should be associated with metrics that are generated for the given event. +type Labeler func(ctx context.Context, e *scheduler.Call) []string + +var defaultLabels = func() map[scheduler.Call_Type][]string { + m := make(map[scheduler.Call_Type][]string) + for k, v := range scheduler.Call_Type_name { + m[scheduler.Call_Type(k)] = []string{strings.ToLower(v)} + } + return m +}() + +func defaultLabeler(ctx context.Context, e *scheduler.Call) []string { + return defaultLabels[e.GetType()] +} + +// Metrics generates a Rule that invokes the given harness for each event, using the labels generated by the Labeler. +// Panics if harness or labeler is nil. +func Metrics(harness metrics.Harness, labeler Labeler) Rule { + if harness == nil { + panic("harness is a required parameter") + } + if labeler == nil { + labeler = defaultLabeler + } return func(ctx context.Context, e *scheduler.Call, z mesos.Response, err error, ch Chain) (context.Context, *scheduler.Call, mesos.Response, error) { - typename := strings.ToLower(e.GetType().String()) + labels := labeler(ctx, e) harness(func() error { ctx, e, z, err = ch(ctx, e, z, err) return err - }, typename) + }, labels...) return ctx, e, z, err } } diff --git a/api/v1/lib/extras/scheduler/callrules/metrics_generated_test.go b/api/v1/lib/extras/scheduler/callrules/metrics_generated_test.go index bbf40e17..13ec903d 100644 --- a/api/v1/lib/extras/scheduler/callrules/metrics_generated_test.go +++ b/api/v1/lib/extras/scheduler/callrules/metrics_generated_test.go @@ -1,6 +1,6 @@ package callrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Call:&scheduler.Call{} -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Call:&scheduler.Call{} -type ET:scheduler.Call_Type -type Z:mesos.Response:&mesos.ResponseWrapper{} -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( @@ -23,7 +23,7 @@ func TestMetrics(t *testing.T) { i++ return f() } - r = Metrics(h) + r = Metrics(h, func(_ context.Context, _ *scheduler.Call) []string { return nil }) ) var zp = &mesos.ResponseWrapper{} for ti, tc := range []struct { diff --git a/api/v1/lib/extras/scheduler/eventrules/gen.go b/api/v1/lib/extras/scheduler/eventrules/gen.go index 623de0e3..8b668346 100644 --- a/api/v1/lib/extras/scheduler/eventrules/gen.go +++ b/api/v1/lib/extras/scheduler/eventrules/gen.go @@ -4,4 +4,4 @@ package eventrules //go:generate go run ../../gen/rule_handlers.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/scheduler -import github.com/mesos/mesos-go/api/v1/lib/scheduler/events -type E:*scheduler.Event -type H:events.Handler -type HF:events.HandlerFunc -output handlers_generated.go -//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Event:&scheduler.Event{} -output metrics_generated.go +//go:generate go run ../../gen/rule_metrics.go ../../gen/gen.go -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Event:&scheduler.Event{} -type ET:scheduler.Event_Type -output metrics_generated.go diff --git a/api/v1/lib/extras/scheduler/eventrules/metrics_generated.go b/api/v1/lib/extras/scheduler/eventrules/metrics_generated.go index abe43ab1..dfe1bdb8 100644 --- a/api/v1/lib/extras/scheduler/eventrules/metrics_generated.go +++ b/api/v1/lib/extras/scheduler/eventrules/metrics_generated.go @@ -1,10 +1,11 @@ package eventrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Event:&scheduler.Event{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Event:&scheduler.Event{} -type ET:scheduler.Event_Type -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( "context" + "strings" "github.com/mesos/mesos-go/api/v1/lib/extras/metrics" @@ -12,13 +13,36 @@ import ( "github.com/mesos/mesos-go/api/v1/lib/scheduler" ) -func Metrics(harness metrics.Harness) Rule { +// Labeler generates a set of strings that should be associated with metrics that are generated for the given event. +type Labeler func(ctx context.Context, e *scheduler.Event) []string + +var defaultLabels = func() map[scheduler.Event_Type][]string { + m := make(map[scheduler.Event_Type][]string) + for k, v := range scheduler.Event_Type_name { + m[scheduler.Event_Type(k)] = []string{strings.ToLower(v)} + } + return m +}() + +func defaultLabeler(ctx context.Context, e *scheduler.Event) []string { + return defaultLabels[e.GetType()] +} + +// Metrics generates a Rule that invokes the given harness for each event, using the labels generated by the Labeler. +// Panics if harness or labeler is nil. +func Metrics(harness metrics.Harness, labeler Labeler) Rule { + if harness == nil { + panic("harness is a required parameter") + } + if labeler == nil { + labeler = defaultLabeler + } return func(ctx context.Context, e *scheduler.Event, err error, ch Chain) (context.Context, *scheduler.Event, error) { - typename := strings.ToLower(e.GetType().String()) + labels := labeler(ctx, e) harness(func() error { ctx, e, err = ch(ctx, e, err) return err - }, typename) + }, labels...) return ctx, e, err } } diff --git a/api/v1/lib/extras/scheduler/eventrules/metrics_generated_test.go b/api/v1/lib/extras/scheduler/eventrules/metrics_generated_test.go index 06095745..b4c87b59 100644 --- a/api/v1/lib/extras/scheduler/eventrules/metrics_generated_test.go +++ b/api/v1/lib/extras/scheduler/eventrules/metrics_generated_test.go @@ -1,6 +1,6 @@ package eventrules -// go generate -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Event:&scheduler.Event{} -output metrics_generated.go +// go generate -import github.com/mesos/mesos-go/api/v1/lib/scheduler -type E:*scheduler.Event:&scheduler.Event{} -type ET:scheduler.Event_Type -output metrics_generated.go // GENERATED CODE FOLLOWS; DO NOT EDIT. import ( @@ -22,7 +22,7 @@ func TestMetrics(t *testing.T) { i++ return f() } - r = Metrics(h) + r = Metrics(h, func(_ context.Context, _ *scheduler.Event) []string { return nil }) ) for ti, tc := range []struct { ctx context.Context