Merge pull request #3900 from influxdata/logs-viewer/histogram-bars-sort
Sort histogram bars and tooltip in the order of severitypull/10616/head
commit
8ec536832d
ui
src
logs
constants
containers
shared/components
types
test/shared/components
__snapshots__
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -36,3 +36,5 @@ export interface HistogramColor {
|
||||||
group: string
|
group: string
|
||||||
color: string
|
color: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type SortFn = (a: HistogramDatum, b: HistogramDatum) => number
|
||||||
|
|
|
@ -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} />)
|
||||||
|
|
|
@ -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]}
|
||||||
|
|
Loading…
Reference in New Issue