grafana/public/app/features/explore/Logs.tsx

225 lines
6.3 KiB
TypeScript
Raw Normal View History

import React, { PureComponent } from 'react';
import {
rangeUtil,
RawTimeRange,
LogLevel,
TimeZone,
AbsoluteTimeRange,
LogsMetaKind,
LogsDedupStrategy,
LogRowModel,
LogsDedupDescription,
LogsMetaItem,
GraphSeriesXY,
} from '@grafana/data';
import { Switch, LogLabels, ToggleButtonGroup, ToggleButton, LogRows } from '@grafana/ui';
import { ExploreGraphPanel } from './ExploreGraphPanel';
function renderMetaItem(value: any, kind: LogsMetaKind) {
if (kind === LogsMetaKind.LabelsMap) {
return (
2018-12-06 01:08:16 -06:00
<span className="logs-meta-item__labels">
<LogLabels labels={value} plain getRows={() => []} />
</span>
);
}
return value;
}
interface Props {
logRows?: LogRowModel[];
logsMeta?: LogsMetaItem[];
logsSeries?: GraphSeriesXY[];
dedupedRows?: LogRowModel[];
width: number;
highlighterExpressions: string[];
loading: boolean;
absoluteRange: AbsoluteTimeRange;
timeZone: TimeZone;
scanning?: boolean;
2018-11-27 09:35:37 -06:00
scanRange?: RawTimeRange;
2019-02-07 10:46:33 -06:00
dedupStrategy: LogsDedupStrategy;
onChangeTime: (range: AbsoluteTimeRange) => void;
onClickFilterLabel?: (key: string, value: string) => void;
onClickFilterOutLabel?: (key: string, value: string) => void;
2018-11-27 09:35:37 -06:00
onStartScanning?: () => void;
onStopScanning?: () => void;
2019-02-07 10:46:33 -06:00
onDedupStrategyChange: (dedupStrategy: LogsDedupStrategy) => void;
onToggleLogLevel: (hiddenLogLevels: LogLevel[]) => void;
getRowContext?: (row: LogRowModel, options?: any) => Promise<any>;
}
interface State {
showTime: boolean;
}
export class Logs extends PureComponent<Props, State> {
state = {
showTime: true,
};
onChangeDedup = (dedup: LogsDedupStrategy) => {
2019-02-07 10:46:33 -06:00
const { onDedupStrategyChange } = this.props;
if (this.props.dedupStrategy === dedup) {
return onDedupStrategyChange(LogsDedupStrategy.none);
}
return onDedupStrategyChange(dedup);
};
onChangeTime = (event?: React.SyntheticEvent) => {
const target = event && (event.target as HTMLInputElement);
if (target) {
this.setState({
showTime: target.checked,
});
}
};
onToggleLogLevel = (hiddenRawLevels: string[]) => {
const hiddenLogLevels: LogLevel[] = hiddenRawLevels.map(level => LogLevel[level as LogLevel]);
this.props.onToggleLogLevel(hiddenLogLevels);
};
2018-11-27 09:35:37 -06:00
onClickScan = (event: React.SyntheticEvent) => {
event.preventDefault();
if (this.props.onStartScanning) {
this.props.onStartScanning();
}
2018-11-27 09:35:37 -06:00
};
onClickStopScan = (event: React.SyntheticEvent) => {
event.preventDefault();
if (this.props.onStopScanning) {
this.props.onStopScanning();
}
};
render() {
const {
logRows,
logsMeta,
logsSeries,
highlighterExpressions,
loading = false,
onClickFilterLabel,
onClickFilterOutLabel,
timeZone,
scanning,
scanRange,
width,
dedupedRows,
absoluteRange,
onChangeTime,
} = this.props;
if (!logRows) {
return null;
}
const { showTime } = this.state;
2019-02-07 10:46:33 -06:00
const { dedupStrategy } = this.props;
const hasData = logRows && logRows.length > 0;
const dedupCount = dedupedRows
? dedupedRows.reduce((sum, row) => (row.duplicates ? sum + row.duplicates : sum), 0)
: 0;
const meta = logsMeta ? [...logsMeta] : [];
2019-02-07 10:46:33 -06:00
if (dedupStrategy !== LogsDedupStrategy.none) {
meta.push({
label: 'Dedup count',
value: dedupCount,
kind: LogsMetaKind.Number,
});
}
2018-11-27 09:35:37 -06:00
const scanText = scanRange ? `Scanning ${rangeUtil.describeTimeRange(scanRange)}` : 'Scanning...';
const series = logsSeries ? logsSeries : [];
return (
2018-12-06 01:08:16 -06:00
<div className="logs-panel">
<div className="logs-panel-graph">
<ExploreGraphPanel
series={series}
width={width}
onHiddenSeriesChanged={this.onToggleLogLevel}
loading={loading}
absoluteRange={absoluteRange}
isStacked={true}
showPanel={false}
showingGraph={true}
showingTable={true}
timeZone={timeZone}
showBars={true}
showLines={false}
onUpdateTimeRange={onChangeTime}
/>
</div>
2018-12-06 01:08:16 -06:00
<div className="logs-panel-options">
<div className="logs-panel-controls">
<Switch label="Time" checked={showTime} onChange={this.onChangeTime} transparent />
<ToggleButtonGroup label="Dedup" transparent={true}>
{Object.keys(LogsDedupStrategy).map((dedupType: string, i) => (
2018-12-11 03:00:29 -06:00
<ToggleButton
key={i}
value={dedupType}
onChange={this.onChangeDedup}
2019-02-07 10:46:33 -06:00
selected={dedupStrategy === dedupType}
// @ts-ignore
2018-12-11 03:00:29 -06:00
tooltip={LogsDedupDescription[dedupType]}
>
{dedupType}
</ToggleButton>
))}
</ToggleButtonGroup>
</div>
</div>
{hasData && meta && (
<div className="logs-panel-meta">
{meta.map(item => (
<div className="logs-panel-meta__item" key={item.label}>
<span className="logs-panel-meta__label">{item.label}:</span>
<span className="logs-panel-meta__value">{renderMetaItem(item.value, item.kind)}</span>
</div>
))}
</div>
)}
2018-12-07 10:23:35 -06:00
<LogRows
logRows={logRows}
deduplicatedRows={dedupedRows}
dedupStrategy={dedupStrategy}
getRowContext={this.props.getRowContext}
highlighterExpressions={highlighterExpressions}
rowLimit={logRows ? logRows.length : undefined}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
showTime={showTime}
timeZone={timeZone}
/>
{!loading && !hasData && !scanning && (
<div className="logs-panel-nodata">
No logs found.
<a className="link" onClick={this.onClickScan}>
Scan for older logs
</a>
</div>
)}
2018-11-27 09:35:37 -06:00
{scanning && (
2018-12-06 01:08:16 -06:00
<div className="logs-panel-nodata">
2018-11-27 09:35:37 -06:00
<span>{scanText}</span>
<a className="link" onClick={this.onClickStopScan}>
Stop scan
</a>
</div>
)}
</div>
);
}
}