diff --git a/public/app/features/logs/components/panel/LogLine.tsx b/public/app/features/logs/components/panel/LogLine.tsx
index 9999b946a0e..d6eb485ff42 100644
--- a/public/app/features/logs/components/panel/LogLine.tsx
+++ b/public/app/features/logs/components/panel/LogLine.tsx
@@ -236,7 +236,7 @@ const DisplayedFields = ({
const { matchingUids, search } = useLogListSearchContext();
const searchWords = useMemo(() => {
- const searchWords = log.searchWords && log.searchWords[0] ? log.searchWords : [];
+ const searchWords = log.searchWords && log.searchWords[0] ? log.searchWords.slice() : [];
if (search && matchingUids?.includes(log.uid)) {
searchWords.push(search);
}
@@ -271,7 +271,7 @@ const LogLineBody = ({ log, styles }: { log: LogListModel; styles: LogLineStyles
const { matchingUids, search } = useLogListSearchContext();
const highlight = useMemo(() => {
- const searchWords = log.searchWords && log.searchWords[0] ? log.searchWords : [];
+ const searchWords = log.searchWords && log.searchWords[0] ? log.searchWords.slice() : [];
if (search && matchingUids?.includes(log.uid)) {
searchWords.push(search);
}
diff --git a/public/app/features/logs/components/panel/LogList.test.tsx b/public/app/features/logs/components/panel/LogList.test.tsx
index dbe8dfe78a2..e0cf493bd67 100644
--- a/public/app/features/logs/components/panel/LogList.test.tsx
+++ b/public/app/features/logs/components/panel/LogList.test.tsx
@@ -259,5 +259,33 @@ describe('LogList', () => {
expect(screen.queryByPlaceholderText('Search in logs')).not.toBeInTheDocument();
});
+
+ test('Does not conflict with search words', async () => {
+ logs = [
+ createLogRow({ uid: '1' }),
+ createLogRow({ uid: '2', entry: '(?i)some text', searchWords: ['some text'] }),
+ ];
+
+ render();
+
+ expect(screen.queryByPlaceholderText('Search in logs')).not.toBeInTheDocument();
+ expect(screen.getByText('log message 1')).toBeInTheDocument();
+ expect(screen.getByText('some text')).toBeInTheDocument();
+
+ await userEvent.keyboard('{Control>}{f}{/Control}');
+
+ expect(screen.getByPlaceholderText('Search in logs')).toBeInTheDocument();
+
+ await userEvent.type(screen.getByPlaceholderText('Search in logs'), '(?i)');
+
+ expect(screen.getByText('log message 1')).toBeInTheDocument();
+ expect(screen.getByText('(?i)')).toBeInTheDocument();
+ expect(screen.getByText('some text')).toBeInTheDocument();
+
+ await userEvent.clear(screen.getByPlaceholderText('Search in logs'));
+
+ expect(screen.getByText('log message 1')).toBeInTheDocument();
+ expect(screen.getByText('some text')).toBeInTheDocument();
+ });
});
});
diff --git a/public/app/features/logs/components/panel/LogList.tsx b/public/app/features/logs/components/panel/LogList.tsx
index 5f4cb59b70d..f0f056a1c7b 100644
--- a/public/app/features/logs/components/panel/LogList.tsx
+++ b/public/app/features/logs/components/panel/LogList.tsx
@@ -151,6 +151,7 @@ export const LogList = ({
timeZone,
wrapLogMessage,
}: Props) => {
+ const hasUnescapedContent = useMemo(() => logs.some((log) => log.hasUnescapedContent), [logs]);
return (
{
- const textMatches = [...highlightWords];
+ /**
+ * See:
+ * - https://github.com/grafana/grafana/blob/96f1582c36f94cf4ac7621b7af86bc9e2ad626fb/public/app/features/logs/components/LogRowMessage.tsx#L67
+ * - https://github.com/grafana/grafana/blob/96f1582c36f94cf4ac7621b7af86bc9e2ad626fb/packages/grafana-data/src/text/text.ts#L12
+ */
+ const expressions = highlightWords.map((word) => {
+ const { cleaned, flags } = parseFlags(cleanNeedle(word));
+ return new RegExp(`(?:${cleaned})`, flags);
+ });
if (search) {
- textMatches.push(escapeRegex(search));
+ expressions.push(new RegExp(escapeRegex(search), 'gi'));
}
- if (!textMatches.length) {
+ if (!expressions.length) {
return {};
}
return {
- 'log-search-match': new RegExp(textMatches.join('|'), 'g'),
+ 'log-search-match': expressions,
};
};
+
+const cleanNeedle = (needle: string): string => {
+ return needle.replace(/[[{(][\w,.\/:;<=>?:*+]+$/, '');
+};
diff --git a/public/app/features/logs/components/panel/processing.ts b/public/app/features/logs/components/panel/processing.ts
index 5c5b95abbc3..85520b17d4b 100644
--- a/public/app/features/logs/components/panel/processing.ts
+++ b/public/app/features/logs/components/panel/processing.ts
@@ -88,9 +88,7 @@ export class LogListModel implements LogRowModel {
get body(): string {
if (this._body === undefined) {
- let body = this.collapsed ? this.raw.substring(0, getTruncationLength(null)) : this.raw;
- // Turn it into a single-line log entry for the list
- this._body = body.replace(/(\r\n|\n|\r)/g, '');
+ this._body = this.collapsed ? this.raw.substring(0, getTruncationLength(null)) : this.raw;
}
return this._body;
}
diff --git a/public/app/plugins/panel/logs/module.tsx b/public/app/plugins/panel/logs/module.tsx
index da674495d77..dd034a995aa 100644
--- a/public/app/plugins/panel/logs/module.tsx
+++ b/public/app/plugins/panel/logs/module.tsx
@@ -87,7 +87,6 @@ export const plugin = new PanelPlugin(LogsPanel)
},
],
},
- defaultValue: 'default',
});
}