@grafana/data#LogsDedupStrategy TypeScript Examples
The following examples show how to use
@grafana/data#LogsDedupStrategy.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: LogsPanel.tsx From grafana-chinese with Apache License 2.0 | 6 votes |
LogsPanel: React.FunctionComponent<LogsPanelProps> = ({
data,
timeZone,
options: { showLabels, showTime, wrapLogMessage, sortOrder },
width,
}) => {
if (!data) {
return (
<div className="panel-empty">
<p>No data found in response</p>
</div>
);
}
const newResults = data ? dataFrameToLogsModel(data.series, data.request.intervalMs, timeZone) : null;
const sortedNewResults = sortLogsResult(newResults, sortOrder);
return (
<CustomScrollbar autoHide>
<LogRows
logRows={sortedNewResults.rows}
dedupStrategy={LogsDedupStrategy.none}
highlighterExpressions={[]}
showLabels={showLabels}
showTime={showTime}
wrapLogMessage={wrapLogMessage}
timeZone={timeZone}
allowDetails={true}
/>
</CustomScrollbar>
);
}
Example #2
Source File: selectors.test.ts From grafana-chinese with Apache License 2.0 | 6 votes |
describe('Deduplication selector', () => {
it('returns the same rows if no deduplication', () => {
const dedups = deduplicatedRowsSelector(state as ExploreItemState);
expect(dedups?.length).toBe(11);
expect(dedups).toBe(state.logsResult.rows);
});
it('should correctly extracts rows and deduplicates them', () => {
const dedups = deduplicatedRowsSelector({
...state,
dedupStrategy: LogsDedupStrategy.numbers,
} as ExploreItemState);
expect(dedups?.length).toBe(2);
expect(dedups).not.toBe(state.logsResult.rows);
});
it('should filter out log levels', () => {
let dedups = deduplicatedRowsSelector({
...state,
hiddenLogLevels: [LogLevel.debug],
} as ExploreItemState);
expect(dedups?.length).toBe(2);
expect(dedups).not.toBe(state.logsResult.rows);
dedups = deduplicatedRowsSelector({
...state,
dedupStrategy: LogsDedupStrategy.numbers,
hiddenLogLevels: [LogLevel.debug],
} as ExploreItemState);
expect(dedups?.length).toBe(2);
expect(dedups).not.toBe(state.logsResult.rows);
});
});
Example #3
Source File: logs_model.ts From grafana-chinese with Apache License 2.0 | 6 votes |
function isDuplicateRow(row: LogRowModel, other: LogRowModel, strategy?: LogsDedupStrategy): boolean {
switch (strategy) {
case LogsDedupStrategy.exact:
// Exact still strips dates
return row.entry.replace(isoDateRegexp, '') === other.entry.replace(isoDateRegexp, '');
case LogsDedupStrategy.numbers:
return row.entry.replace(/\d/g, '') === other.entry.replace(/\d/g, '');
case LogsDedupStrategy.signature:
return row.entry.replace(/\w/g, '') === other.entry.replace(/\w/g, '');
default:
return false;
}
}
Example #4
Source File: logs_model.ts From grafana-chinese with Apache License 2.0 | 6 votes |
export function dedupLogRows(rows: LogRowModel[], strategy?: LogsDedupStrategy): LogRowModel[] {
if (strategy === LogsDedupStrategy.none) {
return rows;
}
return rows.reduce((result: LogRowModel[], row: LogRowModel, index) => {
const rowCopy = { ...row };
const previous = result[result.length - 1];
if (index > 0 && isDuplicateRow(row, previous, strategy)) {
previous.duplicates!++;
} else {
rowCopy.duplicates = 0;
result.push(rowCopy);
}
return result;
}, []);
}
Example #5
Source File: explore.test.ts From grafana-chinese with Apache License 2.0 | 6 votes |
DEFAULT_EXPLORE_STATE: ExploreUrlState = {
datasource: null,
queries: [],
range: DEFAULT_RANGE,
mode: ExploreMode.Metrics,
ui: {
showingGraph: true,
showingTable: true,
showingLogs: true,
dedupStrategy: LogsDedupStrategy.none,
},
originPanelId: undefined,
}
Example #6
Source File: reducers.test.ts From grafana-chinese with Apache License 2.0 | 6 votes |
setup = (urlStateOverrides?: any) => {
const update = makeInitialUpdateState();
const urlStateDefaults: ExploreUrlState = {
datasource: 'some-datasource',
queries: [],
range: {
from: '',
to: '',
},
mode: ExploreMode.Metrics,
ui: {
dedupStrategy: LogsDedupStrategy.none,
showingGraph: false,
showingTable: false,
showingLogs: false,
},
};
const urlState: ExploreUrlState = { ...urlStateDefaults, ...urlStateOverrides };
const serializedUrlState = serializeStateToUrlParam(urlState);
const initialState = ({
split: false,
left: { urlState, update },
right: { urlState, update },
} as unknown) as ExploreState;
return {
initialState,
serializedUrlState,
};
}
Example #7
Source File: Logs.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
onChangeDedup = (dedup: LogsDedupStrategy) => {
const { onDedupStrategyChange } = this.props;
if (this.props.dedupStrategy === dedup) {
return onDedupStrategyChange(LogsDedupStrategy.none);
}
return onDedupStrategyChange(dedup);
};
Example #8
Source File: selectors.test.ts From grafana-chinese with Apache License 2.0 | 5 votes |
state: any = {
logsResult: {
rows: [
{
entry: '2019-03-05T11:00:56Z sntpc sntpc[1]: offset=-0.033938, delay=0.000649',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T11:00:26Z sntpc sntpc[1]: offset=-0.033730, delay=0.000581',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:59:56Z sntpc sntpc[1]: offset=-0.034184, delay=0.001089',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:59:26Z sntpc sntpc[1]: offset=-0.033972, delay=0.000582',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:58:56Z sntpc sntpc[1]: offset=-0.033955, delay=0.000606',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:58:26Z sntpc sntpc[1]: offset=-0.034067, delay=0.000616',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:57:56Z sntpc sntpc[1]: offset=-0.034155, delay=0.001021',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:57:26Z sntpc sntpc[1]: offset=-0.035797, delay=0.000883',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:56:56Z sntpc sntpc[1]: offset=-0.046818, delay=0.000605',
logLevel: LogLevel.debug,
},
{
entry: '2019-03-05T10:56:26Z sntpc sntpc[1]: offset=-0.049200, delay=0.000584',
logLevel: LogLevel.error,
},
{
entry:
'2019-11-01T14:53:02Z lifecycle-server time="2019-11-01T14:53:02.563571300Z" level=debug msg="Calling GET /v1.30/containers/c8defad4025e23f503d91b66610f93b5380622c8e871b31a71e29ff0e67653e7/stats?stream=0"',
logLevel: LogLevel.trace,
},
],
},
hiddenLogLevels: undefined,
dedupStrategy: LogsDedupStrategy.none,
}
Example #9
Source File: actions.ts From grafana-chinese with Apache License 2.0 | 5 votes |
changeDedupStrategy = (exploreId: ExploreId, dedupStrategy: LogsDedupStrategy): ThunkResult<void> => {
return dispatch => {
dispatch(updateExploreUIState(exploreId, { dedupStrategy }));
};
}
Example #10
Source File: actions.test.ts From grafana-chinese with Apache License 2.0 | 5 votes |
setup = (updateOverides?: Partial<ExploreUpdateState>) => {
const exploreId = ExploreId.left;
const containerWidth = 1920;
const eventBridge = {} as Emitter;
const ui = { dedupStrategy: LogsDedupStrategy.none, showingGraph: false, showingLogs: false, showingTable: false };
const timeZone = DefaultTimeZone;
const range = testRange;
const urlState: ExploreUrlState = {
datasource: 'some-datasource',
queries: [],
range: range.raw,
mode: ExploreMode.Metrics,
ui,
};
const updateDefaults = makeInitialUpdateState();
const update = { ...updateDefaults, ...updateOverides };
const initialState = {
user: {
orgId: '1',
timeZone,
},
explore: {
[exploreId]: {
initialized: true,
urlState,
containerWidth,
eventBridge,
update,
datasourceInstance: { name: 'some-datasource' },
queries: [] as DataQuery[],
range,
ui,
refreshInterval: {
label: 'Off',
value: 0,
},
},
},
};
return {
initialState,
exploreId,
range,
ui,
containerWidth,
eventBridge,
};
}
Example #11
Source File: LogsContainer.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
handleDedupStrategyChange = (dedupStrategy: LogsDedupStrategy) => {
this.props.changeDedupStrategy(this.props.exploreId, dedupStrategy);
};
Example #12
Source File: LogsContainer.tsx From grafana-chinese with Apache License 2.0 | 5 votes |
render() {
const {
loading,
logsHighlighterExpressions,
logRows,
logsMeta,
logsSeries,
dedupedRows,
onClickFilterLabel,
onClickFilterOutLabel,
onStartScanning,
onStopScanning,
absoluteRange,
timeZone,
scanning,
range,
width,
isLive,
exploreId,
} = this.props;
return (
<>
<LogsCrossFadeTransition visible={isLive}>
<Collapse label="Logs" loading={false} isOpen>
<LiveTailControls exploreId={exploreId}>
{controls => (
<LiveLogsWithTheme
logRows={logRows}
timeZone={timeZone}
stopLive={controls.stop}
isPaused={this.props.isPaused}
onPause={controls.pause}
onResume={controls.resume}
/>
)}
</LiveTailControls>
</Collapse>
</LogsCrossFadeTransition>
<LogsCrossFadeTransition visible={!isLive}>
<Collapse label="Logs" loading={loading} isOpen>
<Logs
dedupStrategy={this.props.dedupStrategy || LogsDedupStrategy.none}
logRows={logRows}
logsMeta={logsMeta}
logsSeries={logsSeries}
dedupedRows={dedupedRows}
highlighterExpressions={logsHighlighterExpressions}
loading={loading}
onChangeTime={this.onChangeTime}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
onStartScanning={onStartScanning}
onStopScanning={onStopScanning}
onDedupStrategyChange={this.handleDedupStrategyChange}
onToggleLogLevel={this.handleToggleLogLevel}
absoluteRange={absoluteRange}
timeZone={timeZone}
scanning={scanning}
scanRange={range.raw}
width={width}
getRowContext={this.getLogRowContext}
getFieldLinks={getLinksFromLogsField}
/>
</Collapse>
</LogsCrossFadeTransition>
</>
);
}
Example #13
Source File: explore.ts From grafana-chinese with Apache License 2.0 | 5 votes |
DEFAULT_UI_STATE = {
showingTable: true,
showingGraph: true,
showingLogs: true,
dedupStrategy: LogsDedupStrategy.none,
}
Example #14
Source File: LogRows.test.tsx From grafana-chinese with Apache License 2.0 | 4 votes |
describe('LogRows', () => {
it('renders rows', () => {
const rows: LogRowModel[] = [makeLog({ uid: '1' }), makeLog({ uid: '2' }), makeLog({ uid: '3' })];
const wrapper = mount(
<LogRows
logRows={rows}
dedupStrategy={LogsDedupStrategy.none}
highlighterExpressions={[]}
showLabels={false}
showTime={false}
wrapLogMessage={true}
timeZone={'utc'}
/>
);
expect(wrapper.find(LogRow).length).toBe(3);
expect(wrapper.contains('log message 1')).toBeTruthy();
expect(wrapper.contains('log message 2')).toBeTruthy();
expect(wrapper.contains('log message 3')).toBeTruthy();
});
it('renders rows only limited number of rows first', () => {
const rows: LogRowModel[] = [makeLog({ uid: '1' }), makeLog({ uid: '2' }), makeLog({ uid: '3' })];
jest.useFakeTimers();
const wrapper = mount(
<LogRows
logRows={rows}
dedupStrategy={LogsDedupStrategy.none}
highlighterExpressions={[]}
showLabels={false}
showTime={false}
wrapLogMessage={true}
timeZone={'utc'}
previewLimit={1}
/>
);
expect(wrapper.find(LogRow).length).toBe(1);
expect(wrapper.contains('log message 1')).toBeTruthy();
jest.runAllTimers();
wrapper.update();
expect(wrapper.find(LogRow).length).toBe(3);
expect(wrapper.contains('log message 1')).toBeTruthy();
expect(wrapper.contains('log message 2')).toBeTruthy();
expect(wrapper.contains('log message 3')).toBeTruthy();
jest.useRealTimers();
});
it('renders deduped rows if supplied', () => {
const rows: LogRowModel[] = [makeLog({ uid: '1' }), makeLog({ uid: '2' }), makeLog({ uid: '3' })];
const dedupedRows: LogRowModel[] = [makeLog({ uid: '4' }), makeLog({ uid: '5' })];
const wrapper = mount(
<LogRows
logRows={rows}
deduplicatedRows={dedupedRows}
dedupStrategy={LogsDedupStrategy.none}
highlighterExpressions={[]}
showLabels={false}
showTime={false}
wrapLogMessage={true}
timeZone={'utc'}
/>
);
expect(wrapper.find(LogRow).length).toBe(2);
expect(wrapper.contains('log message 4')).toBeTruthy();
expect(wrapper.contains('log message 5')).toBeTruthy();
});
it('renders with default preview limit', () => {
// PREVIEW_LIMIT * 2 is there because otherwise we just render all rows
const rows: LogRowModel[] = range(PREVIEW_LIMIT * 2 + 1).map(num => makeLog({ uid: num.toString() }));
const wrapper = mount(
<LogRows
logRows={rows}
dedupStrategy={LogsDedupStrategy.none}
highlighterExpressions={[]}
showLabels={false}
showTime={false}
wrapLogMessage={true}
timeZone={'utc'}
/>
);
expect(wrapper.find(LogRow).length).toBe(100);
});
});
Example #15
Source File: Logs.tsx From grafana-chinese with Apache License 2.0 | 4 votes |
render() {
const {
logRows,
logsMeta,
logsSeries,
highlighterExpressions,
loading = false,
onClickFilterLabel,
onClickFilterOutLabel,
timeZone,
scanning,
scanRange,
width,
dedupedRows,
absoluteRange,
onChangeTime,
getFieldLinks,
} = this.props;
if (!logRows) {
return null;
}
const { showLabels, showTime, wrapLogMessage } = this.state;
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] : [];
if (dedupStrategy !== LogsDedupStrategy.none) {
meta.push({
label: 'Dedup count',
value: dedupCount,
kind: LogsMetaKind.Number,
});
}
const scanText = scanRange ? `Scanning ${rangeUtil.describeTimeRange(scanRange)}` : 'Scanning...';
const series = logsSeries ? logsSeries : [];
return (
<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>
<div className="logs-panel-options">
<div className="logs-panel-controls">
<Switch label="Time" checked={showTime} onChange={this.onChangeTime} transparent />
<Switch label="Unique labels" checked={showLabels} onChange={this.onChangeLabels} transparent />
<Switch label="Wrap lines" checked={wrapLogMessage} onChange={this.onChangewrapLogMessage} transparent />
<ToggleButtonGroup label="Dedup" transparent={true}>
{Object.keys(LogsDedupStrategy).map((dedupType: string, i) => (
<ToggleButton
key={i}
value={dedupType}
onChange={this.onChangeDedup}
selected={dedupStrategy === dedupType}
// @ts-ignore
tooltip={LogsDedupDescription[dedupType]}
>
{dedupType}
</ToggleButton>
))}
</ToggleButtonGroup>
</div>
</div>
{hasData && meta && (
<MetaInfoText
metaItems={meta.map(item => {
return {
label: item.label,
value: renderMetaItem(item.value, item.kind),
};
})}
/>
)}
<LogRows
logRows={logRows}
deduplicatedRows={dedupedRows}
dedupStrategy={dedupStrategy}
getRowContext={this.props.getRowContext}
highlighterExpressions={highlighterExpressions}
rowLimit={logRows ? logRows.length : undefined}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
showLabels={showLabels}
showTime={showTime}
wrapLogMessage={wrapLogMessage}
timeZone={timeZone}
getFieldLinks={getFieldLinks}
/>
{!loading && !hasData && !scanning && (
<div className="logs-panel-nodata">
No logs found.
<a className="link" onClick={this.onClickScan}>
Scan for older logs
</a>
</div>
)}
{scanning && (
<div className="logs-panel-nodata">
<span>{scanText}</span>
<a className="link" onClick={this.onClickStopScan}>
Stop scan
</a>
</div>
)}
</div>
);
}
Example #16
Source File: logs_model.test.ts From grafana-chinese with Apache License 2.0 | 4 votes |
describe('dedupLogRows()', () => {
test('should return rows as is when dedup is set to none', () => {
const rows: LogRowModel[] = [
{
entry: 'WARN test 1.23 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
] as any;
expect(dedupLogRows(rows, LogsDedupStrategy.none)).toMatchObject(rows);
});
test('should dedup on exact matches', () => {
const rows: LogRowModel[] = [
{
entry: 'WARN test 1.23 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
{
entry: 'INFO test 2.44 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
] as any;
expect(dedupLogRows(rows, LogsDedupStrategy.exact)).toEqual([
{
duplicates: 1,
entry: 'WARN test 1.23 on [xxx]',
},
{
duplicates: 0,
entry: 'INFO test 2.44 on [xxx]',
},
{
duplicates: 0,
entry: 'WARN test 1.23 on [xxx]',
},
]);
});
test('should dedup on number matches', () => {
const rows: LogRowModel[] = [
{
entry: 'WARN test 1.2323423 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
{
entry: 'INFO test 2.44 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
] as any;
expect(dedupLogRows(rows, LogsDedupStrategy.numbers)).toEqual([
{
duplicates: 1,
entry: 'WARN test 1.2323423 on [xxx]',
},
{
duplicates: 0,
entry: 'INFO test 2.44 on [xxx]',
},
{
duplicates: 0,
entry: 'WARN test 1.23 on [xxx]',
},
]);
});
test('should dedup on signature matches', () => {
const rows: LogRowModel[] = [
{
entry: 'WARN test 1.2323423 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
{
entry: 'INFO test 2.44 on [xxx]',
},
{
entry: 'WARN test 1.23 on [xxx]',
},
] as any;
expect(dedupLogRows(rows, LogsDedupStrategy.signature)).toEqual([
{
duplicates: 3,
entry: 'WARN test 1.2323423 on [xxx]',
},
]);
});
test('should return to non-deduped state on same log result', () => {
const rows: LogRowModel[] = [
{
entry: 'INFO 123',
},
{
entry: 'WARN 123',
},
{
entry: 'WARN 123',
},
] as any;
expect(dedupLogRows(rows, LogsDedupStrategy.exact)).toEqual([
{
duplicates: 0,
entry: 'INFO 123',
},
{
duplicates: 1,
entry: 'WARN 123',
},
]);
expect(dedupLogRows(rows, LogsDedupStrategy.none)).toEqual(rows);
});
});
Example #17
Source File: LogRows.tsx From grafana-chinese with Apache License 2.0 | 4 votes |
render() {
const {
dedupStrategy,
showLabels,
showTime,
wrapLogMessage,
logRows,
deduplicatedRows,
highlighterExpressions,
timeZone,
onClickFilterLabel,
onClickFilterOutLabel,
rowLimit,
theme,
allowDetails,
previewLimit,
getFieldLinks,
} = this.props;
const { renderAll } = this.state;
const { logsRowsTable, logsRowsHorizontalScroll } = getLogRowStyles(theme);
const dedupedRows = deduplicatedRows ? deduplicatedRows : logRows;
const hasData = logRows && logRows.length > 0;
const dedupCount = dedupedRows
? dedupedRows.reduce((sum, row) => (row.duplicates ? sum + row.duplicates : sum), 0)
: 0;
const showDuplicates = dedupStrategy !== LogsDedupStrategy.none && dedupCount > 0;
const horizontalScrollWindow = wrapLogMessage ? '' : logsRowsHorizontalScroll;
// Staged rendering
const processedRows = dedupedRows ? dedupedRows : [];
const firstRows = processedRows.slice(0, previewLimit!);
const rowCount = Math.min(processedRows.length, rowLimit!);
const lastRows = processedRows.slice(previewLimit!, rowCount);
// React profiler becomes unusable if we pass all rows to all rows and their labels, using getter instead
const getRows = this.makeGetRows(processedRows);
const getRowContext = this.props.getRowContext ? this.props.getRowContext : () => Promise.resolve([]);
return (
<div className={horizontalScrollWindow}>
<table className={logsRowsTable}>
<tbody>
{hasData &&
firstRows.map((row, index) => (
<LogRow
key={row.uid}
getRows={getRows}
getRowContext={getRowContext}
highlighterExpressions={highlighterExpressions}
row={row}
showDuplicates={showDuplicates}
showLabels={showLabels}
showTime={showTime}
wrapLogMessage={wrapLogMessage}
timeZone={timeZone}
allowDetails={allowDetails}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
getFieldLinks={getFieldLinks}
/>
))}
{hasData &&
renderAll &&
lastRows.map((row, index) => (
<LogRow
key={row.uid}
getRows={getRows}
getRowContext={getRowContext}
row={row}
showDuplicates={showDuplicates}
showLabels={showLabels}
showTime={showTime}
wrapLogMessage={wrapLogMessage}
timeZone={timeZone}
allowDetails={allowDetails}
onClickFilterLabel={onClickFilterLabel}
onClickFilterOutLabel={onClickFilterOutLabel}
getFieldLinks={getFieldLinks}
/>
))}
{hasData && !renderAll && (
<tr>
<td colSpan={5}>Rendering {rowCount - previewLimit!} rows...</td>
</tr>
)}
</tbody>
</table>
</div>
);
}