event: make message a normal label

Change-Id: Icbc45d3303e27e5a74e00bf2344c566563a91fc7
Reviewed-on: https://go-review.googlesource.com/c/exp/+/322830
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/logfmt/logfmt.go b/event/adapter/logfmt/logfmt.go
index 26b24f1..40741cf 100644
--- a/event/adapter/logfmt/logfmt.go
+++ b/event/adapter/logfmt/logfmt.go
@@ -83,11 +83,6 @@
 	p.WriteString(" kind=")
 	p.WriteString(kind)
 
-	if ev.Message != "" {
-		p.WriteString(" msg=")
-		p.Quote(ev.Message)
-	}
-
 	for _, l := range ev.Labels {
 		if l.Name == "" {
 			continue
diff --git a/event/bench/event_enabled_test.go b/event/bench/event_enabled_test.go
index d9164ce..0c18d48 100644
--- a/event/bench/event_enabled_test.go
+++ b/event/bench/event_enabled_test.go
@@ -33,21 +33,21 @@
 
 func TestLogEvent(t *testing.T) {
 	testBenchmark(t, eventPrint, eventLog, `
-time=2020-03-05T14:27:48 id=1 kind=log msg=a A=0
-time=2020-03-05T14:27:49 id=2 kind=log msg=b B="A value"
-time=2020-03-05T14:27:50 id=3 kind=log msg=a A=1
-time=2020-03-05T14:27:51 id=4 kind=log msg=b B="Some other value"
-time=2020-03-05T14:27:52 id=5 kind=log msg=a A=22
-time=2020-03-05T14:27:53 id=6 kind=log msg=b B="Some other value"
-time=2020-03-05T14:27:54 id=7 kind=log msg=a A=333
-time=2020-03-05T14:27:55 id=8 kind=log msg=b B=""
-time=2020-03-05T14:27:56 id=9 kind=log msg=a A=4444
-time=2020-03-05T14:27:57 id=10 kind=log msg=b B="prime count of values"
-time=2020-03-05T14:27:58 id=11 kind=log msg=a A=55555
-time=2020-03-05T14:27:59 id=12 kind=log msg=b B=V
-time=2020-03-05T14:28:00 id=13 kind=log msg=a A=666666
-time=2020-03-05T14:28:01 id=14 kind=log msg=b B="A value"
-time=2020-03-05T14:28:02 id=15 kind=log msg=a A=7777777
-time=2020-03-05T14:28:03 id=16 kind=log msg=b B="A value"
+time=2020-03-05T14:27:48 id=1 kind=log A=0 msg=a
+time=2020-03-05T14:27:49 id=2 kind=log B="A value" msg=b
+time=2020-03-05T14:27:50 id=3 kind=log A=1 msg=a
+time=2020-03-05T14:27:51 id=4 kind=log B="Some other value" msg=b
+time=2020-03-05T14:27:52 id=5 kind=log A=22 msg=a
+time=2020-03-05T14:27:53 id=6 kind=log B="Some other value" msg=b
+time=2020-03-05T14:27:54 id=7 kind=log A=333 msg=a
+time=2020-03-05T14:27:55 id=8 kind=log B="" msg=b
+time=2020-03-05T14:27:56 id=9 kind=log A=4444 msg=a
+time=2020-03-05T14:27:57 id=10 kind=log B="prime count of values" msg=b
+time=2020-03-05T14:27:58 id=11 kind=log A=55555 msg=a
+time=2020-03-05T14:27:59 id=12 kind=log B=V msg=b
+time=2020-03-05T14:28:00 id=13 kind=log A=666666 msg=a
+time=2020-03-05T14:28:01 id=14 kind=log B="A value" msg=b
+time=2020-03-05T14:28:02 id=15 kind=log A=7777777 msg=a
+time=2020-03-05T14:28:03 id=16 kind=log B="A value" msg=b
 `)
 }
diff --git a/event/builder.go b/event/builder.go
index 9b5e8a0..a62eaa7 100644
--- a/event/builder.go
+++ b/event/builder.go
@@ -24,7 +24,7 @@
 // all for the very common cases of simple events. The length needs to be large
 // enough to cope with the majority of events but no so large as to cause undue
 // stack pressure.
-const preallocateLabels = 4
+const preallocateLabels = 6
 
 type builder struct {
 	exporter *Exporter
@@ -122,7 +122,7 @@
 func (b Builder) log(message string) {
 	b.data.exporter.mu.Lock()
 	defer b.data.exporter.mu.Unlock()
-	b.data.Event.Message = message
+	b.data.Event.Labels = append(b.data.Event.Labels, Message.Of(message))
 	b.data.exporter.prepare(&b.data.Event)
 	b.data.exporter.log.Log(b.ctx, &b.data.Event)
 }
@@ -205,7 +205,7 @@
 		eb.data.exporter = b.data.exporter
 		eb.data.Event.Parent = b.data.Event.ID
 		// and now deliver the start event
-		b.data.Event.Message = name
+		b.data.Event.Labels = append(b.data.Event.Labels, Trace.Of(name))
 		ctx = newContext(ctx, b.data.exporter, b.data.Event.ID)
 		ctx = b.data.exporter.trace.Start(ctx, &b.data.Event)
 		eb.ctx = ctx
diff --git a/event/common.go b/event/common.go
new file mode 100644
index 0000000..08c95a7
--- /dev/null
+++ b/event/common.go
@@ -0,0 +1,24 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package event
+
+const Message = stringKey("msg")
+const Trace = stringKey("name")
+
+type stringKey string
+
+// Of creates a new message Label.
+func (k stringKey) Of(msg string) Label {
+	return Label{Name: string(k), Value: StringOf(msg)}
+}
+
+func (k stringKey) Find(ev *Event) (string, bool) {
+	for i := len(ev.Labels) - 1; i >= 0; i-- {
+		if ev.Labels[i].Name == string(k) {
+			return ev.Labels[i].Value.String(), true
+		}
+	}
+	return "", false
+}
diff --git a/event/common_test.go b/event/common_test.go
new file mode 100644
index 0000000..5c0797a
--- /dev/null
+++ b/event/common_test.go
@@ -0,0 +1,90 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !race
+
+package event_test
+
+import (
+	"context"
+	"testing"
+
+	"golang.org/x/exp/event"
+)
+
+func TestCommon(t *testing.T) {
+	h := &catchHandler{}
+	ctx := event.WithExporter(context.Background(), event.NewExporter(h))
+
+	const simple = "simple message"
+	const trace = "a trace"
+
+	event.To(ctx).Log(simple)
+	checkFind(t, h, "Log", event.Message, true, simple)
+	checkFind(t, h, "Log", event.Trace, false, "")
+
+	event.To(ctx).Metric()
+	checkFind(t, h, "Metric", event.Message, false, "")
+	checkFind(t, h, "Metric", event.Trace, false, "")
+
+	event.To(ctx).Annotate()
+	checkFind(t, h, "Annotate", event.Message, false, "")
+	checkFind(t, h, "Annotate", event.Trace, false, "")
+
+	_, end := event.To(ctx).Start(trace)
+	checkFind(t, h, "Start", event.Message, false, "")
+	checkFind(t, h, "Start", event.Trace, true, trace)
+
+	end()
+	checkFind(t, h, "End", event.Message, false, "")
+	checkFind(t, h, "End", event.Trace, false, "")
+}
+
+type finder interface {
+	Find(*event.Event) (string, bool)
+}
+
+func checkFind(t *testing.T, h *catchHandler, method string, key finder, match bool, text string) {
+	m, ok := key.Find(&h.ev)
+	if ok && !match {
+		t.Errorf("%s produced an event with a %v", method, key)
+	}
+	if !ok && match {
+		t.Errorf("%s did not produce an event with a %v", method, key)
+	}
+	if m != text {
+		t.Errorf("Expected event with %v %q from %s got %q", key, text, method, m)
+	}
+}
+
+type catchHandler struct {
+	ev event.Event
+}
+
+func (h *catchHandler) Log(ctx context.Context, ev *event.Event) {
+	h.event(ctx, ev)
+}
+
+func (h *catchHandler) Metric(ctx context.Context, ev *event.Event) {
+	h.event(ctx, ev)
+}
+
+func (h *catchHandler) Annotate(ctx context.Context, ev *event.Event) {
+	h.event(ctx, ev)
+}
+
+func (h *catchHandler) Start(ctx context.Context, ev *event.Event) context.Context {
+	h.event(ctx, ev)
+	return ctx
+}
+
+func (h *catchHandler) End(ctx context.Context, ev *event.Event) {
+	h.event(ctx, ev)
+}
+
+func (h *catchHandler) event(ctx context.Context, ev *event.Event) {
+	h.ev = *ev
+	h.ev.Labels = make([]event.Label, len(ev.Labels))
+	copy(h.ev.Labels, ev.Labels)
+}
diff --git a/event/event.go b/event/event.go
index 3fcdde4..ac6fcab 100644
--- a/event/event.go
+++ b/event/event.go
@@ -12,11 +12,10 @@
 // Event holds the information about an event that occurred.
 // It combines the event metadata with the user supplied labels.
 type Event struct {
-	ID      uint64    // unique for this process id of the event
-	Parent  uint64    // id of the parent event for this event
-	At      time.Time // time at which the event is delivered to the exporter.
-	Message string
-	Labels  []Label
+	ID     uint64    // unique for this process id of the event
+	Parent uint64    // id of the parent event for this event
+	At     time.Time // time at which the event is delivered to the exporter.
+	Labels []Label
 }
 
 // LogHandler is a the type for something that handles log events as they occur.
diff --git a/event/event_test.go b/event/event_test.go
index 7085e41..a282bd5 100644
--- a/event/event_test.go
+++ b/event/event_test.go
@@ -37,15 +37,15 @@
 `}, {
 		name:   "log 1",
 		events: func(ctx context.Context) { event.To(ctx).With(l1).Log("a message") },
-		expect: `time=2020-03-05T14:27:48 id=1 kind=log msg="a message" l1=1`,
+		expect: `time=2020-03-05T14:27:48 id=1 kind=log l1=1 msg="a message"`,
 	}, {
 		name:   "log 2",
 		events: func(ctx context.Context) { event.To(ctx).With(l1).With(l2).Log("a message") },
-		expect: `time=2020-03-05T14:27:48 id=1 kind=log msg="a message" l1=1 l2=2`,
+		expect: `time=2020-03-05T14:27:48 id=1 kind=log l1=1 l2=2 msg="a message"`,
 	}, {
 		name:   "log 3",
 		events: func(ctx context.Context) { event.To(ctx).With(l1).With(l2).With(l3).Log("a message") },
-		expect: `time=2020-03-05T14:27:48 id=1 kind=log msg="a message" l1=1 l2=2 l3=3`,
+		expect: `time=2020-03-05T14:27:48 id=1 kind=log l1=1 l2=2 l3=3 msg="a message"`,
 	}, {
 		name: "span",
 		events: func(ctx context.Context) {
@@ -53,7 +53,7 @@
 			end()
 		},
 		expect: `
-time=2020-03-05T14:27:48 id=1 kind=start msg=span
+time=2020-03-05T14:27:48 id=1 kind=start name=span
 time=2020-03-05T14:27:49 id=2 span=1 kind=end
 `}, {
 		name: "span nested",
@@ -65,8 +65,8 @@
 			event.To(child).Log("message")
 		},
 		expect: `
-time=2020-03-05T14:27:48 id=1 kind=start msg=parent
-time=2020-03-05T14:27:49 id=2 span=1 kind=start msg=child
+time=2020-03-05T14:27:48 id=1 kind=start name=parent
+time=2020-03-05T14:27:49 id=2 span=1 kind=start name=child
 time=2020-03-05T14:27:50 id=3 span=2 kind=log msg=message
 time=2020-03-05T14:27:51 id=4 span=2 kind=end
 time=2020-03-05T14:27:52 id=5 span=1 kind=end
@@ -94,8 +94,8 @@
 			b.With(keys.String("myString").Of("some string value")).Log("string event")
 		},
 		expect: `
-time=2020-03-05T14:27:48 id=1 kind=log msg="my event" myInt=6
-time=2020-03-05T14:27:49 id=2 kind=log msg="string event" myString="some string value"
+time=2020-03-05T14:27:48 id=1 kind=log myInt=6 msg="my event"
+time=2020-03-05T14:27:49 id=2 kind=log myString="some string value" msg="string event"
 `}} {
 		buf := &strings.Builder{}
 		e := event.NewExporter(logfmt.NewPrinter(buf))
@@ -117,6 +117,6 @@
 	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:
-	// time=2020-03-05T14:27:48 id=1 kind=log msg="my event" myInt=6
-	// time=2020-03-05T14:27:49 id=2 kind=log msg="error event" myString="some string value"
+	// time=2020-03-05T14:27:48 id=1 kind=log myInt=6 msg="my event"
+	// time=2020-03-05T14:27:49 id=2 kind=log myString="some string value" msg="error event"
 }
