@@ -15,6 +15,7 @@ import (
15
15
"net/http"
16
16
"net/textproto"
17
17
"net/url"
18
+ "os"
18
19
"strconv"
19
20
"time"
20
21
@@ -72,15 +73,21 @@ type RemoteEvaluator struct {
72
73
overrides RulesLimits
73
74
logger log.Logger
74
75
76
+ // we don't want/need to log all the additional context, such as
77
+ // caller=spanlogger.go:116 component=ruler evaluation_mode=remote method=ruler.remoteEvaluation.Query
78
+ // in insights logs, so create a new logger
79
+ insightsLogger log.Logger
80
+
75
81
metrics * metrics
76
82
}
77
83
78
84
func NewRemoteEvaluator (client httpgrpc.HTTPClient , overrides RulesLimits , logger log.Logger , registerer prometheus.Registerer ) (* RemoteEvaluator , error ) {
79
85
return & RemoteEvaluator {
80
- client : client ,
81
- overrides : overrides ,
82
- logger : logger ,
83
- metrics : newMetrics (registerer ),
86
+ client : client ,
87
+ overrides : overrides ,
88
+ logger : logger ,
89
+ insightsLogger : log .NewLogfmtLogger (os .Stderr ),
90
+ metrics : newMetrics (registerer ),
84
91
}, nil
85
92
}
86
93
@@ -220,6 +227,11 @@ func (r *RemoteEvaluator) query(ctx context.Context, orgID, query string, ts tim
220
227
body := []byte (args .Encode ())
221
228
hash := util .HashedQuery (query )
222
229
230
+ // Retrieve rule details from context
231
+ ruleName , ruleType := GetRuleDetailsFromContext (ctx )
232
+
233
+ // Construct the X-Query-Tags header value
234
+ queryTags := fmt .Sprintf ("source=ruler,rule_name=%s,rule_type=%s" , ruleName , ruleType )
223
235
req := httpgrpc.HTTPRequest {
224
236
Method : http .MethodPost ,
225
237
Url : queryEndpointPath ,
@@ -228,7 +240,7 @@ func (r *RemoteEvaluator) query(ctx context.Context, orgID, query string, ts tim
228
240
{Key : textproto .CanonicalMIMEHeaderKey ("User-Agent" ), Values : []string {userAgent }},
229
241
{Key : textproto .CanonicalMIMEHeaderKey ("Content-Type" ), Values : []string {mimeTypeFormPost }},
230
242
{Key : textproto .CanonicalMIMEHeaderKey ("Content-Length" ), Values : []string {strconv .Itoa (len (body ))}},
231
- {Key : textproto .CanonicalMIMEHeaderKey (string (httpreq .QueryTagsHTTPHeader )), Values : []string {"source=ruler" }},
243
+ {Key : textproto .CanonicalMIMEHeaderKey (string (httpreq .QueryTagsHTTPHeader )), Values : []string {queryTags }},
232
244
{Key : textproto .CanonicalMIMEHeaderKey (user .OrgIDHeaderName ), Values : []string {orgID }},
233
245
},
234
246
}
@@ -242,12 +254,12 @@ func (r *RemoteEvaluator) query(ctx context.Context, orgID, query string, ts tim
242
254
instrument .ObserveWithExemplar (ctx , r .metrics .responseSizeBytes .WithLabelValues (orgID ), float64 (len (resp .Body )))
243
255
}
244
256
245
- log : = log .With (logger , "query_hash" , hash , "query" , query , "instant" , ts , "response_time" , time .Since (start ).String ())
257
+ logger = log .With (logger , "query_hash" , hash , "query" , query , "instant" , ts , "response_time" , time .Since (start ).String ())
246
258
247
259
if err != nil {
248
260
r .metrics .failedEvals .WithLabelValues ("error" , orgID ).Inc ()
249
261
250
- level .Warn (log ).Log ("msg" , "failed to evaluate rule" , "err" , err )
262
+ level .Warn (logger ).Log ("msg" , "failed to evaluate rule" , "err" , err )
251
263
return nil , fmt .Errorf ("rule evaluation failed: %w" , err )
252
264
}
253
265
@@ -261,22 +273,27 @@ func (r *RemoteEvaluator) query(ctx context.Context, orgID, query string, ts tim
261
273
r .metrics .failedEvals .WithLabelValues ("upstream_error" , orgID ).Inc ()
262
274
263
275
respBod , _ := io .ReadAll (limitedBody )
264
- level .Warn (log ).Log ("msg" , "rule evaluation failed with non-2xx response" , "response_code" , resp .Code , "response_body" , respBod )
276
+ level .Warn (logger ).Log ("msg" , "rule evaluation failed with non-2xx response" , "response_code" , resp .Code , "response_body" , respBod )
265
277
return nil , fmt .Errorf ("unsuccessful/unexpected response - status code %d" , resp .Code )
266
278
}
267
279
268
280
maxSize := r .overrides .RulerRemoteEvaluationMaxResponseSize (orgID )
269
281
if maxSize > 0 && int64 (len (fullBody )) >= maxSize {
270
282
r .metrics .failedEvals .WithLabelValues ("max_size" , orgID ).Inc ()
271
283
272
- level .Error (log ).Log ("msg" , "rule evaluation exceeded max size" , "max_size" , maxSize , "response_size" , len (fullBody ))
284
+ level .Error (logger ).Log ("msg" , "rule evaluation exceeded max size" , "max_size" , maxSize , "response_size" , len (fullBody ))
273
285
return nil , fmt .Errorf ("%d bytes exceeds response size limit of %d (defined by ruler_remote_evaluation_max_response_size)" , len (resp .Body ), maxSize )
274
286
}
275
287
276
- level .Debug (log ).Log ("msg" , "rule evaluation succeeded" )
288
+ level .Debug (logger ).Log ("msg" , "rule evaluation succeeded" )
277
289
r .metrics .successfulEvals .WithLabelValues (orgID ).Inc ()
278
290
279
- return r .decodeResponse (ctx , resp , orgID )
291
+ dr , err := r .decodeResponse (ctx , resp , orgID )
292
+ if err != nil {
293
+ return nil , err
294
+ }
295
+ level .Info (r .insightsLogger ).Log ("msg" , "request timings" , "insight" , "true" , "source" , "loki_ruler" , "rule_name" , ruleName , "rule_type" , ruleType , "total" , dr .Statistics .Summary .ExecTime , "total_bytes" , dr .Statistics .Summary .TotalBytesProcessed , "query_hash" , util .HashedQuery (query ))
296
+ return dr , err
280
297
}
281
298
282
299
func (r * RemoteEvaluator ) decodeResponse (ctx context.Context , resp * httpgrpc.HTTPResponse , orgID string ) (* logqlmodel.Result , error ) {
0 commit comments