Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions timeserieschart/schemas/migrate/migrate.cue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,17 @@ spec: {
yAxis: max: #max
}

#logBase: [// switch
if (*#panel.fieldConfig.defaults.logBase | null) != null {
#panel.fieldConfig.defaults.logBase
},
null,
][0]
if #logBase != null {
yAxis: logBase: #logBase
yAxis: type: "log"
}

#yAxisLabel: *#panel.fieldConfig.defaults.custom.axisLabel | null
if #yAxisLabel != null if len(#yAxisLabel) > 0 {
yAxis: label: #yAxisLabel
Expand Down
38 changes: 38 additions & 0 deletions timeserieschart/schemas/migrate/tests/basic-4/expected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"kind": "TimeSeriesChart",
"spec": {
"legend": {
"mode": "list",
"position": "bottom",
"values": []
},
"visual": {
"areaOpacity": 0.1,
"connectNulls": false,
"display": "line",
"lineWidth": 1,
"lineStyle": "solid"
},
"yAxis": {
"format": {
"unit": "bytes"
},
"label": "Amount of endpoints succesfully monitored",
"min": 0,
"logBase": 2,
"type": "log"
},
"thresholds": {
"steps": [
{
"color": "#73bf69",
"value": 0
},
{
"color": "#f2cc0c",
"value": 80
}
]
}
}
}
100 changes: 100 additions & 0 deletions timeserieschart/schemas/migrate/tests/basic-4/input.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
{
"datasource": {
"type": "prometheus",
"uid": "${datasource}"
},
"description": "Current raw capacity of DataNode in bytes",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisLabel": "Amount of endpoints succesfully monitored",
"barAlignment": 0,
"barWidthFactor": 0.6,
"drawStyle": "line",
"fillOpacity": 10,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"lineStyle": {
"fill": "solid"
},
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "never",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "line"
}
},
"links": [],
"mappings": [],
"min": 0,
"logBase": 2,
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "semi-dark-yellow",
"value": 80
}
]
},
"unit": "bytes"
},
"overrides": []
},
"gridPos": {
"h": 7,
"w": 6,
"x": 0,
"y": 0
},
"id": 27,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "bottom",
"showLegend": true
},
"tooltip": {
"mode": "multi",
"sort": "desc"
}
},
"pluginVersion": "11.3.0-pre",
"targets": [
{
"datasource": {
"uid": "${datasource}"
},
"editorMode": "code",
"expr": "avg without (instance) (hadoop_hdfs_datanode_capacity{bar_stack_id=\"$bar_stack_id\", _target=~\"$datanode\"})",
"interval": "",
"legendFormat": "{{_target}}",
"range": true,
"refId": "A"
}
],
"title": "datanode_capacity",
"type": "timeseries"
}
3 changes: 2 additions & 1 deletion timeserieschart/schemas/time-series.cue
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ spec: close({
if min != _|_ && max != _|_ {
max: >=min
}
logBase?: 2 | 10
}

#querySettings: [...{
Expand All @@ -67,4 +68,4 @@ spec: close({
}]

#lineStyle: "solid" | "dashed" | "dotted"
#areaOpacity: number & >=0 & <=1 // transparency level from 0 (transparent) to 1 (opaque)
#areaOpacity: number & >=0 & <=1 // transparency level from 0 (transparent) to 1 (opaque)
11 changes: 6 additions & 5 deletions timeserieschart/sdk/go/time-series.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,12 @@ type Visual struct {
}

type YAxis struct {
Show bool `json:"show,omitempty" yaml:"show,omitempty"`
Label string `json:"label,omitempty" yaml:"label,omitempty"`
Format *common.Format `json:"format,omitempty" yaml:"format,omitempty"`
Min float64 `json:"min,omitempty" yaml:"min,omitempty"`
Max float64 `json:"max,omitempty" yaml:"max,omitempty"`
Show bool `json:"show,omitempty" yaml:"show,omitempty"`
Label string `json:"label,omitempty" yaml:"label,omitempty"`
Format *common.Format `json:"format,omitempty" yaml:"format,omitempty"`
Min float64 `json:"min,omitempty" yaml:"min,omitempty"`
Max float64 `json:"max,omitempty" yaml:"max,omitempty"`
LogBase uint `json:"logBase,omitempty" yaml:"logBase,omitempty"`
}

type PluginSpec struct {
Expand Down
8 changes: 6 additions & 2 deletions timeserieschart/src/TimeSeriesChartPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
DEFAULT_VISUAL,
THRESHOLD_PLOT_INTERVAL,
QuerySettingsOptions,
LOG_BASE,
} from './time-series-chart-model';
import {
getTimeSeries,
Expand Down Expand Up @@ -121,10 +122,13 @@
return merge({}, DEFAULT_VISUAL, props.spec.visual);
}, [props.spec.visual]);

