event: simplify Label
The separation of Label and Value was more API surface for no gain.
Change-Id: Idc52fe019953682318dd3ce3e5040d911039861a
Reviewed-on: https://go-review.googlesource.com/c/exp/+/329630
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 cc8b297..451d2de 100644
--- a/event/adapter/logfmt/logfmt.go
+++ b/event/adapter/logfmt/logfmt.go
@@ -48,17 +48,16 @@
func (p *Printer) Event(w io.Writer, ev *event.Event) {
p.needSep = false
if !ev.At.IsZero() {
- p.label(w, "time", event.BytesOf(ev.At.AppendFormat(p.buf[:0], TimeFormat)))
+ p.Label(w, event.Bytes("time", ev.At.AppendFormat(p.buf[:0], TimeFormat)))
}
if !p.SuppressNamespace && ev.Namespace != "" {
- p.label(w, "in", event.StringOf(ev.Namespace))
+ p.Label(w, event.String("in", ev.Namespace))
}
if ev.Parent != 0 {
- p.label(w, "parent", event.BytesOf(strconv.AppendUint(p.buf[:0], ev.Parent, 10)))
+ p.Label(w, event.Bytes("parent", strconv.AppendUint(p.buf[:0], ev.Parent, 10)))
}
-
for _, l := range ev.Labels {
if l.Name == "" {
continue
@@ -67,72 +66,79 @@
}
if ev.TraceID != 0 {
- p.label(w, "trace", event.Uint64Of(ev.TraceID))
+ p.Label(w, event.Uint64("trace", ev.TraceID))
}
if ev.Message != "" {
- p.label(w, "msg", event.StringOf(ev.Message))
+ p.Label(w, event.String("msg", ev.Message))
}
if ev.Name != "" {
- p.label(w, "name", event.StringOf(ev.Name))
+ p.Label(w, event.String("name", ev.Name))
}
if ev.Kind == event.EndKind {
- p.label(w, "end", event.Value{})
+ p.Label(w, event.Value("end", nil))
}
if ev.Error != nil {
- p.label(w, "err", event.ValueOf(ev.Error))
+ p.Label(w, event.Value("err", ev.Error))
}
io.WriteString(w, "\n")
}
func (p *Printer) Label(w io.Writer, l event.Label) {
- p.label(w, l.Name, l.Value)
-}
-
-func (p *Printer) Value(w io.Writer, v event.Value) {
- switch {
- case v.IsString():
- s := v.String()
- if p.QuoteValues || stringNeedQuote(s) {
- p.quoteString(w, s)
- } else {
- io.WriteString(w, s)
- }
- case v.IsBytes():
- buf := v.Bytes()
- if p.QuoteValues || bytesNeedQuote(buf) {
- p.quoteBytes(w, buf)
- } else {
- w.Write(buf)
- }
- case v.IsInt64():
- w.Write(strconv.AppendInt(p.buf[:0], v.Int64(), 10))
- case v.IsUint64():
- w.Write(strconv.AppendUint(p.buf[:0], v.Uint64(), 10))
- case v.IsFloat64():
- w.Write(strconv.AppendFloat(p.buf[:0], v.Float64(), 'g', -1, 64))
- case v.IsBool():
- if v.Bool() {
- io.WriteString(w, "true")
- } else {
- io.WriteString(w, "false")
- }
- default:
- if p.w.Cap() == 0 {
- // we rely on the inliner to cause this to not allocate
- p.w = *bytes.NewBuffer(p.buf[:0])
- }
- fmt.Fprint(&p.w, v.Interface())
- b := p.w.Bytes()
- p.w.Reset()
- if p.QuoteValues || bytesNeedQuote(b) {
- p.quoteBytes(w, b)
- } else {
- w.Write(b)
+ if l.Name == "" {
+ return
+ }
+ if p.needSep {
+ io.WriteString(w, " ")
+ }
+ p.needSep = true
+ p.Ident(w, l.Name)
+ if l.HasValue() {
+ io.WriteString(w, "=")
+ switch {
+ case l.IsString():
+ s := l.String()
+ if p.QuoteValues || stringNeedQuote(s) {
+ p.quoteString(w, s)
+ } else {
+ io.WriteString(w, s)
+ }
+ case l.IsBytes():
+ buf := l.Bytes()
+ if p.QuoteValues || bytesNeedQuote(buf) {
+ p.quoteBytes(w, buf)
+ } else {
+ w.Write(buf)
+ }
+ case l.IsInt64():
+ w.Write(strconv.AppendInt(p.buf[:0], l.Int64(), 10))
+ case l.IsUint64():
+ w.Write(strconv.AppendUint(p.buf[:0], l.Uint64(), 10))
+ case l.IsFloat64():
+ w.Write(strconv.AppendFloat(p.buf[:0], l.Float64(), 'g', -1, 64))
+ case l.IsBool():
+ if l.Bool() {
+ io.WriteString(w, "true")
+ } else {
+ io.WriteString(w, "false")
+ }
+ default:
+ if p.w.Cap() == 0 {
+ // we rely on the inliner to cause this to not allocate
+ p.w = *bytes.NewBuffer(p.buf[:0])
+ }
+ fmt.Fprint(&p.w, l.Interface())
+ b := p.w.Bytes()
+ p.w.Reset()
+ if p.QuoteValues || bytesNeedQuote(b) {
+ p.quoteBytes(w, b)
+ } else {
+ w.Write(b)
+ }
}
}
}
@@ -184,21 +190,6 @@
io.WriteString(w, `"`)
}
-func (p *Printer) label(w io.Writer, name string, value event.Value) {
- if name == "" {
- return
- }
- if p.needSep {
- io.WriteString(w, " ")
- }
- p.needSep = true
- p.Ident(w, name)
- if value.HasValue() {
- io.WriteString(w, "=")
- p.Value(w, value)
- }
-}
-
func stringNeedQuote(s string) bool {
if len(s) == 0 {
return true
diff --git a/event/adapter/logfmt/logfmt_test.go b/event/adapter/logfmt/logfmt_test.go
index be80ade..1be397d 100644
--- a/event/adapter/logfmt/logfmt_test.go
+++ b/event/adapter/logfmt/logfmt_test.go
@@ -62,80 +62,63 @@
}, {
name: "string",
event: event.Event{
- Labels: []event.Label{{
- Name: "v1",
- Value: event.StringOf("text"),
- }, {
- Name: "v2",
- Value: event.StringOf("text with quotes"),
- }, {
- Name: "empty",
- Value: event.StringOf(""),
- }},
+ Labels: []event.Label{
+ event.String("v1", "text"),
+ event.String("v2", "text with quotes"),
+ event.String("empty", ""),
+ },
},
expect: `v1=text v2="text with quotes" empty=""`,
}, {
name: "int",
event: event.Event{
- Labels: []event.Label{{
- Name: "value",
- Value: event.Int64Of(67),
- }},
+ Labels: []event.Label{
+ event.Int64("value", 67),
+ },
},
expect: `value=67`,
}, {
name: "float",
event: event.Event{
- Labels: []event.Label{{
- Name: "value",
- Value: event.Float64Of(263.2),
- }},
+ Labels: []event.Label{
+ event.Float64("value", 263.2),
+ },
},
expect: `value=263.2`,
}, {
name: "bool",
event: event.Event{
- Labels: []event.Label{{
- Name: "v1",
- Value: event.BoolOf(true),
- }, {
- Name: "v2",
- Value: event.BoolOf(false),
- }},
+ Labels: []event.Label{
+ event.Bool("v1", true),
+ event.Bool("v2", false),
+ },
},
expect: `v1=true v2=false`,
}, {
name: "value",
event: event.Event{
- Labels: []event.Label{{
- Name: "v1",
- Value: event.ValueOf(notString{"simple"}),
- }, {
- Name: "v2",
- Value: event.ValueOf(notString{"needs quoting"}),
- }},
+ Labels: []event.Label{
+ event.Value("v1", notString{"simple"}),
+ event.Value("v2", notString{"needs quoting"}),
+ },
},
expect: `v1=simple v2="needs quoting"`,
}, {
name: "empty label",
event: event.Event{
- Labels: []event.Label{{
- Name: "before",
- }, {
- Name: "",
- Value: event.StringOf("text"),
- }, {
- Name: "after",
- }},
+ Labels: []event.Label{
+ event.Value("before", nil),
+ event.String("", "text"),
+ event.Value("after", nil),
+ },
},
expect: `before after`,
}, {
name: "quoted ident",
event: event.Event{
- Labels: []event.Label{{
- Name: "name with space",
- Value: event.StringOf("text"),
- }},
+ Labels: []event.Label{
+ event.String("name with space", "text"),
+ },
},
expect: `"name with space"=text`,
}, {
@@ -153,10 +136,9 @@
}, {
name: "quoting bytes",
event: event.Event{
- Labels: []event.Label{{
- Name: "value",
- Value: event.BytesOf(([]byte)(`bytes "need" quote`)),
- }},
+ Labels: []event.Label{
+ event.Bytes("value", ([]byte)(`bytes "need" quote`)),
+ },
},
expect: `value="bytes \"need\" quote"`,
}} {
@@ -191,10 +173,9 @@
name: "quote values",
printer: logfmt.Printer{QuoteValues: true},
event: event.Event{
- Labels: []event.Label{{
- Name: "value",
- Value: event.StringOf("text"),
- }},
+ Labels: []event.Label{
+ event.String("value", "text"),
+ },
},
before: `value=text`,
after: `value="text"`,
diff --git a/event/alloc_test.go b/event/alloc_test.go
index 80ce051..4e55395 100644
--- a/event/alloc_test.go
+++ b/event/alloc_test.go
@@ -17,8 +17,8 @@
)
func TestAllocs(t *testing.T) {
- anInt := event.Label{Name: "int", Value: event.Int64Of(4)}
- aString := event.Label{Name: "string", Value: event.StringOf("value")}
+ anInt := event.Int64("int", 4)
+ aString := event.String("string", "value")
e := event.NewExporter(logfmt.NewHandler(ioutil.Discard), &event.ExporterOptions{EnableNamespaces: true})
ctx := event.WithExporter(context.Background(), e)
diff --git a/event/common.go b/event/common.go
index b6876e3..34bfc8c 100644
--- a/event/common.go
+++ b/event/common.go
@@ -11,8 +11,8 @@
)
const (
- MetricKey = interfaceKey("metric")
- MetricVal = valueKey("metricValue")
+ MetricKey = "metric"
+ MetricVal = "metricValue"
DurationMetric = interfaceKey("durationMetric")
)
@@ -78,22 +78,14 @@
// 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?
- v.(*Duration).Record(ctx, ev.At.Sub(ev.target.startTime))
+ v.(*DurationDistribution).Record(ctx, ev.At.Sub(ev.target.startTime))
}
ev.Deliver()
}
}
-func (k valueKey) Of(v Value) Label {
- return Label{Name: string(k), Value: v}
-}
-
-func (k valueKey) Find(ev *Event) (Value, bool) {
- return lookupValue(string(k), ev.Labels)
-}
-
func (k interfaceKey) Of(v interface{}) Label {
- return Label{Name: string(k), Value: ValueOf(v)}
+ return Value(string(k), v)
}
func (k interfaceKey) Find(ev *Event) (interface{}, bool) {
@@ -105,11 +97,11 @@
}
-func lookupValue(name string, labels []Label) (Value, bool) {
+func lookupValue(name string, labels []Label) (Label, bool) {
for i := len(labels) - 1; i >= 0; i-- {
if labels[i].Name == name {
- return labels[i].Value, true
+ return labels[i], true
}
}
- return Value{}, false
+ return Label{}, false
}
diff --git a/event/event_test.go b/event/event_test.go
index 857c6c3..8c8ba35 100644
--- a/event/event_test.go
+++ b/event/event_test.go
@@ -207,12 +207,14 @@
}
type testTraceDurationHandler struct {
- got event.Value
+ got event.Label
}
func (t *testTraceDurationHandler) Event(ctx context.Context, ev *event.Event) context.Context {
- if ev.Kind == event.MetricKind {
- t.got, _ = event.MetricVal.Find(ev)
+ for _, l := range ev.Labels {
+ if l.Name == event.MetricVal {
+ t.got = l
+ }
}
return ctx
}
diff --git a/event/keys/keys.go b/event/keys/keys.go
index 574d696..a4463fb 100644
--- a/event/keys/keys.go
+++ b/event/keys/keys.go
@@ -12,11 +12,11 @@
type Value string
// From can be used to get a value from a Label.
-func (k Value) From(l event.Label) interface{} { return l.Value.Interface() }
+func (k Value) From(l event.Label) interface{} { return l.Interface() }
// Of creates a new Label with this key and the supplied value.
func (k Value) Of(v interface{}) event.Label {
- return event.Label{Name: string(k), Value: event.ValueOf(v)}
+ return event.Value(string(k), v)
}
// Tag represents a key for tagging labels that have no value.
@@ -35,133 +35,133 @@
// Of creates a new Label with this key and the supplied value.
func (k Int) Of(v int) event.Label {
- return event.Label{Name: string(k), Value: event.Int64Of(int64(v))}
+ return event.Int64(string(k), int64(v))
}
// From can be used to get a value from a Label.
-func (k Int) From(l event.Label) int { return int(l.Value.Int64()) }
+func (k Int) From(l event.Label) int { return int(l.Int64()) }
// Int8 represents a key
type Int8 string
// Of creates a new Label with this key and the supplied value.
func (k Int8) Of(v int8) event.Label {
- return event.Label{Name: string(k), Value: event.Int64Of(int64(v))}
+ return event.Int64(string(k), int64(v))
}
// From can be used to get a value from a Label.
-func (k Int8) From(l event.Label) int8 { return int8(l.Value.Int64()) }
+func (k Int8) From(l event.Label) int8 { return int8(l.Int64()) }
// Int16 represents a key
type Int16 string
// Of creates a new Label with this key and the supplied value.
func (k Int16) Of(v int16) event.Label {
- return event.Label{Name: string(k), Value: event.Int64Of(int64(v))}
+ return event.Int64(string(k), int64(v))
}
// From can be used to get a value from a Label.
-func (k Int16) From(l event.Label) int16 { return int16(l.Value.Int64()) }
+func (k Int16) From(l event.Label) int16 { return int16(l.Int64()) }
// Int32 represents a key
type Int32 string
// Of creates a new Label with this key and the supplied value.
func (k Int32) Of(v int32) event.Label {
- return event.Label{Name: string(k), Value: event.Int64Of(int64(v))}
+ return event.Int64(string(k), int64(v))
}
// From can be used to get a value from a Label.
-func (k Int32) From(l event.Label) int32 { return int32(l.Value.Int64()) }
+func (k Int32) From(l event.Label) int32 { return int32(l.Int64()) }
// Int64 represents a key
type Int64 string
// Of creates a new Label with this key and the supplied value.
func (k Int64) Of(v int64) event.Label {
- return event.Label{Name: string(k), Value: event.Int64Of(v)}
+ return event.Int64(string(k), v)
}
// From can be used to get a value from a Label.
-func (k Int64) From(l event.Label) int64 { return l.Value.Int64() }
+func (k Int64) From(l event.Label) int64 { return l.Int64() }
// UInt represents a key
type UInt string
// Of creates a new Label with this key and the supplied value.
func (k UInt) Of(v uint) event.Label {
- return event.Label{Name: string(k), Value: event.Uint64Of(uint64(v))}
+ return event.Uint64(string(k), uint64(v))
}
// From can be used to get a value from a Label.
-func (k UInt) From(l event.Label) uint { return uint(l.Value.Uint64()) }
+func (k UInt) From(l event.Label) uint { return uint(l.Uint64()) }
// UInt8 represents a key
type UInt8 string
// Of creates a new Label with this key and the supplied value.
func (k UInt8) Of(v uint8) event.Label {
- return event.Label{Name: string(k), Value: event.Uint64Of(uint64(v))}
+ return event.Uint64(string(k), uint64(v))
}
// From can be used to get a value from a Label.
-func (k UInt8) From(l event.Label) uint8 { return uint8(l.Value.Uint64()) }
+func (k UInt8) From(l event.Label) uint8 { return uint8(l.Uint64()) }
// UInt16 represents a key
type UInt16 string
// Of creates a new Label with this key and the supplied value.
func (k UInt16) Of(v uint16) event.Label {
- return event.Label{Name: string(k), Value: event.Uint64Of(uint64(v))}
+ return event.Uint64(string(k), uint64(v))
}
// From can be used to get a value from a Label.
-func (k UInt16) From(l event.Label) uint16 { return uint16(l.Value.Uint64()) }
+func (k UInt16) From(l event.Label) uint16 { return uint16(l.Uint64()) }
// UInt32 represents a key
type UInt32 string
// Of creates a new Label with this key and the supplied value.
func (k UInt32) Of(v uint32) event.Label {
- return event.Label{Name: string(k), Value: event.Uint64Of(uint64(v))}
+ return event.Uint64(string(k), uint64(v))
}
// From can be used to get a value from a Label.
-func (k UInt32) From(l event.Label) uint32 { return uint32(l.Value.Uint64()) }
+func (k UInt32) From(l event.Label) uint32 { return uint32(l.Uint64()) }
// UInt64 represents a key
type UInt64 string
// Of creates a new Label with this key and the supplied value.
func (k UInt64) Of(v uint64) event.Label {
- return event.Label{Name: string(k), Value: event.Uint64Of(v)}
+ return event.Uint64(string(k), v)
}
// From can be used to get a value from a Label.
-func (k UInt64) From(l event.Label) uint64 { return l.Value.Uint64() }
+func (k UInt64) From(l event.Label) uint64 { return l.Uint64() }
// Float32 represents a key
type Float32 string
// Of creates a new Label with this key and the supplied value.
func (k Float32) Of(v float32) event.Label {
- return event.Label{Name: string(k), Value: event.Float64Of(float64(v))}
+ return event.Float64(string(k), float64(v))
}
// From can be used to get a value from a Label.
-func (k Float32) From(l event.Label) float32 { return float32(l.Value.Float64()) }
+func (k Float32) From(l event.Label) float32 { return float32(l.Float64()) }
// Float64 represents a key
type Float64 string
// Of creates a new Label with this key and the supplied value.
func (k Float64) Of(v float64) event.Label {
- return event.Label{Name: string(k), Value: event.Float64Of(v)}
+ return event.Float64(string(k), v)
}
// From can be used to get a value from a Label.
func (k Float64) From(l event.Label) float64 {
- return l.Value.Float64()
+ return l.Float64()
}
// String represents a key
@@ -169,19 +169,19 @@
// Of creates a new Label with this key and the supplied value.
func (k String) Of(v string) event.Label {
- return event.Label{Name: string(k), Value: event.StringOf(v)}
+ return event.String(string(k), v)
}
// From can be used to get a value from a Label.
-func (k String) From(l event.Label) string { return l.Value.String() }
+func (k String) From(l event.Label) string { return l.String() }
// Bool represents a key
type Bool string
// Of creates a new Label with this key and the supplied value.
func (k Bool) Of(v bool) event.Label {
- return event.Label{Name: string(k), Value: event.BoolOf(v)}
+ return event.Bool(string(k), v)
}
// From can be used to get a value from a Label.
-func (k Bool) From(l event.Label) bool { return l.Value.Bool() }
+func (k Bool) From(l event.Label) bool { return l.Bool() }
diff --git a/event/label.go b/event/label.go
index 1593cf5..57307cc 100644
--- a/event/label.go
+++ b/event/label.go
@@ -13,22 +13,12 @@
"unsafe"
)
-// Value holds any value in an efficient way that avoids allocations for
-// most types.
-type Value struct {
- packed uint64
- untyped interface{}
-}
-
// Label is a named value.
type Label struct {
- Name string
- Value Value
-}
+ Name string
-// Equal reports whether two labels are equal.
-func (l1 Label) Equal(l2 Label) bool {
- return l1.Name == l2.Name && l1.Value.Equal(l2.Value)
+ packed uint64
+ untyped interface{}
}
// stringptr is used in untyped when the Value is a string
@@ -53,43 +43,46 @@
type durationKind struct{}
// HasValue returns true if the value is set to any type.
-func (v *Value) HasValue() bool { return v.untyped != nil }
+func (l Label) HasValue() bool { return l.untyped != nil }
-// Equal reports whether two values are equal.
-func (v1 *Value) Equal(v2 Value) bool {
- if !v1.HasValue() {
- return !v2.HasValue()
+// Equal reports whether two labels are equal.
+func (l Label) Equal(l2 Label) bool {
+ if l.Name != l2.Name {
+ return false
}
- if !v2.HasValue() {
+ if !l.HasValue() {
+ return !l2.HasValue()
+ }
+ if !l2.HasValue() {
return false
}
switch {
- case v1.IsString():
- return v2.IsString() && v1.String() == v2.String()
- case v1.IsInt64():
- return v2.IsInt64() && v1.packed == v2.packed
- case v1.IsUint64():
- return v2.IsUint64() && v1.packed == v2.packed
- case v1.IsFloat64():
- return v2.IsFloat64() && v1.Float64() == v2.Float64()
- case v1.IsBool():
- return v2.IsBool() && v1.packed == v2.packed
- case v1.IsDuration():
- return v2.IsDuration() && v1.packed == v2.packed
+ case l.IsString():
+ return l2.IsString() && l.String() == l2.String()
+ case l.IsInt64():
+ return l2.IsInt64() && l.packed == l2.packed
+ case l.IsUint64():
+ return l2.IsUint64() && l.packed == l2.packed
+ case l.IsFloat64():
+ return l2.IsFloat64() && l.Float64() == l2.Float64()
+ case l.IsBool():
+ return l2.IsBool() && l.packed == l2.packed
+ case l.IsDuration():
+ return l2.IsDuration() && l.packed == l2.packed
default:
- return v1.untyped == v2.untyped
+ return l.untyped == l2.untyped
}
}
-// ValueOf returns a Value for the supplied value.
-func ValueOf(value interface{}) Value {
- return Value{untyped: value}
+// Value returns a Label for the supplied value.
+func Value(name string, value interface{}) Label {
+ return Label{Name: name, untyped: value}
}
// Interface returns the value.
// This will never panic, things that were not set using SetInterface will be
// unpacked and returned anyway.
-func (v Value) Interface() interface{} {
+func (v Label) Interface() interface{} {
switch {
case v.IsString():
return v.String()
@@ -108,16 +101,16 @@
}
}
-// StringOf returns a new Value for a string.
-func StringOf(s string) Value {
+// String returns a new Value for a string.
+func String(name string, s string) Label {
hdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
- return Value{packed: uint64(hdr.Len), untyped: stringptr(hdr.Data)}
+ return Label{Name: name, packed: uint64(hdr.Len), untyped: stringptr(hdr.Data)}
}
// String returns the value as a string.
// This does not panic if v's Kind is not String, instead, it returns a string
// representation of the value in all cases.
-func (v Value) String() string {
+func (v Label) String() string {
if sp, ok := v.untyped.(stringptr); ok {
var s string
hdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
@@ -145,19 +138,19 @@
}
// IsString returns true if the value was built with StringOf.
-func (v Value) IsString() bool {
+func (v Label) IsString() bool {
_, ok := v.untyped.(stringptr)
return ok
}
-// BytesOf returns a new Value for a string.
-func BytesOf(data []byte) Value {
+// Bytes returns a new Value for a string.
+func Bytes(name string, data []byte) Label {
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))
- return Value{packed: uint64(hdr.Len), untyped: bytesptr(hdr.Data)}
+ return Label{Name: name, packed: uint64(hdr.Len), untyped: bytesptr(hdr.Data)}
}
// Bytes returns the value as a bytes array.
-func (v Value) Bytes() []byte {
+func (v Label) Bytes() []byte {
bp, ok := v.untyped.(bytesptr)
if !ok {
panic("Bytes called on non []byte value")
@@ -171,19 +164,19 @@
}
// IsBytes returns true if the value was built with BytesOf.
-func (v Value) IsBytes() bool {
+func (v Label) IsBytes() bool {
_, ok := v.untyped.(bytesptr)
return ok
}
-// Int64Of returns a new Value for a signed integer.
-func Int64Of(u int64) Value {
- return Value{packed: uint64(u), untyped: int64Kind{}}
+// Int64 returns a new Value for a signed integer.
+func Int64(name string, u int64) Label {
+ return Label{Name: name, packed: uint64(u), untyped: int64Kind{}}
}
// Int64 returns the int64 from a value that was set with SetInt64.
// It will panic for any value for which IsInt64 is not true.
-func (v Value) Int64() int64 {
+func (v Label) Int64() int64 {
if !v.IsInt64() {
panic("Int64 called on non int64 value")
}
@@ -191,19 +184,19 @@
}
// IsInt64 returns true if the value was built with SetInt64.
-func (v Value) IsInt64() bool {
+func (v Label) IsInt64() bool {
_, ok := v.untyped.(int64Kind)
return ok
}
-// Uint64Of returns a new Value for an unsigned integer.
-func Uint64Of(u uint64) Value {
- return Value{packed: u, untyped: uint64Kind{}}
+// Uint64 returns a new Value for an unsigned integer.
+func Uint64(name string, u uint64) Label {
+ return Label{Name: name, packed: u, untyped: uint64Kind{}}
}
// Uint64 returns the uint64 from a value that was set with SetUint64.
// It will panic for any value for which IsUint64 is not true.
-func (v Value) Uint64() uint64 {
+func (v Label) Uint64() uint64 {
if !v.IsUint64() {
panic("Uint64 called on non uint64 value")
}
@@ -211,19 +204,19 @@
}
// IsUint64 returns true if the value was built with SetUint64.
-func (v Value) IsUint64() bool {
+func (v Label) IsUint64() bool {
_, ok := v.untyped.(uint64Kind)
return ok
}
-// Float64Of returns a new Value for a floating point number.
-func Float64Of(f float64) Value {
- return Value{packed: math.Float64bits(f), untyped: float64Kind{}}
+// Float64 returns a new Value for a floating point number.
+func Float64(name string, f float64) Label {
+ return Label{Name: name, packed: math.Float64bits(f), untyped: float64Kind{}}
}
// Float64 returns the float64 from a value that was set with SetFloat64.
// It will panic for any value for which IsFloat64 is not true.
-func (v Value) Float64() float64 {
+func (v Label) Float64() float64 {
if !v.IsFloat64() {
panic("Float64 called on non float64 value")
}
@@ -231,22 +224,22 @@
}
// IsFloat64 returns true if the value was built with SetFloat64.
-func (v Value) IsFloat64() bool {
+func (v Label) IsFloat64() bool {
_, ok := v.untyped.(float64Kind)
return ok
}
-// BoolOf returns a new Value for a bool.
-func BoolOf(b bool) Value {
+// Bool returns a new Value for a bool.
+func Bool(name string, b bool) Label {
if b {
- return Value{packed: 1, untyped: boolKind{}}
+ return Label{Name: name, packed: 1, untyped: boolKind{}}
}
- return Value{packed: 0, untyped: boolKind{}}
+ return Label{Name: name, packed: 0, untyped: boolKind{}}
}
// Bool returns the bool from a value that was set with SetBool.
// It will panic for any value for which IsBool is not true.
-func (v Value) Bool() bool {
+func (v Label) Bool() bool {
if !v.IsBool() {
panic("Bool called on non bool value")
}
@@ -257,23 +250,23 @@
}
// IsBool returns true if the value was built with SetBool.
-func (v Value) IsBool() bool {
+func (v Label) IsBool() bool {
_, ok := v.untyped.(boolKind)
return ok
}
-func DurationOf(d time.Duration) Value {
- return Value{packed: uint64(d), untyped: durationKind{}}
+func Duration(name string, d time.Duration) Label {
+ return Label{Name: name, packed: uint64(d), untyped: durationKind{}}
}
-func (v Value) Duration() time.Duration {
+func (v Label) Duration() time.Duration {
if !v.IsDuration() {
panic("Duration called on non-Duration value")
}
return time.Duration(v.packed)
}
-func (v Value) IsDuration() bool {
+func (v Label) IsDuration() bool {
_, ok := v.untyped.(durationKind)
return ok
}
diff --git a/event/label_test.go b/event/label_test.go
index 6617f61..7ca43a8 100644
--- a/event/label_test.go
+++ b/event/label_test.go
@@ -13,34 +13,34 @@
func TestOfAs(t *testing.T) {
const i = 3
- var v event.Value
- v = event.Int64Of(i)
+ var v event.Label
+ v = event.Int64("key", i)
if got := v.Int64(); got != i {
t.Errorf("got %v, want %v", got, i)
}
- v = event.Uint64Of(i)
+ v = event.Uint64("key", i)
if got := v.Uint64(); got != i {
t.Errorf("got %v, want %v", got, i)
}
- v = event.Float64Of(i)
+ v = event.Float64("key", i)
if got := v.Float64(); got != i {
t.Errorf("got %v, want %v", got, i)
}
- v = event.BoolOf(true)
+ v = event.Bool("key", true)
if got := v.Bool(); got != true {
t.Errorf("got %v, want %v", got, true)
}
const s = "foo"
- v = event.StringOf(s)
+ v = event.String("key", s)
if got := v.String(); got != s {
t.Errorf("got %v, want %v", got, s)
}
tm := time.Now()
- v = event.ValueOf(tm)
+ v = event.Value("key", tm)
if got := v.Interface(); got != tm {
t.Errorf("got %v, want %v", got, tm)
}
- var vnil event.Value
+ var vnil event.Label
if got := vnil.Interface(); got != nil {
t.Errorf("got %v, want nil", got)
}
@@ -48,18 +48,18 @@
func TestEqual(t *testing.T) {
var x, y int
- vals := []event.Value{
+ vals := []event.Label{
{},
- event.Int64Of(1),
- event.Int64Of(2),
- event.Uint64Of(3),
- event.Uint64Of(4),
- event.Float64Of(3.5),
- event.Float64Of(3.7),
- event.BoolOf(true),
- event.BoolOf(false),
- event.ValueOf(&x),
- event.ValueOf(&y),
+ event.Int64("key", 1),
+ event.Int64("key", 2),
+ event.Uint64("key", 3),
+ event.Uint64("key", 4),
+ event.Float64("key", 3.5),
+ event.Float64("key", 3.7),
+ event.Bool("key", true),
+ event.Bool("key", false),
+ event.Value("key", &x),
+ event.Value("key", &y),
}
for i, v1 := range vals {
for j, v2 := range vals {
@@ -87,10 +87,10 @@
name string
f func()
}{
- {"int64", func() { event.Float64Of(3).Int64() }},
- {"uint64", func() { event.Int64Of(3).Uint64() }},
- {"float64", func() { event.Uint64Of(3).Float64() }},
- {"bool", func() { event.Int64Of(3).Bool() }},
+ {"int64", func() { event.Float64("key", 3).Int64() }},
+ {"uint64", func() { event.Int64("key", 3).Uint64() }},
+ {"float64", func() { event.Uint64("key", 3).Float64() }},
+ {"bool", func() { event.Int64("key", 3).Bool() }},
} {
if !panics(test.f) {
t.Errorf("%s: got no panic, want panic", test.name)
@@ -100,15 +100,15 @@
func TestString(t *testing.T) {
for _, test := range []struct {
- v event.Value
+ v event.Label
want string
}{
- {event.Int64Of(-3), "-3"},
- {event.Uint64Of(3), "3"},
- {event.Float64Of(.15), "0.15"},
- {event.BoolOf(true), "true"},
- {event.StringOf("foo"), "foo"},
- {event.ValueOf(time.Duration(3 * time.Second)), "3s"},
+ {event.Int64("key", -3), "-3"},
+ {event.Uint64("key", 3), "3"},
+ {event.Float64("key", .15), "0.15"},
+ {event.Bool("key", true), "true"},
+ {event.String("key", "foo"), "foo"},
+ {event.Value("key", time.Duration(3*time.Second)), "3s"},
} {
if got := test.v.String(); got != test.want {
t.Errorf("%#v: got %q, want %q", test.v, got, test.want)
@@ -128,12 +128,12 @@
p = &i
)
a := int(testing.AllocsPerRun(5, func() {
- i = event.Int64Of(1).Int64()
- u = event.Uint64Of(1).Uint64()
- f = event.Float64Of(1).Float64()
- b = event.BoolOf(true).Bool()
- s = event.StringOf("foo").String()
- x = event.ValueOf(p).Interface()
+ i = event.Int64("key", 1).Int64()
+ u = event.Uint64("key", 1).Uint64()
+ f = event.Float64("key", 1).Float64()
+ b = event.Bool("key", true).Bool()
+ s = event.String("key", "foo").String()
+ x = event.Value("key", p).Interface()
}))
if a != 0 {
t.Errorf("got %d allocs, want zero", a)
diff --git a/event/metric.go b/event/metric.go
index 143a5a3..a71f1f1 100644
--- a/event/metric.go
+++ b/event/metric.go
@@ -60,12 +60,6 @@
func (m *MetricDescriptor) Namespace() string { return m.namespace }
func (m *MetricDescriptor) Description() string { return m.description }
-// A MetricValue is a pair of a Metric and a Value.
-type MetricValue struct {
- m Metric
- v Value
-}
-
// A Counter is a metric that counts something cumulatively.
type Counter struct {
*MetricDescriptor
@@ -87,7 +81,7 @@
func (c *Counter) Record(ctx context.Context, v uint64, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
- record(ev, c, Uint64Of(v))
+ record(ev, c, Uint64(MetricVal, v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
@@ -115,35 +109,35 @@
func (g *FloatGauge) Record(ctx context.Context, v float64, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
- record(ev, g, Float64Of(v))
+ record(ev, g, Float64(MetricVal, v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
}
-// A Duration records a distribution of durations.
+// A DurationDistribution records a distribution of durations.
// TODO(generics): Distribution[T]
-type Duration struct {
+type DurationDistribution struct {
*MetricDescriptor
}
// NewDuration creates a new Duration with the given name.
-func NewDuration(name, description string) *Duration {
- return &Duration{newMetricDescriptor(name, description)}
+func NewDuration(name, description string) *DurationDistribution {
+ return &DurationDistribution{newMetricDescriptor(name, description)}
}
// Descriptor returns the receiver's MetricDescriptor.
-func (d *Duration) Descriptor() *MetricDescriptor {
+func (d *DurationDistribution) Descriptor() *MetricDescriptor {
return d.MetricDescriptor
}
// Record converts its argument into a Value and returns a MetricValue with the
// receiver and the value. It is intended to be used as an argument to
// Builder.Metric.
-func (d *Duration) Record(ctx context.Context, v time.Duration, labels ...Label) {
+func (d *DurationDistribution) Record(ctx context.Context, v time.Duration, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
- record(ev, d, DurationOf(v))
+ record(ev, d, Duration(MetricVal, v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
@@ -170,12 +164,12 @@
func (d *IntDistribution) Record(ctx context.Context, v int64, labels ...Label) {
ev := New(ctx, MetricKind)
if ev != nil {
- record(ev, d, Int64Of(v))
+ record(ev, d, Int64(MetricVal, v))
ev.Labels = append(ev.Labels, labels...)
ev.Deliver()
}
}
-func record(ev *Event, m Metric, v Value) {
- ev.Labels = append(ev.Labels, MetricVal.Of(v), MetricKey.Of(ValueOf(m)))
+func record(ev *Event, m Metric, l Label) {
+ ev.Labels = append(ev.Labels, l, Value(MetricKey, m))
}
diff --git a/event/otel/trace.go b/event/otel/trace.go
index 2c43edf..06883e6 100644
--- a/event/otel/trace.go
+++ b/event/otel/trace.go
@@ -44,11 +44,11 @@
for _, l := range ls {
switch l.Name {
case "link":
- opts = append(opts, trace.WithLinks(l.Value.Interface().(trace.Link)))
+ opts = append(opts, trace.WithLinks(l.Interface().(trace.Link)))
case "newRoot":
opts = append(opts, trace.WithNewRoot())
case "spanKind":
- opts = append(opts, trace.WithSpanKind(l.Value.Interface().(trace.SpanKind)))
+ opts = append(opts, trace.WithSpanKind(l.Interface().(trace.SpanKind)))
}
}
return opts
diff --git a/event/severity/severity.go b/event/severity/severity.go
index 64e1441..7d30cab 100644
--- a/event/severity/severity.go
+++ b/event/severity/severity.go
@@ -42,12 +42,12 @@
// Of creates a label for the level.
func (l Level) Label() event.Label {
- return event.Label{Name: Key, Value: event.ValueOf(l)}
+ return event.Value(Key, l)
}
// From can be used to get a value from a Label.
func From(t event.Label) Level {
- return t.Value.Interface().(Level)
+ return t.Interface().(Level)
}
func (l Level) Log(ctx context.Context, msg string, labels ...event.Label) {