prometheus.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { lastValueFrom } from 'rxjs';
  2. import { getBackendSrv } from '@grafana/runtime';
  3. import { RuleNamespace } from 'app/types/unified-alerting';
  4. import { PromRulesResponse } from 'app/types/unified-alerting-dto';
  5. import { getDatasourceAPIUid, GRAFANA_RULES_SOURCE_NAME } from '../utils/datasource';
  6. export interface FetchPromRulesFilter {
  7. dashboardUID: string;
  8. panelId?: number;
  9. }
  10. export interface PrometheusDataSourceConfig {
  11. dataSourceName: string;
  12. }
  13. export function prometheusUrlBuilder(dataSourceConfig: PrometheusDataSourceConfig) {
  14. const { dataSourceName } = dataSourceConfig;
  15. return {
  16. rules: (filter?: FetchPromRulesFilter) => {
  17. const searchParams = new URLSearchParams();
  18. const params = prepareRulesFilterQueryParams(searchParams, filter);
  19. return {
  20. url: `/api/prometheus/${getDatasourceAPIUid(dataSourceName)}/api/v1/rules`,
  21. params: params,
  22. };
  23. },
  24. };
  25. }
  26. export function prepareRulesFilterQueryParams(
  27. params: URLSearchParams,
  28. filter?: FetchPromRulesFilter
  29. ): Record<string, string> {
  30. if (filter?.dashboardUID) {
  31. params.set('dashboard_uid', filter.dashboardUID);
  32. if (filter?.panelId) {
  33. params.set('panel_id', String(filter.panelId));
  34. }
  35. }
  36. return Object.fromEntries(params);
  37. }
  38. export async function fetchRules(dataSourceName: string, filter?: FetchPromRulesFilter): Promise<RuleNamespace[]> {
  39. if (filter?.dashboardUID && dataSourceName !== GRAFANA_RULES_SOURCE_NAME) {
  40. throw new Error('Filtering by dashboard UID is only supported for Grafana Managed rules.');
  41. }
  42. const { url, params } = prometheusUrlBuilder({ dataSourceName }).rules(filter);
  43. const response = await lastValueFrom(
  44. getBackendSrv().fetch<PromRulesResponse>({
  45. url,
  46. params,
  47. showErrorAlert: false,
  48. showSuccessAlert: false,
  49. })
  50. ).catch((e) => {
  51. if ('status' in e && e.status === 404) {
  52. throw new Error('404 from rule state endpoint. Perhaps ruler API is not enabled?');
  53. }
  54. throw e;
  55. });
  56. const nsMap: { [key: string]: RuleNamespace } = {};
  57. response.data.data.groups.forEach((group) => {
  58. group.rules.forEach((rule) => {
  59. rule.query = rule.query || '';
  60. });
  61. if (!nsMap[group.file]) {
  62. nsMap[group.file] = {
  63. dataSourceName,
  64. name: group.file,
  65. groups: [group],
  66. };
  67. } else {
  68. nsMap[group.file].groups.push(group);
  69. }
  70. });
  71. return Object.values(nsMap);
  72. }