" when to > 0', () => {
+ render();
+
+ // 900 seconds -> 15m, 60 seconds -> 1m
+ const container = screen.getByText(/to/i).closest('span') || screen.getByText(/to/i).parentElement || document.body;
+ expect(container).toHaveTextContent(/15m to 1m/);
+ });
+});
diff --git a/public/app/features/alerting/unified/components/TimeRangeLabel.tsx b/public/app/features/alerting/unified/components/TimeRangeLabel.tsx
new file mode 100644
index 00000000000..472aa71d119
--- /dev/null
+++ b/public/app/features/alerting/unified/components/TimeRangeLabel.tsx
@@ -0,0 +1,32 @@
+import { RelativeTimeRange, rangeUtil } from '@grafana/data';
+import { Trans } from '@grafana/i18n';
+
+interface RuleTimeRangeLabelProps {
+ relativeTimeRange: RelativeTimeRange;
+}
+
+/**
+ * Displays a human-readable relative time range label like:
+ * - "15m to now" when to === 0 or not set
+ * - "15m to 1m" when to > 0
+ */
+export function TimeRangeLabel({ relativeTimeRange }: RuleTimeRangeLabelProps) {
+ const fromLabel = rangeUtil.secondsToHms(relativeTimeRange.from);
+ const toSeconds = relativeTimeRange.to ?? 0;
+ const toIsNow = !toSeconds || toSeconds <= 0;
+ const toLabel = toIsNow ? 'now' : rangeUtil.secondsToHms(toSeconds);
+
+ if (toIsNow) {
+ return (
+
+ {'{{from}}'} to now
+
+ );
+ }
+
+ return (
+
+ {'{{from}}'} to {'{{to}}'}
+
+ );
+}
diff --git a/public/app/features/alerting/unified/components/rule-editor/QueryOptions.tsx b/public/app/features/alerting/unified/components/rule-editor/QueryOptions.tsx
index 1b3afdb9c52..c9d319ae215 100644
--- a/public/app/features/alerting/unified/components/rule-editor/QueryOptions.tsx
+++ b/public/app/features/alerting/unified/components/rule-editor/QueryOptions.tsx
@@ -1,11 +1,13 @@
import { css } from '@emotion/css';
import { useState } from 'react';
-import { GrafanaTheme2, RelativeTimeRange, dateTime, getDefaultRelativeTimeRange, rangeUtil } from '@grafana/data';
+import { GrafanaTheme2, RelativeTimeRange, getDefaultRelativeTimeRange } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { Icon, InlineField, RelativeTimeRangePicker, Toggletip, clearButtonStyles, useStyles2 } from '@grafana/ui';
import { AlertQuery } from 'app/types/unified-alerting-dto';
+import { TimeRangeLabel } from '../TimeRangeLabel';
+
import { AlertQueryOptions, MaxDataPointsOption, MinIntervalOption } from './QueryWrapper';
export interface QueryOptionsProps {
@@ -27,8 +29,6 @@ export const QueryOptions = ({
const [showOptions, setShowOptions] = useState(false);
- const timeRange = query.relativeTimeRange ? rangeUtil.relativeToTimeRange(query.relativeTimeRange) : undefined;
-
const separator = , ;
return (
@@ -58,7 +58,9 @@ export const QueryOptions = ({
- {dateTime(timeRange?.from).locale('en').fromNow(true)}
+
+
+
{queryOptions.maxDataPoints && (
<>
diff --git a/public/app/features/alerting/unified/utils/query.ts b/public/app/features/alerting/unified/utils/query.ts
index daa30207e94..3567429653d 100644
--- a/public/app/features/alerting/unified/utils/query.ts
+++ b/public/app/features/alerting/unified/utils/query.ts
@@ -1,5 +1,3 @@
-import { produce } from 'immer';
-
import { DataSourceInstanceSettings } from '@grafana/data';
import { PromQuery } from '@grafana/prometheus';
import { DataQuery } from '@grafana/schema';
@@ -9,7 +7,6 @@ import { AlertQuery } from 'app/types/unified-alerting-dto';
import { isCloudRulesSource, isSupportedExternalRulesSourceType } from './datasource';
import { rulerRuleType } from './rules';
-import { safeParsePrometheusDuration } from './time';
export function alertRuleToQueries(combinedRule: CombinedRule | undefined | null): AlertQuery[] {
if (!combinedRule) {
@@ -19,8 +16,7 @@ export function alertRuleToQueries(combinedRule: CombinedRule | undefined | null
const { rulesSource } = namespace;
if (rulerRuleType.grafana.rule(rulerRule)) {
- const query = rulerRule.grafana_alert.data;
- return widenRelativeTimeRanges(query, rulerRule.for ?? '', combinedRule.group.interval);
+ return rulerRule.grafana_alert.data;
}
if (isCloudRulesSource(rulesSource)) {
@@ -32,37 +28,6 @@ export function alertRuleToQueries(combinedRule: CombinedRule | undefined | null
return [];
}
-/**
- * This function will figure out how large the time range for visualizing the alert rule detail view should be
- * We try to show as much data as is relevant for triaging / root cause analysis
- *
- * The function for it is;
- *
- * Math.max(3 * pending period, query range + (2 * pending period))
- *
- * We can safely ignore the evaluation interval because the pending period is guaranteed to be largen than or equal that
- */
-export function widenRelativeTimeRanges(queries: AlertQuery[], pendingPeriod: string, groupInterval?: string) {
- // if pending period is zero that means inherit from group interval, if that is empty then assume 1m
- const pendingPeriodDurationMillis =
- safeParsePrometheusDuration(pendingPeriod) ?? safeParsePrometheusDuration(groupInterval ?? '1m');
- const pendingPeriodDuration = Math.floor(pendingPeriodDurationMillis / 1000);
-
- return queries.map((query) =>
- produce(query, (draft) => {
- const fromQueryRange = draft.relativeTimeRange?.from ?? 0;
-
- // use whichever has the largest time range
- const from = Math.max(pendingPeriodDuration * 3, fromQueryRange + pendingPeriodDuration * 2);
-
- draft.relativeTimeRange = {
- from,
- to: 0,
- };
- })
- );
-}
-
export function dataQueryToAlertQuery(dataQuery: DataQuery, dataSourceUid: string): AlertQuery {
return {
refId: dataQuery.refId,
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 4a2217515fd..e974a23708a 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -2213,9 +2213,6 @@
"max-data-points": "MD = {{maxDataPoints}}",
"min-interval": "Min. Interval = {{minInterval}}"
},
- "query-preview": {
- "relative-time-range": "<0>{{from}}0> to now"
- },
"queryAndExpressionsStep": {
"disableAdvancedOptions": {
"text": "The selected queries and expressions cannot be converted to default. If you deactivate advanced options, your query and condition will be reset to default settings."
@@ -2561,6 +2558,10 @@
"recording": "{{recordingStats}} recording",
"recovering": "{{recoveringStats}} recovering"
},
+ "rule-time-range-label": {
+ "relative": "<0>{{from}}0> to now",
+ "relative-with-to": "<0>{{from}}0> to <2>{{to}}2>"
+ },
"rule-type-picker": {
"grafana-managed": "Select “Grafana managed” unless you have a Mimir, Loki or Cortex data source with the Ruler API enabled."
},