Skip to content

Commit

Permalink
value_plot
Browse files Browse the repository at this point in the history
  • Loading branch information
epompeii committed Sep 25, 2023
1 parent 9dd63a2 commit ea2ce2b
Show file tree
Hide file tree
Showing 9 changed files with 355 additions and 95 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ sortOrder: 4

## Pending `v0.3.12`
- Change Metric `lower_bound` and `upper_bound` to `lower_value` and `upper_value` respectively
- Add ability to visualize `lower_value` and `upper_value` in Perf Plot

## `v0.3.11`
- Add strongly typed IDs for database entities
Expand Down
6 changes: 6 additions & 0 deletions services/console/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions services/console/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"bulma-divider": "^0.2.0",
"bulma-pricingtable": "^0.2.0",
"bulma-switch": "^2.0.4",
"bulma-tooltip": "^3.0.2",
"d3": "^7.8.5",
"htl": "^0.3.1",
"solid-js": "^1.7.11",
Expand Down
33 changes: 32 additions & 1 deletion services/console/src/components/console/perf/PerfPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
createResource,
createSignal,
} from "solid-js";
import PerfHeader, { PerfQuery } from "./PerfHeader";
import PerfHeader, { type PerfQuery } from "./PerfHeader";
import PerfPlot from "./plot/PerfPlot";
import { createStore } from "solid-js/store";
import {
Expand Down Expand Up @@ -50,13 +50,16 @@ const TAB_PARAM = "tab";
const KEY_PARAM = "key";
const RANGE_PARAM = "range";
const CLEAR_PARAM = "clear";
const LOWER_VALUE_PARAM = "lower_value";
const UPPER_VALUE_PARAM = "upper_value";
const LOWER_BOUNDARY_PARAM = "lower_boundary";
const UPPER_BOUNDARY_PARAM = "upper_boundary";

const DEFAULT_PERF_TAB = PerfTab.REPORTS;
const DEFAULT_PERF_KEY = true;
const DEFAULT_PERF_RANGE = PerfRange.DATE_TIME;
const DEFAULT_PERF_CLEAR = false;
const DEFAULT_PERF_END_VALUE = false;
const DEFAULT_PERF_BOUNDARY = false;

const DEFAULT_PER_PAGE = 8;
Expand Down Expand Up @@ -188,6 +191,12 @@ const PerfPanel = (props: Props) => {
if (!isBoolParam(searchParams[CLEAR_PARAM])) {
initParams[CLEAR_PARAM] = null;
}
if (!isBoolParam(searchParams[LOWER_VALUE_PARAM])) {
initParams[LOWER_VALUE_PARAM] = null;
}
if (!isBoolParam(searchParams[UPPER_VALUE_PARAM])) {
initParams[UPPER_VALUE_PARAM] = null;
}
if (!isBoolParam(searchParams[LOWER_BOUNDARY_PARAM])) {
initParams[LOWER_BOUNDARY_PARAM] = null;
}
Expand Down Expand Up @@ -286,6 +295,13 @@ const PerfPanel = (props: Props) => {
isBoolParamOrDefault(CLEAR_PARAM, DEFAULT_PERF_CLEAR),
);

const lower_value = createMemo(() =>
isBoolParamOrDefault(LOWER_VALUE_PARAM, DEFAULT_PERF_END_VALUE),
);
const upper_value = createMemo(() =>
isBoolParamOrDefault(UPPER_VALUE_PARAM, DEFAULT_PERF_END_VALUE),
);

const lower_boundary = createMemo(() =>
isBoolParamOrDefault(LOWER_BOUNDARY_PARAM, DEFAULT_PERF_BOUNDARY),
);
Expand Down Expand Up @@ -593,6 +609,8 @@ const PerfPanel = (props: Props) => {
?.benchmarks?.map((benchmark) => benchmark.uuid);
setSearchParams({
[CLEAR_PARAM]: true,
[LOWER_VALUE_PARAM]: null,
[UPPER_VALUE_PARAM]: null,
[LOWER_BOUNDARY_PARAM]: null,
[UPPER_BOUNDARY_PARAM]: null,
[REPORT_PARAM]: report?.uuid,
Expand Down Expand Up @@ -670,6 +688,8 @@ const PerfPanel = (props: Props) => {
if (clear) {
setSearchParams({
[CLEAR_PARAM]: true,
[LOWER_VALUE_PARAM]: null,
[UPPER_VALUE_PARAM]: null,
[LOWER_BOUNDARY_PARAM]: null,
[UPPER_BOUNDARY_PARAM]: null,
[REPORT_PARAM]: null,
Expand All @@ -686,6 +706,13 @@ const PerfPanel = (props: Props) => {
}
};

const handleLowerValue = (end: boolean) => {
handleBool(LOWER_VALUE_PARAM, end);
};
const handleUpperValue = (end: boolean) => {
handleBool(UPPER_VALUE_PARAM, end);
};

const handleLowerBoundary = (boundary: boolean) => {
handleBool(LOWER_BOUNDARY_PARAM, boundary);
};
Expand Down Expand Up @@ -731,6 +758,8 @@ const PerfPanel = (props: Props) => {
key={key}
range={range}
clear={clear}
lower_value={lower_value}
upper_value={upper_value}
lower_boundary={lower_boundary}
upper_boundary={upper_boundary}
reports_tab={reports_tab}
Expand All @@ -752,6 +781,8 @@ const PerfPanel = (props: Props) => {
handleKey={handleKey}
handleRange={handleRange}
handleClear={handleClear}
handleLowerValue={handleLowerValue}
handleUpperValue={handleUpperValue}
handleLowerBoundary={handleLowerBoundary}
handleUpperBoundary={handleUpperBoundary}
handleReportChecked={handleReportChecked}
Expand Down
106 changes: 96 additions & 10 deletions services/console/src/components/console/perf/plot/LinePlot.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Plot from "@observablehq/plot";
import * as d3 from "d3";
import { Accessor, createEffect, createSignal } from "solid-js";
import { type Accessor, createEffect, createSignal } from "solid-js";
import { addTooltips } from "./tooltip";
import {
JsonAlertStatus,
Expand All @@ -13,6 +13,8 @@ import { PerfRange } from "../../../../config/types";
export interface Props {
perfData: Accessor<JsonPerf>;
range: Accessor<PerfRange>;
lower_value: Accessor<boolean>;
upper_value: Accessor<boolean>;
lower_boundary: Accessor<boolean>;
upper_boundary: Accessor<boolean>;
perfActive: boolean[];
Expand All @@ -24,7 +26,16 @@ enum Position {
Upper,
}

const position_key = (position: Position) => {
const value_end_position_key = (position: Position) => {
switch (position) {
case Position.Lower:
return "lower_value";
case Position.Upper:
return "upper_value";
}
};

const boundary_position_key = (position: Position) => {
switch (position) {
case Position.Lower:
return "lower_limit";
Expand Down Expand Up @@ -116,10 +127,13 @@ const LinePlot = (props: Props) => {
}

const line_data = [];
const alert_data = [];
perf_metrics.forEach((perf_metric) => {
line_data.push({
const datum = {
report: perf_metric.report,
value: perf_metric.metric?.value,
lower_value: perf_metric.metric?.lower_value,
upper_value: perf_metric.metric?.upper_value,
date_time: new Date(perf_metric.start_time),
number: perf_metric.version?.number,
hash: perf_metric.version?.hash,
Expand All @@ -140,7 +154,11 @@ const LinePlot = (props: Props) => {
? perf_metric.metric?.value * 1.1
: null,
alert: perf_metric.alert,
});
};
line_data.push(datum);
if (perf_metric.alert && is_active(perf_metric.alert)) {
alert_data.push(datum);
}
metrics_found = true;
});

Expand All @@ -164,6 +182,32 @@ const LinePlot = (props: Props) => {
}),
);

// Lower Value
if (props.lower_value()) {
plot_arrays.push(
Plot.line(line_data, value_end_line(x_axis, Position.Lower, color)),
);
plot_arrays.push(
Plot.dot(
line_data,
value_end_dot(x_axis, Position.Lower, color, project_slug),
),
);
}

// Upper Value
if (props.upper_value()) {
plot_arrays.push(
Plot.line(line_data, value_end_line(x_axis, Position.Upper, color)),
);
plot_arrays.push(
Plot.dot(
line_data,
value_end_dot(x_axis, Position.Upper, color, project_slug),
),
);
}

// Lower Boundary
if (props.lower_boundary()) {
plot_arrays.push(
Expand All @@ -181,7 +225,7 @@ const LinePlot = (props: Props) => {
}
alert_arrays.push(
Plot.image(
line_data,
alert_data,
alert_image(x_axis, Position.Lower, project_slug),
),
);
Expand All @@ -203,7 +247,7 @@ const LinePlot = (props: Props) => {
}
alert_arrays.push(
Plot.image(
line_data,
alert_data,
alert_image(x_axis, Position.Upper, project_slug),
),
);
Expand Down Expand Up @@ -283,10 +327,41 @@ const to_title = (prefix, datum, suffix) =>
datum.hash ? `\nVersion Hash: ${datum.hash}` : ""
}\nIteration: ${datum.iteration}${suffix}`;

const value_end_line = (x_axis, position: Position, color) => {
return {
x: x_axis,
y: value_end_position_key(position),
stroke: color,
strokeWidth: 2,
strokeOpacity: 0.9,
strokeDasharray: [3],
};
};

const value_end_dot = (x_axis, position: Position, color, project_slug) => {
return {
x: x_axis,
y: value_end_position_key(position),
stroke: color,
strokeWidth: 2,
strokeOpacity: 0.9,
fill: color,
fillOpacity: 0.9,
title: (datum) => value_end_title(position, datum, ""),
// TODO enable this when there is an endpoint for getting a historical threshold statistic
// That is, the statistic displayed needs to be historical, not current.
// Just like with the Alerts.
// href: (datum) =>
// !is_active(datum.alert) &&
// `/console/projects/${project_slug}/thresholds/${datum.threshold}`,
// target: "_blank",
};
};

const boundary_line = (x_axis, position: Position, color) => {
return {
x: x_axis,
y: position_key(position),
y: boundary_position_key(position),
stroke: color,
strokeWidth: 4,
strokeOpacity: 0.666,
Expand All @@ -297,7 +372,7 @@ const boundary_line = (x_axis, position: Position, color) => {
const boundary_dot = (x_axis, position: Position, color, project_slug) => {
return {
x: x_axis,
y: position_key(position),
y: boundary_position_key(position),
stroke: color,
strokeWidth: 4,
strokeOpacity: 0.666,
Expand Down Expand Up @@ -345,7 +420,7 @@ const is_skipped = (position: Position, datum) =>
const alert_image = (x_axis, position: Position, project_slug) => {
return {
x: x_axis,
y: position_key(position),
y: boundary_position_key(position),
src: (datum) => (is_active(datum.alert) ? SIREN_URL : null),
width: 18,
title: (datum) =>
Expand All @@ -358,12 +433,23 @@ const alert_image = (x_axis, position: Position, project_slug) => {
};
};

const value_end_title = (position: Position, datum, suffix) =>
to_title(
`${position_label(position)} Value: ${
datum[value_end_position_key(position)]
}`,
datum,
suffix,
);

const is_active = (alert: JsonPerfAlert) =>
alert?.status && alert.status == JsonAlertStatus.Active;

const limit_title = (position: Position, datum, suffix) =>
to_title(
`${position_label(position)} Limit: ${datum[position_key(position)]}`,
`${position_label(position)} Limit: ${
datum[boundary_position_key(position)]
}`,
datum,
suffix,
);
Expand Down
10 changes: 10 additions & 0 deletions services/console/src/components/console/perf/plot/PerfPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export interface Props {
key: Accessor<boolean>;
range: Accessor<PerfRange>;
clear: Accessor<boolean>;
lower_value: Accessor<boolean>;
upper_value: Accessor<boolean>;
lower_boundary: Accessor<boolean>;
upper_boundary: Accessor<boolean>;
reports_tab: TabList<JsonReport>;
Expand All @@ -53,6 +55,8 @@ export interface Props {
handleKey: (key: boolean) => void;
handleRange: (range: PerfRange) => void;
handleClear: (clear: boolean) => void;
handleLowerValue: (lower_value: boolean) => void;
handleUpperValue: (upper_value: boolean) => void;
handleLowerBoundary: (lower_boundary: boolean) => void;
handleUpperBoundary: (upper_boundary: boolean) => void;
handleReportChecked: (
Expand Down Expand Up @@ -85,13 +89,17 @@ const PerfPlot = (props: Props) => {
refresh={props.refresh}
range={props.range}
clear={props.clear}
lower_value={props.lower_value}
upper_value={props.upper_value}
lower_boundary={props.lower_boundary}
upper_boundary={props.upper_boundary}
handleMetricKind={props.handleMetricKind}
handleStartTime={props.handleStartTime}
handleEndTime={props.handleEndTime}
handleRange={props.handleRange}
handleClear={props.handleClear}
handleLowerValue={props.handleLowerValue}
handleUpperValue={props.handleUpperValue}
handleLowerBoundary={props.handleLowerBoundary}
handleUpperBoundary={props.handleUpperBoundary}
/>
Expand All @@ -101,6 +109,8 @@ const PerfPlot = (props: Props) => {
fallback={
<Plot
range={props.range}
lower_value={props.lower_value}
upper_value={props.upper_value}
lower_boundary={props.lower_boundary}
upper_boundary={props.upper_boundary}
perfData={props.perfData}
Expand Down
Loading

0 comments on commit ea2ce2b

Please sign in to comment.