// Use the logBase from yAxis options, defaulting to 'none' if not set
const useLogarithmicBase: LOG_BASE = yAxis?.logBase ?? 'none';

Check failure on line 127 in timeserieschart/src/TimeSeriesChartPanel.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

Delete `··`
// convert Perses dashboard format to be ECharts compatible
const echartsYAxis = useMemo(() => {
return convertPanelYAxis(yAxis);
}, [yAxis]);
return convertPanelYAxis(yAxis, useLogarithmicBase);
}, [yAxis, useLogarithmicBase]);

const [selectedLegendItems, setSelectedLegendItems] = useState<SelectedLegendItemState>('ALL');
const [legendSorting, setLegendSorting] = useState<NonNullable<LegendProps['tableProps']>['sorting']>();
Expand Down
29 changes: 27 additions & 2 deletions timeserieschart/src/YAxisOptionsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@
// limitations under the License.

import { Switch, TextField } from '@mui/material';
import { OptionsEditorControl, OptionsEditorGroup, FormatControls } from '@perses-dev/components';

import { OptionsEditorControl, OptionsEditorGroup, FormatControls, SettingsAutocomplete } from '@perses-dev/components';
import { ReactElement } from 'react';
import { DEFAULT_FORMAT, DEFAULT_Y_AXIS, TimeSeriesChartYAxisOptions, Y_AXIS_CONFIG } from './time-series-chart-model';
import { DEFAULT_FORMAT, DEFAULT_Y_AXIS, TimeSeriesChartYAxisOptions, Y_AXIS_CONFIG, LOG_BASE_LABEL, LOG_BASE, LOG_BASE_OPTIONS, LOG_BASE_CONFIG, LOG_VALID_BASES} from './time-series-chart-model';

Check failure on line 18 in timeserieschart/src/YAxisOptionsEditor.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

'LOG_BASE' is defined but never used

Check failure on line 18 in timeserieschart/src/YAxisOptionsEditor.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

'LOG_BASE_LABEL' is defined but never used

Check failure on line 18 in timeserieschart/src/YAxisOptionsEditor.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

Replace `·DEFAULT_FORMAT,·DEFAULT_Y_AXIS,·TimeSeriesChartYAxisOptions,·Y_AXIS_CONFIG,·LOG_BASE_LABEL,·LOG_BASE,·LOG_BASE_OPTIONS,·LOG_BASE_CONFIG,·LOG_VALID_BASES` with `⏎··DEFAULT_FORMAT,⏎··DEFAULT_Y_AXIS,⏎··TimeSeriesChartYAxisOptions,⏎··Y_AXIS_CONFIG,⏎··LOG_BASE_LABEL,⏎··LOG_BASE,⏎··LOG_BASE_OPTIONS,⏎··LOG_BASE_CONFIG,⏎··LOG_VALID_BASES,⏎`

export interface YAxisOptionsEditorProps {
value: TimeSeriesChartYAxisOptions;
onChange: (yAxis: TimeSeriesChartYAxisOptions) => void;
}

export function YAxisOptionsEditor({ value, onChange }: YAxisOptionsEditorProps): ReactElement {

Check failure on line 26 in timeserieschart/src/YAxisOptionsEditor.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

Delete `⏎··`
const logBase = LOG_BASE_CONFIG[LOG_VALID_BASES[value.logBase ?? 'none']];

Check failure on line 28 in timeserieschart/src/YAxisOptionsEditor.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

Delete `··`
return (
<OptionsEditorGroup title="Y Axis">
<OptionsEditorControl
Expand All @@ -47,6 +51,27 @@
})
}
/>
<OptionsEditorControl
label={Y_AXIS_CONFIG.logBase.label}
control={
<SettingsAutocomplete
value={{
...logBase,
id: logBase.label,
}}
options={LOG_BASE_OPTIONS}
onChange={(__, newValue) => {
const updatedValue: TimeSeriesChartYAxisOptions = {
...value,
logBase: newValue.log

Check failure on line 66 in timeserieschart/src/YAxisOptionsEditor.tsx

View workflow job for this annotation

GitHub Actions / lint-npm

Insert `,`
};
onChange(updatedValue);
}}
disabled={value === undefined}
disableClearable
></SettingsAutocomplete>
}
/>
<OptionsEditorControl
label={Y_AXIS_CONFIG.label.label}
control={
Expand Down
25 changes: 25 additions & 0 deletions timeserieschart/src/time-series-chart-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
format?: FormatOptions;
min?: number;
max?: number;
logBase?: LOG_BASE;
}

export interface TooltipSpecOptions {
Expand Down Expand Up @@ -87,6 +88,7 @@
format: DEFAULT_FORMAT,
min: undefined,
max: undefined,
logBase: 'none',
};

export const Y_AXIS_CONFIG = {
Expand All @@ -95,6 +97,7 @@
unit: { label: 'Unit' },
min: { label: 'Min' },
max: { label: 'Max' },
logBase: { label: 'Log Base' },
};

export const DEFAULT_DISPLAY = 'line';
Expand Down Expand Up @@ -183,6 +186,28 @@
step: 0.05,
};

// LogBase outlines the allowed log bases for the log-supported charts.
export type LOG_BASE_LABEL = 'none' | 'log2' | 'log10';
export type LOG_BASE = 'none' | 2 | 10;

// Single source of truth for log base configuration
export const LOG_BASE_CONFIG: Record<LOG_BASE_LABEL, { label: string; log: LOG_BASE }> = {
'none': { label: 'None', log: 'none' },

Check failure on line 195 in timeserieschart/src/time-series-chart-model.ts

View workflow job for this annotation

GitHub Actions / lint-npm

Replace `'none'` with `none`
'log2': { label: '2', log: 2 },

Check failure on line 196 in timeserieschart/src/time-series-chart-model.ts

View workflow job for this annotation

GitHub Actions / lint-npm

Replace `'log2'` with `log2`
'log10': { label: '10', log: 10 },

Check failure on line 197 in timeserieschart/src/time-series-chart-model.ts

View workflow job for this annotation

GitHub Actions / lint-npm

Replace `'log10'` with `log10`
};

// Options array for SettingsAutocomplete
export const LOG_BASE_OPTIONS = Object.entries(LOG_BASE_CONFIG).map(([id, config]) => ({
id: id as LOG_BASE_LABEL,
...config,
}));

// Reverse lookup map from LOG_BASE value to LOG_BASE_LABEL
export const LOG_VALID_BASES: Record<LOG_BASE, LOG_BASE_LABEL> = Object.fromEntries(
Object.entries(LOG_BASE_CONFIG).map(([label, config]) => [config.log, label])
) as Record<LOG_BASE, LOG_BASE_LABEL>;

// Both of these constants help produce a value that is LESS THAN the initial value.
// For positive values, we multiply by a number less than 1 to get this outcome.
// For negative values, we multiply to a number greater than 1 to get this outcome.
Expand Down
2 changes: 1 addition & 1 deletion timeserieschart/src/utils/data-transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ describe('convertPanelYAxis', () => {
min: 0.1,
max: 1,
};
const echartsAxis = convertPanelYAxis(persesAxis);
const echartsAxis = convertPanelYAxis(persesAxis, 'none');
// Axis label is handled outside of echarts since it is built with a custom React component.
expect(echartsAxis).toEqual({
show: true,
Expand Down
Loading