event: add ExporterOptions

Add a struct for configuring an Exporter.

Change-Id: I838410d051b8eeba5272590719c25486e0efcf9c
Reviewed-on: https://go-review.googlesource.com/c/exp/+/324632
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/adapter/eventtest/eventtest.go b/event/adapter/eventtest/eventtest.go
index 4ed96fc..9928955 100644
--- a/event/adapter/eventtest/eventtest.go
+++ b/event/adapter/eventtest/eventtest.go
@@ -57,17 +57,13 @@
 	h.printer.Event(os.Stdout, ev)
 }
 
-// FixedNow updates the exporter in the context to use a time function returned
-// by TestNow to make tests reproducible.
-func FixedNow(ctx context.Context) {
+func ExporterOptions() event.ExporterOptions {
 	nextTime, _ := time.Parse(time.RFC3339Nano, "2020-03-05T14:27:48Z")
-	e, _ := event.FromContext(ctx)
-	if e == nil {
-		return
-	}
-	e.Now = func() time.Time {
-		thisTime := nextTime
-		nextTime = nextTime.Add(time.Second)
-		return thisTime
+	return event.ExporterOptions{
+		Now: func() time.Time {
+			thisTime := nextTime
+			nextTime = nextTime.Add(time.Second)
+			return thisTime
+		},
 	}
 }
diff --git a/event/bench/event_test.go b/event/bench/event_test.go
index 4f34b07..8056b08 100644
--- a/event/bench/event_test.go
+++ b/event/bench/event_test.go
@@ -89,15 +89,11 @@
 }
 
 func eventNoop() context.Context {
-	ctx := event.WithExporter(context.Background(), event.NewExporter(noopHandler{}))
-	eventtest.FixedNow(ctx)
-	return ctx
+	return event.WithExporter(context.Background(), eventtest.ExporterOptions().NewExporter(noopHandler{}))
 }
 
 func eventPrint(w io.Writer) context.Context {
-	ctx := event.WithExporter(context.Background(), event.NewExporter(logfmt.NewHandler(w)))
-	eventtest.FixedNow(ctx)
-	return ctx
+	return event.WithExporter(context.Background(), eventtest.ExporterOptions().NewExporter(logfmt.NewHandler(w)))
 }
 
 func BenchmarkLogEventNoExporter(b *testing.B) {
diff --git a/event/event_test.go b/event/event_test.go
index 3f64305..1d830ed 100644
--- a/event/event_test.go
+++ b/event/event_test.go
@@ -98,8 +98,7 @@
 time=2020-03-05T14:27:49 myString="some string value" msg="string event"
 `}} {
 		buf := &strings.Builder{}
-		ctx := event.WithExporter(ctx, event.NewExporter(logfmt.NewHandler(buf)))
-		eventtest.FixedNow(ctx)
+		ctx := event.WithExporter(ctx, eventtest.ExporterOptions().NewExporter(logfmt.NewHandler(buf)))
 		test.events(ctx)
 		got := strings.TrimSpace(buf.String())
 		expect := strings.TrimSpace(test.expect)
@@ -110,8 +109,7 @@
 }
 
 func ExampleLog() {
-	ctx := event.WithExporter(context.Background(), event.NewExporter(logfmt.NewHandler(os.Stdout)))
-	eventtest.FixedNow(ctx)
+	ctx := event.WithExporter(context.Background(), eventtest.ExporterOptions().NewExporter(logfmt.NewHandler(os.Stdout)))
 	event.To(ctx).With(keys.Int("myInt").Of(6)).Log("my event")
 	event.To(ctx).With(keys.String("myString").Of("some string value")).Log("error event")
 	// Output:
diff --git a/event/export.go b/event/export.go
index 84c6521..5366399 100644
--- a/event/export.go
+++ b/event/export.go
@@ -16,13 +16,24 @@
 
 // Exporter synchronizes the delivery of events to handlers.
 type Exporter struct {
-	Now func() time.Time
+	opts ExporterOptions
 
 	mu        sync.Mutex
 	handler   Handler
 	lastEvent uint64
 }
 
+type ExporterOptions struct {
+	// If non-nil, sets zero Event.At on delivery.
+	Now func() time.Time
+
+	// Disable some event types, for better performance.
+	DisableLogging     bool
+	DisableTracing     bool
+	DisableAnnotations bool
+	DisableMetrics     bool
+}
+
 // contextKey is used as the key for storing a contextValue on the context.
 type contextKeyType struct{}
 
@@ -42,7 +53,11 @@
 // NewExporter creates an Exporter using the supplied handler.
 // Event delivery is serialized to enable safe atomic handling.
 func NewExporter(handler Handler) *Exporter {
-	return &Exporter{Now: time.Now, handler: handler}
+	return (ExporterOptions{}).NewExporter(handler)
+}
+
+func (opts ExporterOptions) NewExporter(handler Handler) *Exporter {
+	return &Exporter{opts: opts, handler: handler}
 }
 
 func setDefaultExporter(e *Exporter) {
@@ -71,14 +86,12 @@
 // then the timestamp will be updated.
 // prepare must be called with the export mutex held.
 func (e *Exporter) prepare(ev *Event) {
-	if e.Now != nil && ev.At.IsZero() {
-		ev.At = e.Now()
+	if e.opts.Now != nil && ev.At.IsZero() {
+		ev.At = e.opts.Now()
 	}
 }
 
-//TODO: decide how to control the enable/disable behaviour
-
-func (e *Exporter) loggingEnabled() bool     { return true }
-func (e *Exporter) annotationsEnabled() bool { return true }
-func (e *Exporter) tracingEnabled() bool     { return true }
-func (e *Exporter) metricsEnabled() bool     { return true }
+func (e *Exporter) loggingEnabled() bool     { return !e.opts.DisableLogging }
+func (e *Exporter) annotationsEnabled() bool { return !e.opts.DisableAnnotations }
+func (e *Exporter) tracingEnabled() bool     { return !e.opts.DisableTracing }
+func (e *Exporter) metricsEnabled() bool     { return !e.opts.DisableMetrics }
diff --git a/event/logging/internal/internal.go b/event/logging/internal/internal.go
index c7b56aa..55abb20 100644
--- a/event/logging/internal/internal.go
+++ b/event/logging/internal/internal.go
@@ -34,7 +34,6 @@
 
 func NewTestExporter() (*event.Exporter, *TestHandler) {
 	te := &TestHandler{}
-	e := event.NewExporter(te)
-	e.Now = func() time.Time { return TestAt }
-	return e, te
+	opts := event.ExporterOptions{Now: func() time.Time { return TestAt }}
+	return opts.NewExporter(te), te
 }
diff --git a/event/severity/severity_test.go b/event/severity/severity_test.go
index f31f0cf..b2f0c8c 100644
--- a/event/severity/severity_test.go
+++ b/event/severity/severity_test.go
@@ -34,8 +34,7 @@
 		expect: `time=2020-03-05T14:27:48 level=info msg="a message"`},
 	} {
 		buf := &strings.Builder{}
-		ctx := event.WithExporter(ctx, event.NewExporter(logfmt.NewHandler(buf)))
-		eventtest.FixedNow(ctx)
+		ctx := event.WithExporter(ctx, eventtest.ExporterOptions().NewExporter(logfmt.NewHandler(buf)))
 		test.events(ctx)
 		got := strings.TrimSpace(buf.String())
 		expect := strings.TrimSpace(test.expect)