Scopes: Remove promql rewrite feature toggle (#112035)
Signed-off-by: bergquist <carl.bergquist@gmail.com> Co-authored-by: Tobias Skarhed <tobias.skarhed@gmail.com>
This commit is contained in:
co-authored by
Tobias Skarhed
parent
248c20a6b6
commit
b2036088ac
@@ -492,11 +492,6 @@ export interface FeatureToggles {
|
||||
*/
|
||||
useMultipleScopeNodesEndpoint?: boolean;
|
||||
/**
|
||||
* In-development feature that will allow injection of labels into prometheus queries.
|
||||
* @default true
|
||||
*/
|
||||
promQLScope?: boolean;
|
||||
/**
|
||||
* In-development feature that will allow injection of labels into loki queries.
|
||||
* @default false
|
||||
*/
|
||||
|
||||
@@ -664,10 +664,6 @@ describe('PrometheusDatasource', () => {
|
||||
});
|
||||
|
||||
describe('interpolateVariablesInQueries', () => {
|
||||
afterEach(() => {
|
||||
config.featureToggles.promQLScope = undefined;
|
||||
});
|
||||
|
||||
it('should call replace function 3 times', () => {
|
||||
const query: PromQuery = {
|
||||
expr: 'test{job="testjob"}',
|
||||
@@ -695,17 +691,32 @@ describe('PrometheusDatasource', () => {
|
||||
expect(ds.enhanceExprWithAdHocFilters).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not apply adhoc filters when promQLScope is enabled', () => {
|
||||
config.featureToggles.promQLScope = true;
|
||||
it('should not apply adhoc filters when scopes with filters are present', () => {
|
||||
ds.enhanceExprWithAdHocFilters = jest.fn();
|
||||
ds.generateScopeFilters = jest.fn();
|
||||
const queries = [
|
||||
// Fix: Use correct types for scopes and filters
|
||||
const typedScopes = [
|
||||
{
|
||||
name: 'test-scope',
|
||||
title: 'Test Scope',
|
||||
type: 'test',
|
||||
filters: [
|
||||
{
|
||||
key: 'bar',
|
||||
operator: 'equals' as const,
|
||||
value: 'baz',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const typedQueries: PromQuery[] = [
|
||||
{
|
||||
refId: 'A',
|
||||
expr: 'rate({bar="baz", job="foo"} [5m]',
|
||||
scopes: typedScopes,
|
||||
},
|
||||
];
|
||||
ds.interpolateVariablesInQueries(queries, {});
|
||||
ds.interpolateVariablesInQueries(typedQueries, {});
|
||||
expect(ds.enhanceExprWithAdHocFilters).not.toHaveBeenCalled();
|
||||
expect(ds.generateScopeFilters).toHaveBeenCalled();
|
||||
});
|
||||
@@ -716,10 +727,6 @@ describe('PrometheusDatasource', () => {
|
||||
replaceMock.mockImplementation((a: string, ...rest: unknown[]) => a);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
config.featureToggles.promQLScope = false;
|
||||
});
|
||||
|
||||
it('should call replace function for legendFormat', () => {
|
||||
const query = {
|
||||
expr: 'test{job="bar"}',
|
||||
@@ -783,7 +790,21 @@ describe('PrometheusDatasource', () => {
|
||||
});
|
||||
|
||||
it('should generate scope filters and **not** apply ad-hoc filters to expr', () => {
|
||||
config.featureToggles.promQLScope = true;
|
||||
const scopes = [
|
||||
{
|
||||
name: 'test-scope',
|
||||
title: 'Test Scope',
|
||||
type: 'test',
|
||||
filters: [
|
||||
{
|
||||
key: 'bar',
|
||||
operator: 'equals' as const,
|
||||
value: 'baz',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
replaceMock.mockImplementation((a: string) => a);
|
||||
const filters = [
|
||||
{
|
||||
@@ -801,17 +822,18 @@ describe('PrometheusDatasource', () => {
|
||||
const query = {
|
||||
expr: 'test{job="bar"}',
|
||||
refId: 'A',
|
||||
scopes: scopes,
|
||||
};
|
||||
|
||||
const expectedScopeFilters: ScopeSpecFilter[] = [
|
||||
{
|
||||
key: 'k1',
|
||||
operator: 'equals',
|
||||
operator: 'equals' as const,
|
||||
value: 'v1',
|
||||
},
|
||||
{
|
||||
key: 'k2',
|
||||
operator: 'not-equals',
|
||||
operator: 'not-equals' as const,
|
||||
value: 'v2',
|
||||
},
|
||||
];
|
||||
@@ -891,13 +913,27 @@ describe('PrometheusDatasource', () => {
|
||||
});
|
||||
|
||||
it('should replace variables in adhoc filters on backend when promQLScope is enabled', () => {
|
||||
config.featureToggles.promQLScope = true;
|
||||
const scopes = [
|
||||
{
|
||||
name: 'test-scope',
|
||||
title: 'Test Scope',
|
||||
type: 'test',
|
||||
filters: [
|
||||
{
|
||||
key: 'bar',
|
||||
operator: 'equals' as const,
|
||||
value: 'baz',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const searchPattern = /\$A/g;
|
||||
replaceMock.mockImplementation((a: string) => a?.replace(searchPattern, '99') ?? a);
|
||||
|
||||
const query = {
|
||||
expr: 'test',
|
||||
refId: 'A',
|
||||
scopes: scopes,
|
||||
};
|
||||
const filters = [
|
||||
{
|
||||
@@ -906,6 +942,7 @@ describe('PrometheusDatasource', () => {
|
||||
value: '$A',
|
||||
},
|
||||
];
|
||||
|
||||
const result = ds.applyTemplateVariables(query, {}, filters);
|
||||
expect(result).toMatchObject({
|
||||
expr: 'test',
|
||||
|
||||
@@ -430,7 +430,7 @@ export class PrometheusDatasource
|
||||
utcOffsetSec: utcOffset * 60,
|
||||
};
|
||||
|
||||
if (config.featureToggles.promQLScope) {
|
||||
if (request.scopes) {
|
||||
processedTarget.scopes = (request.scopes ?? []).map((scope) => ({
|
||||
name: scope.metadata.name,
|
||||
...scope.spec,
|
||||
@@ -543,7 +543,7 @@ export class PrometheusDatasource
|
||||
options.timeRange = getDefaultTimeRange();
|
||||
}
|
||||
|
||||
if (config.featureToggles.promQLScope && (options?.scopes?.length ?? 0) > 0) {
|
||||
if ((options?.scopes?.length ?? 0) > 0) {
|
||||
const suggestions = await this.languageProvider.fetchSuggestions(
|
||||
options.timeRange,
|
||||
options.queries,
|
||||
@@ -574,7 +574,7 @@ export class PrometheusDatasource
|
||||
}
|
||||
|
||||
const requestId = `[${this.uid}][${options.key}]`;
|
||||
if (config.featureToggles.promQLScope && (options?.scopes?.length ?? 0) > 0) {
|
||||
if ((options?.scopes?.length ?? 0) > 0) {
|
||||
return (
|
||||
await this.languageProvider.fetchSuggestions(
|
||||
options.timeRange,
|
||||
@@ -609,7 +609,7 @@ export class PrometheusDatasource
|
||||
scopedVars,
|
||||
this.interpolateExploreMetrics(query.fromExploreMetrics)
|
||||
);
|
||||
const replacedInterpolatedQuery = config.featureToggles.promQLScope
|
||||
const replacedInterpolatedQuery = targetHasScopes(query)
|
||||
? interpolatedQuery
|
||||
: this.templateSrv.replace(
|
||||
this.enhanceExprWithAdHocFilters(filters, interpolatedQuery),
|
||||
@@ -619,7 +619,7 @@ export class PrometheusDatasource
|
||||
|
||||
const expandedQuery = {
|
||||
...query,
|
||||
...(config.featureToggles.promQLScope ? { adhocFilters: this.generateScopeFilters(filters) } : {}),
|
||||
...(query.scopes && query.scopes.length > 0 ? { adhocFilters: this.generateScopeFilters(filters) } : {}),
|
||||
datasource: this.getRef(),
|
||||
expr: replacedInterpolatedQuery,
|
||||
interval: this.templateSrv.replace(query.interval, scopedVars),
|
||||
@@ -791,13 +791,13 @@ export class PrometheusDatasource
|
||||
|
||||
// Apply ad-hoc filters
|
||||
// When ad-hoc filters are applied, we replace again the variables in case the ad-hoc filters also reference a variable
|
||||
const exprWithAdhoc = config.featureToggles.promQLScope
|
||||
const exprWithAdhoc = targetHasScopes(target)
|
||||
? expr
|
||||
: this.templateSrv.replace(this.enhanceExprWithAdHocFilters(filters, expr), variables, this.interpolateQueryExpr);
|
||||
|
||||
return {
|
||||
...target,
|
||||
...(config.featureToggles.promQLScope ? { adhocFilters: this.generateScopeFilters(filters) } : {}),
|
||||
...(targetHasScopes(target) ? { adhocFilters: this.generateScopeFilters(filters) } : {}),
|
||||
expr: exprWithAdhoc,
|
||||
interval: this.templateSrv.replace(target.interval, variables),
|
||||
legendFormat: this.templateSrv.replace(target.legendFormat, variables),
|
||||
@@ -862,6 +862,10 @@ export class PrometheusDatasource
|
||||
}
|
||||
}
|
||||
|
||||
function targetHasScopes(target: PromQuery): boolean {
|
||||
return !!(target.scopes && target.scopes.length > 0);
|
||||
}
|
||||
|
||||
export function extractRuleMappingFromGroups(groups: RawRecordingRules[]): RuleQueryMapping {
|
||||
return groups.reduce<RuleQueryMapping>(
|
||||
(mapping, group) =>
|
||||
|
||||
+29
-31
@@ -161,7 +161,7 @@ type internalQueryModel struct {
|
||||
Interval string `json:"interval,omitempty"`
|
||||
}
|
||||
|
||||
func Parse(ctx context.Context, log glog.Logger, span trace.Span, query backend.DataQuery, dsScrapeInterval string, intervalCalculator intervalv2.Calculator, fromAlert bool, enableScope bool) (*Query, error) {
|
||||
func Parse(ctx context.Context, log glog.Logger, span trace.Span, query backend.DataQuery, dsScrapeInterval string, intervalCalculator intervalv2.Calculator, fromAlert bool) (*Query, error) {
|
||||
model := &internalQueryModel{}
|
||||
if err := json.Unmarshal(query.JSON, model); err != nil {
|
||||
return nil, err
|
||||
@@ -185,38 +185,36 @@ func Parse(ctx context.Context, log glog.Logger, span trace.Span, query backend.
|
||||
timeRange,
|
||||
)
|
||||
|
||||
if enableScope {
|
||||
var scopeFilters []scope.ScopeFilter
|
||||
for _, scope := range model.Scopes {
|
||||
scopeFilters = append(scopeFilters, scope.Filters...)
|
||||
}
|
||||
var scopeFilters []scope.ScopeFilter
|
||||
for _, scope := range model.Scopes {
|
||||
scopeFilters = append(scopeFilters, scope.Filters...)
|
||||
}
|
||||
|
||||
if len(scopeFilters) > 0 {
|
||||
span.SetAttributes(attribute.StringSlice("scopeFilters", func() []string {
|
||||
var filters []string
|
||||
for _, f := range scopeFilters {
|
||||
filters = append(filters, fmt.Sprintf("%q %q %q", f.Key, f.Operator, f.Value))
|
||||
}
|
||||
return filters
|
||||
}()))
|
||||
}
|
||||
|
||||
if len(model.AdhocFilters) > 0 {
|
||||
span.SetAttributes(attribute.StringSlice("adhocFilters", func() []string {
|
||||
var filters []string
|
||||
for _, f := range model.AdhocFilters {
|
||||
filters = append(filters, fmt.Sprintf("%q %q %q", f.Key, f.Operator, f.Value))
|
||||
}
|
||||
return filters
|
||||
}()))
|
||||
}
|
||||
|
||||
if len(scopeFilters) > 0 || len(model.AdhocFilters) > 0 || len(model.GroupByKeys) > 0 {
|
||||
log.Info("Applying scope filters", "scopeFiltersCount", len(scopeFilters), "adhocFiltersCount", len(model.AdhocFilters), "groupByKeysCount", len(model.GroupByKeys))
|
||||
expr, err = ApplyFiltersAndGroupBy(expr, scopeFilters, model.AdhocFilters, model.GroupByKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if len(scopeFilters) > 0 {
|
||||
span.SetAttributes(attribute.StringSlice("scopeFilters", func() []string {
|
||||
var filters []string
|
||||
for _, f := range scopeFilters {
|
||||
filters = append(filters, fmt.Sprintf("%q %q %q", f.Key, f.Operator, f.Value))
|
||||
}
|
||||
return filters
|
||||
}()))
|
||||
}
|
||||
|
||||
if len(model.AdhocFilters) > 0 {
|
||||
span.SetAttributes(attribute.StringSlice("adhocFilters", func() []string {
|
||||
var filters []string
|
||||
for _, f := range model.AdhocFilters {
|
||||
filters = append(filters, fmt.Sprintf("%q %q %q", f.Key, f.Operator, f.Value))
|
||||
}
|
||||
return filters
|
||||
}()))
|
||||
}
|
||||
|
||||
if len(scopeFilters) > 0 || len(model.AdhocFilters) > 0 || len(model.GroupByKeys) > 0 {
|
||||
log.Info("Applying scope filters", "scopeFiltersCount", len(scopeFilters), "adhocFiltersCount", len(model.AdhocFilters), "groupByKeysCount", len(model.GroupByKeys))
|
||||
expr, err = ApplyFiltersAndGroupBy(expr, scopeFilters, model.AdhocFilters, model.GroupByKeys)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestParse(t *testing.T) {
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, true, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, res.ExemplarQuery)
|
||||
})
|
||||
@@ -62,7 +62,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, time.Second*30, res.Step)
|
||||
})
|
||||
@@ -80,7 +80,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, time.Second*15, res.Step)
|
||||
})
|
||||
@@ -98,7 +98,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, time.Minute*20, res.Step)
|
||||
})
|
||||
@@ -116,7 +116,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, time.Minute*2, res.Step)
|
||||
})
|
||||
@@ -134,7 +134,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "240s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "240s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, time.Minute*4, res.Step)
|
||||
})
|
||||
@@ -153,7 +153,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [2m]})", res.Expr)
|
||||
require.Equal(t, 120*time.Second, res.Step)
|
||||
@@ -174,7 +174,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [2m]})", res.Expr)
|
||||
})
|
||||
@@ -193,7 +193,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [120000]})", res.Expr)
|
||||
})
|
||||
@@ -212,7 +212,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [120000]}) + rate(ALERTS{job=\"test\" [2m]})", res.Expr)
|
||||
})
|
||||
@@ -231,7 +231,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [120000]}) + rate(ALERTS{job=\"test\" [2m]})", res.Expr)
|
||||
})
|
||||
@@ -249,7 +249,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [172800s]})", res.Expr)
|
||||
})
|
||||
@@ -267,7 +267,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [172800]})", res.Expr)
|
||||
})
|
||||
@@ -285,7 +285,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [172800s]})", res.Expr)
|
||||
})
|
||||
@@ -303,7 +303,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [0]})", res.Expr)
|
||||
})
|
||||
@@ -321,7 +321,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [1]})", res.Expr)
|
||||
})
|
||||
@@ -339,7 +339,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [172800000]})", res.Expr)
|
||||
})
|
||||
@@ -357,7 +357,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [20]})", res.Expr)
|
||||
})
|
||||
@@ -376,7 +376,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [20m0s]})", res.Expr)
|
||||
})
|
||||
@@ -395,7 +395,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, 1*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [1m0s]})", res.Expr)
|
||||
require.Equal(t, 1*time.Minute, res.Step)
|
||||
@@ -414,7 +414,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, 2*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [135000]})", res.Expr)
|
||||
})
|
||||
@@ -432,7 +432,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, 2*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [135000]}) + rate(ALERTS{job=\"test\" [2m15s]})", res.Expr)
|
||||
})
|
||||
@@ -451,7 +451,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, 2*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "A", res.RefId)
|
||||
})
|
||||
@@ -469,7 +469,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, 2*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "rate(ALERTS{job=\"test\" [135000]}) + rate(ALERTS{job=\"test\" [2m15s]})", res.Expr)
|
||||
})
|
||||
@@ -488,7 +488,7 @@ func TestParse(t *testing.T) {
|
||||
"range": true
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, res.RangeQuery)
|
||||
})
|
||||
@@ -508,7 +508,7 @@ func TestParse(t *testing.T) {
|
||||
"instant": true
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, res.RangeQuery)
|
||||
require.Equal(t, true, res.InstantQuery)
|
||||
@@ -527,7 +527,7 @@ func TestParse(t *testing.T) {
|
||||
"refId": "A"
|
||||
}`, timeRange, time.Duration(1)*time.Minute)
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, res.RangeQuery)
|
||||
})
|
||||
@@ -660,7 +660,7 @@ func TestRateInterval(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
q := mockQuery(tt.args.expr, tt.args.interval, tt.args.intervalMs, tt.args.timeRange)
|
||||
q.MaxDataPoints = 12384
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, tt.args.dsScrapeInterval, intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, tt.args.dsScrapeInterval, intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tt.want.Expr, res.Expr)
|
||||
require.Equal(t, tt.want.Step, res.Step)
|
||||
@@ -695,7 +695,7 @@ func TestRateInterval(t *testing.T) {
|
||||
"utcOffsetSec":3600
|
||||
}`),
|
||||
}
|
||||
res, err := models.Parse(context.Background(), log.New(), span, query, "30s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, query, "30s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "sum(rate(process_cpu_seconds_total[2m0s]))", res.Expr)
|
||||
require.Equal(t, 30*time.Second, res.Step)
|
||||
@@ -730,7 +730,7 @@ func TestRateInterval(t *testing.T) {
|
||||
"maxDataPoints": 1055
|
||||
}`),
|
||||
}
|
||||
res, err := models.Parse(context.Background(), log.New(), span, query, "15s", intervalCalculator, false, false)
|
||||
res, err := models.Parse(context.Background(), log.New(), span, query, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "sum(rate(cache_requests_total[1m0s]))", res.Expr)
|
||||
require.Equal(t, 15*time.Second, res.Step)
|
||||
@@ -812,6 +812,501 @@ func TestAlignTimeRange(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseWithAdhocFilters(t *testing.T) {
|
||||
_, span := tracer.Start(context.Background(), "operation")
|
||||
defer span.End()
|
||||
|
||||
t.Run("parsing query with adhoc filters", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total",
|
||||
"refId": "A",
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "job",
|
||||
"value": "prometheus",
|
||||
"operator": "equals"
|
||||
},
|
||||
{
|
||||
"key": "method",
|
||||
"value": "get",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{job="prometheus",method="get"}`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with adhoc filters using not-equals operator", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total{job=\"grafana\"}",
|
||||
"refId": "A",
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "status",
|
||||
"value": "500",
|
||||
"operator": "not-equals"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{job="grafana",status!="500"}`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with adhoc filters using one-of operator", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total",
|
||||
"refId": "A",
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "status",
|
||||
"values": ["200", "201", "202"],
|
||||
"operator": "one-of"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{status=~"200|201|202"}`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing complex query with adhoc filters", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "rate(http_requests_total{job=\"prometheus\"}[5m]) + rate(http_errors_total{job=\"grafana\"}[5m])",
|
||||
"refId": "A",
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "environment",
|
||||
"value": "production",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `rate(http_requests_total{environment="production",job="prometheus"}[5m]) + rate(http_errors_total{environment="production",job="grafana"}[5m])`, res.Expr)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseWithScopes(t *testing.T) {
|
||||
_, span := tracer.Start(context.Background(), "operation")
|
||||
defer span.End()
|
||||
|
||||
t.Run("parsing query with scope filters", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total",
|
||||
"refId": "A",
|
||||
"scopes": [
|
||||
{
|
||||
"name": "production-scope",
|
||||
"title": "Production Environment",
|
||||
"filters": [
|
||||
{
|
||||
"key": "environment",
|
||||
"value": "production",
|
||||
"operator": "equals"
|
||||
},
|
||||
{
|
||||
"key": "region",
|
||||
"value": "us-west-2",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{environment="production",region="us-west-2"}`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with multiple scopes having same filter key", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total",
|
||||
"refId": "A",
|
||||
"scopes": [
|
||||
{
|
||||
"name": "namespace-scope-1",
|
||||
"title": "Default Namespace",
|
||||
"filters": [
|
||||
{
|
||||
"key": "namespace",
|
||||
"value": "default",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "namespace-scope-2",
|
||||
"title": "Kube System Namespace",
|
||||
"filters": [
|
||||
{
|
||||
"key": "namespace",
|
||||
"value": "kube-system",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{namespace=~"default|kube-system"}`, res.Expr)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseWithScopesAndAdhocFilters(t *testing.T) {
|
||||
_, span := tracer.Start(context.Background(), "operation")
|
||||
defer span.End()
|
||||
|
||||
t.Run("parsing query with both scopes and adhoc filters", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total",
|
||||
"refId": "A",
|
||||
"scopes": [
|
||||
{
|
||||
"name": "production-scope",
|
||||
"title": "Production Environment",
|
||||
"filters": [
|
||||
{
|
||||
"key": "environment",
|
||||
"value": "production",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "job",
|
||||
"value": "prometheus",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{environment="production",job="prometheus"}`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("adhoc filters override scope filters on conflict", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "http_requests_total",
|
||||
"refId": "A",
|
||||
"scopes": [
|
||||
{
|
||||
"name": "staging-scope",
|
||||
"title": "Staging Environment",
|
||||
"filters": [
|
||||
{
|
||||
"key": "environment",
|
||||
"value": "staging",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "environment",
|
||||
"value": "production",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `http_requests_total{environment="production"}`, res.Expr)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseWithGroupByKeys(t *testing.T) {
|
||||
_, span := tracer.Start(context.Background(), "operation")
|
||||
defer span.End()
|
||||
|
||||
t.Run("parsing query with group by keys", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "sum(http_requests_total)",
|
||||
"refId": "A",
|
||||
"groupByKeys": ["job", "instance"]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `sum by (job, instance) (http_requests_total)`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with group by keys and existing group by", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "sum by (job) (http_requests_total)",
|
||||
"refId": "A",
|
||||
"groupByKeys": ["status"]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `sum by (job, status) (http_requests_total)`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with filters and group by keys", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "sum(http_requests_total)",
|
||||
"refId": "A",
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "job",
|
||||
"value": "prometheus",
|
||||
"operator": "equals"
|
||||
}
|
||||
],
|
||||
"groupByKeys": ["status", "method"]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `sum by (status, method) (http_requests_total{job="prometheus"})`, res.Expr)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseComplexScenariosWithFilters(t *testing.T) {
|
||||
_, span := tracer.Start(context.Background(), "operation")
|
||||
defer span.End()
|
||||
|
||||
t.Run("parsing query with regex filters and variables", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(48 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "rate(http_requests_total[$__interval])",
|
||||
"refId": "A",
|
||||
"intervalMs": 60000,
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "job",
|
||||
"value": "prometheus.*",
|
||||
"operator": "regex-match"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
Interval: time.Minute,
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `rate(http_requests_total{job=~"prometheus.*"}[2m])`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with complex expression, scopes, adhoc filters, and group by", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m])) * 100",
|
||||
"refId": "A",
|
||||
"scopes": [
|
||||
{
|
||||
"name": "production-scope",
|
||||
"title": "Production Environment",
|
||||
"filters": [
|
||||
{
|
||||
"key": "environment",
|
||||
"value": "production",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "region",
|
||||
"values": ["us-west-1", "us-west-2", "us-east-1"],
|
||||
"operator": "one-of"
|
||||
}
|
||||
],
|
||||
"groupByKeys": ["job"]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `sum by (job) (rate(http_requests_total{environment="production",region=~"us-west-1|us-west-2|us-east-1"}[5m])) / sum by (job) (rate(http_requests_total{environment="production",region=~"us-west-1|us-west-2|us-east-1"}[5m])) * 100`, res.Expr)
|
||||
})
|
||||
|
||||
t.Run("parsing query with __name__ selector and filters", func(t *testing.T) {
|
||||
timeRange := backend.TimeRange{
|
||||
From: now,
|
||||
To: now.Add(12 * time.Hour),
|
||||
}
|
||||
|
||||
queryJson := `{
|
||||
"expr": "{__name__=\"http_requests_total\"}",
|
||||
"refId": "A",
|
||||
"adhocFilters": [
|
||||
{
|
||||
"key": "namespace",
|
||||
"value": "monitoring",
|
||||
"operator": "equals"
|
||||
}
|
||||
]
|
||||
}`
|
||||
|
||||
q := backend.DataQuery{
|
||||
JSON: []byte(queryJson),
|
||||
TimeRange: timeRange,
|
||||
RefID: "A",
|
||||
}
|
||||
|
||||
res, err := models.Parse(context.Background(), log.New(), span, q, "15s", intervalCalculator, false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, `{__name__="http_requests_total",namespace="monitoring"}`, res.Expr)
|
||||
})
|
||||
}
|
||||
|
||||
func TestQueryTypeDefinitions(t *testing.T) {
|
||||
builder, err := schemabuilder.NewSchemaBuilder(
|
||||
schemabuilder.BuilderOptions{
|
||||
|
||||
@@ -100,10 +100,7 @@ func (s *QueryData) Execute(ctx context.Context, req *backend.QueryDataRequest)
|
||||
Responses: backend.Responses{},
|
||||
}
|
||||
|
||||
var (
|
||||
hasPromQLScopeFeatureFlag = s.featureToggles.IsEnabled("promQLScope")
|
||||
m sync.Mutex
|
||||
)
|
||||
var m sync.Mutex
|
||||
|
||||
concurrentQueryCount, err := req.PluginContext.GrafanaConfig.ConcurrentQueryCount()
|
||||
if err != nil {
|
||||
@@ -113,7 +110,7 @@ func (s *QueryData) Execute(ctx context.Context, req *backend.QueryDataRequest)
|
||||
|
||||
_ = concurrency.ForEachJob(ctx, len(req.Queries), concurrentQueryCount, func(ctx context.Context, idx int) error {
|
||||
query := req.Queries[idx]
|
||||
r := s.handleQuery(ctx, query, fromAlert, hasPromQLScopeFeatureFlag)
|
||||
r := s.handleQuery(ctx, query, fromAlert)
|
||||
if r != nil {
|
||||
m.Lock()
|
||||
result.Responses[query.RefID] = *r
|
||||
@@ -125,11 +122,10 @@ func (s *QueryData) Execute(ctx context.Context, req *backend.QueryDataRequest)
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
func (s *QueryData) handleQuery(ctx context.Context, bq backend.DataQuery, fromAlert,
|
||||
hasPromQLScopeFeatureFlag bool) *backend.DataResponse {
|
||||
func (s *QueryData) handleQuery(ctx context.Context, bq backend.DataQuery, fromAlert bool) *backend.DataResponse {
|
||||
traceCtx, span := s.tracer.Start(ctx, "datasource.prometheus")
|
||||
defer span.End()
|
||||
query, err := models.Parse(ctx, s.log, span, bq, s.TimeInterval, s.intervalCalculator, fromAlert, hasPromQLScopeFeatureFlag)
|
||||
query, err := models.Parse(ctx, s.log, span, bq, s.TimeInterval, s.intervalCalculator, fromAlert)
|
||||
if err != nil {
|
||||
return &backend.DataResponse{
|
||||
Error: err,
|
||||
|
||||
@@ -830,15 +830,6 @@ var (
|
||||
HideFromDocs: true,
|
||||
HideFromAdminPage: true,
|
||||
},
|
||||
{
|
||||
Name: "promQLScope",
|
||||
Description: "In-development feature that will allow injection of labels into prometheus queries.",
|
||||
Stage: FeatureStageGeneralAvailability,
|
||||
Owner: grafanaOSSBigTent,
|
||||
Expression: "true",
|
||||
HideFromDocs: true,
|
||||
HideFromAdminPage: true,
|
||||
},
|
||||
{
|
||||
Name: "logQLScope",
|
||||
Description: "In-development feature that will allow injection of labels into loki queries.",
|
||||
|
||||
@@ -109,7 +109,6 @@ alertingSaveStateCompressed,preview,@grafana/alerting-squad,false,false,false
|
||||
scopeApi,experimental,@grafana/grafana-app-platform-squad,false,false,false
|
||||
useScopeSingleNodeEndpoint,experimental,@grafana/grafana-operator-experience-squad,false,false,true
|
||||
useMultipleScopeNodesEndpoint,experimental,@grafana/grafana-operator-experience-squad,false,false,true
|
||||
promQLScope,GA,@grafana/oss-big-tent,false,false,false
|
||||
logQLScope,privatePreview,@grafana/observability-logs,false,false,false
|
||||
sqlExpressions,preview,@grafana/grafana-datasources-core-services,false,false,false
|
||||
sqlExpressionsColumnAutoComplete,experimental,@grafana/datapro,false,false,true
|
||||
|
||||
|
@@ -447,10 +447,6 @@ const (
|
||||
// Makes the frontend use the 'names' param for fetching multiple scope nodes at once
|
||||
FlagUseMultipleScopeNodesEndpoint = "useMultipleScopeNodesEndpoint"
|
||||
|
||||
// FlagPromQLScope
|
||||
// In-development feature that will allow injection of labels into prometheus queries.
|
||||
FlagPromQLScope = "promQLScope"
|
||||
|
||||
// FlagLogQLScope
|
||||
// In-development feature that will allow injection of labels into loki queries.
|
||||
FlagLogQLScope = "logQLScope"
|
||||
|
||||
@@ -2960,7 +2960,8 @@
|
||||
"metadata": {
|
||||
"name": "promQLScope",
|
||||
"resourceVersion": "1753448760331",
|
||||
"creationTimestamp": "2024-01-29T20:22:17Z"
|
||||
"creationTimestamp": "2024-01-29T20:22:17Z",
|
||||
"deletionTimestamp": "2025-10-05T00:24:17Z"
|
||||
},
|
||||
"spec": {
|
||||
"description": "In-development feature that will allow injection of labels into prometheus queries.",
|
||||
|
||||
Reference in New Issue
Block a user