/
util.go
131 lines (122 loc) · 3.14 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016 Datadog, Inc.
package tracer
import (
"encoding/base64"
"fmt"
"strconv"
"strings"
"gopkg.in/DataDog/dd-trace-go.v1/internal/samplernames"
)
// toFloat64 attempts to convert value into a float64. If the value is an integer
// greater or equal to 2^53 or less than or equal to -2^53, it will not be converted
// into a float64 to avoid losing precision. If it succeeds in converting, toFloat64
// returns the value and true, otherwise 0 and false.
func toFloat64(value interface{}) (f float64, ok bool) {
const max = (int64(1) << 53) - 1
const min = -max
switch i := value.(type) {
case byte:
return float64(i), true
case float32:
return float64(i), true
case float64:
return i, true
case int:
return float64(i), true
case int8:
return float64(i), true
case int16:
return float64(i), true
case int32:
return float64(i), true
case int64:
if i > max || i < min {
return 0, false
}
return float64(i), true
case uint:
return float64(i), true
case uint16:
return float64(i), true
case uint32:
return float64(i), true
case uint64:
if i > uint64(max) {
return 0, false
}
return float64(i), true
case samplernames.SamplerName:
return float64(i), true
default:
return 0, false
}
}
// parseUint64 parses a uint64 from either an unsigned 64 bit base-10 string
// or a signed 64 bit base-10 string representing an unsigned integer
func parseUint64(str string) (uint64, error) {
if strings.HasPrefix(str, "-") {
id, err := strconv.ParseInt(str, 10, 64)
if err != nil {
return 0, err
}
return uint64(id), nil
}
return strconv.ParseUint(str, 10, 64)
}
func isValidPropagatableTraceTag(k, v string) error {
if len(k) == 0 {
return fmt.Errorf("key length must be greater than zero")
}
for _, ch := range k {
if ch < 32 || ch > 126 || ch == ' ' || ch == '=' || ch == ',' {
return fmt.Errorf("key contains an invalid character %d", ch)
}
}
if len(v) == 0 {
return fmt.Errorf("value length must be greater than zero")
}
for _, ch := range v {
if ch < 32 || ch > 126 || ch == '=' || ch == ',' {
return fmt.Errorf("value contains an invalid character %d", ch)
}
}
return nil
}
func parsePropagatableTraceTags(s string) (map[string]string, error) {
if len(s) == 0 {
return nil, nil
}
tags := make(map[string]string)
searchingKey, start := true, 0
var key string
for i, ch := range s {
switch ch {
case '=':
if searchingKey {
if i-start == 0 {
return nil, fmt.Errorf("invalid format")
}
key = s[start:i]
searchingKey, start = false, i+1
}
case ',':
if searchingKey || i-start == 0 {
return nil, fmt.Errorf("invalid format")
}
tags[key] = s[start:i]
searchingKey, start = true, i+1
}
}
if searchingKey || len(s)-start == 0 {
return nil, fmt.Errorf("invalid format")
}
tags[key] = s[start:]
return tags, nil
}
var b64 = base64.StdEncoding.WithPadding(base64.NoPadding)
func b64Encode(s string) string {
return b64.EncodeToString([]byte(s))
}