event: add NopHandler

Add a no-op handler for tests and embedding.

The spelling "Nop" is used by the standard library: ioutil.NopCloser, for
example.

Change-Id: I28cb44ff05943c0a0cea0a5a7280b3cc75e67446
Reviewed-on: https://go-review.googlesource.com/c/exp/+/324634
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 cd794d6..029fd1c 100644
--- a/event/bench/event_test.go
+++ b/event/bench/event_test.go
@@ -89,7 +89,7 @@
 }
 
 func eventNoop() context.Context {
-	return event.WithExporter(context.Background(), event.NewExporter(noopHandler{}, eventtest.ExporterOptions()))
+	return event.WithExporter(context.Background(), event.NewExporter(event.NopHandler{}, eventtest.ExporterOptions()))
 }
 
 func eventPrint(w io.Writer) context.Context {
@@ -119,13 +119,3 @@
 func BenchmarkMetricEventNoop(b *testing.B) {
 	runBenchmark(b, eventPrint(io.Discard), eventMetric)
 }
-
-type noopHandler struct{}
-
-func (noopHandler) Log(ctx context.Context, ev *event.Event)      {}
-func (noopHandler) Metric(ctx context.Context, ev *event.Event)   {}
-func (noopHandler) Annotate(ctx context.Context, ev *event.Event) {}
-func (noopHandler) End(ctx context.Context, ev *event.Event)      {}
-func (noopHandler) Start(ctx context.Context, ev *event.Event) context.Context {
-	return ctx
-}
diff --git a/event/builder_test.go b/event/builder_test.go
index c7c629d..4d3677a 100644
--- a/event/builder_test.go
+++ b/event/builder_test.go
@@ -23,7 +23,7 @@
 		labels = append(labels, keys.Int(fmt.Sprintf("l%d", i)).Of(i))
 	}
 
-	ctx := event.WithExporter(context.Background(), event.NewExporter(noopHandler{}, nil))
+	ctx := event.WithExporter(context.Background(), event.NewExporter(event.NopHandler{}, nil))
 	b1 := event.To(ctx)
 	b1.With(labels[0]).With(labels[1])
 	check(t, b1, labels[:2])
@@ -95,7 +95,7 @@
 }
 
 func TestFailToClone(t *testing.T) {
-	ctx := event.WithExporter(context.Background(), event.NewExporter(noopHandler{}, nil))
+	ctx := event.WithExporter(context.Background(), event.NewExporter(event.NopHandler{}, nil))
 
 	catch := func(f func()) {
 		defer func() {
@@ -128,13 +128,3 @@
 		b1.Log("msg2")
 	})
 }
-
-type noopHandler struct{}
-
-func (noopHandler) Log(ctx context.Context, ev *event.Event)      {}
-func (noopHandler) Metric(ctx context.Context, ev *event.Event)   {}
-func (noopHandler) Annotate(ctx context.Context, ev *event.Event) {}
-func (noopHandler) End(ctx context.Context, ev *event.Event)      {}
-func (noopHandler) Start(ctx context.Context, ev *event.Event) context.Context {
-	return ctx
-}
diff --git a/event/event.go b/event/event.go
index 2c59816..221d0ce 100644
--- a/event/event.go
+++ b/event/event.go
@@ -59,3 +59,15 @@
 func (ev *Event) Is(m Matcher) bool {
 	return m.Matches(ev)
 }
+
+// NopHandler is a handler that does nothing. It can be used for tests, or
+// embedded in a struct to avoid having to implement all the Handler methods.
+type NopHandler struct{}
+
+func (NopHandler) Log(context.Context, *Event)      {}
+func (NopHandler) Metric(context.Context, *Event)   {}
+func (NopHandler) Annotate(context.Context, *Event) {}
+func (NopHandler) End(context.Context, *Event)      {}
+func (NopHandler) Start(ctx context.Context, _ *Event) context.Context {
+	return ctx
+}
diff --git a/event/logging/internal/internal.go b/event/logging/internal/internal.go
index 1f86804..3570d4a 100644
--- a/event/logging/internal/internal.go
+++ b/event/logging/internal/internal.go
@@ -16,6 +16,7 @@
 )
 
 type TestHandler struct {
+	event.NopHandler
 	Got event.Event
 }
 
@@ -25,11 +26,6 @@
 	copy(h.Got.Labels, ev.Labels)
 }
 
-func (h *TestHandler) Annotate(_ context.Context, _ *event.Event)                {}
-func (h *TestHandler) Metric(_ context.Context, _ *event.Event)                  {}
-func (h *TestHandler) Start(ctx context.Context, _ *event.Event) context.Context { return ctx }
-func (h *TestHandler) End(_ context.Context, _ *event.Event)                     {}
-
 var TestAt = time.Now()
 
 func NewTestExporter() (*event.Exporter, *TestHandler) {