Merge pull request from influxdata/logs-viewer/histogram-bars-sort

Sort histogram bars and tooltip in the order of severity
pull/10616/head
Iris Scholten 2018-07-12 15:50:06 -07:00 committed by GitHub
commit 8ec536832d
7 changed files with 73 additions and 26 deletions
ui
src
test/shared/components

View File

@ -138,6 +138,17 @@ export enum SeverityLevelOptions {
debug = 'debug', debug = 'debug',
} }
export const SEVERITY_SORTING_ORDER = {
[SeverityLevelOptions.emerg]: 1,
[SeverityLevelOptions.alert]: 2,
[SeverityLevelOptions.crit]: 3,
[SeverityLevelOptions.err]: 4,
[SeverityLevelOptions.warning]: 5,
[SeverityLevelOptions.notice]: 6,
[SeverityLevelOptions.info]: 7,
[SeverityLevelOptions.debug]: 8,
}
export const DEFAULT_SEVERITY_LEVELS = { export const DEFAULT_SEVERITY_LEVELS = {
[SeverityLevelOptions.emerg]: SeverityColorOptions.ruby, [SeverityLevelOptions.emerg]: SeverityColorOptions.ruby,
[SeverityLevelOptions.alert]: SeverityColorOptions.fire, [SeverityLevelOptions.alert]: SeverityColorOptions.fire,

View File

@ -36,10 +36,18 @@ import PointInTimeDropDown from 'src/logs/components/PointInTimeDropDown'
import {getDeep} from 'src/utils/wrappers' import {getDeep} from 'src/utils/wrappers'
import {colorForSeverity} from 'src/logs/utils/colors' import {colorForSeverity} from 'src/logs/utils/colors'
import OverlayTechnology from 'src/reusable_ui/components/overlays/OverlayTechnology' import OverlayTechnology from 'src/reusable_ui/components/overlays/OverlayTechnology'
import {SeverityFormatOptions, SECONDS_TO_MS} from 'src/logs/constants' import {
SeverityFormatOptions,
SEVERITY_SORTING_ORDER,
SECONDS_TO_MS,
} from 'src/logs/constants'
import {Source, Namespace} from 'src/types' import {Source, Namespace} from 'src/types'
import {HistogramData, HistogramColor} from 'src/types/histogram' import {
HistogramData,
HistogramColor,
HistogramDatum,
} from 'src/types/histogram'
import { import {
Filter, Filter,
SeverityLevelColor, SeverityLevelColor,
@ -330,12 +338,20 @@ class LogsPage extends Component<Props, State> {
colorScale={colorForSeverity} colorScale={colorForSeverity}
colors={histogramColors} colors={histogramColors}
onBarClick={this.handleBarClick} onBarClick={this.handleBarClick}
sortBarGroups={this.handleSortHistogramBarGroups}
/> />
)} )}
</AutoSizer> </AutoSizer>
) )
} }
private handleSortHistogramBarGroups = (
a: HistogramDatum,
b: HistogramDatum
): number => {
return SEVERITY_SORTING_ORDER[b.group] - SEVERITY_SORTING_ORDER[a.group]
}
private get header(): JSX.Element { private get header(): JSX.Element {
const { const {
sources, sources,

View File

@ -15,6 +15,7 @@ import {
HoverData, HoverData,
ColorScale, ColorScale,
HistogramColor, HistogramColor,
SortFn,
} from 'src/types/histogram' } from 'src/types/histogram'
const PADDING_TOP = 0.2 const PADDING_TOP = 0.2
@ -32,6 +33,7 @@ interface Props {
colors: HistogramColor[] colors: HistogramColor[]
colorScale: ColorScale colorScale: ColorScale
onBarClick?: (time: string) => void onBarClick?: (time: string) => void
sortBarGroups: SortFn
} }
interface State { interface State {
@ -46,7 +48,15 @@ class HistogramChart extends PureComponent<Props, State> {
} }
public render() { public render() {
const {width, height, data, colorScale, colors, onBarClick} = this.props const {
width,
height,
data,
colorScale,
colors,
onBarClick,
sortBarGroups,
} = this.props
const {margins} = this const {margins} = this
if (width === 0 || height === 0) { if (width === 0 || height === 0) {
@ -99,6 +109,7 @@ class HistogramChart extends PureComponent<Props, State> {
onHover={this.handleHover} onHover={this.handleHover}
colors={colors} colors={colors}
onBarClick={onBarClick} onBarClick={onBarClick}
sortBarGroups={sortBarGroups}
/> />
</g> </g>
</svg> </svg>

View File

@ -12,6 +12,7 @@ import {
TooltipAnchor, TooltipAnchor,
ColorScale, ColorScale,
HistogramColor, HistogramColor,
SortFn,
} from 'src/types/histogram' } from 'src/types/histogram'
const BAR_BORDER_RADIUS = 3 const BAR_BORDER_RADIUS = 3
@ -29,20 +30,24 @@ const getBarWidth = ({data, xScale, width}): number => {
return Math.round(width / barCount - BAR_PADDING_SIDES) return Math.round(width / barCount - BAR_PADDING_SIDES)
} }
type SortFn = (a: HistogramDatum, b: HistogramDatum) => number interface BarGroup {
key: string
const getSortFn = (data: HistogramData): SortFn => { clip: {
const counts = {} x: number
y: number
for (const d of data) { width: number
if (counts[d.group]) { height: number
counts[d.group] += d.value
} else {
counts[d.group] = d.value
}
} }
bars: Array<{
return (a, b) => counts[b.group] - counts[a.group] key: string
group: string
x: number
y: number
width: number
height: number
fill: string
}>
data: HistogramData
} }
const getBarGroups = ({ const getBarGroups = ({
@ -53,14 +58,14 @@ const getBarGroups = ({
colorScale, colorScale,
hoverData, hoverData,
colors, colors,
sortBarGroups,
}: Partial<Props>): BarGroup[] => { }: Partial<Props>): BarGroup[] => {
const barWidth = getBarWidth({data, xScale, width}) const barWidth = getBarWidth({data, xScale, width})
const sortFn = getSortFn(data)
const visibleData = data.filter(d => d.value !== 0) const visibleData = data.filter(d => d.value !== 0)
const timeGroups = Object.values(_.groupBy(visibleData, 'time')) const timeGroups = Object.values(_.groupBy(visibleData, 'time'))
for (const timeGroup of timeGroups) { for (const timeGroup of timeGroups) {
timeGroup.sort(sortFn) timeGroup.sort(sortBarGroups)
} }
let hoverDataKeys = [] let hoverDataKeys = []
@ -143,6 +148,7 @@ interface Props {
colors: HistogramColor[] colors: HistogramColor[]
onHover: (h: HoverData) => void onHover: (h: HoverData) => void
onBarClick?: (time: string) => void onBarClick?: (time: string) => void
sortBarGroups: SortFn
} }
interface State { interface State {
@ -229,7 +235,7 @@ class HistogramChartBars extends PureComponent<Props, State> {
return return
} }
const {data} = hoverGroup const data = _.get(hoverGroup, 'data').reverse()
const barGroup = e.currentTarget as SVGGElement const barGroup = e.currentTarget as SVGGElement
const boundingRect = barGroup.getBoundingClientRect() const boundingRect = barGroup.getBoundingClientRect()
const boundingRectHeight = boundingRect.bottom - boundingRect.top const boundingRectHeight = boundingRect.bottom - boundingRect.top

View File

@ -36,3 +36,5 @@ export interface HistogramColor {
group: string group: string
color: string color: string
} }
export type SortFn = (a: HistogramDatum, b: HistogramDatum) => number

View File

@ -14,8 +14,8 @@ describe('HistogramChart', () => {
width: 600, width: 600,
height: 400, height: 400,
colorScale: () => 'blue', colorScale: () => 'blue',
onZoom: () => {},
colors: [], colors: [],
sortBarGroups: (a, b) => a.value - b.value,
} }
const wrapper = mount(<HistogramChart {...props} />) const wrapper = mount(<HistogramChart {...props} />)
@ -30,8 +30,8 @@ describe('HistogramChart', () => {
width: 0, width: 0,
height: 0, height: 0,
colorScale: () => 'blue', colorScale: () => 'blue',
onZoom: () => {},
colors: [], colors: [],
sortBarGroups: (a, b) => a.value - b.value,
} }
const wrapper = mount(<HistogramChart {...props} />) const wrapper = mount(<HistogramChart {...props} />)
@ -50,8 +50,8 @@ describe('HistogramChart', () => {
width: 600, width: 600,
height: 400, height: 400,
colorScale: () => 'blue', colorScale: () => 'blue',
onZoom: () => {},
colors: [], colors: [],
sortBarGroups: (a, b) => a.value - b.value,
} }
const wrapper = mount(<HistogramChart {...props} />) const wrapper = mount(<HistogramChart {...props} />)
@ -70,8 +70,8 @@ describe('HistogramChart', () => {
width: 600, width: 600,
height: 400, height: 400,
colorScale: () => 'blue', colorScale: () => 'blue',
onZoom: () => {},
colors: [], colors: [],
sortBarGroups: (a, b) => a.value - b.value,
} }
const wrapper = mount(<HistogramChart {...props} />) const wrapper = mount(<HistogramChart {...props} />)

View File

@ -7,7 +7,7 @@ exports[`HistogramChart displays a HistogramChartSkeleton if empty data is passe
data={Array []} data={Array []}
dataStatus="Done" dataStatus="Done"
height={400} height={400}
onZoom={[Function]} sortBarGroups={[Function]}
width={600} width={600}
> >
<HistogramChartSkeleton <HistogramChartSkeleton
@ -141,7 +141,7 @@ exports[`HistogramChart displays a nothing if passed width and height of 0 1`] =
data={Array []} data={Array []}
dataStatus="Done" dataStatus="Done"
height={0} height={0}
onZoom={[Function]} sortBarGroups={[Function]}
width={0} width={0}
/> />
`; `;
@ -174,7 +174,7 @@ exports[`HistogramChart displays the visualization with bars if nonempty data is
} }
dataStatus="Done" dataStatus="Done"
height={400} height={400}
onZoom={[Function]} sortBarGroups={[Function]}
width={600} width={600}
> >
<svg <svg
@ -341,6 +341,7 @@ exports[`HistogramChart displays the visualization with bars if nonempty data is
} }
height={375} height={375}
onHover={[Function]} onHover={[Function]}
sortBarGroups={[Function]}
width={575} width={575}
xScale={[Function]} xScale={[Function]}
yScale={[Function]} yScale={[Function]}