/
utils.go
209 lines (186 loc) · 4.45 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
package exporter
import (
"fmt"
"github.com/go-kit/kit/log"
"github.com/go-kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"math"
"os"
"strconv"
"strings"
"time"
)
/* ================ Logger ================ */
func configureLogger(levelStr, formatStr string) log.Logger {
var logger log.Logger
switch formatStr {
case "json":
logger = log.NewJSONLogger(log.NewSyncWriter(os.Stderr))
case "logfmt", "":
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
default:
panic("unknown log format: " + formatStr)
}
var lvl level.Option
switch levelStr {
case "debug":
lvl = level.AllowDebug()
case "info":
lvl = level.AllowInfo()
case "warn":
lvl = level.AllowWarn()
case "error":
lvl = level.AllowError()
default:
panic("unknown log level: " + levelStr)
}
logger = level.NewFilter(logger, lvl)
logger = log.With(logger, "timestamp", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
return logger
}
// logDebugf will log debug message
func logDebugf(format string, v ...interface{}) {
level.Debug(Logger).Log("msg", fmt.Sprintf(format, v...))
}
// Infof will log info message
func logInfof(format string, v ...interface{}) {
level.Info(Logger).Log("msg", fmt.Sprintf(format, v...))
}
// logWarnf will log warning message
func logWarnf(format string, v ...interface{}) {
level.Warn(Logger).Log("msg", fmt.Sprintf(format, v...))
}
// logErrorf will log error message
func logErrorf(format string, v ...interface{}) {
level.Error(Logger).Log("msg", fmt.Sprintf(format, v...))
}
// logError will print error message directly
func logError(msg string) {
level.Error(Logger).Log("msg", msg)
}
// logFatalf will log error message
func logFatalf(format string, v ...interface{}) {
level.Error(Logger).Log("msg", fmt.Sprintf(format, v...))
}
/* ================ Auxiliaries ================ */
// castFloat64 will cast datum into float64 with scale & default value
func castFloat64(t interface{}, s string, d string) float64 {
var scale = 1.0
if s != "" {
if scaleFactor, err := strconv.ParseFloat(s, 64); err != nil {
logWarnf("invalid column scale: %v ", s)
} else {
scale = scaleFactor
}
}
switch v := t.(type) {
case int64:
return float64(v) * scale
case float64:
return v * scale
case time.Time:
return float64(v.Unix())
case []byte:
strV := string(v)
result, err := strconv.ParseFloat(strV, 64)
if err != nil {
logWarnf("fail casting []byte to float64: %v", t)
return math.NaN()
}
return result * scale
case string:
result, err := strconv.ParseFloat(v, 64)
if err != nil {
logWarnf("fail casting string to float64: %v", t)
return math.NaN()
}
return result * scale
case bool:
if v {
return 1.0
}
return 0.0
case nil:
if d != "" {
result, err := strconv.ParseFloat(d, 64)
if err != nil {
logWarnf("invalid column default: %v", d)
return math.NaN()
}
return result
}
return math.NaN()
default:
logWarnf("fail casting unknown to float64: %v", t)
return math.NaN()
}
}
// castString will force interface{} into string
func castString(t interface{}) string {
switch v := t.(type) {
case int64:
return fmt.Sprintf("%v", v)
case float64:
return fmt.Sprintf("%v", v)
case time.Time:
return fmt.Sprintf("%v", v.Unix())
case nil:
return ""
case []byte:
// Try and convert to string
return string(v)
case string:
return v
case bool:
if v {
return "true"
}
return "false"
default:
logWarnf("fail casting unknown to string: %v", t)
return ""
}
}
// parseConstLabels turn param string into prometheus.Labels
func parseConstLabels(s string) prometheus.Labels {
labels := make(prometheus.Labels, 0)
s = strings.TrimSpace(s)
if len(s) == 0 {
return nil
}
parts := strings.Split(s, ",")
for _, p := range parts {
keyValue := strings.Split(strings.TrimSpace(p), "=")
if len(keyValue) != 2 {
logErrorf(`malformed labels format %q, should be "key=value"`, p)
continue
}
key := strings.TrimSpace(keyValue[0])
value := strings.TrimSpace(keyValue[1])
if key == "" || value == "" {
continue
}
labels[key] = value
}
if len(labels) == 0 {
return nil
}
return labels
}
// parseCSV will turn a comma separated string into a []string
func parseCSV(s string) (tags []string) {
s = strings.TrimSpace(s)
if len(s) == 0 {
return nil
}
parts := strings.Split(s, ",")
for _, p := range parts {
if tag := strings.TrimSpace(p); len(tag) > 0 {
tags = append(tags, tag)
}
}
if len(tags) == 0 {
return nil
}
return
}