Compare commits

...

14 Commits

Author SHA1 Message Date
Konrad Lalik
5bc67f84e4 Alerting: Fix cache key mismatch in populateGroupsResponseCache
Updates the cache population logic to include `compact` and `limitAlerts`
parameters in the cache key. Previously, the cache was populated with only
`folderUid`, `groupName`, and a hardcoded `limitAlerts: 0`, which caused
cache key mismatches when queries used different parameter values.

Changes:
- Add `PopulateCacheOptions` interface for cache parameters
- Update `populateGroupsResponseCache` to accept options parameter
- Pass `limitAlerts` and `compact` from hook options to cache function

This ensures RTK Query cache keys match the actual query parameters,
enabling proper cache hits and avoiding redundant API calls.
2025-12-16 15:14:00 +01:00
Konrad Lalik
d5fdafed83 Merge branch 'main' of github.com:grafana/grafana into santihernandezc/use_compact_param_alert_rule_list 2025-12-16 14:42:40 +01:00
Konrad Lalik
ae542071d7 Refactor compact parameter to be configurable via hook options
Moves the `compact` parameter from being hardcoded inside the
`useGrafanaGroupsGenerator` hook to being an explicit option in
`UseGeneratorHookOptions`. This improves flexibility and consistency
across the codebase.

Changes:
- Add `compact` parameter to `UseGeneratorHookOptions` interface
- Update `useGrafanaGroupsGenerator` to use `compact` from hook options
- Update all call sites to explicitly pass `shouldUseCompactRulesResponse()`
- Replace direct feature toggle access with `shouldUseCompactRulesResponse()` helper

This change makes the feature toggle decision visible at call sites,
allows for easier testing, and follows the existing pattern used by
other hook options like `populateCache` and `limitAlerts`.
2025-12-16 14:38:42 +01:00
Santiago Hernández
e9b92ce955 Merge branch 'main' of github.com:grafana/grafana into santihernandezc/use_compact_param_alert_rule_list 2025-12-16 09:15:29 +01:00
Santiago Hernández
35e74b3a3a Merge branch 'main' of github.com:grafana/grafana into santihernandezc/use_compact_param_alert_rule_list 2025-12-15 14:21:12 +01:00
Santiago Hernández
68f2f52d9a add a FE feature toggle to get a 'compact' response from the /rules endpoint 2025-12-15 13:42:59 +01:00
Santiago Hernández
d93615d9ec pass 'compact' via pagination context 2025-12-15 13:02:04 +01:00
Santiago Hernández
89be0c4acd don't change old behavior 2025-12-15 12:57:44 +01:00
Santiago Hernández
2733bac3c2 empty 'query' field, stop sending full query JSON 2025-12-15 12:06:35 +01:00
Santiago Hernández
099bf1dab4 tests 2025-12-15 10:56:41 +01:00
Santiago Hernández
13ec5337f4 change name 2025-12-15 10:03:51 +01:00
Santiago Hernández
6bb3389f10 remove benchmark 2025-12-15 09:44:05 +01:00
Santiago Hernández
031712806f wire up compact param 2025-12-12 15:57:36 +01:00
Santiago Hernández
4e68e5e2ce Alerting: Add compact model for alert rules 2025-12-12 15:51:41 +01:00
11 changed files with 76 additions and 5 deletions

View File

