github.com/kiali/kiali@v1.84.0/tracing/jaeger/model/keyvalue.go (about) 1 // Copyright (c) 2019 The Jaeger Authors. 2 // Copyright (c) 2017 Uber Technologies, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 // Cloned from github.com/jaegertracing/jaeger/ 17 18 //nolint 19 package model 20 21 import ( 22 "bytes" 23 "encoding/binary" 24 "encoding/hex" 25 "fmt" 26 "io" 27 "sort" 28 "strconv" 29 ) 30 31 // These constants are kept mostly for backwards compatibility. 32 const ( 33 // StringType indicates the value is a unicode string 34 StringType = ValueType_STRING 35 // BoolType indicates the value is a Boolean encoded as int64 number 0 or 1 36 BoolType = ValueType_BOOL 37 // Int64Type indicates the value is an int64 number 38 Int64Type = ValueType_INT64 39 // Float64Type indicates the value is a float64 number stored as int64 40 Float64Type = ValueType_FLOAT64 41 // BinaryType indicates the value is binary blob stored as a byte array 42 BinaryType = ValueType_BINARY 43 ) 44 45 // KeyValues is a type alias that exposes convenience functions like Sort, FindByKey. 46 type KeyValues []*KeyValue 47 48 // String creates a String-typed KeyValue 49 func String(key string, value string) KeyValue { 50 return KeyValue{Key: key, VType: StringType, VStr: value} 51 } 52 53 // Bool creates a Bool-typed KeyValue 54 func Bool(key string, value bool) KeyValue { 55 return KeyValue{Key: key, VType: BoolType, VBool: value} 56 } 57 58 // Int64 creates a Int64-typed KeyValue 59 func Int64(key string, value int64) KeyValue { 60 return KeyValue{Key: key, VType: Int64Type, VInt64: value} 61 } 62 63 // Float64 creates a Float64-typed KeyValue 64 func Float64(key string, value float64) KeyValue { 65 return KeyValue{Key: key, VType: Float64Type, VFloat64: value} 66 } 67 68 // Binary creates a Binary-typed KeyValue 69 func Binary(key string, value []byte) KeyValue { 70 return KeyValue{Key: key, VType: BinaryType, VBinary: value} 71 } 72 73 // Bool returns the Boolean value stored in this KeyValue or false if it stores a different type. 74 // The caller must check VType before using this method. 75 func (kv *KeyValue) Bool() bool { 76 if kv.VType == BoolType { 77 return kv.VBool 78 } 79 return false 80 } 81 82 // Int64 returns the Int64 value stored in this KeyValue or 0 if it stores a different type. 83 // The caller must check VType before using this method. 84 func (kv *KeyValue) Int64() int64 { 85 if kv.VType == Int64Type { 86 return kv.VInt64 87 } 88 return 0 89 } 90 91 // Float64 returns the Float64 value stored in this KeyValue or 0 if it stores a different type. 92 // The caller must check VType before using this method. 93 func (kv *KeyValue) Float64() float64 { 94 if kv.VType == Float64Type { 95 return kv.VFloat64 96 } 97 return 0 98 } 99 100 // Binary returns the blob ([]byte) value stored in this KeyValue or nil if it stores a different type. 101 // The caller must check VType before using this method. 102 func (kv *KeyValue) Binary() []byte { 103 if kv.VType == BinaryType { 104 return kv.VBinary 105 } 106 return nil 107 } 108 109 // Value returns typed values stored in KeyValue as interface{}. 110 func (kv *KeyValue) Value() interface{} { 111 switch kv.VType { 112 case StringType: 113 return kv.VStr 114 case BoolType: 115 return kv.VBool 116 case Int64Type: 117 return kv.VInt64 118 case Float64Type: 119 return kv.VFloat64 120 case BinaryType: 121 return kv.VBinary 122 default: 123 return fmt.Errorf("unknown type %d", kv.VType) 124 } 125 } 126 127 // AsStringLossy returns a potentially lossy string representation of the value. 128 func (kv *KeyValue) AsStringLossy() string { 129 return kv.asString(true) 130 } 131 132 // AsString returns a string representation of the value. 133 func (kv *KeyValue) AsString() string { 134 return kv.asString(false) 135 } 136 137 func (kv *KeyValue) asString(truncate bool) string { 138 switch kv.VType { 139 case StringType: 140 return kv.VStr 141 case BoolType: 142 if kv.Bool() { 143 return "true" 144 } 145 return "false" 146 case Int64Type: 147 return strconv.FormatInt(kv.Int64(), 10) 148 case Float64Type: 149 return strconv.FormatFloat(kv.Float64(), 'g', 10, 64) 150 case BinaryType: 151 if truncate && len(kv.VBinary) > 256 { 152 return hex.EncodeToString(kv.VBinary[0:256]) + "..." 153 } 154 return hex.EncodeToString(kv.VBinary) 155 default: 156 return fmt.Sprintf("unknown type %d", kv.VType) 157 } 158 } 159 160 // IsLess compares KeyValue object with another KeyValue. 161 // The order is based first on the keys, then on type, and finally on the value. 162 func (kv *KeyValue) IsLess(two *KeyValue) bool { 163 return KeyValueCompare(kv, two) < 0 164 } 165 166 func (kvs KeyValues) Len() int { return len(kvs) } 167 func (kvs KeyValues) Swap(i, j int) { kvs[i], kvs[j] = kvs[j], kvs[i] } 168 func (kvs KeyValues) Less(i, j int) bool { 169 return kvs[i].IsLess(kvs[j]) 170 } 171 172 // Sort does in-place sorting of KeyValues, then by value type, then by value. 173 func (kvs KeyValues) Sort() { 174 sort.Sort(kvs) 175 } 176 177 // FindByKey scans the list of key-values searching for the first one with the given key. 178 // Returns found tag and a boolean flag indicating if the search was successful. 179 func (kvs KeyValues) FindByKey(key string) (*KeyValue, bool) { 180 for _, kv := range kvs { 181 if kv.Key == key { 182 return kv, true 183 } 184 } 185 return &KeyValue{}, false 186 } 187 188 // Equal compares KeyValues with another list. Both lists must be already sorted. 189 func (kvs KeyValues) Equal(other KeyValues) bool { 190 l1, l2 := len(kvs), len(other) 191 if l1 != l2 { 192 return false 193 } 194 for i := 0; i < l1; i++ { 195 if !kvs[i].Equal(&other[i]) { 196 return false 197 } 198 } 199 return true 200 } 201 202 // Hash implements Hash from Hashable. 203 func (kvs KeyValues) Hash(w io.Writer) error { 204 for i := range kvs { 205 if err := kvs[i].Hash(w); err != nil { 206 return err 207 } 208 } 209 return nil 210 } 211 212 // Hash implements Hash from Hashable. 213 func (kv KeyValue) Hash(w io.Writer) error { 214 if _, err := w.Write([]byte(kv.Key)); err != nil { 215 return err 216 } 217 if err := binary.Write(w, binary.BigEndian, uint16(kv.VType)); err != nil { 218 return err 219 } 220 var err error 221 switch kv.VType { 222 case StringType: 223 _, err = w.Write([]byte(kv.VStr)) 224 case BoolType: 225 err = binary.Write(w, binary.BigEndian, kv.VBool) 226 case Int64Type: 227 err = binary.Write(w, binary.BigEndian, kv.VInt64) 228 case Float64Type: 229 err = binary.Write(w, binary.BigEndian, kv.VFloat64) 230 case BinaryType: 231 _, err = w.Write(kv.VBinary) 232 default: 233 err = fmt.Errorf("unknown type %d", kv.VType) 234 } 235 return err 236 } 237 238 func KeyValueCompare(this *KeyValue, that interface{}) int { 239 if that == nil { 240 if this == nil { 241 return 0 242 } 243 return 1 244 } 245 246 that1, ok := that.(*KeyValue) 247 if !ok { 248 that2, ok := that.(KeyValue) 249 if ok { 250 that1 = &that2 251 } else { 252 return 1 253 } 254 } 255 if that1 == nil { 256 if this == nil { 257 return 0 258 } 259 return 1 260 } else if this == nil { 261 return -1 262 } 263 if this.Key != that1.Key { 264 if this.Key < that1.Key { 265 return -1 266 } 267 return 1 268 } 269 if this.VType != that1.VType { 270 if this.VType < that1.VType { 271 return -1 272 } 273 return 1 274 } 275 if this.VStr != that1.VStr { 276 if this.VStr < that1.VStr { 277 return -1 278 } 279 return 1 280 } 281 if this.VBool != that1.VBool { 282 if !this.VBool { 283 return -1 284 } 285 return 1 286 } 287 if this.VInt64 != that1.VInt64 { 288 if this.VInt64 < that1.VInt64 { 289 return -1 290 } 291 return 1 292 } 293 if this.VFloat64 != that1.VFloat64 { 294 if this.VFloat64 < that1.VFloat64 { 295 return -1 296 } 297 return 1 298 } 299 if c := bytes.Compare(this.VBinary, that1.VBinary); c != 0 { 300 return c 301 } 302 return 0 303 } 304 func (this *KeyValue) Equal(that interface{}) bool { 305 if that == nil { 306 return this == nil 307 } 308 309 that1, ok := that.(*KeyValue) 310 if !ok { 311 that2, ok := that.(KeyValue) 312 if ok { 313 that1 = &that2 314 } else { 315 return false 316 } 317 } 318 if that1 == nil { 319 return this == nil 320 } else if this == nil { 321 return false 322 } 323 if this.Key != that1.Key { 324 return false 325 } 326 if this.VType != that1.VType { 327 return false 328 } 329 if this.VStr != that1.VStr { 330 return false 331 } 332 if this.VBool != that1.VBool { 333 return false 334 } 335 if this.VInt64 != that1.VInt64 { 336 return false 337 } 338 if this.VFloat64 != that1.VFloat64 { 339 return false 340 } 341 if !bytes.Equal(this.VBinary, that1.VBinary) { 342 return false 343 } 344 return true 345 }