@@ -5,23 +5,27 @@ import (
5
5
"errors"
6
6
"math"
7
7
"net/http"
8
+ "sort"
8
9
9
10
"github.com/go-kit/log"
10
11
"github.com/go-kit/log/level"
11
12
"github.com/grafana/dskit/httpgrpc"
12
13
"github.com/grafana/dskit/ring"
13
14
"github.com/prometheus/client_golang/prometheus"
15
+ "golang.org/x/sync/errgroup"
14
16
15
17
"github.com/grafana/loki/v3/pkg/logproto"
16
18
"github.com/grafana/loki/v3/pkg/logql/syntax"
17
- "github.com/grafana/loki/v3/pkg/pattern/drain"
18
19
19
20
loki_iter "github.com/grafana/loki/v3/pkg/iter"
20
21
pattern_iter "github.com/grafana/loki/v3/pkg/pattern/iter"
21
22
)
22
23
23
24
// TODO(kolesnikovae): parametrise QueryPatternsRequest
24
- const minClusterSize = 30
25
+ const (
26
+ minClusterSize = 30
27
+ maxPatterns = 300
28
+ )
25
29
26
30
var ErrParseQuery = errors .New ("only byte_over_time and count_over_time queries without filters are supported" )
27
31
@@ -132,36 +136,63 @@ func (q *IngesterQuerier) querySample(ctx context.Context, req *logproto.QuerySa
132
136
return iterators , nil
133
137
}
134
138
135
- func prunePatterns (resp * logproto.QueryPatternsResponse , minClusterSize int , metrics * ingesterQuerierMetrics ) * logproto.QueryPatternsResponse {
136
- pruneConfig := drain .DefaultConfig ()
137
- pruneConfig .SimTh = 1.0 // Merge & de-dup patterns but don't modify them
138
-
139
+ func prunePatterns (resp * logproto.QueryPatternsResponse , minClusterSize int64 , metrics * ingesterQuerierMetrics ) * logproto.QueryPatternsResponse {
139
140
patternsBefore := len (resp .Series )
140
- d := drain .New (pruneConfig , "" , nil )
141
- for _ , p := range resp .Series {
142
- d .TrainPattern (p .GetPattern (), p .Samples )
141
+ total := make ([]int64 , len (resp .Series ))
142
+
143
+ for i , p := range resp .Series {
144
+ for _ , s := range p .Samples {
145
+ total [i ] += s .Value
146
+ }
143
147
}
144
148
145
- resp .Series = resp .Series [:0 ]
146
- for _ , cluster := range d .Clusters () {
147
- if cluster .Size < minClusterSize {
148
- continue
149
+ // Create a slice of structs to keep Series and total together
150
+ type SeriesWithTotal struct {
151
+ Series * logproto.PatternSeries
152
+ Total int64
153
+ }
154
+
155
+ seriesWithTotals := make ([]SeriesWithTotal , len (resp .Series ))
156
+ for i := range resp .Series {
157
+ seriesWithTotals [i ] = SeriesWithTotal {
158
+ Series : resp .Series [i ],
159
+ Total : total [i ],
149
160
}
150
- pattern := d .PatternString (cluster )
151
- if pattern == "" {
152
- continue
161
+ }
162
+
163
+ // Sort the slice of structs by the Total field
164
+ sort .Slice (seriesWithTotals , func (i , j int ) bool {
165
+ return seriesWithTotals [i ].Total > seriesWithTotals [j ].Total
166
+ })
167
+
168
+ // Initialize a variable to keep track of the position for valid series
169
+ pos := 0
170
+
171
+ // Iterate over the seriesWithTotals
172
+ for i := range seriesWithTotals {
173
+ if seriesWithTotals [i ].Total >= minClusterSize {
174
+ // Place the valid series at the current position
175
+ resp .Series [pos ] = seriesWithTotals [i ].Series
176
+ pos ++
153
177
}
154
- resp .Series = append (resp .Series ,
155
- logproto .NewPatternSeries (pattern , cluster .Samples ()))
156
178
}
179
+
180
+ // Slice the resp.Series to include only the valid series
181
+ resp .Series = resp .Series [:pos ]
182
+
183
+ if len (resp .Series ) > maxPatterns {
184
+ resp .Series = resp .Series [:maxPatterns ]
185
+ }
186
+
157
187
metrics .patternsPrunedTotal .Add (float64 (patternsBefore - len (resp .Series )))
158
188
metrics .patternsRetainedTotal .Add (float64 (len (resp .Series )))
189
+
159
190
return resp
160
191
}
161
192
162
193
// ForAllIngesters runs f, in parallel, for all ingesters
163
194
func (q * IngesterQuerier ) forAllIngesters (ctx context.Context , f func (context.Context , logproto.PatternClient ) (interface {}, error )) ([]ResponseFromIngesters , error ) {
164
- replicationSet , err := q .ringClient .Ring ().GetReplicationSetForOperation (ring .Read )
195
+ replicationSet , err := q .ringClient .Ring ().GetAllHealthy (ring .Read )
165
196
if err != nil {
166
197
return nil , err
167
198
}
@@ -174,32 +205,29 @@ type ResponseFromIngesters struct {
174
205
response interface {}
175
206
}
176
207
177
- // forGivenIngesters runs f, in parallel, for given ingesters
178
208
func (q * IngesterQuerier ) forGivenIngesters (ctx context.Context , replicationSet ring.ReplicationSet , f func (context.Context , logproto.PatternClient ) (interface {}, error )) ([]ResponseFromIngesters , error ) {
179
- cfg := ring.DoUntilQuorumConfig {
180
- // Nothing here
181
- }
182
- results , err := ring .DoUntilQuorum (ctx , replicationSet , cfg , func (ctx context.Context , ingester * ring.InstanceDesc ) (ResponseFromIngesters , error ) {
183
- client , err := q .ringClient .Pool ().GetClientFor (ingester .Addr )
184
- if err != nil {
185
- return ResponseFromIngesters {addr : ingester .Addr }, err
186
- }
187
-
188
- resp , err := f (ctx , client .(logproto.PatternClient ))
189
- if err != nil {
190
- return ResponseFromIngesters {addr : ingester .Addr }, err
191
- }
192
-
193
- return ResponseFromIngesters {ingester .Addr , resp }, nil
194
- }, func (ResponseFromIngesters ) {
195
- // Nothing to do
196
- })
197
- if err != nil {
209
+ g , ctx := errgroup .WithContext (ctx )
210
+ responses := make ([]ResponseFromIngesters , len (replicationSet .Instances ))
211
+
212
+ for i , ingester := range replicationSet .Instances {
213
+ ingester := ingester
214
+ i := i
215
+ g .Go (func () error {
216
+ client , err := q .ringClient .Pool ().GetClientFor (ingester .Addr )
217
+ if err != nil {
218
+ return err
219
+ }
220
+
221
+ resp , err := f (ctx , client .(logproto.PatternClient ))
222
+ if err != nil {
223
+ return err
224
+ }
225
+ responses [i ] = ResponseFromIngesters {addr : ingester .Addr , response : resp }
226
+ return nil
227
+ })
228
+ }
229
+ if err := g .Wait (); err != nil {
198
230
return nil , err
199
231
}
200
-
201
- responses := make ([]ResponseFromIngesters , 0 , len (results ))
202
- responses = append (responses , results ... )
203
-
204
- return responses , err
232
+ return responses , nil
205
233
}
0 commit comments