diff --git a/event/logging/egokit/gokit_test.go b/event/logging/egokit/gokit_test.go
index e2cc659..92b2545 100644
--- a/event/logging/egokit/gokit_test.go
+++ b/event/logging/egokit/gokit_test.go
@@ -20,14 +20,14 @@
 	ctx := event.WithExporter(context.Background(), e)
 	log.Log(ctx, "msg", "mess", "level", 1, "name", "n/m", "traceID", 17, "resource", "R")
 	want := &event.Event{
-		ID:      1,
-		At:      internal.TestAt,
-		Message: "mess",
+		ID: 1,
+		At: internal.TestAt,
 		Labels: []event.Label{
 			keys.Value("level").Of(1),
 			keys.Value("name").Of("n/m"),
 			keys.Value("traceID").Of(17),
 			keys.Value("resource").Of("R"),
+			event.Message.Of("mess"),
 		},
 	}
 	if diff := cmp.Diff(want, &h.Got); diff != "" {
diff --git a/event/logging/elogr/logr_test.go b/event/logging/elogr/logr_test.go
index 85054c2..abbd284 100644
--- a/event/logging/elogr/logr_test.go
+++ b/event/logging/elogr/logr_test.go
@@ -20,14 +20,14 @@
 	log = log.WithName("m")
 	log.Info("mess", "traceID", 17, "resource", "R")
 	want := &event.Event{
-		At:      internal.TestAt,
-		ID:      1,
-		Message: "mess",
+		At: internal.TestAt,
+		ID: 1,
 		Labels: []event.Label{
 			internal.LevelKey.Of(3),
 			internal.NameKey.Of("n/m"),
 			keys.Value("traceID").Of(17),
 			keys.Value("resource").Of("R"),
+			event.Message.Of("mess"),
 		},
 	}
 	if diff := cmp.Diff(want, &th.Got); diff != "" {
diff --git a/event/logging/elogrus/logrus_test.go b/event/logging/elogrus/logrus_test.go
index 187ec9a..d57dddf 100644
--- a/event/logging/elogrus/logrus_test.go
+++ b/event/logging/elogrus/logrus_test.go
@@ -27,12 +27,12 @@
 	log.WithContext(ctx).WithField("traceID", 17).WithField("resource", "R").Info("mess")
 
 	want := &event.Event{
-		ID:      1,
-		Message: "mess",
+		ID: 1,
 		Labels: []event.Label{
 			internal.LevelKey.Of(4),
 			keys.Value("traceID").Of(17),
 			keys.Value("resource").Of("R"),
+			event.Message.Of("mess"),
 		},
 	}
 	th.Got.At = want.At
diff --git a/event/logging/ezap/zap_test.go b/event/logging/ezap/zap_test.go
index 20a22a1..5855bd2 100644
--- a/event/logging/ezap/zap_test.go
+++ b/event/logging/ezap/zap_test.go
@@ -22,14 +22,14 @@
 	log = log.Named("n/m")
 	log.Info("mess", zap.Float64("pi", 3.14))
 	want := &event.Event{
-		ID:      1,
-		Message: "mess",
+		ID: 1,
 		Labels: []event.Label{
 			keys.Int64("traceID").Of(17),
 			keys.String("resource").Of("R"),
 			internal.LevelKey.Of(0),
 			internal.NameKey.Of("n/m"),
 			keys.Float64("pi").Of(3.14),
+			event.Message.Of("mess"),
 		},
 	}
 	h.Got.At = want.At
diff --git a/event/otel/trace.go b/event/otel/trace.go
index bc75376..2cc56a4 100644
--- a/event/otel/trace.go
+++ b/event/otel/trace.go
@@ -25,7 +25,8 @@
 
 func (t *TraceHandler) Start(ctx context.Context, e *event.Event) context.Context {
 	opts := labelsToSpanOptions(e.Labels)
-	octx, span := t.tracer.Start(ctx, e.Message, opts...)
+	name, _ := event.Trace.Find(e)
+	octx, span := t.tracer.Start(ctx, name, opts...)
 	return context.WithValue(octx, spanKey{}, span)
 }
 
diff --git a/event/severity/severity_test.go b/event/severity/severity_test.go
index 11422cd..478770e 100644
--- a/event/severity/severity_test.go
+++ b/event/severity/severity_test.go
@@ -27,11 +27,11 @@
 	}{{
 		name:   "debug",
 		events: func(ctx context.Context) { event.To(ctx).With(severity.Debug).Log("a message") },
-		expect: `time=2020-03-05T14:27:48 id=1 kind=log msg="a message" level=debug`,
+		expect: `time=2020-03-05T14:27:48 id=1 kind=log level=debug msg="a message"`,
 	}, {
 		name:   "info",
 		events: func(ctx context.Context) { event.To(ctx).With(severity.Info).Log("a message") },
-		expect: `time=2020-03-05T14:27:48 id=1 kind=log msg="a message" level=info`},
+		expect: `time=2020-03-05T14:27:48 id=1 kind=log level=info msg="a message"`},
 	} {
 		buf := &strings.Builder{}
 		e := event.NewExporter(logfmt.NewPrinter(buf))