diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 526babb9840..e51c249038c 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -96,6 +96,7 @@ export { GraphSeriesToggler, GraphSeriesTogglerAPI } from './Graph/GraphSeriesTo export { Collapse, ControlledCollapse } from './Collapse/Collapse'; export { CollapsableSection } from './Collapse/CollapsableSection'; export { LogLabels } from './Logs/LogLabels'; +export { LogMessageAnsi } from './Logs/LogMessageAnsi'; export { LogRows } from './Logs/LogRows'; export { getLogRowStyles } from './Logs/getLogRowStyles'; export { ToggleButtonGroup, ToggleButton } from './ToggleButtonGroup/ToggleButtonGroup'; diff --git a/public/app/features/explore/LiveLogs.test.tsx b/public/app/features/explore/LiveLogs.test.tsx index f9b50ddb8fe..3d07cd20748 100644 --- a/public/app/features/explore/LiveLogs.test.tsx +++ b/public/app/features/explore/LiveLogs.test.tsx @@ -55,10 +55,45 @@ describe('LiveLogs', () => { expect(wrapper.contains('log message 5')).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( + {}} + 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 => { - const uid = overides.uid || '1'; +const makeLog = (overrides: Partial): LogRowModel => { + const uid = overrides.uid || '1'; const entry = `log message ${uid}`; return { uid, @@ -75,6 +110,6 @@ const makeLog = (overides: Partial): LogRowModel => { timeEpochNs: '1000000', timeLocal: '', timeUtc: '', - ...overides, + ...overrides, }; }; diff --git a/public/app/features/explore/LiveLogs.tsx b/public/app/features/explore/LiveLogs.tsx index 73405d6cc6e..b8122c43577 100644 --- a/public/app/features/explore/LiveLogs.tsx +++ b/public/app/features/explore/LiveLogs.tsx @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import { css, cx } from 'emotion'; 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 { ElapsedTime } from './ElapsedTime'; @@ -151,7 +151,7 @@ class LiveLogs extends PureComponent { return ( {dateTimeFormat(row.timeEpochMs, { timeZone })} - {row.entry} + {row.hasAnsi ? : row.entry} ); })}