Skip to content

Commit

Permalink
Charts Without Grafana (#2049)
Browse files Browse the repository at this point in the history
* Wip on TimeSeriesLineChart component

* Time Series line chart without border on dot

* Add support for multiple time series with different colors in
TimeSeries chart

* Tooltip text alignment in TimeSeriesLineChart

* Npm run format and lint

* TimeSeriesLineChart test

* TimeSeriesLineChart stories with live updates example

* Fix TimeSeriesLineChart zoom fetching

* Add prometheus and node exporter as optional docker compose profile

* Add ChartTimeSeries data structure to charts context

* Add HostCpuChart data structure to charts context

* Add HostDataFetcher Behaviour to charts context

* Wip implementation of host charts using prometheus

* Add example agentID labels to prometheus dev conf

* Chart time series structure with utc datetime as timestamp

* Add agentID to host chart query

* Prometheus in docker compose start with predefined seed

* Wip on chart context entrypoint

* Add busy irqs to host chart cpu

* Prometheus api, implementing host data fetcher

* Add tests for prometheus chart integration

* prometheus api chart testing

* Removed dedicated profile to prometheus and and node-exporter

* Refactored usage of deftype in charts context

* Charts context entrypoint performs charts queries

* Prometheus api handles no result case

* Add tests for Charts module

* Prometheus data fetching of hosts memory data

* Add host memory chart to Charts context

* Mix credo fix

* Charts context check if host exists before querying for charts

* Chart controller with host cpu chart action

* Host memory chart action in ChartController

* Change agentID label in prometheus config with a fixture agent

* Move TimeSeriesChart component in common module

* fix relabel config in prometheus dev config

* Changed default step parameter for query range to 60 seconds

* Charts modules now uses Datetime module for intervals

* Chart controller with ISO8601 timestamps

* TimeSeriesLineChart supports 6 series

* TimeSeriesLineChart component supports plain date object

* Wip on host chart component

* Removed grafanaPublicURL reference from assets

* remove grafana from docker compose

* Remove grafana from elixir code

* Removed grafana dashboard from priv

* Remove grafana from docs and readme

* Leftovers grafana removal from elixir code

* Custom scale and legend in TimeSeriesLineChart

* Fix TimeSeriesLineChart stories

* Chart controller fix mispell

* fix chart

* Npm run lint

* npm format

* Skip prometheus integration test, ci not ready

* mix credo

* mix format

* Fix HostDetails test, mock chart request

* Remove example from timestamp field in ChartTimeSeries openapi schema

* mix format

* Disabled chart controller test for missing prometheus in ci

* host details e2e stub chart request

* prettier on e2e test

* npm format

* support for api charts mocking globally in e2e

* HostChart guard for chartjs chartref when data is missing

* Fix charts request stub

* Host cpu chart values are normalized for the numbers of cpus

* Fix HostDetails cpu chart scale

* Add prometheus integration tests

* Remove charts request stubbing in e2e tests

* Host memory chart 3 hour interval

* Review feedbacks

* Addressing feedbacks
  • Loading branch information
CDimonaco authored Dec 22, 2023
1 parent 3b30fb9 commit 9a3fdc7
Show file tree
Hide file tree
Showing 46 changed files with 2,088 additions and 13,217 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Here's a non-comprehensive list of the capabilities provided by the [Trento Web]
## Monitoring

It is important in critical business systems to have access to relevant information about _how things are going_.
Currently, Trento provides basic integration with **Grafana** and **Prometheus**.
Currently, Trento provides basic integration with **Prometheus**.

See [related documentation](./guides/monitoring/monitoring.md) for more information.

Expand Down
209 changes: 209 additions & 0 deletions assets/js/common/TimeSeriesLineChart/TimeSeriesLineChart.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import React, { useEffect, useState } from 'react';
import {
Chart as ChartJS,
Legend,
LinearScale,
LineElement,
LogarithmicScale,
PointElement,
TimeScale,
Tooltip,
} from 'chart.js';
import ZoomPlugin from 'chartjs-plugin-zoom';
import classNames from 'classnames';
import 'chartjs-adapter-date-fns';
import { Line } from 'react-chartjs-2';

const AVAILABLE_COLORS = [
{
line: '#A5EED4',
point: '#58CF9B',
},
{
line: '#FEF08A',
point: '#FACC15',
},
{
line: '#FECACA',
point: '#F87171',
},
{
line: '#BFDBFE',
point: '#60A5FA',
},
{
line: '#E5E7EB',
point: '#9CA3AF',
},
{
line: '#004DCF',
point: '#1273DE',
},
];

ChartJS.register(
LinearScale,
PointElement,
LineElement,
TimeScale,
Legend,
LogarithmicScale,
Tooltip,
ZoomPlugin
);

function TimeSeriesLineChart({
chartRef,
chartWrapperClassNames,
className,
datasets,
end,
onIntervalChange,
start,
title,
yAxisMaxValue,
yAxisLabelFormatter = (value) => value,
yAxisScaleType = 'linear',
}) {
const onZoomChange = ({
chart: {
scales: { x },
},
}) => onIntervalChange(x.min, x.max);

const [chartDatasets, setChartDatasets] = useState([]);
const [zoomOptions, setZoomOptions] = useState({
limits: {
x: { min: 'original', max: 'original', minRange: 60 * 1000 },
},
zoom: {
wheel: {
enabled: true,
},
drag: {
enabled: true,
},
pan: {
enabled: false,
},
mode: 'x',
onZoomComplete: onZoomChange,
// Prevent zoom reset on legend change, https://github.com/chartjs/chartjs-plugin-zoom/issues/256#issuecomment-1826812558
onZoomStart: (e) =>
e.point.x > e.chart.chartArea.left &&
e.point.x < e.chart.chartArea.right &&
e.point.y > e.chart.chartArea.top &&
e.point.y < e.chart.chartArea.bottom,
},
});

useEffect(() => {
const newDatasets = datasets.map((d, i) => ({
label: d.name,
data: d.timeFrames.map(({ time, value }) => ({
x: time,
y: value,
})),
borderColor: AVAILABLE_COLORS[i].line,
pointBackgroundColor: AVAILABLE_COLORS[i].point,
pointBorderWidth: 0,
pointRadius: 1.8,
pointHoverRadius: 8,
}));

setChartDatasets(newDatasets);
}, [datasets]);

useEffect(() => {
setZoomOptions((currentOptions) => ({
...currentOptions,
limits: {
x: {
...currentOptions.x,
min: start.getTime(),
max: end.getTime(),
},
},
}));
}, [start, end]);

const scales = {
x: {
position: 'bottom',
min: start,
max: end,
type: 'time',
ticks: {
autoSkip: true,
autoSkipPadding: 50,
maxRotation: 0,
},
time: {
displayFormats: {
hour: 'HH:mm',
minute: 'HH:mm',
second: 'HH:mm:ss',
},
},
},
y: {
type: yAxisScaleType,
position: 'left',
max: yAxisMaxValue,
ticks: {
callback: yAxisLabelFormatter,
},
},
};

const options = {
scales,
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
titleAlign: 'center',
bodyAlign: 'center',
footerAlign: 'center',
displayColors: 'false',
},
legend: {
position: 'bottom',
},
},
};

if (datasets.length > 6) {
throw new Error(
'TimeSeriesLineChart component supports a maximum of 6 datasets'
);
}

return (
<div
className={classNames(
'mt-4 bg-white shadow rounded-lg py-4 px-8 mx-auto',
className
)}
>
<h2 className="font-bold text-center text-xl"> {title} </h2>
<div
className={classNames(
'pt-6 relative text-center h-[90%] w-full flex justify-center',
chartWrapperClassNames
)}
>
<Line
ref={chartRef}
options={{
...options,
plugins: { ...options.plugins, zoom: zoomOptions },
}}
data={{ datasets: chartDatasets }}
/>
</div>
</div>
);
}

export default TimeSeriesLineChart;
Loading

0 comments on commit 9a3fdc7

Please sign in to comment.