grafana/public/app/features/explore/LogLabelStats.tsx
Dominik Prokop a9c94ec93b
Explore: Update the way Loki retrieve log context (#17204)
* Move log's typings into grafana/ui
* Update the way context is retrieved for Loki

Major changes:

1. getLogRowContext expects row to be of LogRowModel type
2. getLogRowContext accepts generic options object, specific to a datasource of interest. limit option has been removed, and now it's a part of Loki's context query options (see below)
3. LogRowContextProvider performs two queries now. Before, it was Loki ds that performed queries in both directions when getLogRowContext.
4. Loki's getLogRowContext accepts options object of a type:

interface LokiContextQueryOptions {
    direction?: 'BACKWARD' | 'FORWARD';
    limit?: number;
}

This will enable querying in either direction independently and also slightly simplifies the way query errors are handled.

LogRowContextProvider maps the results to a Loki specific context types, basically string[][], as raw log lines are displayed in first version.
2019-05-22 23:10:05 +02:00

77 lines
2.6 KiB
TypeScript

import React, { PureComponent } from 'react';
import classnames from 'classnames';
import { LogLabelStatsModel } from '@grafana/ui';
function LogLabelStatsRow(logLabelStatsModel: LogLabelStatsModel) {
const { active, count, proportion, value } = logLabelStatsModel;
const percent = `${Math.round(proportion * 100)}%`;
const barStyle = { width: percent };
const className = classnames('logs-stats-row', { 'logs-stats-row--active': active });
return (
<div className={className}>
<div className="logs-stats-row__label">
<div className="logs-stats-row__value" title={value}>
{value}
</div>
<div className="logs-stats-row__count">{count}</div>
<div className="logs-stats-row__percent">{percent}</div>
</div>
<div className="logs-stats-row__bar">
<div className="logs-stats-row__innerbar" style={barStyle} />
</div>
</div>
);
}
const STATS_ROW_LIMIT = 5;
interface Props {
stats: LogLabelStatsModel[];
label: string;
value: string;
rowCount: number;
onClickClose: () => void;
}
export class LogLabelStats extends PureComponent<Props> {
render() {
const { label, rowCount, stats, value, onClickClose } = this.props;
const topRows = stats.slice(0, STATS_ROW_LIMIT);
let activeRow = topRows.find(row => row.value === value);
let otherRows = stats.slice(STATS_ROW_LIMIT);
const insertActiveRow = !activeRow;
// Remove active row from other to show extra
if (insertActiveRow) {
activeRow = otherRows.find(row => row.value === value);
otherRows = otherRows.filter(row => row.value !== value);
}
const otherCount = otherRows.reduce((sum, row) => sum + row.count, 0);
const topCount = topRows.reduce((sum, row) => sum + row.count, 0);
const total = topCount + otherCount;
const otherProportion = otherCount / total;
return (
<div className="logs-stats">
<div className="logs-stats__header">
<span className="logs-stats__title">
{label}: {total} of {rowCount} rows have that label
</span>
<span className="logs-stats__close fa fa-remove" onClick={onClickClose} />
</div>
<div className="logs-stats__body">
{topRows.map(stat => (
<LogLabelStatsRow key={stat.value} {...stat} active={stat.value === value} />
))}
{insertActiveRow && activeRow && <LogLabelStatsRow key={activeRow.value} {...activeRow} active />}
{otherCount > 0 && (
<LogLabelStatsRow key="__OTHERS__" count={otherCount} value="Other" proportion={otherProportion} />
)}
</div>
</div>
);
}
}