diff --git a/src/components/output.tsx b/src/components/output.tsx index 429b004..8b205b2 100644 --- a/src/components/output.tsx +++ b/src/components/output.tsx @@ -13,6 +13,19 @@ import { import { useEnv } from '../components/env.tsx'; +const DEFAULT_VAR_LOKI_DATASOURCE = new DatasourceVariableBuilder("loki") + .label("Logs Data source") + .type("loki") + .regex("(?!grafanacloud).+(?!-alert-state-history|-usage-insight)") + .multi(false); + +const DEFAULT_VAR_PROMETHEUS_DATASOURCE = new DatasourceVariableBuilder("prometheus") + .label("Metrics Data source") + .type("prometheus") + .regex("(?!grafanacloud-usage|grafanacloud-ml-metrics).+") + .multi(false); + + export default function Component({ goBack, goForward, dashboardData }) { const env = useEnv(); const grafanaBaseurl = env?.["BUN_PUBLIC_GRAFANA_BASEURL"]; @@ -28,29 +41,36 @@ export default function Component({ goBack, goForward, dashboardData }) { new TimePickerBuilder() .refreshIntervals(["1m", "5m", "15m", "30m", "1h", "6h", "1d", "7d"]) ) - .withVariable( - new DatasourceVariableBuilder("prometheus") - .label("Metrics Data source") - .type("prometheus") - .regex("(?!grafanacloud-usage|grafanacloud-ml-metrics).+") - .multi(false) - ) - .withVariable( - new DatasourceVariableBuilder("loki") - .label("Logs Data source") - .type("loki") - .regex("(?!grafanacloud.+usage-insights|grafanacloud.+alert-state-history).+") - .multi(false) - ); - - // Inject variables contributed by enabled features + + // Inject variables contributed by enabled features, deduplicating by name + // so that multiple features using the same datasource type (ex: prometheus, + // loki) don't produce duplicate variables in the output. + const seenVariables = new Map(); + // TODO: Mayyybe there is a better way for this to avoid dupes sources dashboardData.features.forEach((feat) => { if (!feat.enabled) return; feat.variables.forEach((variable) => { - dashboard = dashboard.withVariable(variable); + const built = variable.build(); + if (!seenVariables.has(built.name)) { + seenVariables.set(built.name, variable); + } }); }); + // Check and add loki and prometheus datasources if they were not set. + + if(!seenVariables.has("loki")){ + seenVariables.set("loki", DEFAULT_VAR_LOKI_DATASOURCE); + } + + if(!seenVariables.has("prometheus")){ + seenVariables.set("prometheus", DEFAULT_VAR_PROMETHEUS_DATASOURCE); + } + + seenVariables.forEach((variable) => { + dashboard = dashboard.withVariable(variable); + }); + dashboard = dashboard.withRow(new RowBuilder("Overview")); dashboard = dashboard.withPanel( diff --git a/src/features/logs.tsx b/src/features/logs.tsx index 5d8e8c4..8ad8a2b 100644 --- a/src/features/logs.tsx +++ b/src/features/logs.tsx @@ -1,10 +1,10 @@ import { useState } from 'react'; +import { BigValueGraphMode } from '@grafana/grafana-foundation-sdk/common'; import { DataqueryBuilder as LokiDataqueryBuilder } from '@grafana/grafana-foundation-sdk/loki'; -import { PanelBuilder as LogsPanelBuilder } from '@grafana/grafana-foundation-sdk/logs'; import { LogsDedupStrategy } from '@grafana/grafana-foundation-sdk/common'; +import { PanelBuilder as LogsPanelBuilder } from '@grafana/grafana-foundation-sdk/logs'; import { PanelBuilder as StatsPanelBuilder } from '@grafana/grafana-foundation-sdk/stat'; -import { BigValueGraphMode } from '@grafana/grafana-foundation-sdk/common'; import { PanelBuilder as TextPanelBuilder, diff --git a/src/features/metrics.tsx b/src/features/metrics.tsx index 922331b..5616346 100644 --- a/src/features/metrics.tsx +++ b/src/features/metrics.tsx @@ -1,9 +1,9 @@ -import { PanelBuilder as TimeSeriesPanelBuilder } from '@grafana/grafana-foundation-sdk/timeseries'; +import { useState } from 'react'; + import { DataqueryBuilder as PrometheusDataqueryBuilder } from '@grafana/grafana-foundation-sdk/prometheus'; -import { VizLegendOptionsBuilder } from '@grafana/grafana-foundation-sdk/common'; import { PanelBuilder as TextPanelBuilder, TextMode } from '@grafana/grafana-foundation-sdk/text'; - -import { useState } from 'react'; +import { PanelBuilder as TimeSeriesPanelBuilder } from '@grafana/grafana-foundation-sdk/timeseries'; +import { VizLegendOptionsBuilder } from '@grafana/grafana-foundation-sdk/common'; import { usePersistentState } from '../lib/usePersistentState.ts'; diff --git a/src/features/novus.tsx b/src/features/novus.tsx index cc3cb53..020aff6 100644 --- a/src/features/novus.tsx +++ b/src/features/novus.tsx @@ -1,18 +1,18 @@ import { useState, useEffect, type ReactNode } from "react"; import { useAuth } from "react-oidc-context"; -import { useEnv } from "../components/env.tsx"; import { AutoComplete } from "primereact/autocomplete"; import { - PanelBuilder, - ConstantVariableBuilder, AdHocVariableBuilder, - VariableHide, + ConstantVariableBuilder, + DatasourceVariableBuilder, + FieldColorModeId, + MappingType, + PanelBuilder, ThresholdsConfigBuilder, ThresholdsMode, - MappingType, - FieldColorModeId, + VariableHide, } from "@grafana/grafana-foundation-sdk/dashboard"; import { DataqueryBuilder as PrometheusDataqueryBuilder } from "@grafana/grafana-foundation-sdk/prometheus"; @@ -21,6 +21,7 @@ import { PanelBuilder as TextPanelBuilder, TextMode } from "@grafana/grafana-fou import { usePersistentState } from "../lib/usePersistentState.ts"; import { queryPrometheus } from "../lib/prometheusQuerier.ts"; +import { useEnv } from "../components/env.tsx"; export const FeatureID = "novus"; export const FeatureName = "Novus Runtime Information"; @@ -92,7 +93,24 @@ function buildVariables(runtime: string) { .build(); podFilter.filters = [{ key: "pod", operator: "!~", value: "novus-.*" }]; + // We know that Novus users have data for prom and loki in Novus' datasources + // so we try to be smort and set them. + const promDatasource = new DatasourceVariableBuilder("prometheus") + .label("Metrics Data source") + .hide(VariableHide.HideVariable) + .type("prometheus") + .regex(".+Novus.+") + .multi(false); + const lokiDatasource = new DatasourceVariableBuilder("loki") + .label("Logs Data source") + .hide(VariableHide.HideVariable) + .type("loki") + .regex(".+Novus.+") + .multi(false) + return [ + promDatasource, + lokiDatasource, new ConstantVariableBuilder("namespace") .label("Novus Runtime / namespace") .value(runtime),