event: separate metric types with Record methods
This is an alternative to having metrics as builders. Instead we use
the same builder for everything, but BuilderMetric takes a type that
is a pair of a Metric and Value. These pairs are created by the Record
metric of each Metric type.
This has the main advantage of separate builders -- typed metric
values -- without the downsides of repeated code, both in the
implementation and the client.
Change-Id: I8d39880b364975416e6fe94f6545fd3fe201aa61
Reviewed-on: https://go-review.googlesource.com/c/exp/+/326390
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/event/bench/event_test.go b/event/bench/event_test.go
index 637c621..07d45a8 100644
--- a/event/bench/event_test.go
+++ b/event/bench/event_test.go
@@ -71,14 +71,14 @@
gauge = event.NewFloatGauge("gauge")
eventMetric = Hooks{
AStart: func(ctx context.Context, a int) context.Context {
- gauge.To(ctx).With(aStat.Of(a)).Record(1)
- gauge.To(ctx).With(aCount.Of(1)).Record(1)
+ event.To(ctx).With(aStat.Of(a)).Metric(gauge.Record(1))
+ event.To(ctx).With(aCount.Of(1)).Metric(gauge.Record(1))
return ctx
},
AEnd: func(ctx context.Context) {},
BStart: func(ctx context.Context, b string) context.Context {
- gauge.To(ctx).With(bLength.Of(len(b))).Record(1)
- gauge.To(ctx).With(bCount.Of(1)).Record(1)
+ event.To(ctx).With(bLength.Of(len(b))).Metric(gauge.Record(1))
+ event.To(ctx).With(bCount.Of(1)).Metric(gauge.Record(1))
return ctx
},
BEnd: func(ctx context.Context) {},
diff --git a/event/builder.go b/event/builder.go
index 5b14267..6966078 100644
--- a/event/builder.go
+++ b/event/builder.go
@@ -185,35 +185,23 @@
b.done()
}
-// Metric is a helper that calls Deliver with MetricKind.
-// func (b Builder) Metric(m *Metric, value Value) {
-// if b.data == nil {
-// return
-// }
-// checkValid(b.data, b.builderID)
-// if b.data.exporter.metricsEnabled() {
-// b.data.exporter.mu.Lock()
-// defer b.data.exporter.mu.Unlock()
-// if b.data.Event.Namespace == "" {
-// b.data.Event.Namespace = m.Namespace()
-// }
-// b.data.Event.Labels = append(b.data.Event.Labels, MetricValue.Of(value), MetricKey.Of(ValueOf(m)))
-// b.data.exporter.prepare(&b.data.Event)
-// b.data.exporter.handler.Metric(b.ctx, &b.data.Event)
-// }
-// b.done()
-// }
-
-// func (b Builder) Count(m *Metric) {
-// if m.Kind() != Counter {
-// panic("Builder.Count called on non-counter")
-// }
-// b.Metric(m, Int64Of(1))
-// }
-
-// func (b Builder) Since(m *Metric, start time.Time) {
-// b.Metric(m, DurationOf(time.Since(start)))
-// }
+func (b Builder) Metric(mv MetricValue) {
+ if b.data == nil {
+ return
+ }
+ checkValid(b.data, b.builderID)
+ if b.data.exporter.metricsEnabled() {
+ b.data.exporter.mu.Lock()
+ defer b.data.exporter.mu.Unlock()
+ if b.data.Event.Namespace == "" {
+ b.data.Event.Namespace = mv.m.Descriptor().Namespace()
+ }
+ b.data.Event.Labels = append(b.data.Event.Labels, MetricVal.Of(mv.v), MetricKey.Of(ValueOf(mv.m)))
+ b.data.exporter.prepare(&b.data.Event)
+ b.data.exporter.handler.Metric(b.ctx, &b.data.Event)
+ }
+ b.done()
+}
// Annotate is a helper that calls Deliver with AnnotateKind.
func (b Builder) Annotate() {
diff --git a/event/common.go b/event/common.go
index f7b426e..2d58a94 100644
--- a/event/common.go
+++ b/event/common.go
@@ -9,7 +9,7 @@
const Trace = traceKey("trace")
const End = tagKey("end")
const MetricKey = valueKey("metric")
-const MetricValue = valueKey("metricValue")
+const MetricVal = valueKey("metricValue")
type stringKey string
type traceKey string
diff --git a/event/common_test.go b/event/common_test.go
index 6470f1f..27764df 100644
--- a/event/common_test.go
+++ b/event/common_test.go
@@ -25,7 +25,7 @@
checkFind(t, h, "Log", event.Message, true, simple)
checkFind(t, h, "Log", event.Name, false, "")
- m.To(ctx).Record(3)
+ event.To(ctx).Metric(m.Record(3))
checkFind(t, h, "Metric", event.Message, false, "")
checkFind(t, h, "Metric", event.Name, false, "")
diff --git a/event/event_test.go b/event/event_test.go
index 210f29c..1656e56 100644
--- a/event/event_test.go
+++ b/event/event_test.go
@@ -76,16 +76,16 @@
time=2020-03-05T14:27:52 parent=1 end
`}, {
name: "counter",
- events: func(ctx context.Context) { counter.To(ctx).With(l1).Record(2) },
+ events: func(ctx context.Context) { event.To(ctx).With(l1).Metric(counter.Record(2)) },
expect: `time=2020-03-05T14:27:48 l1=1 metricValue=2 metric=Metric("golang.org/x/exp/event_test/hits")`,
}, {
name: "gauge",
- events: func(ctx context.Context) { gauge.To(ctx).With(l1).Record(98.6) },
+ events: func(ctx context.Context) { event.To(ctx).With(l1).Metric(gauge.Record(98.6)) },
expect: `time=2020-03-05T14:27:48 l1=1 metricValue=98.6 metric=Metric("golang.org/x/exp/event_test/temperature")`,
}, {
name: "duration",
events: func(ctx context.Context) {
- latency.To(ctx).With(l1).With(l2).Record(3 * time.Second)
+ event.To(ctx).With(l1).With(l2).Metric(latency.Record(3 * time.Second))
},
expect: `time=2020-03-05T14:27:48 l1=1 l2=2 metricValue=3s metric=Metric("golang.org/x/exp/event_test/latency")`,
}, {
diff --git a/event/metric.go b/event/metric.go
index 15861b3..9ca35c8 100644
--- a/event/metric.go
+++ b/event/metric.go
@@ -5,7 +5,6 @@
package event
import (
- "context"
"fmt"
"time"
)
@@ -54,8 +53,8 @@
return m
}
-func (m *MetricDescriptor) Name() string { return m.name }
-func (m *MetricDescriptor) Namespace() string { return m.namespace }
+func (m MetricDescriptor) Name() string { return m.name }
+func (m MetricDescriptor) Namespace() string { return m.namespace }
// A counter is a metric that counts something cumulatively.
type Counter struct {
@@ -70,47 +69,13 @@
return c.MetricDescriptor
}
-func (c *Counter) To(ctx context.Context) CounterBuilder {
- b := CounterBuilder{builderCommon: builderCommon{ctx: ctx}, c: c}
- b.data = newBuilder(ctx)
- if b.data != nil {
- b.builderID = b.data.id
- }
- return b
+type MetricValue struct {
+ m Metric
+ v Value
}
-type CounterBuilder struct {
- builderCommon
- c *Counter
-}
-
-func (b CounterBuilder) With(label Label) CounterBuilder {
- b.addLabel(label)
- return b
-}
-
-func (b CounterBuilder) WithAll(labels ...Label) CounterBuilder {
- b.addLabels(labels)
- return b
-}
-
-func (b CounterBuilder) Record(v uint64) {
- record(b.builderCommon, b.c, Uint64Of(v))
-}
-
-func record(b builderCommon, m Metric, v Value) {
- if b.data == nil {
- return
- }
- checkValid(b.data, b.builderID)
- if b.data.exporter.metricsEnabled() {
- b.data.exporter.mu.Lock()
- defer b.data.exporter.mu.Unlock()
- b.data.Event.Labels = append(b.data.Event.Labels, MetricValue.Of(v), MetricKey.Of(ValueOf(m)))
- b.data.exporter.prepare(&b.data.Event)
- b.data.exporter.handler.Metric(b.ctx, &b.data.Event)
- }
- b.done()
+func (c *Counter) Record(v uint64) MetricValue {
+ return MetricValue{c, Uint64Of(v)}
}
// A FloatGauge records a single floating-point value that may go up or down.
@@ -127,32 +92,8 @@
return g.MetricDescriptor
}
-func (g *FloatGauge) To(ctx context.Context) FloatGaugeBuilder {
- b := FloatGaugeBuilder{builderCommon: builderCommon{ctx: ctx}, g: g}
- b.data = newBuilder(ctx)
- if b.data != nil {
- b.builderID = b.data.id
- }
- return b
-}
-
-type FloatGaugeBuilder struct {
- builderCommon
- g *FloatGauge
-}
-
-func (b FloatGaugeBuilder) With(label Label) FloatGaugeBuilder {
- b.addLabel(label)
- return b
-}
-
-func (b FloatGaugeBuilder) WithAll(labels ...Label) FloatGaugeBuilder {
- b.addLabels(labels)
- return b
-}
-
-func (b FloatGaugeBuilder) Record(v float64) {
- record(b.builderCommon, b.g, Float64Of(v))
+func (g *FloatGauge) Record(v float64) MetricValue {
+ return MetricValue{g, Float64Of(v)}
}
// A Duration records a distribution of durations.
@@ -169,30 +110,6 @@
return d.MetricDescriptor
}
-func (d *Duration) To(ctx context.Context) DurationBuilder {
- b := DurationBuilder{builderCommon: builderCommon{ctx: ctx}, d: d}
- b.data = newBuilder(ctx)
- if b.data != nil {
- b.builderID = b.data.id
- }
- return b
-}
-
-type DurationBuilder struct {
- builderCommon
- d *Duration
-}
-
-func (b DurationBuilder) With(label Label) DurationBuilder {
- b.addLabel(label)
- return b
-}
-
-func (b DurationBuilder) WithAll(labels ...Label) DurationBuilder {
- b.addLabels(labels)
- return b
-}
-
-func (b DurationBuilder) Record(v time.Duration) {
- record(b.builderCommon, b.d, DurationOf(v))
+func (d *Duration) Record(v time.Duration) MetricValue {
+ return MetricValue{d, DurationOf(v)}
}