value.go

  1// Copyright The OpenTelemetry Authors
  2// SPDX-License-Identifier: Apache-2.0
  3
  4package attribute // import "go.opentelemetry.io/otel/attribute"
  5
  6import (
  7	"encoding/json"
  8	"fmt"
  9	"reflect"
 10	"strconv"
 11
 12	"go.opentelemetry.io/otel/internal"
 13	"go.opentelemetry.io/otel/internal/attribute"
 14)
 15
 16//go:generate stringer -type=Type
 17
 18// Type describes the type of the data Value holds.
 19type Type int // nolint: revive  // redefines builtin Type.
 20
 21// Value represents the value part in key-value pairs.
 22type Value struct {
 23	vtype    Type
 24	numeric  uint64
 25	stringly string
 26	slice    interface{}
 27}
 28
 29const (
 30	// INVALID is used for a Value with no value set.
 31	INVALID Type = iota
 32	// BOOL is a boolean Type Value.
 33	BOOL
 34	// INT64 is a 64-bit signed integral Type Value.
 35	INT64
 36	// FLOAT64 is a 64-bit floating point Type Value.
 37	FLOAT64
 38	// STRING is a string Type Value.
 39	STRING
 40	// BOOLSLICE is a slice of booleans Type Value.
 41	BOOLSLICE
 42	// INT64SLICE is a slice of 64-bit signed integral numbers Type Value.
 43	INT64SLICE
 44	// FLOAT64SLICE is a slice of 64-bit floating point numbers Type Value.
 45	FLOAT64SLICE
 46	// STRINGSLICE is a slice of strings Type Value.
 47	STRINGSLICE
 48)
 49
 50// BoolValue creates a BOOL Value.
 51func BoolValue(v bool) Value {
 52	return Value{
 53		vtype:   BOOL,
 54		numeric: internal.BoolToRaw(v),
 55	}
 56}
 57
 58// BoolSliceValue creates a BOOLSLICE Value.
 59func BoolSliceValue(v []bool) Value {
 60	return Value{vtype: BOOLSLICE, slice: attribute.BoolSliceValue(v)}
 61}
 62
 63// IntValue creates an INT64 Value.
 64func IntValue(v int) Value {
 65	return Int64Value(int64(v))
 66}
 67
 68// IntSliceValue creates an INTSLICE Value.
 69func IntSliceValue(v []int) Value {
 70	var int64Val int64
 71	cp := reflect.New(reflect.ArrayOf(len(v), reflect.TypeOf(int64Val)))
 72	for i, val := range v {
 73		cp.Elem().Index(i).SetInt(int64(val))
 74	}
 75	return Value{
 76		vtype: INT64SLICE,
 77		slice: cp.Elem().Interface(),
 78	}
 79}
 80
 81// Int64Value creates an INT64 Value.
 82func Int64Value(v int64) Value {
 83	return Value{
 84		vtype:   INT64,
 85		numeric: internal.Int64ToRaw(v),
 86	}
 87}
 88
 89// Int64SliceValue creates an INT64SLICE Value.
 90func Int64SliceValue(v []int64) Value {
 91	return Value{vtype: INT64SLICE, slice: attribute.Int64SliceValue(v)}
 92}
 93
 94// Float64Value creates a FLOAT64 Value.
 95func Float64Value(v float64) Value {
 96	return Value{
 97		vtype:   FLOAT64,
 98		numeric: internal.Float64ToRaw(v),
 99	}
100}
101
102// Float64SliceValue creates a FLOAT64SLICE Value.
103func Float64SliceValue(v []float64) Value {
104	return Value{vtype: FLOAT64SLICE, slice: attribute.Float64SliceValue(v)}
105}
106
107// StringValue creates a STRING Value.
108func StringValue(v string) Value {
109	return Value{
110		vtype:    STRING,
111		stringly: v,
112	}
113}
114
115// StringSliceValue creates a STRINGSLICE Value.
116func StringSliceValue(v []string) Value {
117	return Value{vtype: STRINGSLICE, slice: attribute.StringSliceValue(v)}
118}
119
120// Type returns a type of the Value.
121func (v Value) Type() Type {
122	return v.vtype
123}
124
125// AsBool returns the bool value. Make sure that the Value's type is
126// BOOL.
127func (v Value) AsBool() bool {
128	return internal.RawToBool(v.numeric)
129}
130
131// AsBoolSlice returns the []bool value. Make sure that the Value's type is
132// BOOLSLICE.
133func (v Value) AsBoolSlice() []bool {
134	if v.vtype != BOOLSLICE {
135		return nil
136	}
137	return v.asBoolSlice()
138}
139
140func (v Value) asBoolSlice() []bool {
141	return attribute.AsBoolSlice(v.slice)
142}
143
144// AsInt64 returns the int64 value. Make sure that the Value's type is
145// INT64.
146func (v Value) AsInt64() int64 {
147	return internal.RawToInt64(v.numeric)
148}
149
150// AsInt64Slice returns the []int64 value. Make sure that the Value's type is
151// INT64SLICE.
152func (v Value) AsInt64Slice() []int64 {
153	if v.vtype != INT64SLICE {
154		return nil
155	}
156	return v.asInt64Slice()
157}
158
159func (v Value) asInt64Slice() []int64 {
160	return attribute.AsInt64Slice(v.slice)
161}
162
163// AsFloat64 returns the float64 value. Make sure that the Value's
164// type is FLOAT64.
165func (v Value) AsFloat64() float64 {
166	return internal.RawToFloat64(v.numeric)
167}
168
169// AsFloat64Slice returns the []float64 value. Make sure that the Value's type is
170// FLOAT64SLICE.
171func (v Value) AsFloat64Slice() []float64 {
172	if v.vtype != FLOAT64SLICE {
173		return nil
174	}
175	return v.asFloat64Slice()
176}
177
178func (v Value) asFloat64Slice() []float64 {
179	return attribute.AsFloat64Slice(v.slice)
180}
181
182// AsString returns the string value. Make sure that the Value's type
183// is STRING.
184func (v Value) AsString() string {
185	return v.stringly
186}
187
188// AsStringSlice returns the []string value. Make sure that the Value's type is
189// STRINGSLICE.
190func (v Value) AsStringSlice() []string {
191	if v.vtype != STRINGSLICE {
192		return nil
193	}
194	return v.asStringSlice()
195}
196
197func (v Value) asStringSlice() []string {
198	return attribute.AsStringSlice(v.slice)
199}
200
201type unknownValueType struct{}
202
203// AsInterface returns Value's data as interface{}.
204func (v Value) AsInterface() interface{} {
205	switch v.Type() {
206	case BOOL:
207		return v.AsBool()
208	case BOOLSLICE:
209		return v.asBoolSlice()
210	case INT64:
211		return v.AsInt64()
212	case INT64SLICE:
213		return v.asInt64Slice()
214	case FLOAT64:
215		return v.AsFloat64()
216	case FLOAT64SLICE:
217		return v.asFloat64Slice()
218	case STRING:
219		return v.stringly
220	case STRINGSLICE:
221		return v.asStringSlice()
222	}
223	return unknownValueType{}
224}
225
226// Emit returns a string representation of Value's data.
227func (v Value) Emit() string {
228	switch v.Type() {
229	case BOOLSLICE:
230		return fmt.Sprint(v.asBoolSlice())
231	case BOOL:
232		return strconv.FormatBool(v.AsBool())
233	case INT64SLICE:
234		j, err := json.Marshal(v.asInt64Slice())
235		if err != nil {
236			return fmt.Sprintf("invalid: %v", v.asInt64Slice())
237		}
238		return string(j)
239	case INT64:
240		return strconv.FormatInt(v.AsInt64(), 10)
241	case FLOAT64SLICE:
242		j, err := json.Marshal(v.asFloat64Slice())
243		if err != nil {
244			return fmt.Sprintf("invalid: %v", v.asFloat64Slice())
245		}
246		return string(j)
247	case FLOAT64:
248		return fmt.Sprint(v.AsFloat64())
249	case STRINGSLICE:
250		j, err := json.Marshal(v.asStringSlice())
251		if err != nil {
252			return fmt.Sprintf("invalid: %v", v.asStringSlice())
253		}
254		return string(j)
255	case STRING:
256		return v.stringly
257	default:
258		return "unknown"
259	}
260}
261
262// MarshalJSON returns the JSON encoding of the Value.
263func (v Value) MarshalJSON() ([]byte, error) {
264	var jsonVal struct {
265		Type  string
266		Value interface{}
267	}
268	jsonVal.Type = v.Type().String()
269	jsonVal.Value = v.AsInterface()
270	return json.Marshal(jsonVal)
271}