@@ -422,6 +422,11 @@ export interface FeatureToggles {
*/
alertingQueryOptimization?: boolean;
/**
* Returns compact API responses for alert rules list, reducing payload size by omitting the query, notification settings, and metadata
* @default false
*/
alertingCompactRulesResponse?: boolean;
/**
* Distributes alert rule evaluations more evenly over time, including spreading out rules within the same group. Disables sequential evaluation if enabled.
*/
jitterAlertRulesWithinGroups?: boolean;

View File

@@ -686,6 +686,13 @@ var (
Owner: grafanaAlertingSquad,
Expression: "false",
},
{
Name: "alertingCompactRulesResponse",
Description: "Returns compact API responses for alert rules list, reducing payload size by omitting the query, notification settings, and metadata",
Stage: FeatureStageExperimental,
Owner: grafanaAlertingSquad,
Expression: "false",
},
{
Name: "jitterAlertRulesWithinGroups",
Description: "Distributes alert rule evaluations more evenly over time, including spreading out rules within the same group. Disables sequential evaluation if enabled.",

View File

@@ -95,6 +95,7 @@ tableSharedCrosshair,experimental,@grafana/dataviz-squad,false,false,true
kubernetesFeatureToggles,experimental,@grafana/grafana-operator-experience-squad,false,false,true
cloudRBACRoles,preview,@grafana/identity-access-team,false,true,false
alertingQueryOptimization,GA,@grafana/alerting-squad,false,false,false
alertingCompactRulesResponse,experimental,@grafana/alerting-squad,false,false,false
jitterAlertRulesWithinGroups,preview,@grafana/alerting-squad,false,true,false
secretsManagementAppPlatform,experimental,@grafana/grafana-operator-experience-squad,false,false,false
secretsManagementAppPlatformUI,experimental,@grafana/grafana-operator-experience-squad,false,false,false
1 Name Stage Owner requiresDevMode RequiresRestart FrontendOnly
95 kubernetesFeatureToggles experimental @grafana/grafana-operator-experience-squad false false true
96 cloudRBACRoles preview @grafana/identity-access-team false true false
97 alertingQueryOptimization GA @grafana/alerting-squad false false false
98 alertingCompactRulesResponse experimental @grafana/alerting-squad false false false
99 jitterAlertRulesWithinGroups preview @grafana/alerting-squad false true false
100 secretsManagementAppPlatform experimental @grafana/grafana-operator-experience-squad false false false
101 secretsManagementAppPlatformUI experimental @grafana/grafana-operator-experience-squad false false false

View File

@@ -279,6 +279,10 @@ const (
// Optimizes eligible queries in order to reduce load on datasources
FlagAlertingQueryOptimization = "alertingQueryOptimization"
// FlagAlertingCompactRulesResponse
// Returns compact API responses for alert rules list, reducing payload size by omitting the query, notification settings, and metadata
FlagAlertingCompactRulesResponse = "alertingCompactRulesResponse"
// FlagJitterAlertRulesWithinGroups
// Distributes alert rule evaluations more evenly over time, including spreading out rules within the same group. Disables sequential evaluation if enabled.
FlagJitterAlertRulesWithinGroups = "jitterAlertRulesWithinGroups"

View File

@@ -195,6 +195,22 @@
"codeowner": "@grafana/alerting-squad"
}
},
{
"metadata": {
"name": "alertingCompactRulesResponse",
"resourceVersion": "1765802340688",
"creationTimestamp": "2025-12-15T12:24:06Z",
"annotations": {
"grafana.app/updatedTimestamp": "2025-12-15 12:39:00.688866597 +0000 UTC"
}
},
"spec": {
"description": "Returns compact API responses for alert rules list, reducing payload size by omitting the query, notification settings, and metadata",
"stage": "experimental",
"codeowner": "@grafana/alerting-squad",
"expression": "false"
}
},
{
"metadata": {
"name": "alertingDisableSendAlertsExternal",

View File

@@ -47,6 +47,7 @@ export type GrafanaPromRulesOptions = Omit<PromRulesOptions, 'ruleSource' | 'nam
title?: string;
searchGroupName?: string;
type?: 'alerting' | 'recording';
compact?: boolean;
ruleMatchers?: string[];
};
@@ -103,6 +104,7 @@ export const prometheusApi = alertingApi.injectEndpoints({
datasources,
searchGroupName,
dashboardUid,
compact,
ruleMatchers,
}) => ({
url: `api/prometheus/grafana/api/v1/rules`,
@@ -122,6 +124,7 @@ export const prometheusApi = alertingApi.injectEndpoints({
'search.rule_name': title,
'search.rule_group': searchGroupName,
dashboard_uid: dashboardUid,
compact: compact,
rule_matcher: ruleMatchers,
},
}),
@@ -135,16 +138,26 @@ export const prometheusApi = alertingApi.injectEndpoints({
}),
});
export interface PopulateCacheOptions {
limitAlerts?: number;
compact?: boolean;
}
export function usePopulateGrafanaPrometheusApiCache() {
const dispatch = useDispatch();
const populateGroupsResponseCache = useCallback(
(groups: GrafanaPromRuleGroupDTO[]) => {
(groups: GrafanaPromRuleGroupDTO[], options: PopulateCacheOptions = {}) => {
dispatch(
prometheusApi.util.upsertQueryEntries(
groups.map((group) => ({
endpointName: 'getGrafanaGroups',
arg: { folderUid: group.folderUid, groupName: group.name, limitAlerts: 0 },
arg: {
folderUid: group.folderUid,
groupName: group.name,
limitAlerts: options.limitAlerts ?? 0,
compact: options.compact,
},
value: { data: { groups: [group] }, status: 'success' },
}))
)

View File

@@ -26,3 +26,5 @@ export const shouldUseBackendFilters = () => config.featureToggles.alertingUIUse
export const shouldUseFullyCompatibleBackendFilters = () =>
config.featureToggles.alertingUIUseFullyCompatBackendFilters ?? false;
export const shouldUseCompactRulesResponse = () => config.featureToggles.alertingCompactRulesResponse ?? false;

View File

@@ -7,6 +7,7 @@ import { Alert, Stack, useStyles2 } from '@grafana/ui';
import { GrafanaRuleGroupIdentifier } from 'app/types/unified-alerting';
import { prometheusApi } from '../api/prometheusApi';
import { shouldUseCompactRulesResponse } from '../featureToggles';
import { useContinuousPagination } from '../hooks/usePagination';
import { DEFAULT_PER_PAGE_PAGINATION_RULES_PER_GROUP, RULE_LIST_POLL_INTERVAL_MS } from '../utils/constants';
@@ -44,6 +45,7 @@ export function GrafanaGroupLoader({
folderUid: groupIdentifier.namespace.uid,
groupName: groupIdentifier.groupName,
limitAlerts: 0,
compact: shouldUseCompactRulesResponse(),
},
{ pollingInterval: RULE_LIST_POLL_INTERVAL_MS }
);

View File

@@ -7,6 +7,7 @@ import { GrafanaPromRuleGroupDTO, PromRuleGroupDTO } from 'app/types/unified-ale
import { FolderActionsButton } from '../components/folder-actions/FolderActionsButton';
import { GrafanaNoRulesCTA } from '../components/rules/NoRulesCTA';
import { shouldUseCompactRulesResponse } from '../featureToggles';
import { GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource';
import { groups } from '../utils/navigation';
@@ -47,6 +48,7 @@ function PaginatedGroupsLoader({ groupFilter, namespaceFilter }: LoaderProps) {
const grafanaGroupsGenerator = useGrafanaGroupsGenerator({
populateCache: needsClientSideFiltering ? false : true,
limitAlerts: 0,
compact: shouldUseCompactRulesResponse(),
});
// If there are no filters we can match one frontend page to one API page.

View File

@@ -15,6 +15,11 @@ interface UseGeneratorHookOptions {
*/
populateCache?: boolean;
limitAlerts?: number;
/**
* Whether to use compact response format from the API.
* Typically controlled by the alertingCompactRulesResponse feature toggle.
*/
compact?: boolean;
}
export function usePrometheusGroupsGenerator() {
@@ -76,15 +81,25 @@ export function useGrafanaGroupsGenerator(hookOptions: UseGeneratorHookOptions =
...fetchOptions,
limitAlerts: hookOptions.limitAlerts,
...fetchOptions.filter,
compact: hookOptions.compact,
}).unwrap();
if (hookOptions.populateCache) {
populateGroupsResponseCache(response.data.groups);
populateGroupsResponseCache(response.data.groups, {
limitAlerts: hookOptions.limitAlerts,
compact: hookOptions.compact,
});
}
return response;
},
[getGrafanaGroups, hookOptions.limitAlerts, hookOptions.populateCache, populateGroupsResponseCache]
[
getGrafanaGroups,
hookOptions.limitAlerts,
hookOptions.compact,
hookOptions.populateCache,
populateGroupsResponseCache,
]
);
return useCallback(

View File

@@ -15,6 +15,7 @@ import {
PromRuleGroupDTO,
} from 'app/types/unified-alerting-dto';
import { shouldUseCompactRulesResponse } from '../../featureToggles';
import { RuleSource, RulesFilter } from '../../search/rulesSearchParser';
import {
getDataSourceByUid,
@@ -76,7 +77,10 @@ export function useFilteredRulesIteratorProvider() {
const allExternalRulesSources = getExternalRulesSources();
const prometheusGroupsGenerator = usePrometheusGroupsGenerator();
const grafanaGroupsGenerator = useGrafanaGroupsGenerator({ limitAlerts: 0 });
const grafanaGroupsGenerator = useGrafanaGroupsGenerator({
limitAlerts: 0,
compact: shouldUseCompactRulesResponse(),
});
const getFilteredRulesIterable = (filterState: RulesFilter, options: FetchGroupsLimitOptions): GetIteratorResult => {
/* this is the abort controller that allows us to stop an AsyncIterable */