diff --git a/public/app/features/logs/components/LogRow.tsx b/public/app/features/logs/components/LogRow.tsx index 390cbd04704..f4b8697ae56 100644 --- a/public/app/features/logs/components/LogRow.tsx +++ b/public/app/features/logs/components/LogRow.tsx @@ -1,5 +1,6 @@ import { cx } from '@emotion/css'; import { debounce } from 'lodash'; +import memoizeOne from 'memoize-one'; import React, { PureComponent } from 'react'; import { Field, LinkModel, LogRowModel, LogsSortOrder, dateTimeFormat, CoreApp, DataFrame } from '@grafana/data'; @@ -157,6 +158,12 @@ class UnThemedLogRow extends PureComponent { } }; + escapeRow = memoizeOne((row: LogRowModel, forceEscape: boolean | undefined) => { + return row.hasUnescapedContent && forceEscape + ? { ...row, entry: escapeUnescapedString(row.entry), raw: escapeUnescapedString(row.raw) } + : row; + }); + render() { const { getRows, @@ -191,10 +198,7 @@ class UnThemedLogRow extends PureComponent { [styles.highlightBackground]: permalinked && !this.state.showDetails, }); - const processedRow = - row.hasUnescapedContent && forceEscape - ? { ...row, entry: escapeUnescapedString(row.entry), raw: escapeUnescapedString(row.raw) } - : row; + const processedRow = this.escapeRow(row, forceEscape); return ( <> diff --git a/public/app/features/logs/utils.test.ts b/public/app/features/logs/utils.test.ts index ed58cfa8c04..f73a0d43f6e 100644 --- a/public/app/features/logs/utils.test.ts +++ b/public/app/features/logs/utils.test.ts @@ -14,6 +14,7 @@ import { calculateLogsLabelStats, calculateStats, checkLogsError, + escapeUnescapedString, getLogLevel, getLogLevelFromKey, getLogsVolumeMaximumRange, @@ -469,3 +470,12 @@ describe('getLogsVolumeDimensions', () => { expect(maximumRange).toEqual({ from: 5, to: 25 }); }); }); + +describe('escapeUnescapedString', () => { + it('does not modify strings without unescaped characters', () => { + expect(escapeUnescapedString('a simple string')).toBe('a simple string'); + }); + it('escapes unescaped strings', () => { + expect(escapeUnescapedString(`\\r\\n|\\n|\\t|\\r`)).toBe(`\n|\n|\t|\n`); + }); +});