Like Prometheus, but for logs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
loki/pkg/querier/queryrange/metrics.go

97 lines
3.1 KiB

package queryrange
import (
"context"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/grafana/loki/v3/pkg/logql"
"github.com/grafana/loki/v3/pkg/logql/syntax"
"github.com/grafana/loki/v3/pkg/querier/queryrange/queryrangebase"
v1 "github.com/grafana/loki/v3/pkg/storage/bloom/v1"
)
type Metrics struct {
*queryrangebase.InstrumentMiddlewareMetrics
*queryrangebase.RetryMiddlewareMetrics
*MiddlewareMapperMetrics
*SplitByMetrics
*LogResultCacheMetrics
*QueryMetrics
*queryrangebase.ResultsCacheMetrics
}
type MiddlewareMapperMetrics struct {
shardMapper *logql.MapperMetrics
rangeMapper *logql.MapperMetrics
}
func NewMiddlewareMapperMetrics(registerer prometheus.Registerer) *MiddlewareMapperMetrics {
return &MiddlewareMapperMetrics{
shardMapper: logql.NewShardMapperMetrics(registerer),
rangeMapper: logql.NewRangeMapperMetrics(registerer),
}
}
func NewMetrics(registerer prometheus.Registerer, metricsNamespace string) *Metrics {
return &Metrics{
InstrumentMiddlewareMetrics: queryrangebase.NewInstrumentMiddlewareMetrics(registerer, metricsNamespace),
RetryMiddlewareMetrics: queryrangebase.NewRetryMiddlewareMetrics(registerer, metricsNamespace),
MiddlewareMapperMetrics: NewMiddlewareMapperMetrics(registerer),
SplitByMetrics: NewSplitByMetrics(registerer),
LogResultCacheMetrics: NewLogResultCacheMetrics(registerer),
QueryMetrics: NewMiddlewareQueryMetrics(registerer, metricsNamespace),
ResultsCacheMetrics: queryrangebase.NewResultsCacheMetrics(registerer),
}
}
type QueryMetrics struct {
receivedLabelFilters prometheus.Histogram
}
func NewMiddlewareQueryMetrics(registerer prometheus.Registerer, metricsNamespace string) *QueryMetrics {
return &QueryMetrics{
receivedLabelFilters: promauto.With(registerer).NewHistogram(prometheus.HistogramOpts{
Namespace: metricsNamespace,
Name: "query_frontend_query_label_filters",
Help: "Number of label matcher expressions per query.",
Buckets: prometheus.ExponentialBuckets(1, 2, 9), // 1 -> 256
}),
}
}
// QueryMetricsMiddleware can be inserted into the middleware chain to expose timing information.
func QueryMetricsMiddleware(metrics *QueryMetrics) queryrangebase.Middleware {
return queryrangebase.MiddlewareFunc(func(next queryrangebase.Handler) queryrangebase.Handler {
return queryrangebase.HandlerFunc(func(ctx context.Context, req queryrangebase.Request) (queryrangebase.Response, error) {
var expr syntax.Expr
switch r := req.(type) {
case *LokiRequest:
if r.Plan != nil {
expr = r.Plan.AST
}
case *LokiInstantRequest:
if r.Plan != nil {
expr = r.Plan.AST
}
default:
return next.Do(ctx, req)
}
// The plan should always be present, but if it's not, we'll parse the query to get the filters.
if expr == nil {
var err error
expr, err = syntax.ParseExpr(req.GetQuery())
if err != nil {
return nil, err
}
}
filters := v1.ExtractTestableLabelMatchers(expr)
metrics.receivedLabelFilters.Observe(float64(len(filters)))
return next.Do(ctx, req)
})
})
}