1
import React, { FC, ReactNode } from 'react';
3
import { Alert, Button, ButtonGroup, Table } from 'reactstrap';
5
import SeriesName from './SeriesName';
6
import { Metric, Histogram } from '../../types/types';
8
import moment from 'moment';
10
import HistogramChart from './HistogramChart';
12
export interface DataTableProps {
17
result: InstantSample[];
21
result: RangeSamples[];
31
useLocalTime: boolean;
34
interface InstantSample {
37
histogram?: SampleHistogram;
40
interface RangeSamples {
42
values?: SampleValue[];
43
histograms?: SampleHistogram[];
46
type SampleValue = [number, string];
47
type SampleHistogram = [number, Histogram];
49
const limitSeries = <S extends InstantSample | RangeSamples>(series: S[]): S[] => {
50
const maxSeries = 10000;
52
if (series.length > maxSeries) {
53
return series.slice(0, maxSeries);
58
const DataTable: FC<DataTableProps> = ({ data, useLocalTime }) => {
59
const [scale, setScale] = React.useState<'linear' | 'exponential'>('exponential');
62
return <Alert color="light">No data queried yet</Alert>;
65
if (data.result === null || data.result.length === 0) {
66
return <Alert color="secondary">Empty query result</Alert>;
69
const maxFormattableSize = 1000;
70
let rows: ReactNode[] = [];
72
const doFormat = data.result.length <= maxFormattableSize;
73
switch (data.resultType) {
75
rows = (limitSeries(data.result) as InstantSample[]).map((s: InstantSample, index: number): ReactNode => {
79
<SeriesName labels={s.metric} format={doFormat} />
82
{s.value && s.value[1]}
85
<HistogramChart histogram={s.histogram[1]} index={index} scale={scale} />
86
<div className="histogram-summary-wrapper">
87
<div className="histogram-summary">
89
<strong>Total count:</strong> {s.histogram[1].count}
92
<strong>Sum:</strong> {s.histogram[1].sum}
95
<div className="histogram-summary">
96
<span>x-axis scale:</span>
97
<ButtonGroup className="stacked-input" size="sm">
99
title="Show histogram on exponential scale"
100
onClick={() => setScale('exponential')}
101
active={scale === 'exponential'}
106
title="Show histogram on linear scale"
107
onClick={() => setScale('linear')}
108
active={scale === 'linear'}
115
{histogramTable(s.histogram[1])}
122
limited = rows.length !== data.result.length;
125
rows = (limitSeries(data.result) as RangeSamples[]).map((s, seriesIdx) => {
126
const valuesAndTimes = s.values
127
? s.values.map((v, valIdx) => {
128
const printedDatetime = moment.unix(v[0]).toISOString(useLocalTime);
130
<React.Fragment key={valIdx}>
131
{v[1]} @{<span title={printedDatetime}>{v[0]}</span>}
137
const histogramsAndTimes = s.histograms
138
? s.histograms.map((h, hisIdx) => {
139
const printedDatetime = moment.unix(h[0]).toISOString(useLocalTime);
141
<React.Fragment key={-hisIdx}>
142
{histogramTable(h[1])} @{<span title={printedDatetime}>{h[0]}</span>}
149
<tr style={{ whiteSpace: 'pre' }} key={seriesIdx}>
151
<SeriesName labels={s.metric} format={doFormat} />
154
{valuesAndTimes} {histogramsAndTimes}
159
limited = rows.length !== data.result.length;
165
<td>{data.result[1]}</td>
173
<td>{data.result[1]}</td>
178
return <Alert color="danger">Unsupported result value type</Alert>;
184
<Alert color="danger">
185
<strong>Warning:</strong> Fetched {data.result.length} metrics, only displaying first {rows.length}.
189
<Alert color="secondary">
190
<strong>Notice:</strong> Showing more than {maxFormattableSize} series, turning off label formatting for
194
<Table hover size="sm" className="data-table">
195
<tbody>{rows}</tbody>
201
const leftDelim = (br: number): string => (br === 3 || br === 1 ? '[' : '(');
202
const rightDelim = (br: number): string => (br === 3 || br === 0 ? ']' : ')');
204
export const bucketRangeString = ([boundaryRule, leftBoundary, rightBoundary, _]: [
210
return `${leftDelim(boundaryRule)}${leftBoundary} -> ${rightBoundary}${rightDelim(boundaryRule)}`;
213
export const histogramTable = (h: Histogram): ReactNode => (
214
<Table size="xs" responsive bordered>
217
<th style={{ textAlign: 'center' }} colSpan={2}>
227
{h.buckets?.map((b, i) => (
229
<td>{bucketRangeString(b)}</td>
236
export default DataTable;