mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
internal/trace: interpret string ID arguments for experimental events
Currently one of the reasons experimental events are tricky to use is because: - There's no way to take advantage of the existing infrastructure, like strings and stacks, and - There's no way to attach arbitrary data to an event (except through strings, possibly). Fix this by abstracting away the raw arguments in an ExperimentalEvent and requiring access to the arguments via a new method, ArgValue. This returns a Value, which gives us an opportunity to construct a typed value for the raw argument dynamically, and a way to access existing tables. The type of the argument is deduced from conventions for the argument's name. This seems more than sufficient for experimental events. To make this work, we also need to add a "string" variant to the Value type. This may be a little confusing since they're primarily used for metrics, but one could imagine other scenarios in which this is useful, such as including build information in the trace as a metric, so I think this is fine. This change also updates the Value API to accomodate a String method for use with things that expect a fmt.Stringer, which means renaming the value assertion methods to have a "To" prefix. Change-Id: I43a2334f6cd306122c5b94641a6252ca4258b39f Reviewed-on: https://go-review.googlesource.com/c/go/+/645135 Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
659b895067
commit
49eba8b15b
6 changed files with 79 additions and 34 deletions
|
|
@ -4,12 +4,16 @@
|
|||
|
||||
package trace
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Value is a dynamically-typed value obtained from a trace.
|
||||
type Value struct {
|
||||
kind ValueKind
|
||||
scalar uint64
|
||||
kind ValueKind
|
||||
pointer unsafe.Pointer
|
||||
scalar uint64
|
||||
}
|
||||
|
||||
// ValueKind is the type of a dynamically-typed value from a trace.
|
||||
|
|
@ -18,6 +22,7 @@ type ValueKind uint8
|
|||
const (
|
||||
ValueBad ValueKind = iota
|
||||
ValueUint64
|
||||
ValueString
|
||||
)
|
||||
|
||||
// Kind returns the ValueKind of the value.
|
||||
|
|
@ -30,24 +35,41 @@ func (v Value) Kind() ValueKind {
|
|||
return v.kind
|
||||
}
|
||||
|
||||
// Uint64 returns the uint64 value for a MetricSampleUint64.
|
||||
// ToUint64 returns the uint64 value for a ValueUint64.
|
||||
//
|
||||
// Panics if this metric sample's Kind is not MetricSampleUint64.
|
||||
func (v Value) Uint64() uint64 {
|
||||
// Panics if this Value's Kind is not ValueUint64.
|
||||
func (v Value) ToUint64() uint64 {
|
||||
if v.kind != ValueUint64 {
|
||||
panic("Uint64 called on Value of a different Kind")
|
||||
panic("ToUint64 called on Value of a different Kind")
|
||||
}
|
||||
return v.scalar
|
||||
}
|
||||
|
||||
// valueAsString produces a debug string value.
|
||||
// ToString returns the uint64 value for a ValueString.
|
||||
//
|
||||
// This isn't just Value.String because we may want to use that to store
|
||||
// string values in the future.
|
||||
func valueAsString(v Value) string {
|
||||
// Panics if this Value's Kind is not ValueString.
|
||||
func (v Value) ToString() string {
|
||||
if v.kind != ValueString {
|
||||
panic("ToString called on Value of a different Kind")
|
||||
}
|
||||
return unsafe.String((*byte)(v.pointer), int(v.scalar))
|
||||
}
|
||||
|
||||
func uint64Value(x uint64) Value {
|
||||
return Value{kind: ValueUint64, scalar: x}
|
||||
}
|
||||
|
||||
func stringValue(s string) Value {
|
||||
return Value{kind: ValueString, scalar: uint64(len(s)), pointer: unsafe.Pointer(unsafe.StringData(s))}
|
||||
}
|
||||
|
||||
// String returns the string representation of the value.
|
||||
func (v Value) String() string {
|
||||
switch v.Kind() {
|
||||
case ValueUint64:
|
||||
return fmt.Sprintf("Uint64(%d)", v.scalar)
|
||||
return fmt.Sprintf("Value{Uint64(%d)}", v.ToUint64())
|
||||
case ValueString:
|
||||
return fmt.Sprintf("Value{String(%s)}", v.ToString())
|
||||
}
|
||||
return "Bad"
|
||||
return "Value{Bad}"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue