mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 01:36:08 +08:00
Fix/logs issues main (#7758)
* fix: context log data fix in list view * fix: fix query builder and quick filters in light mode * chore: add desc * chore: added test case * fix: fix redirect url when not in logs view * chore: minor fix * chore: minor fix * chore: minor test fix --------- Co-authored-by: Aditya Singh <adityasingh@Adityas-MacBook-Pro.local>
This commit is contained in:
parent
f4d029bd12
commit
76ed58c481
@ -3,6 +3,7 @@
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
border-right: 1px solid var(--bg-slate-400);
|
||||
color: var(--bg-vanilla-100);
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
@ -74,6 +75,7 @@
|
||||
.quick-filters {
|
||||
background-color: var(--bg-vanilla-100);
|
||||
border-right: 1px solid var(--bg-vanilla-300);
|
||||
color: var(--bg-ink-200);
|
||||
|
||||
.header {
|
||||
border-bottom: 1px solid var(--bg-vanilla-300);
|
||||
|
@ -5,6 +5,7 @@ import RawLogView from 'components/Logs/RawLogView';
|
||||
import OverlayScrollbar from 'components/OverlayScrollbar/OverlayScrollbar';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import ROUTES from 'constants/routes';
|
||||
import ShowButton from 'container/LogsContextList/ShowButton';
|
||||
import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils';
|
||||
import { useOptionsMenu } from 'container/OptionsMenu';
|
||||
@ -14,7 +15,6 @@ import { ORDERBY_FILTERS } from 'container/QueryBuilder/filters/OrderByFilter/co
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Virtuoso } from 'react-virtuoso';
|
||||
import { ILog } from 'types/api/logs/log';
|
||||
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
@ -106,8 +106,6 @@ function ContextLogRenderer({
|
||||
|
||||
const urlQuery = useUrlQuery();
|
||||
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const handleLogClick = useCallback(
|
||||
(logId: string): void => {
|
||||
urlQuery.set(QueryParams.activeLogId, `"${logId}"`);
|
||||
@ -117,11 +115,10 @@ function ContextLogRenderer({
|
||||
encodeURIComponent(JSON.stringify(query)),
|
||||
);
|
||||
|
||||
const link = `${pathname}?${urlQuery.toString()}`;
|
||||
|
||||
const link = `${ROUTES.LOGS_EXPLORER}?${urlQuery.toString()}`;
|
||||
window.open(link, '_blank', 'noopener,noreferrer');
|
||||
},
|
||||
[pathname, query, urlQuery],
|
||||
[query, urlQuery],
|
||||
);
|
||||
|
||||
const getItemContent = useCallback(
|
||||
@ -143,7 +140,9 @@ function ContextLogRenderer({
|
||||
linesPerRow={1}
|
||||
fontSize={options.fontSize}
|
||||
selectedFields={convertKeysToColumnFields(
|
||||
options.selectColumns ?? defaultLogsSelectedColumns,
|
||||
options.selectColumns?.length
|
||||
? options.selectColumns
|
||||
: defaultLogsSelectedColumns,
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
@ -0,0 +1,145 @@
|
||||
import {
|
||||
act,
|
||||
render,
|
||||
RenderResult,
|
||||
screen,
|
||||
waitFor,
|
||||
} from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { ENVIRONMENT } from 'constants/env';
|
||||
import { initialQueriesMap } from 'constants/queryBuilder';
|
||||
import { server } from 'mocks-server/server';
|
||||
import { rest } from 'msw';
|
||||
import { QueryBuilderContext } from 'providers/QueryBuilder';
|
||||
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
|
||||
import TimezoneProvider from 'providers/Timezone';
|
||||
import { Provider } from 'react-redux';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { VirtuosoMockContext } from 'react-virtuoso';
|
||||
import store from 'store';
|
||||
|
||||
import ContextLogRenderer from '../ContextLogRenderer';
|
||||
import {
|
||||
mockLog,
|
||||
mockQuery,
|
||||
mockQueryRangeResponse,
|
||||
mockTagFilter,
|
||||
} from './mockData';
|
||||
|
||||
// Mock the useContextLogData hook
|
||||
const mockHandleRunQuery = jest.fn();
|
||||
|
||||
jest.mock('uplot', () => {
|
||||
const paths = {
|
||||
spline: jest.fn(),
|
||||
bars: jest.fn(),
|
||||
};
|
||||
const uplotMock = jest.fn(() => ({
|
||||
paths,
|
||||
}));
|
||||
return {
|
||||
paths,
|
||||
default: uplotMock,
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('container/OptionsMenu', () => ({
|
||||
useOptionsMenu: (): any => ({
|
||||
options: {
|
||||
fontSize: 'medium',
|
||||
selectColumns: [],
|
||||
},
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('hooks/useSafeNavigate', () => ({
|
||||
useSafeNavigate: (): any => ({
|
||||
safeNavigate: jest.fn(),
|
||||
}),
|
||||
}));
|
||||
|
||||
// Common wrapper component for tests
|
||||
const renderContextLogRenderer = (): RenderResult => {
|
||||
const defaultProps = {
|
||||
isEdit: false,
|
||||
query: mockQuery,
|
||||
log: mockLog,
|
||||
filters: mockTagFilter,
|
||||
};
|
||||
|
||||
return render(
|
||||
<MemoryRouter>
|
||||
<TimezoneProvider>
|
||||
<Provider store={store}>
|
||||
<MockQueryClientProvider>
|
||||
<QueryBuilderContext.Provider
|
||||
value={
|
||||
{
|
||||
currentQuery: initialQueriesMap.traces,
|
||||
handleRunQuery: mockHandleRunQuery,
|
||||
} as any
|
||||
}
|
||||
>
|
||||
<VirtuosoMockContext.Provider
|
||||
value={{ viewportHeight: 300, itemHeight: 50 }}
|
||||
>
|
||||
<ContextLogRenderer
|
||||
isEdit={defaultProps.isEdit}
|
||||
query={defaultProps.query}
|
||||
log={defaultProps.log}
|
||||
filters={defaultProps.filters}
|
||||
/>
|
||||
</VirtuosoMockContext.Provider>
|
||||
</QueryBuilderContext.Provider>
|
||||
</MockQueryClientProvider>
|
||||
</Provider>
|
||||
</TimezoneProvider>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
};
|
||||
|
||||
describe('ContextLogRenderer', () => {
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
rest.get(`${ENVIRONMENT.baseURL}/api/v1/logs`, (req, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json({ logs: [mockLog] })),
|
||||
),
|
||||
);
|
||||
server.use(
|
||||
rest.post(`${ENVIRONMENT.baseURL}/api/v3/query_range`, (req, res, ctx) =>
|
||||
res(ctx.status(200), ctx.json(mockQueryRangeResponse)),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('renders without crashing', async () => {
|
||||
await act(async () => {
|
||||
renderContextLogRenderer();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText('Load more')).toHaveLength(2);
|
||||
expect(screen.getByText(/Test log message/)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('loads new logs when clicking Load more button', async () => {
|
||||
await act(async () => {
|
||||
renderContextLogRenderer();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText('Load more')).toHaveLength(2);
|
||||
expect(screen.getByText(/Test log message/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
const loadMoreButtons = screen.getAllByText('Load more');
|
||||
await act(async () => {
|
||||
await userEvent.click(loadMoreButtons[1]);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getAllByText(/Failed to authenticate/)).toHaveLength(3);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,146 @@
|
||||
import { ILog } from 'types/api/logs/log';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
DataTypes,
|
||||
} from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
import { DataSource } from 'types/common/queryBuilder';
|
||||
|
||||
export const mockLog: ILog = {
|
||||
id: 'test-log-id',
|
||||
date: '2024-03-20T10:00:00Z',
|
||||
timestamp: '2024-03-20T10:00:00Z',
|
||||
body: 'Test log message',
|
||||
attributesString: {},
|
||||
attributesInt: {},
|
||||
attributesFloat: {},
|
||||
attributes_string: {},
|
||||
severityText: 'info',
|
||||
severityNumber: 0,
|
||||
traceId: '',
|
||||
spanID: '',
|
||||
traceFlags: 0,
|
||||
resources_string: {},
|
||||
scope_string: {},
|
||||
severity_text: 'info',
|
||||
severity_number: 0,
|
||||
};
|
||||
|
||||
export const mockQuery: Query = {
|
||||
queryType: EQueryType.QUERY_BUILDER,
|
||||
builder: {
|
||||
queryData: [
|
||||
{
|
||||
aggregateOperator: 'count',
|
||||
disabled: false,
|
||||
queryName: 'A',
|
||||
groupBy: [],
|
||||
orderBy: [],
|
||||
limit: 100,
|
||||
dataSource: DataSource.LOGS,
|
||||
aggregateAttribute: {
|
||||
key: 'body',
|
||||
type: 'string',
|
||||
dataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
},
|
||||
timeAggregation: 'sum',
|
||||
functions: [],
|
||||
having: [],
|
||||
stepInterval: 60,
|
||||
legend: '',
|
||||
filters: {
|
||||
items: [],
|
||||
op: 'AND',
|
||||
},
|
||||
expression: 'A',
|
||||
reduceTo: 'sum',
|
||||
},
|
||||
],
|
||||
queryFormulas: [],
|
||||
},
|
||||
clickhouse_sql: [],
|
||||
id: 'test-query-id',
|
||||
promql: [],
|
||||
};
|
||||
|
||||
const mockBaseAutocompleteData: BaseAutocompleteData = {
|
||||
key: 'service',
|
||||
type: 'string',
|
||||
dataType: DataTypes.String,
|
||||
isColumn: true,
|
||||
};
|
||||
|
||||
export const mockTagFilter: TagFilter = {
|
||||
items: [
|
||||
{
|
||||
id: 'test-filter-id',
|
||||
key: mockBaseAutocompleteData,
|
||||
op: '=',
|
||||
value: 'test-service',
|
||||
},
|
||||
],
|
||||
op: 'AND',
|
||||
};
|
||||
|
||||
export const mockQueryRangeResponse = {
|
||||
status: 'success',
|
||||
data: {
|
||||
resultType: '',
|
||||
result: [
|
||||
{
|
||||
queryName: 'A',
|
||||
list: [
|
||||
{
|
||||
timestamp: '2025-04-29T09:55:22.462039242Z',
|
||||
data: {
|
||||
attributes_bool: {},
|
||||
attributes_number: {},
|
||||
attributes_string: {
|
||||
'log.file.path':
|
||||
'/var/log/pods/generator_mongodb-0_755b8973-28c1-4698-a20f-22ee85c52c3f/mongodb/0.log',
|
||||
'log.iostream': 'stdout',
|
||||
logtag: 'F',
|
||||
},
|
||||
body:
|
||||
'{"t":{"$date":"2025-04-29T09:55:22.461+00:00"},"s":"I", "c":"ACCESS", "id":5286307, "ctx":"conn231150","msg":"Failed to authenticate","attr":{"client":"10.32.2.33:58258","isSpeculative":false,"isClusterMember":false,"mechanism":"SCRAM-SHA-1","user":"$(MONGO_USER)","db":"admin","error":"UserNotFound: Could not find user \\"$(MONGO_USER)\\" for db \\"admin\\"","result":11,"metrics":{"conversation_duration":{"micros":473,"summary":{"0":{"step":1,"step_total":2,"duration_micros":446}}}},"extraInfo":{}}}',
|
||||
id: '2wOlVEhbqYipTUgs3PRMFF1hqjJ',
|
||||
resources_string: {
|
||||
'cloud.account.id': 'signoz-staging',
|
||||
'cloud.availability_zone': 'us-central1-c',
|
||||
'cloud.platform': 'gcp_kubernetes_engine',
|
||||
'cloud.provider': 'gcp',
|
||||
'container.image.name': 'docker.io/bitnami/mongodb',
|
||||
'container.image.tag': '7.0.14-debian-12-r0',
|
||||
'deployment.environment': 'sample-flask',
|
||||
'host.id': '6006012725680193244',
|
||||
'host.name': 'gke-mgmt-pl-generator-e2st4-sp-41c1bdc8-d54x',
|
||||
'k8s.cluster.name': 'mgmt',
|
||||
'k8s.container.name': 'mongodb',
|
||||
'k8s.container.restart_count': '0',
|
||||
'k8s.namespace.name': 'generator',
|
||||
'k8s.node.name': 'gke-mgmt-pl-generator-e2st4-sp-41c1bdc8-d54x',
|
||||
'k8s.node.uid': 'ef650183-226d-41c0-8295-aeec210b15dd',
|
||||
'k8s.pod.name': 'mongodb-0',
|
||||
'k8s.pod.start_time': '2025-04-26T04:47:44Z',
|
||||
'k8s.pod.uid': '755b8973-28c1-4698-a20f-22ee85c52c3f',
|
||||
'k8s.statefulset.name': 'mongodb',
|
||||
'os.type': 'linux',
|
||||
'service.name': 'mongodb',
|
||||
},
|
||||
scope_name: '',
|
||||
scope_string: {},
|
||||
scope_version: '',
|
||||
severity_number: 0,
|
||||
severity_text: '',
|
||||
span_id: '',
|
||||
trace_flags: 0,
|
||||
trace_id: '',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
@ -134,6 +134,8 @@ export const useContextLogData = ({
|
||||
enabled: !!requestData,
|
||||
onSuccess: handleSuccess,
|
||||
},
|
||||
undefined, // params
|
||||
false, // isDependentOnQB
|
||||
);
|
||||
|
||||
const handleShowNextLines = useCallback(() => {
|
||||
|
@ -285,6 +285,12 @@
|
||||
|
||||
.lightMode {
|
||||
.query-builder-search-v2 {
|
||||
.ant-select-selector {
|
||||
border-color: var(--bg-vanilla-300) !important;
|
||||
background-color: var(--bg-vanilla-100) !important;
|
||||
color: var(--bg-ink-200);
|
||||
}
|
||||
|
||||
.content {
|
||||
.operator-for {
|
||||
.operator-for-text {
|
||||
|
@ -4,7 +4,6 @@
|
||||
.all-errors-quick-filter-section {
|
||||
width: 0%;
|
||||
flex-shrink: 0;
|
||||
color: var(--bg-vanilla-100);
|
||||
}
|
||||
|
||||
.all-errors-right-section {
|
||||
|
Loading…
x
Reference in New Issue
Block a user