From 1915efbc951c5112177d08331a389d40de3b07c9 Mon Sep 17 00:00:00 2001 From: Sam Jewell <2903904+samjewell@users.noreply.github.com> Date: Mon, 18 Nov 2024 12:05:08 +0000 Subject: [PATCH 01/14] SQL Expressions: Simplify where code is being stubbed out (#96227) * Rename from DuckDB * Remove unused function --- pkg/expr/sql/db.go | 4 ---- pkg/expr/sql/parser.go | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/pkg/expr/sql/db.go b/pkg/expr/sql/db.go index 1e7aca0c1b6..90e23342c4b 100644 --- a/pkg/expr/sql/db.go +++ b/pkg/expr/sql/db.go @@ -9,10 +9,6 @@ import ( type DB struct { } -func (db *DB) TablesList(rawSQL string) ([]string, error) { - return nil, errors.New("not implemented") -} - func (db *DB) RunCommands(commands []string) (string, error) { return "", errors.New("not implemented") } diff --git a/pkg/expr/sql/parser.go b/pkg/expr/sql/parser.go index a5ca1fb6f5b..b5456b3b6ff 100644 --- a/pkg/expr/sql/parser.go +++ b/pkg/expr/sql/parser.go @@ -20,10 +20,10 @@ var logger = log.New("sql_expr") // TablesList returns a list of tables for the sql statement func TablesList(rawSQL string) ([]string, error) { - duckDB := NewInMemoryDB() + db := NewInMemoryDB() rawSQL = strings.Replace(rawSQL, "'", "''", -1) cmd := fmt.Sprintf("SELECT json_serialize_sql('%s')", rawSQL) - ret, err := duckDB.RunCommands([]string{cmd}) + ret, err := db.RunCommands([]string{cmd}) if err != nil { logger.Error("error serializing sql", "error", err.Error(), "sql", rawSQL, "cmd", cmd) return nil, fmt.Errorf("error serializing sql: %s", err.Error()) From 2ff9baa271053c018f34d6e9f1c34beeb9b0549f Mon Sep 17 00:00:00 2001 From: Sven Grossmann Date: Mon, 18 Nov 2024 13:07:59 +0100 Subject: [PATCH 02/14] Sidecar: Always hide at `/login` page (#96621) --- .../services/SidecarContext_EXPERIMENTAL.ts | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/grafana-runtime/src/services/SidecarContext_EXPERIMENTAL.ts b/packages/grafana-runtime/src/services/SidecarContext_EXPERIMENTAL.ts index dd689499573..9f8d6e42d9e 100644 --- a/packages/grafana-runtime/src/services/SidecarContext_EXPERIMENTAL.ts +++ b/packages/grafana-runtime/src/services/SidecarContext_EXPERIMENTAL.ts @@ -1,12 +1,15 @@ import { createContext, useContext } from 'react'; import { useObservable } from 'react-use'; +import { locationService as mainLocationService } from './LocationService'; import { SidecarService_EXPERIMENTAL, sidecarServiceSingleton_EXPERIMENTAL } from './SidecarService_EXPERIMENTAL'; export const SidecarContext_EXPERIMENTAL = createContext( sidecarServiceSingleton_EXPERIMENTAL ); +const HIDDEN_ROUTES = ['/login']; + /** * This is the main way to interact with the sidecar service inside a react context. It provides a wrapper around the * service props so that even though they are observables we just pass actual values to the components. @@ -24,17 +27,33 @@ export function useSidecar_EXPERIMENTAL() { const initialContext = useObservable(service.initialContextObservable, service.initialContext); const activePluginId = useObservable(service.activePluginIdObservable, service.activePluginId); const locationService = service.getLocationService(); + const forceHidden = HIDDEN_ROUTES.includes(mainLocationService.getLocation().pathname); return { - activePluginId, - initialContext, + activePluginId: forceHidden ? undefined : activePluginId, + initialContext: forceHidden ? undefined : initialContext, locationService, // TODO: currently this allows anybody to open any app, in the future we should probably scope this to the // current app but that means we will need to incorporate this better into the plugin platform APIs which // we will do once the functionality is reasonably stable - openApp: (pluginId: string, context?: unknown) => service.openApp(pluginId, context), - openAppV2: (pluginId: string, path?: string) => service.openAppV2(pluginId, path), + openApp: (pluginId: string, context?: unknown) => { + if (forceHidden) { + return; + } + return service.openApp(pluginId, context); + }, + openAppV2: (pluginId: string, path?: string) => { + if (forceHidden) { + return; + } + return service.openAppV2(pluginId, path); + }, closeApp: () => service.closeApp(), - isAppOpened: (pluginId: string) => service.isAppOpened(pluginId), + isAppOpened: (pluginId: string) => { + if (forceHidden) { + return false; + } + return service.isAppOpened(pluginId); + }, }; } From 78930314c3775f711de8a58a03c082cee01c2dee Mon Sep 17 00:00:00 2001 From: Andreas Christou Date: Mon, 18 Nov 2024 12:27:40 +0000 Subject: [PATCH 03/14] CloudMonitoring: Improve metric handling for `DISTRIBUTION` value types (#96412) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Set crossSeriesReducer value based on metric valueType * Update label retrieval to retrieve all values * Update tests * Update documentation * Add tooltip * fix typo * Docs lint --------- Co-authored-by: Irene Rodríguez --- .../query-editor/index.md | 13 +++- .../components/Aggregation.tsx | 8 ++- .../VisualMetricQueryEditor.test.tsx | 59 ++++++++++++++++++- .../components/VisualMetricQueryEditor.tsx | 5 ++ .../datasource/cloud-monitoring/datasource.ts | 3 +- 5 files changed, 81 insertions(+), 7 deletions(-) diff --git a/docs/sources/datasources/google-cloud-monitoring/query-editor/index.md b/docs/sources/datasources/google-cloud-monitoring/query-editor/index.md index 937ff627a37..87e1ee9d85b 100644 --- a/docs/sources/datasources/google-cloud-monitoring/query-editor/index.md +++ b/docs/sources/datasources/google-cloud-monitoring/query-editor/index.md @@ -66,8 +66,17 @@ The metrics query editor helps you select metrics, group and aggregate by labels 1. _(Optional)_ Use the plus and minus icons in the filter and group-by sections to add and remove filters or group-by clauses. Google Cloud Monitoring supports several metrics types, such as `GAUGE`, `DELTA,` and `CUMULATIVE`. -Each supports different aggregation options, such as reducers and aligners. -The metrics query editor lists available aggregation methods for a selected metric, and sets a default reducer and aligner when you select a metric. +Each supports different aggregation options, such as reducers and aligners. Additionally, metrics have specific value types that can be either scalar or a distribution. + +The metrics query editor lists available aggregation methods for a selected metric, and sets a default aggregation, reducer and aligner when you select a metric. + +In the case that the metric value type is a distribution, the aggregation will be set by default to the mean. For scalar value types, there is no aggregation by default. + +The various metrics are documented [here](https://cloud.google.com/monitoring/api/metrics_gcp) and further details on the kinds and types of metrics can be found [here](https://cloud.google.com/monitoring/api/v3/kinds-and-types). + +{{% admonition type="note" %}} +Distribution metrics are typically best visualized as either a heatmap or histogram. When visualizing in this way, aggregation is not necessary. However, for other visualization types, performance degradation may be observed when attempting to query distribution metrics that are not aggregated due to the number of potential buckets that can be returned. For more information on how to visualize distribution metrics refer to [this page](https://cloud.google.com/monitoring/charts/charting-distribution-metrics). +{{% /admonition %}} ### Apply a filter diff --git a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx index 94e9afd71e4..8d9c874bb38 100644 --- a/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx +++ b/public/app/plugins/datasource/cloud-monitoring/components/Aggregation.tsx @@ -22,7 +22,13 @@ export const Aggregation = (props: Props) => { const selected = useSelectedFromOptions(aggOptions, props); return ( - +