2023-10-13 11:54:33 +00:00
|
|
|
package rule
|
2020-06-01 10:46:37 +00:00
|
|
|
|
|
|
|
import (
|
2022-09-15 10:40:22 +00:00
|
|
|
"fmt"
|
|
|
|
"net/http"
|
2020-06-01 10:46:37 +00:00
|
|
|
"sort"
|
2022-09-15 10:40:22 +00:00
|
|
|
"strings"
|
2020-06-01 10:46:37 +00:00
|
|
|
"time"
|
2020-06-29 19:21:03 +00:00
|
|
|
|
2023-10-10 09:40:27 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/app/vmalert/datasource"
|
2020-06-29 19:21:03 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/prompbmarshal"
|
2024-11-14 11:23:39 +00:00
|
|
|
"github.com/VictoriaMetrics/VictoriaMetrics/lib/promrelabel"
|
2020-06-01 10:46:37 +00:00
|
|
|
)
|
|
|
|
|
2024-11-14 11:23:39 +00:00
|
|
|
// newTimeSeries first sorts given labels, then returns new time series.
|
|
|
|
func newTimeSeries(values []float64, timestamps []int64, labels []prompbmarshal.Label) prompbmarshal.TimeSeries {
|
|
|
|
promrelabel.SortLabels(labels)
|
2021-06-09 09:20:38 +00:00
|
|
|
ts := prompbmarshal.TimeSeries{
|
2024-11-14 11:23:39 +00:00
|
|
|
Labels: labels,
|
2021-06-09 09:20:38 +00:00
|
|
|
Samples: make([]prompbmarshal.Sample, len(values)),
|
|
|
|
}
|
|
|
|
for i := range values {
|
|
|
|
ts.Samples[i] = prompbmarshal.Sample{
|
|
|
|
Value: values[i],
|
|
|
|
Timestamp: time.Unix(timestamps[i], 0).UnixNano() / 1e6,
|
|
|
|
}
|
|
|
|
}
|
2022-03-29 13:09:07 +00:00
|
|
|
return ts
|
|
|
|
}
|
2022-09-15 10:40:22 +00:00
|
|
|
|
|
|
|
type curlWriter struct {
|
|
|
|
b strings.Builder
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cw *curlWriter) string() string {
|
|
|
|
res := "curl " + cw.b.String()
|
|
|
|
cw.b.Reset()
|
|
|
|
return strings.TrimSpace(res)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cw *curlWriter) addWithEsc(str string) {
|
|
|
|
escStr := `'` + strings.Replace(str, `'`, `'\''`, -1) + `'`
|
|
|
|
cw.add(escStr)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cw *curlWriter) add(str string) {
|
|
|
|
cw.b.WriteString(str)
|
|
|
|
cw.b.WriteString(" ")
|
|
|
|
}
|
|
|
|
|
|
|
|
func requestToCurl(req *http.Request) string {
|
2022-12-10 10:04:15 +00:00
|
|
|
if req == nil || req.URL == nil {
|
2022-09-15 10:40:22 +00:00
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
cw := &curlWriter{}
|
|
|
|
|
|
|
|
schema := req.URL.Scheme
|
|
|
|
requestURL := req.URL.String()
|
2023-10-10 09:40:27 +00:00
|
|
|
if !datasource.ShowDatasourceURL() {
|
|
|
|
requestURL = req.URL.Redacted()
|
|
|
|
}
|
2022-09-15 10:40:22 +00:00
|
|
|
if schema == "" {
|
|
|
|
schema = "http"
|
|
|
|
if req.TLS != nil {
|
|
|
|
schema = "https"
|
|
|
|
}
|
|
|
|
requestURL = schema + "://" + req.Host + requestURL
|
|
|
|
}
|
|
|
|
|
|
|
|
if schema == "https" {
|
|
|
|
cw.add("-k")
|
|
|
|
}
|
|
|
|
|
|
|
|
cw.add("-X")
|
|
|
|
cw.add(req.Method)
|
|
|
|
|
|
|
|
var keys []string
|
|
|
|
for k := range req.Header {
|
|
|
|
keys = append(keys, k)
|
|
|
|
}
|
|
|
|
sort.Strings(keys)
|
|
|
|
|
|
|
|
for _, k := range keys {
|
|
|
|
cw.add("-H")
|
2023-10-10 09:40:27 +00:00
|
|
|
if !datasource.ShowDatasourceURL() && isSecreteHeader(k) {
|
|
|
|
cw.addWithEsc(fmt.Sprintf("%s: <secret>", k))
|
|
|
|
continue
|
|
|
|
}
|
2022-09-15 10:40:22 +00:00
|
|
|
cw.addWithEsc(fmt.Sprintf("%s: %s", k, strings.Join(req.Header[k], " ")))
|
|
|
|
}
|
|
|
|
|
|
|
|
cw.addWithEsc(requestURL)
|
|
|
|
return cw.string()
|
|
|
|
}
|
2023-10-10 09:40:27 +00:00
|
|
|
|
|
|
|
var secretWords = []string{"auth", "pass", "key", "secret", "token"}
|
|
|
|
|
|
|
|
func isSecreteHeader(str string) bool {
|
|
|
|
s := strings.ToLower(str)
|
|
|
|
for _, secret := range secretWords {
|
|
|
|
if strings.Contains(s, secret) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|