cloudflare/pint

Public

mirrored from https://github.com/cloudflare/pintAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.1.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

internal/promapi/range.go

97lines · modecode

1package promapi
2
3import (
4 "context"
5 "fmt"
6 "net"
7 "time"
8
9 "github.com/prometheus/client_golang/api"
10 v1 "github.com/prometheus/client_golang/api/prometheus/v1"
11 "github.com/prometheus/common/model"
12 "github.com/rs/zerolog/log"
13)
14
15type RangeQueryResult struct {
16 Samples []*model.SampleStream
17 Start time.Time
18 End time.Time
19 DurationSeconds float64
20}
21
22func RangeQuery(uri string, timeout time.Duration, expr string, start, end time.Time, step time.Duration, lockKey *string) (*RangeQueryResult, error) {
23 key := uri
24 if lockKey != nil {
25 key = *lockKey
26 }
27
28 log.Debug().
29 Str("key", key).
30 Str("uri", uri).
31 Str("query", expr).
32 Time("start", start).
33 Time("end", end).
34 Str("step", HumanizeDuration(step)).
35 Msg("Scheduling prometheus range query")
36
37 km.Lock(key)
38 defer km.Unlock((key))
39
40 log.Debug().Str("uri", uri).Str("query", expr).Msg("Range query started")
41
42 client, err := api.NewClient(api.Config{Address: uri})
43 if err != nil {
44 log.Error().Err(err).Msg("Failed to setup new Prometheus API client")
45 return nil, err
46 }
47
48 v1api := v1.NewAPI(client)
49 ctx, cancel := context.WithTimeout(context.Background(), timeout)
50 defer cancel()
51
52 r := v1.Range{
53 Start: start,
54 End: end,
55 Step: step,
56 }
57 qstart := time.Now()
58 result, _, err := v1api.QueryRange(ctx, expr, r)
59 duration := time.Since(qstart)
60 log.Debug().
61 Str("uri", uri).
62 Str("query", expr).
63 Str("duration", HumanizeDuration(duration)).
64 Msg("Range query completed")
65 if err != nil {
66 log.Error().Err(err).Str("uri", uri).Str("query", expr).Msg("Range query failed")
67 if err, ok := err.(net.Error); ok && err.Timeout() {
68 delta := end.Sub(start) / 2
69 log.Warn().Str("delta", HumanizeDuration(delta)).Msg("Retrying request with smaller range")
70 b, _ := start.MarshalText()
71 newKey := fmt.Sprintf("%s/retry/%s", key, string(b))
72 return RangeQuery(uri, timeout, expr, start.Add(delta), end, step, &newKey)
73 }
74 return nil, err
75 }
76
77 qr := RangeQueryResult{
78 DurationSeconds: duration.Seconds(),
79 Start: start,
80 End: end,
81 }
82
83 switch result.Type() {
84 case model.ValMatrix:
85 samples := result.(model.Matrix)
86 qr.Samples = samples
87
88 case model.ValString:
89 fmt.Println("ValString")
90 default:
91 log.Error().Err(err).Str("uri", uri).Str("query", expr).Msgf("Range query returned unknown result type: %v", result)
92 return nil, fmt.Errorf("unknown result type: %v", result)
93 }
94 log.Debug().Str("uri", uri).Str("query", expr).Int("samples", len(qr.Samples)).Msg("Parsed range response")
95
96 return &qr, nil
97}
98