| // Copyright The OpenTelemetry Authors |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package label |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "reflect" |
| "strconv" |
| "unsafe" |
| |
| "go.opentelemetry.io/otel/internal" |
| ) |
| |
| //go:generate stringer -type=Type |
| |
| // Type describes the type of the data Value holds. |
| type Type int |
| |
| // Value represents the value part in key-value pairs. |
| type Value struct { |
| vtype Type |
| numeric uint64 |
| stringly string |
| // TODO Lazy value type? |
| |
| array interface{} |
| } |
| |
| const ( |
| INVALID Type = iota // No value. |
| BOOL // Boolean value, use AsBool() to get it. |
| INT32 // 32 bit signed integral value, use AsInt32() to get it. |
| INT64 // 64 bit signed integral value, use AsInt64() to get it. |
| UINT32 // 32 bit unsigned integral value, use AsUint32() to get it. |
| UINT64 // 64 bit unsigned integral value, use AsUint64() to get it. |
| FLOAT32 // 32 bit floating point value, use AsFloat32() to get it. |
| FLOAT64 // 64 bit floating point value, use AsFloat64() to get it. |
| STRING // String value, use AsString() to get it. |
| ARRAY // Array value of arbitrary type, use AsArray() to get it. |
| ) |
| |
| // BoolValue creates a BOOL Value. |
| func BoolValue(v bool) Value { |
| return Value{ |
| vtype: BOOL, |
| numeric: internal.BoolToRaw(v), |
| } |
| } |
| |
| // Int64Value creates an INT64 Value. |
| func Int64Value(v int64) Value { |
| return Value{ |
| vtype: INT64, |
| numeric: internal.Int64ToRaw(v), |
| } |
| } |
| |
| // Uint64Value creates a UINT64 Value. |
| func Uint64Value(v uint64) Value { |
| return Value{ |
| vtype: UINT64, |
| numeric: internal.Uint64ToRaw(v), |
| } |
| } |
| |
| // Float64Value creates a FLOAT64 Value. |
| func Float64Value(v float64) Value { |
| return Value{ |
| vtype: FLOAT64, |
| numeric: internal.Float64ToRaw(v), |
| } |
| } |
| |
| // Int32Value creates an INT32 Value. |
| func Int32Value(v int32) Value { |
| return Value{ |
| vtype: INT32, |
| numeric: internal.Int32ToRaw(v), |
| } |
| } |
| |
| // Uint32Value creates a UINT32 Value. |
| func Uint32Value(v uint32) Value { |
| return Value{ |
| vtype: UINT32, |
| numeric: internal.Uint32ToRaw(v), |
| } |
| } |
| |
| // Float32Value creates a FLOAT32 Value. |
| func Float32Value(v float32) Value { |
| return Value{ |
| vtype: FLOAT32, |
| numeric: internal.Float32ToRaw(v), |
| } |
| } |
| |
| // StringValue creates a STRING Value. |
| func StringValue(v string) Value { |
| return Value{ |
| vtype: STRING, |
| stringly: v, |
| } |
| } |
| |
| // IntValue creates either an INT32 or an INT64 Value, depending on whether |
| // the int type is 32 or 64 bits wide. |
| func IntValue(v int) Value { |
| if unsafe.Sizeof(v) == 4 { |
| return Int32Value(int32(v)) |
| } |
| return Int64Value(int64(v)) |
| } |
| |
| // UintValue creates either a UINT32 or a UINT64 Value, depending on whether |
| // the uint type is 32 or 64 bits wide. |
| func UintValue(v uint) Value { |
| if unsafe.Sizeof(v) == 4 { |
| return Uint32Value(uint32(v)) |
| } |
| return Uint64Value(uint64(v)) |
| } |
| |
| // ArrayValue creates an ARRAY value from an array or slice. |
| // Only arrays or slices of bool, int, int32, int64, uint, uint32, uint64, |
| // float, float32, float64, or string types are allowed. Specifically, arrays |
| // and slices can not contain other arrays, slices, structs, or non-standard |
| // types. If the passed value is not an array or slice of these types an |
| // INVALID value is returned. |
| func ArrayValue(v interface{}) Value { |
| switch reflect.TypeOf(v).Kind() { |
| case reflect.Array, reflect.Slice: |
| // get array type regardless of dimensions |
| typ := reflect.TypeOf(v).Elem() |
| kind := typ.Kind() |
| switch kind { |
| case reflect.Bool, reflect.Int, reflect.Int32, reflect.Int64, |
| reflect.Float32, reflect.Float64, reflect.String, |
| reflect.Uint, reflect.Uint32, reflect.Uint64: |
| val := reflect.ValueOf(v) |
| length := val.Len() |
| frozen := reflect.Indirect(reflect.New(reflect.ArrayOf(length, typ))) |
| reflect.Copy(frozen, val) |
| return Value{ |
| vtype: ARRAY, |
| array: frozen.Interface(), |
| } |
| default: |
| return Value{vtype: INVALID} |
| } |
| } |
| return Value{vtype: INVALID} |
| } |
| |
| // Type returns a type of the Value. |
| func (v Value) Type() Type { |
| return v.vtype |
| } |
| |
| // AsBool returns the bool value. Make sure that the Value's type is |
| // BOOL. |
| func (v Value) AsBool() bool { |
| return internal.RawToBool(v.numeric) |
| } |
| |
| // AsInt32 returns the int32 value. Make sure that the Value's type is |
| // INT32. |
| func (v Value) AsInt32() int32 { |
| return internal.RawToInt32(v.numeric) |
| } |
| |
| // AsInt64 returns the int64 value. Make sure that the Value's type is |
| // INT64. |
| func (v Value) AsInt64() int64 { |
| return internal.RawToInt64(v.numeric) |
| } |
| |
| // AsUint32 returns the uint32 value. Make sure that the Value's type |
| // is UINT32. |
| func (v Value) AsUint32() uint32 { |
| return internal.RawToUint32(v.numeric) |
| } |
| |
| // AsUint64 returns the uint64 value. Make sure that the Value's type is |
| // UINT64. |
| func (v Value) AsUint64() uint64 { |
| return internal.RawToUint64(v.numeric) |
| } |
| |
| // AsFloat32 returns the float32 value. Make sure that the Value's |
| // type is FLOAT32. |
| func (v Value) AsFloat32() float32 { |
| return internal.RawToFloat32(v.numeric) |
| } |
| |
| // AsFloat64 returns the float64 value. Make sure that the Value's |
| // type is FLOAT64. |
| func (v Value) AsFloat64() float64 { |
| return internal.RawToFloat64(v.numeric) |
| } |
| |
| // AsString returns the string value. Make sure that the Value's type |
| // is STRING. |
| func (v Value) AsString() string { |
| return v.stringly |
| } |
| |
| // AsArray returns the array Value as an interface{}. |
| func (v Value) AsArray() interface{} { |
| return v.array |
| } |
| |
| type unknownValueType struct{} |
| |
| // AsInterface returns Value's data as interface{}. |
| func (v Value) AsInterface() interface{} { |
| switch v.Type() { |
| case ARRAY: |
| return v.AsArray() |
| case BOOL: |
| return v.AsBool() |
| case INT32: |
| return v.AsInt32() |
| case INT64: |
| return v.AsInt64() |
| case UINT32: |
| return v.AsUint32() |
| case UINT64: |
| return v.AsUint64() |
| case FLOAT32: |
| return v.AsFloat32() |
| case FLOAT64: |
| return v.AsFloat64() |
| case STRING: |
| return v.stringly |
| } |
| return unknownValueType{} |
| } |
| |
| // Emit returns a string representation of Value's data. |
| func (v Value) Emit() string { |
| switch v.Type() { |
| case ARRAY: |
| return fmt.Sprint(v.array) |
| case BOOL: |
| return strconv.FormatBool(v.AsBool()) |
| case INT32: |
| return strconv.FormatInt(int64(v.AsInt32()), 10) |
| case INT64: |
| return strconv.FormatInt(v.AsInt64(), 10) |
| case UINT32: |
| return strconv.FormatUint(uint64(v.AsUint32()), 10) |
| case UINT64: |
| return strconv.FormatUint(v.AsUint64(), 10) |
| case FLOAT32: |
| return fmt.Sprint(v.AsFloat32()) |
| case FLOAT64: |
| return fmt.Sprint(v.AsFloat64()) |
| case STRING: |
| return v.stringly |
| default: |
| return "unknown" |
| } |
| } |
| |
| // MarshalJSON returns the JSON encoding of the Value. |
| func (v Value) MarshalJSON() ([]byte, error) { |
| var jsonVal struct { |
| Type string |
| Value interface{} |
| } |
| jsonVal.Type = v.Type().String() |
| jsonVal.Value = v.AsInterface() |
| return json.Marshal(jsonVal) |
| } |