Skip to content

Commit 8494cab

Browse files
authored
Out-of-order Flag : Added option for sending out of order samples (#68)
* changed implementation of shuffleTimeStamps Signed-off-by: Vanshikav123 <[email protected]> * resolving conflicts and improve test Signed-off-by: Vanshikav123 <[email protected]> --------- Signed-off-by: Vanshikav123 <[email protected]> Signed-off-by: Vanshika <[email protected]>
1 parent 7534117 commit 8494cab

File tree

3 files changed

+83
-6
lines changed

3 files changed

+83
-6
lines changed

Diff for: cmd/avalanche.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ var (
5656
remoteTenant = kingpin.Flag("remote-tenant", "Tenant ID to include in remote_write send").Default("0").String()
5757
tlsClientInsecure = kingpin.Flag("tls-client-insecure", "Skip certificate check on tls connection").Default("false").Bool()
5858
remoteTenantHeader = kingpin.Flag("remote-tenant-header", "Tenant ID to include in remote_write send. The default, is the default tenant header expected by Cortex.").Default("X-Scope-OrgID").String()
59+
outOfOrder = kingpin.Flag("out-of-order", "Enable out-of-order timestamps in remote write requests").Default("true").Bool()
5960
)
6061

6162
func main() {
@@ -123,6 +124,7 @@ func main() {
123124
InsecureSkipVerify: *tlsClientInsecure,
124125
},
125126
TenantHeader: *remoteTenantHeader,
127+
OutOfOrder: *outOfOrder,
126128
}
127129

128130
// Collect Pprof during the write only if not collecting within a regular interval.
@@ -136,7 +138,7 @@ func main() {
136138
)
137139
if *remotePprofInterval > 0 {
138140
if len(*remotePprofURLs) == 0 {
139-
log.Fatal("remote profiling interval specified wihout any remote pprof urls")
141+
log.Fatal("remote profiling interval specified without any remote pprof urls")
140142
}
141143
suffix := rand.Intn(1000)
142144
go func() {
@@ -170,7 +172,7 @@ func main() {
170172
return
171173
}
172174

173-
fmt.Printf("Serving ur metrics at localhost:%v/metrics\n", *port)
175+
fmt.Printf("Serving your metrics at localhost:%v/metrics\n", *port)
174176
err = metrics.ServeMetrics(*port)
175177
if err != nil {
176178
log.Fatal(err)

Diff for: metrics/write.go

+19-4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type ConfigWrite struct {
5454
Tenant string
5555
TLSClientConfig tls.Config
5656
TenantHeader string
57+
OutOfOrder bool
5758
}
5859

5960
// Client for the remote write requests.
@@ -108,7 +109,7 @@ func cloneRequest(r *http.Request) *http.Request {
108109
}
109110

110111
func (c *Client) write() error {
111-
tss, err := collectMetrics()
112+
tss, err := collectMetrics(c.config.OutOfOrder)
112113
if err != nil {
113114
return err
114115
}
@@ -140,7 +141,7 @@ func (c *Client) write() error {
140141
select {
141142
case <-c.config.UpdateNotify:
142143
log.Println("updating remote write metrics")
143-
tss, err = collectMetrics()
144+
tss, err = collectMetrics(c.config.OutOfOrder)
144145
if err != nil {
145146
merr.Add(err)
146147
}
@@ -193,14 +194,28 @@ func updateTimetamps(tss []prompb.TimeSeries) []prompb.TimeSeries {
193194
return tss
194195
}
195196

196-
func collectMetrics() ([]prompb.TimeSeries, error) {
197+
func collectMetrics(outOfOrder bool) ([]prompb.TimeSeries, error) {
197198
metricsMux.Lock()
198199
defer metricsMux.Unlock()
199200
metricFamilies, err := promRegistry.Gather()
200201
if err != nil {
201202
return nil, err
202203
}
203-
return ToTimeSeriesSlice(metricFamilies), nil
204+
tss := ToTimeSeriesSlice(metricFamilies)
205+
if outOfOrder {
206+
tss = shuffleTimestamps(tss)
207+
}
208+
return tss, nil
209+
}
210+
func shuffleTimestamps(tss []prompb.TimeSeries) []prompb.TimeSeries {
211+
now := time.Now().UnixMilli()
212+
offsets := []int64{0, -60 * 1000, -5 * 60 * 1000}
213+
214+
for i := range tss {
215+
offset := offsets[i%len(offsets)]
216+
tss[i].Samples[0].Timestamp = now + offset
217+
}
218+
return tss
204219
}
205220

206221
// ToTimeSeriesSlice converts a slice of metricFamilies containing samples into a slice of TimeSeries

Diff for: metrics/write_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright 2022 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package metrics
15+
16+
import (
17+
"testing"
18+
"time"
19+
20+
"github.com/prometheus/prometheus/prompb"
21+
)
22+
23+
func TestShuffleTimestamps(t *testing.T) {
24+
now := time.Now().UnixMilli()
25+
26+
tss := []prompb.TimeSeries{
27+
{Samples: []prompb.Sample{{Timestamp: now}}},
28+
{Samples: []prompb.Sample{{Timestamp: now}}},
29+
{Samples: []prompb.Sample{{Timestamp: now}}},
30+
}
31+
32+
shuffledTSS := shuffleTimestamps(tss)
33+
34+
offsets := []int64{0, -60 * 1000, -5 * 60 * 1000}
35+
for _, ts := range shuffledTSS {
36+
timestampValid := false
37+
for _, offset := range offsets {
38+
expectedTimestamp := now + offset
39+
if ts.Samples[0].Timestamp == expectedTimestamp {
40+
timestampValid = true
41+
break
42+
}
43+
}
44+
if !timestampValid {
45+
t.Errorf("Timestamp %v is not in the expected offsets: %v", ts.Samples[0].Timestamp, offsets)
46+
}
47+
}
48+
49+
outOfOrder := false
50+
for i := 1; i < len(shuffledTSS); i++ {
51+
if shuffledTSS[i].Samples[0].Timestamp < shuffledTSS[i-1].Samples[0].Timestamp {
52+
outOfOrder = true
53+
break
54+
}
55+
}
56+
57+
if !outOfOrder {
58+
t.Error("Timestamps are not out of order")
59+
}
60+
}

0 commit comments

Comments
 (0)