mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-02 04:31:17 +08:00
Merge branch 'develop' into chore/analytics
This commit is contained in:
commit
1e035be978
9
frontend/src/container/AllError/constant.ts
Normal file
9
frontend/src/container/AllError/constant.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
const DEFAULT_FILTER_VALUE = '';
|
||||||
|
const EXCEPTION_TYPE_FILTER_NAME = 'exceptionType';
|
||||||
|
const SERVICE_NAME_FILTER_NAME = 'serviceName';
|
||||||
|
|
||||||
|
export {
|
||||||
|
DEFAULT_FILTER_VALUE,
|
||||||
|
EXCEPTION_TYPE_FILTER_NAME,
|
||||||
|
SERVICE_NAME_FILTER_NAME,
|
||||||
|
};
|
@ -17,6 +17,7 @@ import getAll from 'api/errors/getAll';
|
|||||||
import getErrorCounts from 'api/errors/getErrorCounts';
|
import getErrorCounts from 'api/errors/getErrorCounts';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
import createQueryParams from 'lib/createQueryParams';
|
import createQueryParams from 'lib/createQueryParams';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import React, { useCallback, useEffect, useMemo } from 'react';
|
import React, { useCallback, useEffect, useMemo } from 'react';
|
||||||
@ -30,7 +31,11 @@ import { Exception, PayloadProps } from 'types/api/errors/getAll';
|
|||||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
extractFilterValues,
|
||||||
|
getDefaultFilterValue,
|
||||||
getDefaultOrder,
|
getDefaultOrder,
|
||||||
|
getFilterString,
|
||||||
|
getFilterValues,
|
||||||
getNanoSeconds,
|
getNanoSeconds,
|
||||||
getOffSet,
|
getOffSet,
|
||||||
getOrder,
|
getOrder,
|
||||||
@ -43,15 +48,27 @@ function AllErrors(): JSX.Element {
|
|||||||
const { maxTime, minTime, loading } = useSelector<AppState, GlobalReducer>(
|
const { maxTime, minTime, loading } = useSelector<AppState, GlobalReducer>(
|
||||||
(state) => state.globalTime,
|
(state) => state.globalTime,
|
||||||
);
|
);
|
||||||
const { search, pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
const params = useMemo(() => new URLSearchParams(search), [search]);
|
const params = useUrlQuery();
|
||||||
|
|
||||||
const { t } = useTranslation(['common']);
|
const { t } = useTranslation(['common']);
|
||||||
|
const {
|
||||||
const updatedOrder = getOrder(params.get(urlKey.order));
|
updatedOrder,
|
||||||
const getUpdatedOffset = getOffSet(params.get(urlKey.offset));
|
getUpdatedOffset,
|
||||||
const getUpdatedParams = getOrderParams(params.get(urlKey.orderParam));
|
getUpdatedParams,
|
||||||
const getUpdatedPageSize = getUpdatePageSize(params.get(urlKey.pageSize));
|
getUpdatedPageSize,
|
||||||
|
getUpdatedExceptionType,
|
||||||
|
getUpdatedServiceName,
|
||||||
|
} = useMemo(
|
||||||
|
() => ({
|
||||||
|
updatedOrder: getOrder(params.get(urlKey.order)),
|
||||||
|
getUpdatedOffset: getOffSet(params.get(urlKey.offset)),
|
||||||
|
getUpdatedParams: getOrderParams(params.get(urlKey.orderParam)),
|
||||||
|
getUpdatedPageSize: getUpdatePageSize(params.get(urlKey.pageSize)),
|
||||||
|
getUpdatedExceptionType: getFilterString(params.get(urlKey.exceptionType)),
|
||||||
|
getUpdatedServiceName: getFilterString(params.get(urlKey.serviceName)),
|
||||||
|
}),
|
||||||
|
[params],
|
||||||
|
);
|
||||||
|
|
||||||
const updatedPath = useMemo(
|
const updatedPath = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -60,6 +77,8 @@ function AllErrors(): JSX.Element {
|
|||||||
offset: getUpdatedOffset,
|
offset: getUpdatedOffset,
|
||||||
orderParam: getUpdatedParams,
|
orderParam: getUpdatedParams,
|
||||||
pageSize: getUpdatedPageSize,
|
pageSize: getUpdatedPageSize,
|
||||||
|
exceptionType: getUpdatedExceptionType,
|
||||||
|
serviceName: getUpdatedServiceName,
|
||||||
})}`,
|
})}`,
|
||||||
[
|
[
|
||||||
pathname,
|
pathname,
|
||||||
@ -67,6 +86,8 @@ function AllErrors(): JSX.Element {
|
|||||||
getUpdatedOffset,
|
getUpdatedOffset,
|
||||||
getUpdatedParams,
|
getUpdatedParams,
|
||||||
getUpdatedPageSize,
|
getUpdatedPageSize,
|
||||||
|
getUpdatedExceptionType,
|
||||||
|
getUpdatedServiceName,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -81,6 +102,8 @@ function AllErrors(): JSX.Element {
|
|||||||
limit: getUpdatedPageSize,
|
limit: getUpdatedPageSize,
|
||||||
offset: getUpdatedOffset,
|
offset: getUpdatedOffset,
|
||||||
orderParam: getUpdatedParams,
|
orderParam: getUpdatedParams,
|
||||||
|
exceptionType: getUpdatedExceptionType,
|
||||||
|
serviceName: getUpdatedServiceName,
|
||||||
}),
|
}),
|
||||||
enabled: !loading,
|
enabled: !loading,
|
||||||
},
|
},
|
||||||
@ -108,14 +131,43 @@ function AllErrors(): JSX.Element {
|
|||||||
|
|
||||||
const filterIcon = useCallback(() => <SearchOutlined />, []);
|
const filterIcon = useCallback(() => <SearchOutlined />, []);
|
||||||
|
|
||||||
const handleSearch = (
|
const handleSearch = useCallback(
|
||||||
|
(
|
||||||
confirm: (param?: FilterConfirmProps) => void,
|
confirm: (param?: FilterConfirmProps) => void,
|
||||||
|
filterValue: string,
|
||||||
|
filterKey: string,
|
||||||
): VoidFunction => (): void => {
|
): VoidFunction => (): void => {
|
||||||
|
const { exceptionFilterValue, serviceFilterValue } = getFilterValues(
|
||||||
|
getUpdatedServiceName,
|
||||||
|
getUpdatedExceptionType,
|
||||||
|
filterKey,
|
||||||
|
filterValue,
|
||||||
|
);
|
||||||
|
history.replace(
|
||||||
|
`${pathname}?${createQueryParams({
|
||||||
|
order: updatedOrder,
|
||||||
|
offset: getUpdatedOffset,
|
||||||
|
orderParam: getUpdatedParams,
|
||||||
|
pageSize: getUpdatedPageSize,
|
||||||
|
exceptionType: exceptionFilterValue,
|
||||||
|
serviceName: serviceFilterValue,
|
||||||
|
})}`,
|
||||||
|
);
|
||||||
confirm();
|
confirm();
|
||||||
};
|
},
|
||||||
|
[
|
||||||
|
getUpdatedExceptionType,
|
||||||
|
getUpdatedOffset,
|
||||||
|
getUpdatedPageSize,
|
||||||
|
getUpdatedParams,
|
||||||
|
getUpdatedServiceName,
|
||||||
|
pathname,
|
||||||
|
updatedOrder,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
const filterDropdownWrapper = useCallback(
|
const filterDropdownWrapper = useCallback(
|
||||||
({ setSelectedKeys, selectedKeys, confirm, placeholder }) => {
|
({ setSelectedKeys, selectedKeys, confirm, placeholder, filterKey }) => {
|
||||||
return (
|
return (
|
||||||
<Card size="small">
|
<Card size="small">
|
||||||
<Space align="start" direction="vertical">
|
<Space align="start" direction="vertical">
|
||||||
@ -126,11 +178,16 @@ function AllErrors(): JSX.Element {
|
|||||||
setSelectedKeys(e.target.value ? [e.target.value] : [])
|
setSelectedKeys(e.target.value ? [e.target.value] : [])
|
||||||
}
|
}
|
||||||
allowClear
|
allowClear
|
||||||
onPressEnter={handleSearch(confirm)}
|
defaultValue={getDefaultFilterValue(
|
||||||
|
filterKey,
|
||||||
|
getUpdatedServiceName,
|
||||||
|
getUpdatedExceptionType,
|
||||||
|
)}
|
||||||
|
onPressEnter={handleSearch(confirm, selectedKeys[0], filterKey)}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={handleSearch(confirm)}
|
onClick={handleSearch(confirm, selectedKeys[0], filterKey)}
|
||||||
icon={<SearchOutlined />}
|
icon={<SearchOutlined />}
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
@ -140,7 +197,7 @@ function AllErrors(): JSX.Element {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[],
|
[getUpdatedExceptionType, getUpdatedServiceName, handleSearch],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onExceptionTypeFilter = useCallback(
|
const onExceptionTypeFilter = useCallback(
|
||||||
@ -167,6 +224,7 @@ function AllErrors(): JSX.Element {
|
|||||||
(
|
(
|
||||||
onFilter: ColumnType<Exception>['onFilter'],
|
onFilter: ColumnType<Exception>['onFilter'],
|
||||||
placeholder: string,
|
placeholder: string,
|
||||||
|
filterKey: string,
|
||||||
): ColumnType<Exception> => ({
|
): ColumnType<Exception> => ({
|
||||||
onFilter,
|
onFilter,
|
||||||
filterIcon,
|
filterIcon,
|
||||||
@ -176,6 +234,7 @@ function AllErrors(): JSX.Element {
|
|||||||
selectedKeys,
|
selectedKeys,
|
||||||
confirm,
|
confirm,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
filterKey,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
[filterIcon, filterDropdownWrapper],
|
[filterIcon, filterDropdownWrapper],
|
||||||
@ -186,7 +245,7 @@ function AllErrors(): JSX.Element {
|
|||||||
title: 'Exception Type',
|
title: 'Exception Type',
|
||||||
dataIndex: 'exceptionType',
|
dataIndex: 'exceptionType',
|
||||||
key: 'exceptionType',
|
key: 'exceptionType',
|
||||||
...getFilter(onExceptionTypeFilter, 'Search By Exception'),
|
...getFilter(onExceptionTypeFilter, 'Search By Exception', 'exceptionType'),
|
||||||
render: (value, record): JSX.Element => (
|
render: (value, record): JSX.Element => (
|
||||||
<Tooltip overlay={(): JSX.Element => value}>
|
<Tooltip overlay={(): JSX.Element => value}>
|
||||||
<Link
|
<Link
|
||||||
@ -266,26 +325,35 @@ function AllErrors(): JSX.Element {
|
|||||||
updatedOrder,
|
updatedOrder,
|
||||||
'serviceName',
|
'serviceName',
|
||||||
),
|
),
|
||||||
...getFilter(onApplicationTypeFilter, 'Search By Application'),
|
...getFilter(
|
||||||
|
onApplicationTypeFilter,
|
||||||
|
'Search By Application',
|
||||||
|
'serviceName',
|
||||||
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const onChangeHandler: TableProps<Exception>['onChange'] = (
|
const onChangeHandler: TableProps<Exception>['onChange'] = (
|
||||||
paginations,
|
paginations,
|
||||||
_,
|
filters,
|
||||||
sorter,
|
sorter,
|
||||||
) => {
|
) => {
|
||||||
if (!Array.isArray(sorter)) {
|
if (!Array.isArray(sorter)) {
|
||||||
const { pageSize = 0, current = 0 } = paginations;
|
const { pageSize = 0, current = 0 } = paginations;
|
||||||
const { columnKey = '', order } = sorter;
|
const { columnKey = '', order } = sorter;
|
||||||
const updatedOrder = order === 'ascend' ? 'ascending' : 'descending';
|
const updatedOrder = order === 'ascend' ? 'ascending' : 'descending';
|
||||||
|
const { exceptionType, serviceName } = extractFilterValues(filters, {
|
||||||
|
serviceName: getUpdatedServiceName,
|
||||||
|
exceptionType: getUpdatedExceptionType,
|
||||||
|
});
|
||||||
history.replace(
|
history.replace(
|
||||||
`${pathname}?${createQueryParams({
|
`${pathname}?${createQueryParams({
|
||||||
order: updatedOrder,
|
order: updatedOrder,
|
||||||
offset: (current - 1) * pageSize,
|
offset: (current - 1) * pageSize,
|
||||||
orderParam: columnKey,
|
orderParam: columnKey,
|
||||||
pageSize,
|
pageSize,
|
||||||
|
exceptionType,
|
||||||
|
serviceName,
|
||||||
})}`,
|
})}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
import { SortOrder } from 'antd/lib/table/interface';
|
import { FilterValue, SortOrder } from 'antd/lib/table/interface';
|
||||||
import Timestamp from 'timestamp-nano';
|
import Timestamp from 'timestamp-nano';
|
||||||
import { Order, OrderBy } from 'types/api/errors/getAll';
|
import { Order, OrderBy } from 'types/api/errors/getAll';
|
||||||
|
|
||||||
|
import {
|
||||||
|
DEFAULT_FILTER_VALUE,
|
||||||
|
EXCEPTION_TYPE_FILTER_NAME,
|
||||||
|
SERVICE_NAME_FILTER_NAME,
|
||||||
|
} from './constant';
|
||||||
|
|
||||||
export const isOrder = (order: string | null): order is Order =>
|
export const isOrder = (order: string | null): order is Order =>
|
||||||
!!(order === 'ascending' || order === 'descending');
|
!!(order === 'ascending' || order === 'descending');
|
||||||
|
|
||||||
@ -10,6 +16,8 @@ export const urlKey = {
|
|||||||
offset: 'offset',
|
offset: 'offset',
|
||||||
orderParam: 'orderParam',
|
orderParam: 'orderParam',
|
||||||
pageSize: 'pageSize',
|
pageSize: 'pageSize',
|
||||||
|
exceptionType: 'exceptionType',
|
||||||
|
serviceName: 'serviceName',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isOrderParams = (orderBy: string | null): orderBy is OrderBy => {
|
export const isOrderParams = (orderBy: string | null): orderBy is OrderBy => {
|
||||||
@ -87,3 +95,94 @@ export const getUpdatePageSize = (pageSize: string | null): number => {
|
|||||||
}
|
}
|
||||||
return 10;
|
return 10;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFilterString = (filter: string | null): string => {
|
||||||
|
if (filter) {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getDefaultFilterValue = (
|
||||||
|
filterKey: string | null,
|
||||||
|
serviceName: string,
|
||||||
|
exceptionType: string,
|
||||||
|
): string | undefined => {
|
||||||
|
let defaultValue: string | undefined;
|
||||||
|
switch (filterKey) {
|
||||||
|
case SERVICE_NAME_FILTER_NAME:
|
||||||
|
defaultValue = serviceName;
|
||||||
|
break;
|
||||||
|
case EXCEPTION_TYPE_FILTER_NAME:
|
||||||
|
defaultValue = exceptionType;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return defaultValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFilterValues = (
|
||||||
|
serviceName: string,
|
||||||
|
exceptionType: string,
|
||||||
|
filterKey: string,
|
||||||
|
filterValue: string,
|
||||||
|
): { exceptionFilterValue: string; serviceFilterValue: string } => {
|
||||||
|
let serviceFilterValue = serviceName;
|
||||||
|
let exceptionFilterValue = exceptionType;
|
||||||
|
switch (filterKey) {
|
||||||
|
case EXCEPTION_TYPE_FILTER_NAME:
|
||||||
|
exceptionFilterValue = filterValue;
|
||||||
|
break;
|
||||||
|
case SERVICE_NAME_FILTER_NAME:
|
||||||
|
serviceFilterValue = filterValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return { exceptionFilterValue, serviceFilterValue };
|
||||||
|
};
|
||||||
|
|
||||||
|
type FilterValues = { exceptionType: string; serviceName: string };
|
||||||
|
|
||||||
|
const extractSingleFilterValue = (
|
||||||
|
filterName: string,
|
||||||
|
filters: Filter,
|
||||||
|
): string => {
|
||||||
|
const filterValues = filters[filterName];
|
||||||
|
|
||||||
|
if (
|
||||||
|
!filterValues ||
|
||||||
|
!Array.isArray(filterValues) ||
|
||||||
|
filterValues.length === 0
|
||||||
|
) {
|
||||||
|
return DEFAULT_FILTER_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(filterValues[0]);
|
||||||
|
};
|
||||||
|
|
||||||
|
type Filter = Record<string, FilterValue | null>;
|
||||||
|
|
||||||
|
export const extractFilterValues = (
|
||||||
|
filters: Filter,
|
||||||
|
prefilledFilters: FilterValues,
|
||||||
|
): FilterValues => {
|
||||||
|
const filterValues: FilterValues = {
|
||||||
|
exceptionType: prefilledFilters.exceptionType,
|
||||||
|
serviceName: prefilledFilters.serviceName,
|
||||||
|
};
|
||||||
|
if (filters[EXCEPTION_TYPE_FILTER_NAME]) {
|
||||||
|
filterValues.exceptionType = extractSingleFilterValue(
|
||||||
|
EXCEPTION_TYPE_FILTER_NAME,
|
||||||
|
filters,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (filters[SERVICE_NAME_FILTER_NAME]) {
|
||||||
|
filterValues.serviceName = extractSingleFilterValue(
|
||||||
|
SERVICE_NAME_FILTER_NAME,
|
||||||
|
filters,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return filterValues;
|
||||||
|
};
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import { Button, Row } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { QueryFields } from './utils';
|
||||||
|
|
||||||
|
interface SearchFieldsActionBarProps {
|
||||||
|
fieldsQuery: QueryFields[][];
|
||||||
|
applyUpdate: () => void;
|
||||||
|
clearFilters: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SearchFieldsActionBar({
|
||||||
|
fieldsQuery,
|
||||||
|
applyUpdate,
|
||||||
|
clearFilters,
|
||||||
|
}: SearchFieldsActionBarProps): JSX.Element | null {
|
||||||
|
if (fieldsQuery.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row style={{ justifyContent: 'flex-end', paddingRight: '2.4rem' }}>
|
||||||
|
<Button
|
||||||
|
type="default"
|
||||||
|
onClick={clearFilters}
|
||||||
|
style={{ marginRight: '1rem' }}
|
||||||
|
>
|
||||||
|
Clear Filter
|
||||||
|
</Button>
|
||||||
|
<Button type="primary" onClick={applyUpdate}>
|
||||||
|
Apply
|
||||||
|
</Button>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default SearchFieldsActionBar;
|
@ -1,10 +1,11 @@
|
|||||||
import { Button, notification, Row } from 'antd';
|
import { notification } from 'antd';
|
||||||
import { flatten } from 'lodash-es';
|
import { flatten } from 'lodash-es';
|
||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import { ILogsReducer } from 'types/reducer/logs';
|
import { ILogsReducer } from 'types/reducer/logs';
|
||||||
|
|
||||||
|
import { SearchFieldsActionBar } from './ActionBar';
|
||||||
import QueryBuilder from './QueryBuilder/QueryBuilder';
|
import QueryBuilder from './QueryBuilder/QueryBuilder';
|
||||||
import Suggestions from './Suggestions';
|
import Suggestions from './Suggestions';
|
||||||
import {
|
import {
|
||||||
@ -68,9 +69,7 @@ function SearchFields({
|
|||||||
[fieldsQuery, setFieldsQuery],
|
[fieldsQuery, setFieldsQuery],
|
||||||
);
|
);
|
||||||
|
|
||||||
const applyUpdate = useCallback(
|
const applyUpdate = useCallback((): void => {
|
||||||
(e): void => {
|
|
||||||
e.preventDefault();
|
|
||||||
const flatParsedQuery = flatten(fieldsQuery);
|
const flatParsedQuery = flatten(fieldsQuery);
|
||||||
|
|
||||||
if (!fieldsQueryIsvalid(flatParsedQuery)) {
|
if (!fieldsQueryIsvalid(flatParsedQuery)) {
|
||||||
@ -83,9 +82,13 @@ function SearchFields({
|
|||||||
keyPrefixRef.current = hashCode(JSON.stringify(flatParsedQuery));
|
keyPrefixRef.current = hashCode(JSON.stringify(flatParsedQuery));
|
||||||
updateParsedQuery(flatParsedQuery);
|
updateParsedQuery(flatParsedQuery);
|
||||||
onDropDownToggleHandler(false)();
|
onDropDownToggleHandler(false)();
|
||||||
},
|
}, [onDropDownToggleHandler, fieldsQuery, updateParsedQuery]);
|
||||||
[onDropDownToggleHandler, fieldsQuery, updateParsedQuery],
|
|
||||||
);
|
const clearFilters = useCallback((): void => {
|
||||||
|
keyPrefixRef.current = hashCode(JSON.stringify([]));
|
||||||
|
updateParsedQuery([]);
|
||||||
|
onDropDownToggleHandler(false)();
|
||||||
|
}, [onDropDownToggleHandler, updateParsedQuery]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -96,11 +99,11 @@ function SearchFields({
|
|||||||
fieldsQuery={fieldsQuery}
|
fieldsQuery={fieldsQuery}
|
||||||
setFieldsQuery={setFieldsQuery}
|
setFieldsQuery={setFieldsQuery}
|
||||||
/>
|
/>
|
||||||
<Row style={{ justifyContent: 'flex-end', paddingRight: '2.4rem' }}>
|
<SearchFieldsActionBar
|
||||||
<Button type="primary" onClick={applyUpdate}>
|
applyUpdate={applyUpdate}
|
||||||
Apply
|
clearFilters={clearFilters}
|
||||||
</Button>
|
fieldsQuery={fieldsQuery}
|
||||||
</Row>
|
/>
|
||||||
<Suggestions applySuggestion={addSuggestedField} />
|
<Suggestions applySuggestion={addSuggestedField} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -15,6 +15,8 @@ export interface Props {
|
|||||||
orderParam?: OrderBy;
|
orderParam?: OrderBy;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
|
exceptionType?: string;
|
||||||
|
serviceName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Exception {
|
export interface Exception {
|
||||||
|
@ -2528,8 +2528,35 @@ func (r *ClickHouseReader) ListErrors(ctx context.Context, queryParams *model.Li
|
|||||||
|
|
||||||
var getErrorResponses []model.Error
|
var getErrorResponses []model.Error
|
||||||
|
|
||||||
query := fmt.Sprintf("SELECT any(exceptionType) as exceptionType, any(exceptionMessage) as exceptionMessage, count() AS exceptionCount, min(timestamp) as firstSeen, max(timestamp) as lastSeen, any(serviceName) as serviceName, groupID FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU GROUP BY groupID", r.TraceDB, r.errorTable)
|
query := "SELECT any(exceptionMessage) as exceptionMessage, count() AS exceptionCount, min(timestamp) as firstSeen, max(timestamp) as lastSeen, groupID"
|
||||||
|
if len(queryParams.ServiceName) != 0 {
|
||||||
|
query = query + ", serviceName"
|
||||||
|
} else {
|
||||||
|
query = query + ", any(serviceName) as serviceName"
|
||||||
|
}
|
||||||
|
if len(queryParams.ExceptionType) != 0 {
|
||||||
|
query = query + ", exceptionType"
|
||||||
|
} else {
|
||||||
|
query = query + ", any(exceptionType) as exceptionType"
|
||||||
|
}
|
||||||
|
query += fmt.Sprintf(" FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.errorTable)
|
||||||
args := []interface{}{clickhouse.Named("timestampL", strconv.FormatInt(queryParams.Start.UnixNano(), 10)), clickhouse.Named("timestampU", strconv.FormatInt(queryParams.End.UnixNano(), 10))}
|
args := []interface{}{clickhouse.Named("timestampL", strconv.FormatInt(queryParams.Start.UnixNano(), 10)), clickhouse.Named("timestampU", strconv.FormatInt(queryParams.End.UnixNano(), 10))}
|
||||||
|
|
||||||
|
if len(queryParams.ServiceName) != 0 {
|
||||||
|
query = query + " AND serviceName ilike @serviceName"
|
||||||
|
args = append(args, clickhouse.Named("serviceName", "%"+queryParams.ServiceName+"%"))
|
||||||
|
}
|
||||||
|
if len(queryParams.ExceptionType) != 0 {
|
||||||
|
query = query + " AND exceptionType ilike @exceptionType"
|
||||||
|
args = append(args, clickhouse.Named("exceptionType", "%"+queryParams.ExceptionType+"%"))
|
||||||
|
}
|
||||||
|
query = query + " GROUP BY groupID"
|
||||||
|
if len(queryParams.ServiceName) != 0 {
|
||||||
|
query = query + ", serviceName"
|
||||||
|
}
|
||||||
|
if len(queryParams.ExceptionType) != 0 {
|
||||||
|
query = query + ", exceptionType"
|
||||||
|
}
|
||||||
if len(queryParams.OrderParam) != 0 {
|
if len(queryParams.OrderParam) != 0 {
|
||||||
if queryParams.Order == constants.Descending {
|
if queryParams.Order == constants.Descending {
|
||||||
query = query + " ORDER BY " + queryParams.OrderParam + " DESC"
|
query = query + " ORDER BY " + queryParams.OrderParam + " DESC"
|
||||||
@ -2564,7 +2591,14 @@ func (r *ClickHouseReader) CountErrors(ctx context.Context, queryParams *model.C
|
|||||||
|
|
||||||
query := fmt.Sprintf("SELECT count(distinct(groupID)) FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.errorTable)
|
query := fmt.Sprintf("SELECT count(distinct(groupID)) FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.errorTable)
|
||||||
args := []interface{}{clickhouse.Named("timestampL", strconv.FormatInt(queryParams.Start.UnixNano(), 10)), clickhouse.Named("timestampU", strconv.FormatInt(queryParams.End.UnixNano(), 10))}
|
args := []interface{}{clickhouse.Named("timestampL", strconv.FormatInt(queryParams.Start.UnixNano(), 10)), clickhouse.Named("timestampU", strconv.FormatInt(queryParams.End.UnixNano(), 10))}
|
||||||
|
if len(queryParams.ServiceName) != 0 {
|
||||||
|
query = query + " AND serviceName = @serviceName"
|
||||||
|
args = append(args, clickhouse.Named("serviceName", queryParams.ServiceName))
|
||||||
|
}
|
||||||
|
if len(queryParams.ExceptionType) != 0 {
|
||||||
|
query = query + " AND exceptionType = @exceptionType"
|
||||||
|
args = append(args, clickhouse.Named("exceptionType", queryParams.ExceptionType))
|
||||||
|
}
|
||||||
err := r.db.QueryRow(ctx, query, args...).Scan(&errorCount)
|
err := r.db.QueryRow(ctx, query, args...).Scan(&errorCount)
|
||||||
zap.S().Info(query)
|
zap.S().Info(query)
|
||||||
|
|
||||||
@ -3233,7 +3267,8 @@ func (r *ClickHouseReader) UpdateLogField(ctx context.Context, field *model.Upda
|
|||||||
// remove index
|
// remove index
|
||||||
query := fmt.Sprintf("ALTER TABLE %s.%s ON CLUSTER %s DROP INDEX IF EXISTS %s_idx", r.logsDB, r.logsLocalTable, cluster, field.Name)
|
query := fmt.Sprintf("ALTER TABLE %s.%s ON CLUSTER %s DROP INDEX IF EXISTS %s_idx", r.logsDB, r.logsLocalTable, cluster, field.Name)
|
||||||
err := r.db.Exec(ctx, query)
|
err := r.db.Exec(ctx, query)
|
||||||
if err != nil {
|
// we are ignoring errors with code 341 as it is an error with updating old part https://github.com/SigNoz/engineering-pod/issues/919#issuecomment-1366344346
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "code: 341") {
|
||||||
return &model.ApiError{Err: err, Typ: model.ErrorInternal}
|
return &model.ApiError{Err: err, Typ: model.ErrorInternal}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -480,6 +480,8 @@ func parseListErrorsRequest(r *http.Request) (*model.ListErrorsParams, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("offset param is not in correct format")
|
return nil, errors.New("offset param is not in correct format")
|
||||||
}
|
}
|
||||||
|
serviceName := r.URL.Query().Get("serviceName")
|
||||||
|
exceptionType := r.URL.Query().Get("exceptionType")
|
||||||
|
|
||||||
params := &model.ListErrorsParams{
|
params := &model.ListErrorsParams{
|
||||||
Start: startTime,
|
Start: startTime,
|
||||||
@ -488,6 +490,8 @@ func parseListErrorsRequest(r *http.Request) (*model.ListErrorsParams, error) {
|
|||||||
Order: order,
|
Order: order,
|
||||||
Limit: int64(limitInt),
|
Limit: int64(limitInt),
|
||||||
Offset: int64(offsetInt),
|
Offset: int64(offsetInt),
|
||||||
|
ServiceName: serviceName,
|
||||||
|
ExceptionType: exceptionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
return params, nil
|
return params, nil
|
||||||
|
@ -302,11 +302,15 @@ type ListErrorsParams struct {
|
|||||||
OrderParam string
|
OrderParam string
|
||||||
Order string
|
Order string
|
||||||
Offset int64
|
Offset int64
|
||||||
|
ServiceName string
|
||||||
|
ExceptionType string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CountErrorsParams struct {
|
type CountErrorsParams struct {
|
||||||
Start *time.Time
|
Start *time.Time
|
||||||
End *time.Time
|
End *time.Time
|
||||||
|
ServiceName string
|
||||||
|
ExceptionType string
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetErrorParams struct {
|
type GetErrorParams struct {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user