From ddc378421378cafc727dea9d5020d7594bcd8195 Mon Sep 17 00:00:00 2001
From: Gilles De Mey <gilles.de.mey@gmail.com>
Date: Mon, 7 Aug 2023 17:19:29 +0200
Subject: [PATCH] Alerting: Fix "see graph button" for cloud rules (#72980)

Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com>
Co-authored-by: Giordano Ricci <me@giordanoricci.com>
---
 .../rule-viewer/RuleViewerVisualization.tsx           | 11 +++++------
 .../components/rules/RuleDetailsActionButtons.tsx     |  2 +-
 .../app/features/alerting/unified/utils/misc.test.ts  | 11 ++++++++++-
 public/app/features/alerting/unified/utils/misc.ts    |  9 ++++++---
 4 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx b/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx
index bce99753e24..68486537dcb 100644
--- a/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx
+++ b/public/app/features/alerting/unified/components/rule-viewer/RuleViewerVisualization.tsx
@@ -12,6 +12,7 @@ import {
   urlUtil,
 } from '@grafana/data';
 import { config } from '@grafana/runtime';
+import { DataSourceRef } from '@grafana/schema';
 import { DateTimePicker, LinkButton, useStyles2 } from '@grafana/ui';
 import { isExpressionQuery } from 'app/features/expressions/guards';
 import { AccessControlAction } from 'app/types';
@@ -90,22 +91,20 @@ export function RuleViewerVisualization({
   );
 }
 
-function createExploreLink(settings: DataSourceInstanceSettings, model: AlertDataQuery): string {
-  const { name } = settings;
+function createExploreLink(settings: DataSourceRef, model: AlertDataQuery): string {
+  const { uid, type } = settings;
   const { refId, ...rest } = model;
 
   /*
     In my testing I've found some alerts that don't have a data source embedded inside the model.
-
     At this moment in time it is unclear to me why some alert definitions not have a data source embedded in the model.
-    Ideally we'd resolve the datasource name to the proper datasource Ref "{ type: string, uid: string }" and pass that in to the model.
 
     I don't think that should happen here, the fact that the datasource ref is sometimes missing here is a symptom of another cause. (Gilles)
    */
   return urlUtil.renderUrl(`${config.appSubUrl}/explore`, {
     left: JSON.stringify({
-      datasource: name,
-      queries: [{ refId: 'A', ...rest }],
+      datasource: settings.uid,
+      queries: [{ refId: 'A', ...rest, datasource: { type, uid } }],
       range: { from: 'now-1h', to: 'now' },
     }),
   });
diff --git a/public/app/features/alerting/unified/components/rules/RuleDetailsActionButtons.tsx b/public/app/features/alerting/unified/components/rules/RuleDetailsActionButtons.tsx
index adfdbe9504e..a93c11a7644 100644
--- a/public/app/features/alerting/unified/components/rules/RuleDetailsActionButtons.tsx
+++ b/public/app/features/alerting/unified/components/rules/RuleDetailsActionButtons.tsx
@@ -91,7 +91,7 @@ export const RuleDetailsActionButtons = ({ rule, rulesSource, isViewMode }: Prop
         variant="primary"
         icon="chart-line"
         target="__blank"
-        href={createExploreLink(rulesSource.name, rule.query)}
+        href={createExploreLink(rulesSource, rule.query)}
       >
         See graph
       </LinkButton>
diff --git a/public/app/features/alerting/unified/utils/misc.test.ts b/public/app/features/alerting/unified/utils/misc.test.ts
index e4aaf53b28e..24fe248b5f6 100644
--- a/public/app/features/alerting/unified/utils/misc.test.ts
+++ b/public/app/features/alerting/unified/utils/misc.test.ts
@@ -1,4 +1,4 @@
-import { sortAlerts, wrapWithQuotes, escapeQuotes } from 'app/features/alerting/unified/utils/misc';
+import { sortAlerts, wrapWithQuotes, escapeQuotes, createExploreLink } from 'app/features/alerting/unified/utils/misc';
 import { SortOrder } from 'app/plugins/panel/alertlist/types';
 import { Alert } from 'app/types/unified-alerting';
 import { GrafanaAlertState } from 'app/types/unified-alerting-dto';
@@ -86,3 +86,12 @@ describe('Unified Altering misc', () => {
     });
   });
 });
+
+describe('createExploreLink', () => {
+  it('should create a correct explore link', () => {
+    const url = createExploreLink({ uid: 'uid', type: 'type' }, 'cpu_utilization > 0.5');
+    expect(url).toBe(
+      '/explore?left=%7B%22datasource%22%3A%22uid%22%2C%22queries%22%3A%5B%7B%22refId%22%3A%22A%22%2C%22datasource%22%3A%7B%22uid%22%3A%22uid%22%2C%22type%22%3A%22type%22%7D%2C%22expr%22%3A%22cpu_utilization+%3E+0.5%22%7D%5D%2C%22range%22%3A%7B%22from%22%3A%22now-1h%22%2C%22to%22%3A%22now%22%7D%7D'
+    );
+  });
+});
diff --git a/public/app/features/alerting/unified/utils/misc.ts b/public/app/features/alerting/unified/utils/misc.ts
index 5373aeb3c88..ce60ea9f338 100644
--- a/public/app/features/alerting/unified/utils/misc.ts
+++ b/public/app/features/alerting/unified/utils/misc.ts
@@ -1,6 +1,7 @@
 import { sortBy } from 'lodash';
 
 import { UrlQueryMap, Labels, DataSourceInstanceSettings, DataSourceJsonData } from '@grafana/data';
+import { DataSourceRef } from '@grafana/schema';
 import { alertInstanceKey } from 'app/features/alerting/unified/utils/rules';
 import { SortOrder } from 'app/plugins/panel/alertlist/types';
 import { Alert, CombinedRule, FilterState, RulesSource, SilenceFilterState } from 'app/types/unified-alerting';
@@ -27,11 +28,13 @@ export function createViewLink(ruleSource: RulesSource, rule: CombinedRule, retu
   return createUrl(`/alerting/${paramSource}/${paramId}/view`, { returnTo });
 }
 
-export function createExploreLink(dataSourceName: string, query: string) {
+export function createExploreLink(datasource: DataSourceRef, query: string) {
+  const { uid, type } = datasource;
+
   return createUrl(`/explore`, {
     left: JSON.stringify({
-      datasource: dataSourceName,
-      queries: [{ refId: 'A', datasource: dataSourceName, expr: query }],
+      datasource: datasource.uid,
+      queries: [{ refId: 'A', datasource: { uid, type }, expr: query }],
       range: { from: 'now-1h', to: 'now' },
     }),
   });