feat: sort logs in ascending order (#2895)

* feat: sort logs in ascending order

Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: Rubens Rafael <70234898+RubensRafael@users.noreply.github.com>
Co-authored-by: RubensRafael <rubensrafael2@live.com>

* refactor: requested changes

Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: RubensRafael <rubensrafael2@live.com>

* fix: lint

Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: RubensRafael <rubensrafael2@live.com>

* chore: removed the magic string

---------

Co-authored-by: gitstart <gitstart@users.noreply.github.com>
Co-authored-by: gitstart <gitstart@gitstart.com>
Co-authored-by: Nitesh Singh <nitesh.singh@gitstart.dev>
Co-authored-by: Rubens Rafael <70234898+RubensRafael@users.noreply.github.com>
Co-authored-by: Palash Gupta <palashgdev@gmail.com>
Co-authored-by: RubensRafael <rubensrafael2@live.com>
Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
Co-authored-by: niteshsingh1357 <niteshsingh1357@gmail.com>
This commit is contained in:
GitStart 2023-06-29 09:41:49 +01:00 committed by GitHub
parent 1eabacbaf4
commit 64d4532a6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 125 additions and 13 deletions

View File

@ -14,4 +14,6 @@ export enum QueryParams {
resourceAttributes = 'resourceAttribute',
graphType = 'graphType',
widgetId = 'widgetId',
order = 'order',
q = 'q',
}

View File

@ -7,6 +7,7 @@ import { getMinMax } from 'container/TopNav/AutoRefresh/config';
import dayjs from 'dayjs';
import { Pagination } from 'hooks/queryPagination';
import { FlatLogData } from 'lib/logs/flatLogData';
import { OrderPreferenceItems } from 'pages/Logs/config';
import * as Papa from 'papaparse';
import { memo, useCallback, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux';
@ -31,6 +32,7 @@ function LogControls(): JSX.Element | null {
isLoading: isLogsLoading,
isLoadingAggregate,
logs,
order,
} = useSelector<AppState, ILogsReducer>((state) => state.logs);
const globalTime = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
@ -160,6 +162,7 @@ function LogControls(): JSX.Element | null {
loading={isLoading}
size="small"
type="link"
disabled={order === OrderPreferenceItems.ASC}
onClick={handleGoToLatest}
>
<FastBackwardOutlined /> Go to latest

View File

@ -2,6 +2,7 @@ import { MinusCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import { Button, Col, Popover } from 'antd';
import getStep from 'lib/getStep';
import { generateFilterQuery } from 'lib/logs/generateFilterQuery';
import { getIdConditions } from 'pages/Logs/utils';
import { memo, useMemo } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
@ -45,6 +46,7 @@ function ActionItem({
idStart,
liveTail,
idEnd,
order,
} = useSelector<AppState, ILogsReducer>((store) => store.logs);
const dispatch = useDispatch<Dispatch<AppActions>>();
@ -72,11 +74,10 @@ function ActionItem({
q: updatedQueryString,
limit: logLinesPerPage,
orderBy: 'timestamp',
order: 'desc',
order,
timestampStart: minTime,
timestampEnd: maxTime,
...(idStart ? { idGt: idStart } : {}),
...(idEnd ? { idLt: idEnd } : {}),
...getIdConditions(idStart, idEnd, order),
});
getLogsAggregate({
timestampStart: minTime,

View File

@ -2,6 +2,7 @@ import { Input, InputRef, Popover } from 'antd';
import useUrlQuery from 'hooks/useUrlQuery';
import getStep from 'lib/getStep';
import debounce from 'lodash-es/debounce';
import { getIdConditions } from 'pages/Logs/utils';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
@ -33,7 +34,7 @@ function SearchFilter({
const [searchText, setSearchText] = useState(queryString);
const [showDropDown, setShowDropDown] = useState(false);
const searchRef = useRef<InputRef>(null);
const { logLinesPerPage, idEnd, idStart, liveTail } = useSelector<
const { logLinesPerPage, idEnd, idStart, liveTail, order } = useSelector<
AppState,
ILogsReducer
>((state) => state.logs);
@ -99,11 +100,10 @@ function SearchFilter({
q: customQuery,
limit: logLinesPerPage,
orderBy: 'timestamp',
order: 'desc',
order,
timestampStart: minTime,
timestampEnd: maxTime,
...(idStart ? { idGt: idStart } : {}),
...(idEnd ? { idLt: idEnd } : {}),
...getIdConditions(idStart, idEnd, order),
});
getLogsAggregate({
@ -128,6 +128,7 @@ function SearchFilter({
logLinesPerPage,
globalTime,
getLogsFields,
order,
],
);
@ -160,6 +161,7 @@ function SearchFilter({
dispatch,
globalTime.maxTime,
globalTime.minTime,
order,
]);
const onPopOverChange = useCallback(

View File

@ -1,3 +1,4 @@
import { QueryParams } from 'constants/query';
import { getMinMax } from 'container/TopNav/AutoRefresh/config';
import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
@ -25,6 +26,7 @@ export function useSearchParser(): {
const dispatch = useDispatch<Dispatch<AppActions>>();
const {
searchFilter: { parsedQuery, queryString },
order,
} = useSelector<AppState, ILogsReducer>((store) => store.logs);
const urlQuery = useUrlQuery();
@ -39,7 +41,7 @@ export function useSearchParser(): {
(updatedQueryString: string) => {
history.replace({
pathname: history.location.pathname,
search: `?q=${updatedQueryString}`,
search: `?${QueryParams.q}=${updatedQueryString}&${QueryParams.order}=${order}`,
});
const globalTime = getMinMax(selectedTime, minTime, maxTime);

View File

@ -25,3 +25,24 @@ export const logsOptions = ['raw', 'table'];
export const defaultSelectStyle: CSSProperties = {
minWidth: '6rem',
};
export enum OrderPreferenceItems {
DESC = 'desc',
ASC = 'asc',
}
export const orderItems: OrderPreference[] = [
{
name: 'Descending',
enum: OrderPreferenceItems.DESC,
},
{
name: 'Ascending',
enum: OrderPreferenceItems.ASC,
},
];
export interface OrderPreference {
name: string;
enum: OrderPreferenceItems;
}

View File

@ -1,4 +1,5 @@
import { Button, Col, Divider, Popover, Row, Select, Space } from 'antd';
import { QueryParams } from 'constants/query';
import LogControls from 'container/LogControls';
import LogDetailedView from 'container/LogDetailedView';
import LogLiveTail from 'container/LogLiveTail';
@ -6,20 +7,31 @@ import LogsAggregate from 'container/LogsAggregate';
import LogsFilters from 'container/LogsFilters';
import LogsSearchFilter from 'container/LogsSearchFilter';
import LogsTable from 'container/LogsTable';
import history from 'lib/history';
import { useCallback, useMemo } from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { Dispatch } from 'redux';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { SET_DETAILED_LOG_DATA } from 'types/actions/logs';
import { SET_DETAILED_LOG_DATA, SET_LOGS_ORDER } from 'types/actions/logs';
import { ILog } from 'types/api/logs/log';
import { ILogsReducer } from 'types/reducer/logs';
import { defaultSelectStyle, logsOptions } from './config';
import {
defaultSelectStyle,
logsOptions,
orderItems,
OrderPreferenceItems,
} from './config';
import { useSelectedLogView } from './hooks';
import PopoverContent from './PopoverContent';
import SpaceContainer from './styles';
function Logs(): JSX.Element {
const dispatch = useDispatch<Dispatch<AppActions>>();
const { order } = useSelector<AppState, ILogsReducer>((store) => store.logs);
const location = useLocation();
const showExpandedLog = useCallback(
(logData: ILog) => {
@ -67,6 +79,16 @@ function Logs(): JSX.Element {
[handleViewModeOptionChange],
);
const handleChangeOrder = (value: OrderPreferenceItems): void => {
dispatch({
type: SET_LOGS_ORDER,
payload: value,
});
const params = new URLSearchParams(location.search);
params.set(QueryParams.order, value);
history.push({ search: params.toString() });
};
return (
<>
<SpaceContainer
@ -101,6 +123,16 @@ function Logs(): JSX.Element {
<Button>Format</Button>
</Popover>
)}
<Select
style={defaultSelectStyle}
defaultValue={order}
onChange={handleChangeOrder}
>
{orderItems.map((item) => (
<Select.Option key={item.enum}>{item.name}</Select.Option>
))}
</Select>
</Space>
</Col>

View File

@ -1,7 +1,29 @@
import { LogViewMode } from 'container/LogsTable';
import { viewModeOptionList } from './config';
import { OrderPreferenceItems, viewModeOptionList } from './config';
export const isLogViewMode = (value: unknown): value is LogViewMode =>
typeof value === 'string' &&
viewModeOptionList.some((option) => option.key === value);
export const getIdConditions = (
idStart: string,
idEnd: string,
order: OrderPreferenceItems,
): Record<string, string> => {
const idConditions: Record<string, string> = {};
if (idStart && order === OrderPreferenceItems.ASC) {
idConditions.idLt = idStart;
} else if (idStart) {
idConditions.idGt = idStart;
}
if (idEnd && order === OrderPreferenceItems.ASC) {
idConditions.idGt = idEnd;
} else if (idEnd) {
idConditions.idLt = idEnd;
}
return idConditions;
};

View File

@ -1,4 +1,5 @@
import { parseQuery } from 'lib/logql';
import { OrderPreferenceItems } from 'pages/Logs/config';
import {
ADD_SEARCH_FIELD_QUERY_STRING,
FLUSH_LOGS,
@ -17,6 +18,7 @@ import {
SET_LOG_LINES_PER_PAGE,
SET_LOGS,
SET_LOGS_AGGREGATE_SERIES,
SET_LOGS_ORDER,
SET_SEARCH_QUERY_PARSED_PAYLOAD,
SET_SEARCH_QUERY_STRING,
SET_VIEW_MODE,
@ -49,6 +51,10 @@ const initialState: ILogsReducer = {
liveTailStartRange: 15,
selectedLogId: null,
detailedLog: null,
order:
(new URLSearchParams(window.location.search).get(
'order',
) as ILogsReducer['order']) ?? OrderPreferenceItems.DESC,
};
export const LogsReducer = (
@ -129,6 +135,17 @@ export const LogsReducer = (
logs: logsData,
};
}
case SET_LOGS_ORDER: {
const order = action.payload;
return {
...state,
order,
idStart: '',
idEnd: '',
};
}
case SET_LOG_LINES_PER_PAGE: {
return {
...state,

View File

@ -1,6 +1,7 @@
import { LogViewMode } from 'container/LogsTable';
import { Pagination } from 'hooks/queryPagination';
import { ILogQLParsedQueryItem } from 'lib/logql/types';
import { OrderPreferenceItems } from 'pages/Logs/config';
import { IField, IFieldMoveToSelected, IFields } from 'types/api/logs/fields';
import { TLogsLiveTailState } from 'types/api/logs/liveTail';
import { ILog } from 'types/api/logs/log';
@ -34,6 +35,7 @@ export const SET_LINES_PER_ROW = 'SET_LINES_PER_ROW';
export const SET_VIEW_MODE = 'SET_VIEW_MODE';
export const UPDATE_SELECTED_FIELDS = 'LOGS_UPDATE_SELECTED_FIELDS';
export const UPDATE_INTERESTING_FIELDS = 'LOGS_UPDATE_INTERESTING_FIELDS';
export const SET_LOGS_ORDER = 'SET_LOGS_ORDER';
export interface GetFields {
type: typeof GET_FIELDS;
@ -141,6 +143,11 @@ export interface UpdateSelectedInterestFields {
};
}
export interface SetLogsOrder {
type: typeof SET_LOGS_ORDER;
payload: OrderPreferenceItems;
}
export type LogsActions =
| GetFields
| SetFields
@ -164,4 +171,5 @@ export type LogsActions =
| SetLiveTailStartTime
| SetLinesPerRow
| SetViewMode
| UpdateSelectedInterestFields;
| UpdateSelectedInterestFields
| SetLogsOrder;

View File

@ -1,6 +1,7 @@
import { LogViewMode } from 'container/LogsTable';
import { Pagination } from 'hooks/queryPagination';
import { ILogQLParsedQueryItem } from 'lib/logql/types';
import { OrderPreferenceItems } from 'pages/Logs/config';
import { IFields } from 'types/api/logs/fields';
import { TLogsLiveTailState } from 'types/api/logs/liveTail';
import { ILog } from 'types/api/logs/log';
@ -25,6 +26,7 @@ export interface ILogsReducer {
detailedLog: null | ILog;
liveTail: TLogsLiveTailState;
liveTailStartRange: number; // time in minutes
order: OrderPreferenceItems;
}
export default ILogsReducer;