mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
Logs: Add possibility to download logs in JSON format (#61394)
* add implementation of `logRowsToReadableJson` * add test for logRowsToReadableJson * add json, txt download buttons * changed downloadmenu to `Menu` * set closed state when menu closes * removed unused css * removed unused imports * remove isOpen state * remove unused import * add tests * remove untouched file
This commit is contained in:
@@ -27,7 +27,7 @@ export const getAllFields = memoizeOne(
|
||||
/**
|
||||
* creates fields from the dataframe-fields, adding data-links, when field.config.links exists
|
||||
*/
|
||||
const getDataframeFields = memoizeOne(
|
||||
export const getDataframeFields = memoizeOne(
|
||||
(
|
||||
row: LogRowModel,
|
||||
getFieldLinks?: (field: Field, rowIndex: number, dataFrame: DataFrame) => Array<LinkModel<Field>>
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getLogLevelFromKey,
|
||||
sortLogsResult,
|
||||
checkLogsError,
|
||||
logRowsToReadableJson,
|
||||
} from './utils';
|
||||
|
||||
describe('getLoglevel()', () => {
|
||||
@@ -205,3 +206,58 @@ describe('checkLogsError()', () => {
|
||||
expect(checkLogsError(log)).toStrictEqual({ hasError: true, errorMessage: 'Error Message' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('logRowsToReadableJson', () => {
|
||||
const testRow: LogRowModel = {
|
||||
rowIndex: 1,
|
||||
entryFieldIndex: 0,
|
||||
dataFrame: new MutableDataFrame(),
|
||||
entry: 'test entry',
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {
|
||||
foo: 'bar',
|
||||
},
|
||||
logLevel: LogLevel.info,
|
||||
raw: '',
|
||||
timeEpochMs: 10,
|
||||
timeEpochNs: '123456789',
|
||||
timeFromNow: '',
|
||||
timeLocal: '',
|
||||
timeUtc: '',
|
||||
uid: '2',
|
||||
};
|
||||
const testDf = new MutableDataFrame();
|
||||
testDf.addField({ name: 'foo2', values: ['bar2'] });
|
||||
const testRow2: LogRowModel = {
|
||||
rowIndex: 0,
|
||||
entryFieldIndex: -1,
|
||||
dataFrame: testDf,
|
||||
entry: 'test entry',
|
||||
hasAnsi: false,
|
||||
hasUnescapedContent: false,
|
||||
labels: {
|
||||
foo: 'bar',
|
||||
},
|
||||
logLevel: LogLevel.info,
|
||||
raw: '',
|
||||
timeEpochMs: 10,
|
||||
timeEpochNs: '123456789',
|
||||
timeFromNow: '',
|
||||
timeLocal: '',
|
||||
timeUtc: '',
|
||||
uid: '2',
|
||||
};
|
||||
|
||||
it('should format a single row', () => {
|
||||
const result = logRowsToReadableJson([testRow]);
|
||||
|
||||
expect(result).toEqual([{ line: 'test entry', timestamp: '123456789', fields: { foo: 'bar' } }]);
|
||||
});
|
||||
|
||||
it('should format a df field row', () => {
|
||||
const result = logRowsToReadableJson([testRow2]);
|
||||
|
||||
expect(result).toEqual([{ line: 'test entry', timestamp: '123456789', fields: { foo: 'bar', foo2: 'bar2' } }]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,8 @@ import { countBy, chain } from 'lodash';
|
||||
|
||||
import { LogLevel, LogRowModel, LogLabelStatsModel, LogsModel, LogsSortOrder } from '@grafana/data';
|
||||
|
||||
import { getDataframeFields } from './components/logParser';
|
||||
|
||||
/**
|
||||
* Returns the log level of a log line.
|
||||
* Parse the line for level words. If no level is found, it returns `LogLevel.unknown`.
|
||||
@@ -129,3 +131,21 @@ export const checkLogsError = (logRow: LogRowModel): { hasError: boolean; errorM
|
||||
|
||||
export const escapeUnescapedString = (string: string) =>
|
||||
string.replace(/\\r\\n|\\n|\\t|\\r/g, (match: string) => (match.slice(1) === 't' ? '\t' : '\n'));
|
||||
|
||||
export function logRowsToReadableJson(logs: LogRowModel[]) {
|
||||
return logs.map((log) => {
|
||||
const fields = getDataframeFields(log).reduce<Record<string, string>>((acc, field) => {
|
||||
acc[field.key] = field.value;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
line: log.entry,
|
||||
timestamp: log.timeEpochNs,
|
||||
fields: {
|
||||
...fields,
|
||||
...log.labels,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user