datasources: allow special http header to opt-in to new-mode query handling (#109349)

datasources: allow opt-in to new features using a http header

Co-authored-by: Sarah Zinger <sarah.zinger@grafana.com>
This commit is contained in:
Gábor Farkas
2025-08-15 12:05:12 -04:00
committed by GitHub
co-authored by Sarah Zinger
parent 5270d8e53f
commit e1843bf1ae
3 changed files with 54 additions and 6 deletions
+14 -5
View File
@@ -70,6 +70,9 @@ func ProvideService(
type Service interface {
Run(ctx context.Context) error
QueryData(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error)
// this is more "forward compatible", for example supports per-query time ranges
QueryDataNew(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error)
}
// Gives us compile time error if the service does not adhere to the contract of the interface
@@ -86,7 +89,6 @@ type ServiceImpl struct {
concurrentQueryLimit int
mtDatasourceClientBuilder mtdsclient.MTDatasourceClientBuilder
headers map[string]string
supportLocalTimeRange bool
}
// Run ServiceImpl.
@@ -96,7 +98,7 @@ func (s *ServiceImpl) Run(ctx context.Context) error {
}
// QueryData processes queries and returns query responses. It handles queries to single or mixed datasources, as well as expressions.
func (s *ServiceImpl) QueryData(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error) {
func (s *ServiceImpl) queryData(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest, supportLocaltimeRange bool) (*backend.QueryDataResponse, error) {
fromAlert := false
for header, val := range s.headers {
if header == models.FromAlertHeaderName && val == "true" {
@@ -104,7 +106,7 @@ func (s *ServiceImpl) QueryData(ctx context.Context, user identity.Requester, sk
}
}
// Parse the request into parsed queries grouped by datasource uid
parsedReq, err := s.parseMetricRequest(ctx, user, skipDSCache, reqDTO, s.supportLocalTimeRange)
parsedReq, err := s.parseMetricRequest(ctx, user, skipDSCache, reqDTO, supportLocaltimeRange)
if err != nil {
return nil, err
}
@@ -121,6 +123,14 @@ func (s *ServiceImpl) QueryData(ctx context.Context, user identity.Requester, sk
return s.executeConcurrentQueries(ctx, user, skipDSCache, reqDTO, parsedReq.parsedQueries)
}
func (s *ServiceImpl) QueryData(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error) {
return s.queryData(ctx, user, skipDSCache, reqDTO, false)
}
func (s *ServiceImpl) QueryDataNew(ctx context.Context, user identity.Requester, skipDSCache bool, reqDTO dtos.MetricRequest) (*backend.QueryDataResponse, error) {
return s.queryData(ctx, user, skipDSCache, reqDTO, true)
}
// splitResponse contains the results of a concurrent data source query - the response and any headers
type splitResponse struct {
responses backend.Responses
@@ -223,9 +233,8 @@ func QueryData(ctx context.Context, log log.Logger, dscache datasources.CacheSer
mtDatasourceClientBuilder: mtDatasourceClientBuilder,
headers: headers,
concurrentQueryLimit: 16, // TODO: make it configurable
supportLocalTimeRange: true,
}
return s.QueryData(ctx, nil, false, reqDTO)
return s.QueryDataNew(ctx, nil, false, reqDTO)
}
// handleExpressions handles queries when there is an expression.