event: give every event an ID

This helps clean up prepare, and enables some other useful abilities to identify
events in handlers.

Change-Id: I2d638aecfefeafae872435f2bfe16f0b503c96bc
Reviewed-on: https://go-review.googlesource.com/c/exp/+/333070
Trust: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/event/adapter/gokit/gokit_test.go b/event/adapter/gokit/gokit_test.go
index dedf75b..d76dfaf 100644
--- a/event/adapter/gokit/gokit_test.go
+++ b/event/adapter/gokit/gokit_test.go
@@ -20,7 +20,7 @@
 	ctx, h := eventtest.NewCapture()
 	log.Log(ctx, "msg", "mess", "level", 1, "name", "n/m", "traceID", 17, "resource", "R")
 	want := []event.Event{{
-		At:   eventtest.InitialTime,
+		ID:   1,
 		Kind: event.LogKind,
 		Labels: []event.Label{
 			event.Value("level", 1),
diff --git a/event/adapter/logfmt/logfmt.go b/event/adapter/logfmt/logfmt.go
index c3eca4f..d635a48 100644
--- a/event/adapter/logfmt/logfmt.go
+++ b/event/adapter/logfmt/logfmt.go
@@ -76,7 +76,7 @@
 		p.Label(w, l)
 	}
 
-	if ev.ID != 0 {
+	if ev.ID != 0 && ev.Kind == event.StartKind {
 		p.separator(w)
 		io.WriteString(w, `trace=`)
 		w.Write(strconv.AppendUint(p.buf[:0], ev.ID, 10))
diff --git a/event/adapter/logfmt/logfmt_test.go b/event/adapter/logfmt/logfmt_test.go
index 0fdb62b..90b0e6f 100644
--- a/event/adapter/logfmt/logfmt_test.go
+++ b/event/adapter/logfmt/logfmt_test.go
@@ -28,7 +28,7 @@
 		expect: ``,
 	}, {
 		name:   "span",
-		event:  event.Event{ID: 34},
+		event:  event.Event{ID: 34, Kind: event.StartKind},
 		expect: `trace=34`,
 	}, {
 		name:   "parent",
diff --git a/event/adapter/logr/logr_test.go b/event/adapter/logr/logr_test.go
index 0582ba3..66a60f0 100644
--- a/event/adapter/logr/logr_test.go
+++ b/event/adapter/logr/logr_test.go
@@ -22,7 +22,7 @@
 	log = log.WithName("m")
 	log.Info("mess", "traceID", 17, "resource", "R")
 	want := []event.Event{{
-		At:   eventtest.InitialTime,
+		ID:   1,
 		Kind: event.LogKind,
 		Labels: []event.Label{
 			severity.Debug.Label(),
diff --git a/event/adapter/logrus/logrus_test.go b/event/adapter/logrus/logrus_test.go
index 4915361..467485e 100644
--- a/event/adapter/logrus/logrus_test.go
+++ b/event/adapter/logrus/logrus_test.go
@@ -28,6 +28,7 @@
 	log.WithContext(ctx).WithField("traceID", 17).WithField("resource", "R").Info("mess")
 
 	want := []event.Event{{
+		ID:   1,
 		Kind: event.LogKind,
 		Labels: []event.Label{
 			severity.Info.Label(),
diff --git a/event/adapter/zap/zap_test.go b/event/adapter/zap/zap_test.go
index a928bfb..55461bf 100644
--- a/event/adapter/zap/zap_test.go
+++ b/event/adapter/zap/zap_test.go
@@ -23,6 +23,7 @@
 	log = log.Named("n/m")
 	log.Info("mess", zap.Float64("pi", 3.14))
 	want := []event.Event{{
+		ID:   1,
 		Kind: event.LogKind,
 		Labels: []event.Label{
 			event.Int64("traceID", 17),
diff --git a/event/common.go b/event/common.go
index e98d20b..fbe002b 100644
--- a/event/common.go
+++ b/event/common.go
@@ -7,7 +7,6 @@
 import (
 	"context"
 	"fmt"
-	"sync/atomic"
 )
 
 const (
@@ -71,8 +70,7 @@
 	if ev != nil {
 		ev.Labels = append(ev.Labels, String("name", name))
 		ev.Labels = append(ev.Labels, labels...)
-		ev.ID = atomic.AddUint64(&ev.target.exporter.lastEvent, 1)
-		ev.target.exporter.prepare(ev)
+		ev.prepare()
 		ev.ctx = newContext(ev.ctx, ev.target.exporter, ev.ID, ev.At)
 		ctx = ev.Deliver()
 	}
@@ -83,7 +81,7 @@
 	ev := New(ctx, EndKind)
 	if ev != nil {
 		ev.Labels = append(ev.Labels, labels...)
-		ev.target.exporter.prepare(ev)
+		ev.prepare()
 		// this was an end event, do we need to send a duration?
 		if v, ok := DurationMetric.Find(ev); ok {
 			//TODO: do we want the rest of the values from the end event?
diff --git a/event/event.go b/event/event.go
index beff412..bc9ae85 100644
--- a/event/event.go
+++ b/event/event.go
@@ -108,17 +108,21 @@
 // This also returns the event to the pool, it is an error to do anything
 // with the event after it is delivered.
 func (ev *Event) Deliver() context.Context {
-	e := ev.target.exporter
 	// get the event ready to send
-	e.prepare(ev)
-	// now hold the lock while we deliver the event
-	e.mu.Lock()
-	defer e.mu.Unlock()
-	ctx := e.handler.Event(ev.ctx, ev)
+	ev.prepare()
+	ctx := ev.deliver()
 	eventPool.Put(ev)
 	return ctx
 }
 
+func (ev *Event) deliver() context.Context {
+	// hold the lock while we deliver the event
+	e := ev.target.exporter
+	e.mu.Lock()
+	defer e.mu.Unlock()
+	return e.handler.Event(ev.ctx, ev)
+}
+
 func (ev *Event) Find(name string) Label {
 	for _, l := range ev.Labels {
 		if l.Name == name {
diff --git a/event/export.go b/event/export.go
index 9307c44..0189599 100644
--- a/event/export.go
+++ b/event/export.go
@@ -97,7 +97,11 @@
 // then the timestamp will be updated.
 // If automatic namespaces are enabled and the event doesn't have a namespace,
 // one based on the caller's import path will be provided.
-func (e *Exporter) prepare(ev *Event) {
+func (ev *Event) prepare() {
+	e := ev.target.exporter
+	if ev.ID == 0 {
+		ev.ID = atomic.AddUint64(&e.lastEvent, 1)
+	}
 	if e.opts.Now != nil && ev.At.IsZero() {
 		ev.At = e.opts.Now()
 	}