Commit 2c724e0a by Valentin Agachi Committed by GitHub

Explore: support ANSI colors in live logs (#28895)

Closes #28893

Co-authored-by: Ivana <ivana.huckova@gmail.com>
parent e834ad00
...@@ -96,6 +96,7 @@ export { GraphSeriesToggler, GraphSeriesTogglerAPI } from './Graph/GraphSeriesTo ...@@ -96,6 +96,7 @@ export { GraphSeriesToggler, GraphSeriesTogglerAPI } from './Graph/GraphSeriesTo
export { Collapse, ControlledCollapse } from './Collapse/Collapse'; export { Collapse, ControlledCollapse } from './Collapse/Collapse';
export { CollapsableSection } from './Collapse/CollapsableSection'; export { CollapsableSection } from './Collapse/CollapsableSection';
export { LogLabels } from './Logs/LogLabels'; export { LogLabels } from './Logs/LogLabels';
export { LogMessageAnsi } from './Logs/LogMessageAnsi';
export { LogRows } from './Logs/LogRows'; export { LogRows } from './Logs/LogRows';
export { getLogRowStyles } from './Logs/getLogRowStyles'; export { getLogRowStyles } from './Logs/getLogRowStyles';
export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup'; export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup';
......
...@@ -55,10 +55,45 @@ describe('LiveLogs', () => { ...@@ -55,10 +55,45 @@ describe('LiveLogs', () => {
expect(wrapper.contains('log message 5')).toBeTruthy(); expect(wrapper.contains('log message 5')).toBeTruthy();
expect(wrapper.contains('log message 6')).toBeTruthy(); expect(wrapper.contains('log message 6')).toBeTruthy();
}); });
it('renders ansi logs', () => {
const rows: LogRowModel[] = [
makeLog({ uid: '1' }),
makeLog({ hasAnsi: true, raw: 'log message \u001B[31m2\u001B[0m', uid: '2' }),
makeLog({ hasAnsi: true, raw: 'log message \u001B[31m3\u001B[0m', uid: '3' }),
];
const wrapper = mount(
<LiveLogsWithTheme
logRows={rows}
timeZone={'utc'}
stopLive={() => {}}
onPause={() => {}}
onResume={() => {}}
isPaused={true}
/>
);
expect(wrapper.contains('log message 1')).toBeTruthy();
expect(wrapper.contains('log message 2')).not.toBeTruthy();
expect(wrapper.contains('log message 3')).not.toBeTruthy();
expect(wrapper.find('LogMessageAnsi')).toHaveLength(2);
expect(
wrapper
.find('LogMessageAnsi')
.first()
.prop('value')
).toBe('log message \u001B[31m2\u001B[0m');
expect(
wrapper
.find('LogMessageAnsi')
.last()
.prop('value')
).toBe('log message \u001B[31m3\u001B[0m');
});
}); });
const makeLog = (overides: Partial<LogRowModel>): LogRowModel => { const makeLog = (overrides: Partial<LogRowModel>): LogRowModel => {
const uid = overides.uid || '1'; const uid = overrides.uid || '1';
const entry = `log message ${uid}`; const entry = `log message ${uid}`;
return { return {
uid, uid,
...@@ -75,6 +110,6 @@ const makeLog = (overides: Partial<LogRowModel>): LogRowModel => { ...@@ -75,6 +110,6 @@ const makeLog = (overides: Partial<LogRowModel>): LogRowModel => {
timeEpochNs: '1000000', timeEpochNs: '1000000',
timeLocal: '', timeLocal: '',
timeUtc: '', timeUtc: '',
...overides, ...overrides,
}; };
}; };
...@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; ...@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import { css, cx } from 'emotion'; import { css, cx } from 'emotion';
import tinycolor from 'tinycolor2'; import tinycolor from 'tinycolor2';
import { Themeable, withTheme, getLogRowStyles, Icon } from '@grafana/ui'; import { LogMessageAnsi, Themeable, withTheme, getLogRowStyles, Icon } from '@grafana/ui';
import { GrafanaTheme, LogRowModel, TimeZone, dateTimeFormat } from '@grafana/data'; import { GrafanaTheme, LogRowModel, TimeZone, dateTimeFormat } from '@grafana/data';
import { ElapsedTime } from './ElapsedTime'; import { ElapsedTime } from './ElapsedTime';
...@@ -151,7 +151,7 @@ class LiveLogs extends PureComponent<Props, State> { ...@@ -151,7 +151,7 @@ class LiveLogs extends PureComponent<Props, State> {
return ( return (
<tr className={cx(logsRow, styles.logsRowFade)} key={row.uid}> <tr className={cx(logsRow, styles.logsRowFade)} key={row.uid}>
<td className={cx(logsRowLocalTime)}>{dateTimeFormat(row.timeEpochMs, { timeZone })}</td> <td className={cx(logsRowLocalTime)}>{dateTimeFormat(row.timeEpochMs, { timeZone })}</td>
<td className={cx(logsRowMessage)}>{row.entry}</td> <td className={cx(logsRowMessage)}>{row.hasAnsi ? <LogMessageAnsi value={row.raw} /> : row.entry}</td>
</tr> </tr>
); );
})} })}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment