mirror of
https://github.com/grafana/grafana.git
synced 2026-02-03 20:49:50 -05:00
Log Line Context: Add support for default displayed fields (#117162)
* LogLineContext: Integrate default displayed fields with reset fields button * Remove unused import * Lint
This commit is contained in:
parent
a6f4c5da5d
commit
3ba197e0b9
2 changed files with 135 additions and 2 deletions
|
|
@ -7,8 +7,11 @@ import {
|
|||
LogsSortOrder,
|
||||
SplitOpenOptions,
|
||||
} from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
import { dataFrameToLogsModel } from '../../logsModel';
|
||||
import { LOG_LINE_BODY_FIELD_NAME } from '../LogDetailsBody';
|
||||
import { getDisplayedFieldsForLogs, identifyOTelLanguages, OTEL_LOG_LINE_ATTRIBUTES_FIELD_NAME } from '../otel/formats';
|
||||
|
||||
import { DEFAULT_TIME_WINDOW, LogLineContext, PAGE_SIZE } from './LogLineContext';
|
||||
|
||||
|
|
@ -19,6 +22,7 @@ jest.mock('@grafana/assistant', () => ({
|
|||
openAssistant: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
jest.mock('../otel/formats');
|
||||
|
||||
const dfBefore = createDataFrame({
|
||||
fields: [
|
||||
|
|
@ -79,6 +83,9 @@ jest.mock('app/features/explore/state/main', () => ({
|
|||
},
|
||||
}));
|
||||
|
||||
jest.mocked(getDisplayedFieldsForLogs).mockReturnValue([]);
|
||||
jest.mocked(identifyOTelLanguages).mockReturnValue([]);
|
||||
|
||||
const logs = dataFrameToLogsModel([dfNow]);
|
||||
const row = logs.rows[0];
|
||||
|
||||
|
|
@ -606,4 +613,120 @@ describe('LogLineContext', () => {
|
|||
).not.toBeInTheDocument();
|
||||
expect(screen.getAllByText('foo123')).toHaveLength(3);
|
||||
});
|
||||
|
||||
test('Should hide "Show original logs" button when there are no displayed fields', async () => {
|
||||
render(
|
||||
<LogLineContext
|
||||
log={row}
|
||||
open={true}
|
||||
onClose={() => {}}
|
||||
getRowContext={getRowContext}
|
||||
timeZone={timeZone}
|
||||
sortOrder={LogsSortOrder.Descending}
|
||||
displayedFields={[]}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Log context')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', {
|
||||
name: /show original logs/i,
|
||||
})
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should show "Show original logs" button when displayed fields are provided', async () => {
|
||||
const displayedFields = ['level', 'label'];
|
||||
|
||||
render(
|
||||
<LogLineContext
|
||||
log={row}
|
||||
open={true}
|
||||
onClose={() => {}}
|
||||
getRowContext={getRowContext}
|
||||
timeZone={timeZone}
|
||||
sortOrder={LogsSortOrder.Descending}
|
||||
displayedFields={displayedFields}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Log context')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Button should be visible when displayedFields are provided and differ from defaultDisplayedFields
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: /show original logs/i,
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('Default displayed fields', () => {
|
||||
const originalFlagValue = config.featureToggles.otelLogsFormatting;
|
||||
beforeEach(() => {
|
||||
config.featureToggles.otelLogsFormatting = true;
|
||||
jest
|
||||
.mocked(getDisplayedFieldsForLogs)
|
||||
.mockReturnValue([LOG_LINE_BODY_FIELD_NAME, OTEL_LOG_LINE_ATTRIBUTES_FIELD_NAME]);
|
||||
});
|
||||
afterAll(() => {
|
||||
config.featureToggles.otelLogsFormatting = originalFlagValue;
|
||||
});
|
||||
|
||||
test('Should show "Show original logs" button when displayed fields are different than the default fields', async () => {
|
||||
const displayedFields = ['level', 'label'];
|
||||
|
||||
render(
|
||||
<LogLineContext
|
||||
log={row}
|
||||
open={true}
|
||||
onClose={() => {}}
|
||||
getRowContext={getRowContext}
|
||||
timeZone={timeZone}
|
||||
sortOrder={LogsSortOrder.Descending}
|
||||
displayedFields={displayedFields}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Log context')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', {
|
||||
name: /show original logs/i,
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('Should not show "Show original logs" button when displayed fields match the default fields', async () => {
|
||||
const displayedFields = [LOG_LINE_BODY_FIELD_NAME, OTEL_LOG_LINE_ATTRIBUTES_FIELD_NAME];
|
||||
|
||||
render(
|
||||
<LogLineContext
|
||||
log={row}
|
||||
open={true}
|
||||
onClose={() => {}}
|
||||
getRowContext={getRowContext}
|
||||
timeZone={timeZone}
|
||||
sortOrder={LogsSortOrder.Descending}
|
||||
displayedFields={displayedFields}
|
||||
/>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Log context')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', {
|
||||
name: /show original logs/i,
|
||||
})
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
LogRowModel,
|
||||
LogsDedupStrategy,
|
||||
LogsSortOrder,
|
||||
shallowCompare,
|
||||
store,
|
||||
TimeRange,
|
||||
} from '@grafana/data';
|
||||
|
|
@ -37,7 +38,7 @@ import { LoadingIndicator } from '../LoadingIndicator';
|
|||
|
||||
import { LogLineDetailsLog } from './LogLineDetailsLog';
|
||||
import { LogLineMenuCustomItem } from './LogLineMenu';
|
||||
import { LogList } from './LogList';
|
||||
import { LogList, LogListOptions } from './LogList';
|
||||
import { LogListModel } from './processing';
|
||||
import { ScrollToLogsEvent } from './virtualization';
|
||||
|
||||
|
|
@ -100,6 +101,7 @@ export const LogLineContext = memo(
|
|||
: DEFAULT_TIME_WINDOW.toString();
|
||||
const [timeWindow, setTimeWindow] = useState(parseInt(defaultTimeWindow, 10));
|
||||
const [displayedFields, setDisplayedFields] = useState<string[]>(displayedFieldsProp);
|
||||
const [defaultDisplayedFields, setDefaultDisplayedFields] = useState<string[]>([]);
|
||||
|
||||
const eventBusRef = useRef(new EventBusSrv());
|
||||
|
||||
|
|
@ -343,6 +345,12 @@ export const LogLineContext = memo(
|
|||
}
|
||||
}, [log.datasourceUid]);
|
||||
|
||||
const onLogOptionsChange = useCallback((option: LogListOptions, value: string | string[] | boolean) => {
|
||||
if (option === 'defaultDisplayedFields' && Array.isArray(value)) {
|
||||
setDefaultDisplayedFields(value);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={open}
|
||||
|
|
@ -386,7 +394,8 @@ export const LogLineContext = memo(
|
|||
/>
|
||||
</Stack>
|
||||
)}
|
||||
{displayedFields.length > 0 && (
|
||||
{/** Show button to reset if there are displayed fields and they are different than the defaults */}
|
||||
{displayedFields.length > 0 && shallowCompare(displayedFields, defaultDisplayedFields) === false && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={resetFields}
|
||||
|
|
@ -444,6 +453,7 @@ export const LogLineContext = memo(
|
|||
loading={aboveState === LoadingState.Loading || belowState === LoadingState.Loading}
|
||||
permalinkedLogId={log.uid}
|
||||
onPermalinkClick={onPermalinkClick}
|
||||
onLogOptionsChange={onLogOptionsChange}
|
||||
onClickHideField={hideField}
|
||||
onClickShowField={showField}
|
||||
setDisplayedFields={setDisplayedFields}
|
||||
|
|
|
|||
Loading…
Reference in a new issue