mirror of https://github.com/grafana/grafana
Logs: Use GraphNG to plot log histograms (#34531)
* Switch to GraphNG for Logs Histogram * Remove redundant timeZone It was used just to format timestamp in the tooltip but it's not needed anymore. * Add tests for creating logs histogram data * Update decoractors tests * Adjust bar width to be more like in the old graph * Fix tooltip pointer color * Test tooltip pointer color * Decouple graph config from uPlot internals * Ensure nested properties are not mutated when overrides are applied * Add legend toggling for Explore graphs * Remove unused component ExploreGraphNGPanel is now used in Explore * Code formatting * allow multiple bars pathBuilders to be globally cached with different settings Co-authored-by: Leon Sorokin <leeoniya@gmail.com>pull/35020/head
parent
c6a78a6bd7
commit
f4a40a4d85
@ -1,172 +0,0 @@ |
||||
import React, { PureComponent } from 'react'; |
||||
import { css, cx } from '@emotion/css'; |
||||
import { GrafanaTheme, TimeZone, AbsoluteTimeRange, GraphSeriesXY, dateTime } from '@grafana/data'; |
||||
|
||||
import { |
||||
Themeable, |
||||
GraphWithLegend, |
||||
LegendDisplayMode, |
||||
withTheme, |
||||
Collapse, |
||||
GraphSeriesToggler, |
||||
GraphSeriesTogglerAPI, |
||||
VizTooltip, |
||||
Icon, |
||||
TooltipDisplayMode, |
||||
} from '@grafana/ui'; |
||||
|
||||
const MAX_NUMBER_OF_TIME_SERIES = 20; |
||||
|
||||
const getStyles = (theme: GrafanaTheme) => ({ |
||||
timeSeriesDisclaimer: css` |
||||
label: time-series-disclaimer; |
||||
width: 300px; |
||||
margin: ${theme.spacing.sm} auto; |
||||
padding: 10px 0; |
||||
border-radius: ${theme.border.radius.md}; |
||||
text-align: center; |
||||
background-color: ${theme.isLight ? theme.palette.white : theme.palette.dark4}; |
||||
`,
|
||||
disclaimerIcon: css` |
||||
label: disclaimer-icon; |
||||
color: ${theme.palette.yellow}; |
||||
margin-right: ${theme.spacing.xs}; |
||||
`,
|
||||
showAllTimeSeries: css` |
||||
label: show-all-time-series; |
||||
cursor: pointer; |
||||
color: ${theme.colors.linkExternal}; |
||||
`,
|
||||
}); |
||||
|
||||
interface Props extends Themeable { |
||||
ariaLabel?: string; |
||||
series?: GraphSeriesXY[] | null; |
||||
width: number; |
||||
absoluteRange: AbsoluteTimeRange; |
||||
loading?: boolean; |
||||
showPanel: boolean; |
||||
showBars: boolean; |
||||
showLines: boolean; |
||||
isStacked: boolean; |
||||
timeZone?: TimeZone; |
||||
onUpdateTimeRange: (absoluteRange: AbsoluteTimeRange) => void; |
||||
onHiddenSeriesChanged?: (hiddenSeries: string[]) => void; |
||||
} |
||||
|
||||
interface State { |
||||
hiddenSeries: string[]; |
||||
showAllTimeSeries: boolean; |
||||
} |
||||
|
||||
class UnThemedExploreGraphPanel extends PureComponent<Props, State> { |
||||
state: State = { |
||||
hiddenSeries: [], |
||||
showAllTimeSeries: false, |
||||
}; |
||||
|
||||
onShowAllTimeSeries = () => { |
||||
this.setState({ |
||||
showAllTimeSeries: true, |
||||
}); |
||||
}; |
||||
|
||||
onChangeTime = (from: number, to: number) => { |
||||
const { onUpdateTimeRange } = this.props; |
||||
onUpdateTimeRange({ from, to }); |
||||
}; |
||||
|
||||
renderGraph = () => { |
||||
const { |
||||
ariaLabel, |
||||
width, |
||||
series, |
||||
onHiddenSeriesChanged, |
||||
timeZone, |
||||
absoluteRange, |
||||
showPanel, |
||||
showBars, |
||||
showLines, |
||||
isStacked, |
||||
} = this.props; |
||||
const { showAllTimeSeries } = this.state; |
||||
|
||||
if (!series) { |
||||
return null; |
||||
} |
||||
|
||||
const timeRange = { |
||||
from: dateTime(absoluteRange.from), |
||||
to: dateTime(absoluteRange.to), |
||||
raw: { |
||||
from: dateTime(absoluteRange.from), |
||||
to: dateTime(absoluteRange.to), |
||||
}, |
||||
}; |
||||
|
||||
const height = showPanel ? 200 : 100; |
||||
const lineWidth = showLines ? 1 : 5; |
||||
const seriesToShow = showAllTimeSeries ? series : series.slice(0, MAX_NUMBER_OF_TIME_SERIES); |
||||
return ( |
||||
<GraphSeriesToggler series={seriesToShow} onHiddenSeriesChanged={onHiddenSeriesChanged}> |
||||
{({ onSeriesToggle, toggledSeries }: GraphSeriesTogglerAPI) => { |
||||
return ( |
||||
<GraphWithLegend |
||||
ariaLabel={ariaLabel} |
||||
legendDisplayMode={LegendDisplayMode.List} |
||||
height={height} |
||||
placement={'bottom'} |
||||
width={width} |
||||
timeRange={timeRange} |
||||
timeZone={timeZone} |
||||
showBars={showBars} |
||||
showLines={showLines} |
||||
showPoints={false} |
||||
onToggleSort={() => {}} |
||||
series={toggledSeries} |
||||
isStacked={isStacked} |
||||
lineWidth={lineWidth} |
||||
onSeriesToggle={onSeriesToggle} |
||||
onHorizontalRegionSelected={this.onChangeTime} |
||||
> |
||||
{/* For logs we are using mulit mode until we refactor logs histogram to use barWidth instead of lineWidth to render bars */} |
||||
<VizTooltip mode={showBars ? TooltipDisplayMode.Multi : TooltipDisplayMode.Single} /> |
||||
</GraphWithLegend> |
||||
); |
||||
}} |
||||
</GraphSeriesToggler> |
||||
); |
||||
}; |
||||
|
||||
render() { |
||||
const { series, showPanel, loading, theme } = this.props; |
||||
const { showAllTimeSeries } = this.state; |
||||
const style = getStyles(theme); |
||||
|
||||
return ( |
||||
<> |
||||
{series && series.length > MAX_NUMBER_OF_TIME_SERIES && !showAllTimeSeries && ( |
||||
<div className={cx([style.timeSeriesDisclaimer])}> |
||||
<Icon className={style.disclaimerIcon} name="exclamation-triangle" /> |
||||
{`Showing only ${MAX_NUMBER_OF_TIME_SERIES} time series. `} |
||||
<span |
||||
className={cx([style.showAllTimeSeries])} |
||||
onClick={this.onShowAllTimeSeries} |
||||
>{`Show all ${series.length}`}</span> |
||||
</div> |
||||
)} |
||||
|
||||
{showPanel && ( |
||||
<Collapse label="Graph" loading={loading} isOpen> |
||||
{this.renderGraph()} |
||||
</Collapse> |
||||
)} |
||||
|
||||
{!showPanel && this.renderGraph()} |
||||
</> |
||||
); |
||||
} |
||||
} |
||||
|
||||
export const ExploreGraphPanel = withTheme(UnThemedExploreGraphPanel); |
||||
ExploreGraphPanel.displayName = 'ExploreGraphPanel'; |
Loading…
Reference in new issue