diff --git a/frontend/src/container/LogDetailedView/TableView.tsx b/frontend/src/container/LogDetailedView/TableView.tsx index 9237136349..929e827dc3 100644 --- a/frontend/src/container/LogDetailedView/TableView.tsx +++ b/frontend/src/container/LogDetailedView/TableView.tsx @@ -22,6 +22,7 @@ import { ILog } from 'types/api/logs/log'; import ActionItem, { ActionItemProps } from './ActionItem'; import FieldRenderer from './FieldRenderer'; import { + filterKeyForField, flattenObject, jsonToDataNodes, recursiveParseJSON, @@ -98,11 +99,12 @@ function TableView({ title: 'Action', width: 11, render: (fieldData: Record): JSX.Element | null => { - const fieldKey = fieldData.field.split('.').slice(-1); - if (!RESTRICTED_FIELDS.includes(fieldKey[0])) { + const fieldFilterKey = filterKeyForField(fieldData.field); + + if (!RESTRICTED_FIELDS.includes(fieldFilterKey)) { return ( @@ -119,7 +121,6 @@ function TableView({ align: 'left', ellipsis: true, render: (field: string, record): JSX.Element => { - const fieldKey = field.split('.').slice(-1); const renderedField = ; if (record.field === 'trace_id') { @@ -148,10 +149,11 @@ function TableView({ ); } - if (!RESTRICTED_FIELDS.includes(fieldKey[0])) { + const fieldFilterKey = filterKeyForField(field); + if (!RESTRICTED_FIELDS.includes(fieldFilterKey)) { return ( diff --git a/frontend/src/container/LogDetailedView/utils.tsx b/frontend/src/container/LogDetailedView/utils.tsx index f31534ace8..cb1b1a2e53 100644 --- a/frontend/src/container/LogDetailedView/utils.tsx +++ b/frontend/src/container/LogDetailedView/utils.tsx @@ -132,6 +132,16 @@ export const generateFieldKeyForArray = ( export const removeObjectFromString = (str: string): string => str.replace(/\[object Object\]./g, ''); +// Split `str` on the first occurrence of `delimiter` +// For example, will return `['a', 'b.c']` when splitting `'a.b.c'` at dots +const splitOnce = (str: string, delimiter: string): string[] => { + const parts = str.split(delimiter); + if (parts.length < 2) { + return parts; + } + return [parts[0], parts.slice(1).join(delimiter)]; +}; + export const getFieldAttributes = (field: string): IFieldAttributes => { let dataType; let newField; @@ -140,18 +150,30 @@ export const getFieldAttributes = (field: string): IFieldAttributes => { if (field.startsWith('attributes_')) { logType = MetricsType.Tag; const stringWithoutPrefix = field.slice('attributes_'.length); - const parts = stringWithoutPrefix.split('.'); + const parts = splitOnce(stringWithoutPrefix, '.'); [dataType, newField] = parts; } else if (field.startsWith('resources_')) { logType = MetricsType.Resource; const stringWithoutPrefix = field.slice('resources_'.length); - const parts = stringWithoutPrefix.split('.'); + const parts = splitOnce(stringWithoutPrefix, '.'); [dataType, newField] = parts; } return { dataType, newField, logType }; }; +// Returns key to be used when filtering for `field` via +// the query builder. This is useful for powering filtering +// by field values from log details view. +export const filterKeyForField = (field: string): string => { + // Must work for all 3 of the following types of cases + // timestamp -> timestamp + // attributes_string.log.file -> log.file + // resources_string.k8s.pod.name -> k8s.pod.name + const fieldAttribs = getFieldAttributes(field); + return fieldAttribs?.newField || field; +}; + export const aggregateAttributesResourcesToString = (logData: ILog): string => { const outputJson: ILogAggregateAttributesResources = { body: logData.body,