-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathutils.go
215 lines (191 loc) · 4.72 KB
/
utils.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package evaluation
import (
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"sync"
"time"
"github.com/Unknwon/com"
"github.com/ianlancetaylor/demangle"
"github.com/spf13/cast"
model "github.com/uber/jaeger/model/json"
)
func uptoIndex(arry []interface{}, idx int) int {
if len(arry) <= idx {
return len(arry) - 1
}
return idx
}
func toFloat64Slice(i interface{}) []float64 {
res, _ := toFloat64SliceE(i)
return res
}
func toFloat64SliceE(i interface{}) ([]float64, error) {
if i == nil {
return []float64{}, fmt.Errorf("unable to cast %#v of type %T to []float64", i, i)
}
switch v := i.(type) {
case []float64:
return v, nil
}
kind := reflect.TypeOf(i).Kind()
switch kind {
case reflect.Slice, reflect.Array:
s := reflect.ValueOf(i)
a := make([]float64, s.Len())
for j := 0; j < s.Len(); j++ {
val, err := cast.ToFloat64E(s.Index(j).Interface())
if err != nil {
return []float64{}, fmt.Errorf("unable to cast %#v of type %T to []float64", i, i)
}
a[j] = val
}
return a, nil
default:
return []float64{}, fmt.Errorf("unable to cast %#v of type %T to []float64", i, i)
}
}
func int64SliceToStringSlice(us []int64) []string {
res := make([]string, len(us))
for ii, u := range us {
res[ii] = cast.ToString(u)
}
return res
}
func float64SliceToStringSlice(us []float64) []string {
res := make([]string, len(us))
for ii, u := range us {
res[ii] = cast.ToString(u)
}
return res
}
func uint64SliceToStringSlice(us []uint64) []string {
res := make([]string, len(us))
for ii, u := range us {
res[ii] = cast.ToString(u)
}
return res
}
func predictSpanIndexOf(span model.Span, cPredictSpans Spans) int {
for ii, predictSpan := range cPredictSpans {
if span.ParentSpanID == predictSpan.SpanID {
return ii
}
for _, ref := range span.References {
if ref.RefType == model.ChildOf && ref.SpanID == predictSpan.SpanID {
return ii
}
}
}
return -1
}
func tagsOf(span model.Span) map[string]string {
res := map[string]string{}
for _, lg := range span.Logs {
for _, fld := range lg.Fields {
res[fld.Key] = cast.ToString(fld.Value)
}
}
for _, tag := range span.Tags {
res[tag.Key] = cast.ToString(tag.Value)
}
return res
}
func parentOf(span model.Span) model.SpanID {
if span.ParentSpanID != "" {
return span.ParentSpanID
}
for _, ref := range span.References {
if ref.RefType == model.ChildOf {
return ref.SpanID
}
}
return model.SpanID("")
}
func sliceToString(args []interface{}) []string {
res := make([]string, len(args))
for ii, arg := range args {
res[ii] = cast.ToString(arg)
}
return res
}
func float64SliceToString(args []float64) []string {
res := make([]string, len(args))
for ii, arg := range args {
res[ii] = cast.ToString(arg)
}
return res
}
// Random number state.
// We generate random temporary file names so that there's a good
// chance the file doesn't exist yet - keeps the number of tries in
// TempFile to a minimum.
var rand uint32
var randmu sync.Mutex
func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}
func nextRandom() string {
randmu.Lock()
r := rand
if r == 0 {
r = reseed()
}
r = r*1664525 + 1013904223 // constants from Numerical Recipes
rand = r
randmu.Unlock()
return strconv.Itoa(int(1e9 + r%1e9))[1:]
}
// TempFile creates a new temporary file in the directory dir,
// opens the file for reading and writing, and returns the resulting *os.File.
// The filename is generated by taking pattern and adding a random
// string to the end. If pattern includes a "*", the random string
// replaces the last "*".
// If dir is the empty string, TempFile uses the default directory
// for temporary files (see os.TempDir).
// Multiple programs calling TempFile simultaneously
// will not choose the same file. The caller can use f.Name()
// to find the pathname of the file. It is the caller's responsibility
// to remove the file when no longer needed.
func TempFile(dir, pattern string) string {
if dir == "" {
dir = os.TempDir()
}
var prefix, suffix string
if pos := strings.LastIndex(pattern, "*"); pos != -1 {
prefix, suffix = pattern[:pos], pattern[pos+1:]
} else {
prefix = pattern
}
var name string
nconflict := 0
for i := 0; i < 10000; i++ {
name = filepath.Join(dir, prefix+nextRandom()+suffix)
if com.IsFile(name) {
if nconflict++; nconflict > 10 {
randmu.Lock()
rand = reseed()
randmu.Unlock()
}
continue
}
break
}
if !com.IsDir(filepath.Dir(name)) {
os.MkdirAll(filepath.Dir(name), os.ModePerm)
}
return name
}
func demangleName(mangledName string) string {
name, err := demangle.ToString(mangledName)
if err != nil {
return mangledName
}
return name
}
func unitName(d time.Duration) string {
return strings.TrimPrefix(d.String(), "1")
}