Add per-tenant Grafana Explore URL format for alert GeneratorURL#7302
Add per-tenant Grafana Explore URL format for alert GeneratorURL#7302CharlieTLe wants to merge 2 commits intocortexproject:masterfrom
Conversation
Add support for tenants to configure alert GeneratorURL to use Grafana Explore format instead of the default Prometheus /graph format. This is controlled by three new per-tenant settings: ruler_alert_generator_url_format, ruler_grafana_datasource_uid, and ruler_grafana_org_id. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Charlie Le <charlie_le@apple.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Charlie Le <charlie_le@apple.com>
yeya24
left a comment
There was a problem hiding this comment.
@rajagopalanand Can you help take a look?
friedrichg
left a comment
There was a problem hiding this comment.
I gave a review, but I think we do not care what parameters are send to the url. We don't care about grafana org IDs
I think we should make this general enough to be used by any metrics explorer.
Maybe consider renaming the function as explore and not have any grafana
I am thinking of something that would support for example:
explore
what do you think?
| cortex_overrides{limit_name="reject_old_samples",user="tenant-a"} 0 | ||
| cortex_overrides{limit_name="reject_old_samples_max_age",user="tenant-a"} 1.2096e+06 | ||
| cortex_overrides{limit_name="ruler_evaluation_delay_duration",user="tenant-a"} 0 | ||
| cortex_overrides{limit_name="ruler_grafana_org_id",user="tenant-a"} 0 |
There was a problem hiding this comment.
I think this should never be 0. The default org id as zero should be rejected as invalid.
Consider putting
-
if l.RulerGrafanaOrgID < 1 { -
return errors.New("ruler_grafana_org_id must be greater than or equal to 1") -
}
in UnmarshalYaml and UnmarshallJSON in limits.go
| if orgID == 0 { | ||
| orgID = 1 | ||
| } |
There was a problem hiding this comment.
| if orgID == 0 { | |
| orgID = 1 | |
| } |
Should not be needed after my other comment
| if orgID == 0 { | ||
| orgID = 1 | ||
| } | ||
| return grafanaExploreLink(externalURL, expr, datasourceUID, orgID) |
There was a problem hiding this comment.
I think is better we make grafanaExploreLink return errors if the url cannot be generated. For example: empty datasource
and if get errors we should log the error and fallback to prometheus still
|
|
||
| # Grafana datasource UID for alert generator URLs when format is | ||
| # grafana-explore. | ||
| [ruler_grafana_datasource_uid: <string> | default = ""] |
There was a problem hiding this comment.
it's not clear looking at this configuration that empty is not valid.
| }, | ||
| }, | ||
| "range": map[string]string{ | ||
| "from": "now-1h", |
There was a problem hiding this comment.
this looks like it should be configurable. Maybe there is a way to configure the whole pane as a configurable json. At the end of the day, we don't care for this
Summary
GeneratorURLto use Grafana Explore format instead of the default Prometheus/graphformatruler_alert_generator_url_format,ruler_grafana_datasource_uid, andruler_grafana_org_idruler_external_urloverride so tenants can have different external URLs without changing the global ruler configWhen
ruler_alert_generator_url_formatis set tografana-explore, the GeneratorURL in fired alerts becomes a Grafana Explore link (e.g.http://grafana:3000/explore?schemaVersion=1&panes=...&orgId=1) with the alert expression and datasource UID pre-filled. Clicking "See source" on an alert in Grafana opens Explore with the correct query, datasource, and time range.New per-tenant config options
ruler_external_url""(uses global)ruler_alert_generator_url_formatprometheusorgrafana-explore""(prometheus)ruler_grafana_datasource_uid""ruler_grafana_org_id1Example runtime config
Test plan
grafanaExploreLinkURL generation with various expressions and special charactersuserExternalURLtracking per-tenant URL changesSendAlertswith custom generator URL functiongrafana-exploreformat — confirmed the "See source" link opens Grafana Explore with correct datasource and query🤖 Generated with Claude Code