logs: merge log-lines-based and full-range histogram (#50507)

* logs: merge old-histogram and new-histogram

* better variable names

* better names

* refactor

* refactor

* refactor

* logs: remove log-volume-loading indicator
This commit is contained in:
Gábor Farkas 2022-06-17 11:42:46 +02:00 committed by GitHub
parent 033654f93f
commit a22e9a0e0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 56 deletions

View File

@ -24,7 +24,6 @@ import {
DataQueryResponse,
} from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { TooltipDisplayMode } from '@grafana/schema';
import {
RadioButtonGroup,
LogRows,
@ -40,7 +39,6 @@ import { dedupLogRows, filterLogLevels } from 'app/core/logs_model';
import store from 'app/core/store';
import { ExploreId } from 'app/types/explore';
import { ExploreGraph } from './ExploreGraph';
import { LogsMetaRow } from './LogsMetaRow';
import LogsNavigation from './LogsNavigation';
import { LogsVolumePanel } from './LogsVolumePanel';
@ -330,30 +328,19 @@ class UnthemedLogs extends PureComponent<Props, State> {
return (
<>
{logsSeries && logsSeries.length ? (
<>
<div className={styles.infoText}>
This datasource does not support full-range histograms. The graph is based on the logs seen in the
response.
</div>
<ExploreGraph
graphStyle="lines"
data={logsSeries}
height={150}
width={width}
tooltipDisplayMode={TooltipDisplayMode.Multi}
absoluteRange={visibleRange || absoluteRange}
timeZone={timeZone}
loadingState={loadingState}
onChangeTime={onChangeTime}
onHiddenSeriesChanged={this.onToggleLogLevel}
/>
</>
) : undefined}
<LogsVolumePanel
absoluteRange={absoluteRange}
width={width}
logsVolumeData={logsVolumeData}
logLinesBasedData={
logsSeries
? {
data: logsSeries,
state: loadingState,
}
: undefined
}
logLinesBasedDataVisibleRange={visibleRange}
onUpdateTimeRange={onChangeTime}
timeZone={timeZone}
splitOpen={splitOpen}
@ -547,9 +534,5 @@ const getStyles = (theme: GrafanaTheme2, wrapLogMessage: boolean) => {
overflow-y: visible;
width: 100%;
`,
infoText: css`
font-size: ${theme.typography.size.sm};
color: ${theme.colors.text.secondary};
`,
};
};

View File

@ -21,6 +21,8 @@ function renderPanel(logsVolumeData?: DataQueryResponse) {
width={100}
onUpdateTimeRange={() => {}}
logsVolumeData={logsVolumeData}
logLinesBasedData={undefined}
logLinesBasedDataVisibleRange={undefined}
onLoadLogsVolume={() => {}}
onHiddenSeriesChanged={() => null}
/>

View File

@ -1,14 +1,24 @@
import { css } from '@emotion/css';
import React, { useState } from 'react';
import { AbsoluteTimeRange, DataQueryError, DataQueryResponse, LoadingState, SplitOpen, TimeZone } from '@grafana/data';
import {
AbsoluteTimeRange,
DataQueryError,
DataQueryResponse,
GrafanaTheme2,
LoadingState,
SplitOpen,
TimeZone,
} from '@grafana/data';
import { Alert, Button, Collapse, InlineField, TooltipDisplayMode, useStyles2, useTheme2 } from '@grafana/ui';
import { ExploreGraph } from './ExploreGraph';
type Props = {
logsVolumeData?: DataQueryResponse;
logsVolumeData: DataQueryResponse | undefined;
absoluteRange: AbsoluteTimeRange;
logLinesBasedData: DataQueryResponse | undefined;
logLinesBasedDataVisibleRange: AbsoluteTimeRange | undefined;
timeZone: TimeZone;
splitOpen: SplitOpen;
width: number;
@ -46,29 +56,64 @@ function ErrorAlert(props: { error: DataQueryError }) {
);
}
function createVisualisationData(
logLinesBased: DataQueryResponse | undefined,
logLinesBasedVisibleRange: AbsoluteTimeRange | undefined,
fullRangeData: DataQueryResponse | undefined,
absoluteRange: AbsoluteTimeRange
):
| {
logsVolumeData: DataQueryResponse;
fullRangeData: boolean;
range: AbsoluteTimeRange;
}
| undefined {
if (fullRangeData !== undefined) {
return {
logsVolumeData: fullRangeData,
fullRangeData: true,
range: absoluteRange,
};
}
if (logLinesBased !== undefined) {
return {
logsVolumeData: logLinesBased,
fullRangeData: false,
range: logLinesBasedVisibleRange || absoluteRange,
};
}
return undefined;
}
export function LogsVolumePanel(props: Props) {
const {
width,
logsVolumeData,
absoluteRange,
timeZone,
splitOpen,
onUpdateTimeRange,
onLoadLogsVolume,
onHiddenSeriesChanged,
} = props;
const { width, timeZone, splitOpen, onUpdateTimeRange, onLoadLogsVolume, onHiddenSeriesChanged } = props;
const theme = useTheme2();
const styles = useStyles2(getStyles);
const spacing = parseInt(theme.spacing(2).slice(0, -2), 10);
const height = 150;
const data = createVisualisationData(
props.logLinesBasedData,
props.logLinesBasedDataVisibleRange,
props.logsVolumeData,
props.absoluteRange
);
if (data === undefined) {
return null;
}
const { logsVolumeData, fullRangeData, range } = data;
if (logsVolumeData.error !== undefined) {
return <ErrorAlert error={logsVolumeData.error} />;
}
let LogsVolumePanelContent;
if (!logsVolumeData) {
return null;
} else if (logsVolumeData?.error) {
return <ErrorAlert error={logsVolumeData?.error} />;
} else if (logsVolumeData?.state === LoadingState.Loading) {
if (logsVolumeData?.state === LoadingState.Loading) {
LogsVolumePanelContent = <span>Log volume is loading...</span>;
} else if (logsVolumeData?.data) {
if (logsVolumeData.data.length > 0) {
@ -79,7 +124,7 @@ export function LogsVolumePanel(props: Props) {
data={logsVolumeData.data}
height={height}
width={width - spacing}
absoluteRange={absoluteRange}
absoluteRange={range}
onChangeTime={onUpdateTimeRange}
timeZone={timeZone}
splitOpenFn={splitOpen}
@ -92,30 +137,37 @@ export function LogsVolumePanel(props: Props) {
}
}
const zoomRatio = logsLevelZoomRatio(logsVolumeData, absoluteRange);
let zoomLevelInfo;
let extraInfo;
if (fullRangeData) {
const zoomRatio = logsLevelZoomRatio(logsVolumeData, range);
if (zoomRatio !== undefined && zoomRatio < 1) {
zoomLevelInfo = (
<InlineField label="Reload log volume" transparent>
<Button size="xs" icon="sync" variant="secondary" onClick={onLoadLogsVolume} id="reload-volume" />
</InlineField>
if (zoomRatio !== undefined && zoomRatio < 1) {
extraInfo = (
<InlineField label="Reload log volume" transparent>
<Button size="xs" icon="sync" variant="secondary" onClick={onLoadLogsVolume} id="reload-volume" />
</InlineField>
);
}
} else {
extraInfo = (
<div className={styles.oldInfoText}>
This datasource does not support full-range histograms. The graph is based on the logs seen in the response.
</div>
);
}
return (
<Collapse label="" isOpen={true} loading={logsVolumeData?.state === LoadingState.Loading}>
<Collapse label="" isOpen={true}>
<div style={{ height }} className={styles.contentContainer}>
{LogsVolumePanelContent}
</div>
<div className={styles.zoomInfoContainer}>{zoomLevelInfo}</div>
<div className={styles.extraInfoContainer}>{extraInfo}</div>
</Collapse>
);
}
const getStyles = () => {
const getStyles = (theme: GrafanaTheme2) => {
return {
zoomInfoContainer: css`
extraInfoContainer: css`
display: flex;
justify-content: end;
position: absolute;
@ -127,6 +179,10 @@ const getStyles = () => {
align-items: center;
justify-content: center;
`,
oldInfoText: css`
font-size: ${theme.typography.size.sm};
color: ${theme.colors.text.secondary};
`,
};
};