diff --git a/devenv/dev-dashboards/panel-table/table_tests_new.json b/devenv/dev-dashboards/panel-table/table_tests_new.json index d3dfb294fb1..ba7632bc5f5 100644 --- a/devenv/dev-dashboards/panel-table/table_tests_new.json +++ b/devenv/dev-dashboards/panel-table/table_tests_new.json @@ -393,6 +393,10 @@ "value": { "mode": "continuous-GrYlRd" } + }, + { + "id": "unit", + "value": "r/sec" } ] }, @@ -538,6 +542,10 @@ "fixedColor": "red", "mode": "fixed" } + }, + { + "id": "unit", + "value": "r/sec" } ] }, @@ -563,6 +571,10 @@ "fixedColor": "purple", "mode": "fixed" } + }, + { + "id": "unit", + "value": "ms" } ] }, diff --git a/docs/sources/developers/kinds/composable/table/panelcfg/schema-reference.md b/docs/sources/developers/kinds/composable/table/panelcfg/schema-reference.md index 6ec9c79f28b..0fbc39fba01 100644 --- a/docs/sources/developers/kinds/composable/table/panelcfg/schema-reference.md +++ b/docs/sources/developers/kinds/composable/table/panelcfg/schema-reference.md @@ -170,6 +170,7 @@ It extends [GraphFieldConfig](#graphfieldconfig). | `fillOpacity` | number | No | | *(Inherited from [GraphFieldConfig](#graphfieldconfig))* | | `gradientMode` | string | No | | *(Inherited from [GraphFieldConfig](#graphfieldconfig))*
TODO docs
Possible values are: `none`, `opacity`, `hue`, `scheme`. | | `hideFrom` | [HideSeriesConfig](#hideseriesconfig) | No | | *(Inherited from [GraphFieldConfig](#graphfieldconfig))*
TODO docs | +| `hideValue` | boolean | No | | | | `lineColor` | string | No | | *(Inherited from [GraphFieldConfig](#graphfieldconfig))* | | `lineInterpolation` | string | No | | *(Inherited from [GraphFieldConfig](#graphfieldconfig))*
TODO docs
Possible values are: `linear`, `smooth`, `stepBefore`, `stepAfter`. | | `lineStyle` | [LineStyle](#linestyle) | No | | *(Inherited from [GraphFieldConfig](#graphfieldconfig))*
TODO docs | diff --git a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md index c7ac4e7dc09..f55c69dbd46 100644 --- a/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md +++ b/docs/sources/panels-visualizations/query-transform-data/transform-data/index.md @@ -995,11 +995,10 @@ Here is the result after adding a Limit transformation with a value of '3': ### Time series to table transform -> **Note:** This transformation is available in Grafana 9.5+ as an opt-in beta feature. -> Modify Grafana [configuration file][] to enable the `timeSeriesTable` [feature toggle][] to use it. - Use this transformation to convert time series result into a table, converting time series data frame into a "Trend" field. "Trend" field can then be rendered using [sparkline cell type][], producing an inline sparkline for each table row. If there are multiple time series queries, each will result in a separate table data frame. These can be joined using join or merge transforms to produce a single table with multiple sparklines per row. +For each generated "Trend" field value calculation function can be selected. Default is "last non null value". This value will be displayed next to the sparkline and used for sorting table rows. + ### Format Time {{% admonition type="note" %}} diff --git a/docs/sources/panels-visualizations/visualizations/table/index.md b/docs/sources/panels-visualizations/visualizations/table/index.md index 2f63da7e825..8459bf2b13f 100644 --- a/docs/sources/panels-visualizations/visualizations/table/index.md +++ b/docs/sources/panels-visualizations/visualizations/table/index.md @@ -148,12 +148,9 @@ If you have a field value that is an image URL or a base64 encoded image you can ### Sparkline -> **Note:** This cell type is available in Grafana 9.5+ as an opt-in beta feature. -> Modify Grafana [configuration file][] to enable the `timeSeriesTable` [feature toggle][] to use it. - Shows value rendered as a sparkline. Requires [time series to table][] data transform. -{{< figure src="/static/img/docs/tables/sparkline.png" max-width="500px" caption="Sparkline" class="docs-image--no-shadow" >}} +{{< figure src="/static/img/docs/tables/sparkline2.png" max-width="500px" caption="Sparkline" class="docs-image--no-shadow" >}} ## Cell value inspect diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 8e54ac4c557..808935d95e3 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -104,7 +104,6 @@ Experimental features might be changed or removed without prior notice. | `lokiQuerySplitting` | Split large interval queries into subqueries with smaller time intervals | | `lokiQuerySplittingConfig` | Give users the option to configure split durations for Loki queries | | `individualCookiePreferences` | Support overriding cookie preferences per user | -| `timeSeriesTable` | Enable time series table transformer & sparkline cell type | | `clientTokenRotation` | Replaces the current in-request token rotation so that the client initiates the rotation | | `lokiLogsDataplane` | Changes logs responses from Loki to be compliant with the dataplane specification. | | `disableSSEDataplane` | Disables dataplane specific processing in server side expressions. | diff --git a/packages/grafana-data/src/dataframe/processDataFrame.ts b/packages/grafana-data/src/dataframe/processDataFrame.ts index 402f4962508..a0e95a773b6 100644 --- a/packages/grafana-data/src/dataframe/processDataFrame.ts +++ b/packages/grafana-data/src/dataframe/processDataFrame.ts @@ -23,6 +23,7 @@ import { PanelData, LoadingState, GraphSeriesValue, + DataFrameWithValue, } from '../types/index'; import { arrayToDataFrame } from './ArrayDataFrame'; @@ -303,6 +304,9 @@ export const isTableData = (data: unknown): data is DataFrame => Boolean(data && export const isDataFrame = (data: unknown): data is DataFrame => Boolean(data && data.hasOwnProperty('fields')); +export const isDataFrameWithValue = (data: unknown): data is DataFrameWithValue => + Boolean(isDataFrame(data) && data.hasOwnProperty('value')); + /** * Inspect any object and return the results as a DataFrame */ diff --git a/packages/grafana-data/src/transformations/fieldReducer.ts b/packages/grafana-data/src/transformations/fieldReducer.ts index 8bd30767015..8e2eea0f791 100644 --- a/packages/grafana-data/src/transformations/fieldReducer.ts +++ b/packages/grafana-data/src/transformations/fieldReducer.ts @@ -30,6 +30,10 @@ export enum ReducerID { uniqueValues = 'uniqueValues', } +export function isReducerID(id: string): id is ReducerID { + return Object.keys(ReducerID).includes(id); +} + // Internal function type FieldReducer = (field: Field, ignoreNulls: boolean, nullAsZero: boolean) => FieldCalcs; diff --git a/packages/grafana-data/src/types/dataFrame.ts b/packages/grafana-data/src/types/dataFrame.ts index 0154d8014c9..c4712e91ac4 100644 --- a/packages/grafana-data/src/types/dataFrame.ts +++ b/packages/grafana-data/src/types/dataFrame.ts @@ -247,6 +247,11 @@ export interface DataFrame extends QueryResultBase { length: number; } +// Data frame that include aggregate value, for use by timeSeriesTableTransformer / chart cell type +export interface DataFrameWithValue extends DataFrame { + value: number | null; +} + /** * @public * Like a field, but properties are optional and values may be a simple array diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 912bae6fb32..89d6b15eb2d 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -65,7 +65,6 @@ export interface FeatureToggles { individualCookiePreferences?: boolean; gcomOnlyExternalOrgRoleSync?: boolean; prometheusMetricEncyclopedia?: boolean; - timeSeriesTable?: boolean; influxdbBackendMigration?: boolean; clientTokenRotation?: boolean; prometheusDataplane?: boolean; diff --git a/packages/grafana-schema/src/common/common.gen.ts b/packages/grafana-schema/src/common/common.gen.ts index 1c034f48a77..76676b232cc 100644 --- a/packages/grafana-schema/src/common/common.gen.ts +++ b/packages/grafana-schema/src/common/common.gen.ts @@ -756,6 +756,7 @@ export interface TableBarGaugeCellOptions { * Sparkline cell options */ export interface TableSparklineCellOptions extends GraphFieldConfig { + hideValue?: boolean; type: TableCellDisplayMode.Sparkline; } diff --git a/packages/grafana-schema/src/common/table.cue b/packages/grafana-schema/src/common/table.cue index 8f703604a73..27026f6d79b 100644 --- a/packages/grafana-schema/src/common/table.cue +++ b/packages/grafana-schema/src/common/table.cue @@ -59,6 +59,7 @@ TableBarGaugeCellOptions: { TableSparklineCellOptions: { GraphFieldConfig type: TableCellDisplayMode & "sparkline" + hideValue?: bool } @cuetsy(kind="interface") // Colored background cell options diff --git a/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx b/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx index 47797c619f6..895f849104f 100644 --- a/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx +++ b/packages/grafana-ui/src/components/StatsPicker/StatsPicker.tsx @@ -1,7 +1,7 @@ import { difference } from 'lodash'; import React, { PureComponent } from 'react'; -import { fieldReducers, SelectableValue } from '@grafana/data'; +import { fieldReducers, SelectableValue, FieldReducerInfo } from '@grafana/data'; import { Select } from '../Select/Select'; @@ -15,6 +15,7 @@ export interface Props { width?: number; menuPlacement?: 'auto' | 'bottom' | 'top'; inputId?: string; + filterOptions?: (ext: FieldReducerInfo) => boolean; } export class StatsPicker extends PureComponent { @@ -63,9 +64,10 @@ export class StatsPicker extends PureComponent { }; render() { - const { stats, allowMultiple, defaultStat, placeholder, className, menuPlacement, width, inputId } = this.props; + const { stats, allowMultiple, defaultStat, placeholder, className, menuPlacement, width, inputId, filterOptions } = + this.props; - const select = fieldReducers.selectOptions(stats); + const select = fieldReducers.selectOptions(stats, filterOptions); return (