in dashboards-observability/public/components/trace_analytics/components/dashboard/dashboard.tsx [27:220]
export function Dashboard(props: DashboardProps) {
const [tableItems, setTableItems] = useState([]);
const [throughputPltItems, setThroughputPltItems] = useState({ items: [], fixedInterval: '1h' });
const [errorRatePltItems, setErrorRatePltItems] = useState({ items: [], fixedInterval: '1h' });
const [serviceMap, setServiceMap] = useState<ServiceObject>({});
const [serviceMapIdSelected, setServiceMapIdSelected] = useState<'latency' | 'error_rate' | 'throughput'>('latency');
const [percentileMap, setPercentileMap] = useState<{ [traceGroup: string]: number[] }>({});
const [redirect, setRedirect] = useState(true);
const [loading, setLoading] = useState(false);
useEffect(() => {
props.chrome.setBreadcrumbs([
props.parentBreadcrumb,
{
text: 'Trace analytics',
href: '#/trace_analytics/home',
},
{
text: 'Dashboards',
href: '#/trace_analytics/home',
},
]);
const validFilters = getValidFilterFields('dashboard');
props.setFilters([
...props.filters.map((filter) => ({
...filter,
locked: validFilters.indexOf(filter.field) === -1,
})),
]);
setRedirect(false);
}, []);
useEffect(() => {
if (!redirect && props.indicesExist) refresh();
}, [props.filters, props.startTime, props.endTime]);
const refresh = async () => {
setLoading(true);
const DSL = filtersToDsl(props.filters, props.query, props.startTime, props.endTime);
const timeFilterDSL = filtersToDsl([], '', props.startTime, props.endTime);
const latencyTrendStartTime = dateMath
.parse(props.endTime)
?.subtract(24, 'hours')
.toISOString()!;
const latencyTrendDSL = filtersToDsl(
props.filters,
props.query,
latencyTrendStartTime,
props.endTime
);
const fixedInterval = minFixedInterval(props.startTime, props.endTime);
handleDashboardRequest(
props.http,
DSL,
timeFilterDSL,
latencyTrendDSL,
tableItems,
setTableItems,
setPercentileMap
).then(() => setLoading(false));
handleDashboardThroughputPltRequest(
props.http,
DSL,
fixedInterval,
throughputPltItems,
setThroughputPltItems
);
handleDashboardErrorRatePltRequest(
props.http,
DSL,
fixedInterval,
errorRatePltItems,
setErrorRatePltItems
);
handleServiceMapRequest(props.http, DSL, serviceMap, setServiceMap);
};
const addFilter = (filter: FilterType) => {
for (const addedFilter of props.filters) {
if (
addedFilter.field === filter.field &&
addedFilter.operator === filter.operator &&
addedFilter.value === filter.value
) {
return;
}
}
const newFilters = [...props.filters, filter];
props.setFilters(newFilters);
};
const addPercentileFilter = (condition = 'gte', additionalFilters = [] as FilterType[]) => {
if (tableItems.length === 0 || Object.keys(percentileMap).length === 0) return;
for (let i = 0; i < props.filters.length; i++) {
if (props.filters[i].custom) {
const newFilter = JSON.parse(JSON.stringify(props.filters[i]));
newFilter.custom.query.bool.should.forEach((should: any) =>
should.bool.must.forEach((must: any) => {
const range = must?.range?.['traceGroupFields.durationInNanos'];
if (range) {
const duration = range.lt || range.lte || range.gt || range.gte;
if (duration || duration === 0) {
must.range['traceGroupFields.durationInNanos'] = {
[condition]: duration,
};
}
}
})
);
newFilter.value = condition === 'gte' ? '>= 95th' : '< 95th';
const newFilters = [...props.filters, ...additionalFilters];
newFilters.splice(i, 1, newFilter);
props.setFilters(newFilters);
return;
}
}
const percentileMaps = Object.keys(percentileMap).map((traceGroup) => ({
traceGroupName: traceGroup,
durationFilter: { [condition]: milliToNanoSec(percentileMap[traceGroup][1]) },
}));
const percentileFilter = getPercentileFilter(
percentileMaps,
condition === 'gte' ? '>= 95th' : '< 95th'
);
const newFilters = [...props.filters, percentileFilter, ...additionalFilters];
props.setFilters(newFilters);
};
return (
<>
<EuiTitle size="l">
<h2 style={{ fontWeight: 430 }}>Dashboard</h2>
</EuiTitle>
<SearchBar
query={props.query}
filters={props.filters}
setFilters={props.setFilters}
setQuery={props.setQuery}
startTime={props.startTime}
setStartTime={props.setStartTime}
endTime={props.endTime}
setEndTime={props.setEndTime}
refresh={refresh}
page="dashboard"
/>
<EuiSpacer size="m" />
{props.indicesExist ? (
<>
<DashboardTable
items={tableItems}
filters={props.filters}
addFilter={addFilter}
addPercentileFilter={addPercentileFilter}
setRedirect={setRedirect}
loading={loading}
/>
<EuiSpacer />
<EuiFlexGroup alignItems="baseline">
<EuiFlexItem grow={4}>
<ServiceMap
addFilter={addFilter}
serviceMap={serviceMap}
idSelected={serviceMapIdSelected}
setIdSelected={setServiceMapIdSelected}
/>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup direction="column">
<EuiFlexItem>
<ErrorRatePlt
items={errorRatePltItems}
setStartTime={props.setStartTime}
setEndTime={props.setEndTime}
/>
</EuiFlexItem>
<EuiFlexItem>
<ThroughputPlt
items={throughputPltItems}
setStartTime={props.setStartTime}
setEndTime={props.setEndTime}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</>
) : (
<MissingConfigurationMessage />
)}
</>
);
}