diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 0fb029f5f3..530d6acf5f 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,5 +1,5 @@ # stage1 as builder -FROM node:12.18.0 as builder +FROM node:12.22.0 as builder # Add Maintainer Info LABEL maintainer="signoz" diff --git a/frontend/src/components/Graph/index.tsx b/frontend/src/components/Graph/index.tsx index 703b77c3d5..0659f686e1 100644 --- a/frontend/src/components/Graph/index.tsx +++ b/frontend/src/components/Graph/index.tsx @@ -51,6 +51,7 @@ Chart.register( ); function Graph({ + animate = true, data, type, title, @@ -58,15 +59,14 @@ function Graph({ onClickHandler, name, yAxisUnit = 'short', + forceReRender, }: GraphProps): JSX.Element { const { isDarkMode } = useSelector((state) => state.app); const chartRef = useRef(null); const currentTheme = isDarkMode ? 'dark' : 'light'; - const xAxisTimeUnit = useXAxisTimeUnit(data); // Computes the relevant time unit for x axis by analyzing the time stamp data const lineChartRef = useRef(); - const getGridColor = useCallback(() => { if (currentTheme === undefined) { return 'rgba(231,233,237,0.1)'; @@ -86,6 +86,9 @@ function Graph({ if (chartRef.current !== null) { const options: ChartOptions = { + animation: { + duration: animate ? 200 : 0, + }, responsive: true, maintainAspectRatio: false, interaction: { @@ -117,8 +120,8 @@ function Graph({ unit: xAxisTimeUnit?.unitName || 'minute', stepSize: xAxisTimeUnit?.stepSize || 1, displayFormats: { - millisecond: 'hh:mm:ss', - second: 'hh:mm:ss', + millisecond: 'HH:mm:ss', + second: 'HH:mm:ss', minute: 'HH:mm', hour: 'MM/dd HH:mm', day: 'MM/dd', @@ -166,11 +169,23 @@ function Graph({ plugins: [legend(name, data.datasets.length > 3)], }); } - }, [chartRef, data, type, title, isStacked, getGridColor, onClickHandler]); + }, [ + animate, + title, + getGridColor, + xAxisTimeUnit?.unitName, + xAxisTimeUnit?.stepSize, + isStacked, + type, + data, + name, + yAxisUnit, + onClickHandler, + ]); useEffect(() => { buildChart(); - }, [buildChart]); + }, [buildChart, forceReRender]); return (
@@ -181,6 +196,7 @@ function Graph({ } interface GraphProps { + animate?: boolean; type: ChartType; data: Chart['data']; title?: string; @@ -189,6 +205,7 @@ interface GraphProps { onClickHandler?: graphOnClickHandler; name: string; yAxisUnit?: string; + forceReRender?: boolean | null | number; } export type graphOnClickHandler = ( diff --git a/frontend/src/constants/app.ts b/frontend/src/constants/app.ts index 4530a6509f..0506378458 100644 --- a/frontend/src/constants/app.ts +++ b/frontend/src/constants/app.ts @@ -5,3 +5,5 @@ export const WITHOUT_SESSION_PATH = ['/redirect']; export const AUTH0_REDIRECT_PATH = '/redirect'; export const DEFAULT_AUTH0_APP_REDIRECTION_PATH = ROUTES.APPLICATION; + +export const IS_SIDEBAR_COLLAPSED = 'isSideBarCollapsed' \ No newline at end of file diff --git a/frontend/src/container/MetricsApplication/Tabs/Application.tsx b/frontend/src/container/MetricsApplication/Tabs/Application.tsx index 7303065544..09370793ab 100644 --- a/frontend/src/container/MetricsApplication/Tabs/Application.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/Application.tsx @@ -107,7 +107,7 @@ function Application({ getWidget }: DashboardProps): JSX.Element { View Traces - Application latency in ms + Application latency { @@ -175,7 +175,7 @@ function Application({ getWidget }: DashboardProps): JSX.Element { View Traces - Request per sec + Requests @@ -210,7 +210,7 @@ function Application({ getWidget }: DashboardProps): JSX.Element { - Error Percentage (%) + Error Percentage @@ -33,7 +33,7 @@ function DBCall({ getWidget }: DBCallProps): JSX.Element { - Database Calls Avg Duration (in ms) + Database Calls Avg Duration - External Call Error Percentage (%) + External Call Error Percentage diff --git a/frontend/src/container/SideNav/index.tsx b/frontend/src/container/SideNav/index.tsx index 3279da587c..293516edb5 100644 --- a/frontend/src/container/SideNav/index.tsx +++ b/frontend/src/container/SideNav/index.tsx @@ -1,13 +1,16 @@ import { Menu, Typography } from 'antd'; +import getLocalStorageKey from 'api/browser/localstorage/get'; +import { IS_SIDEBAR_COLLAPSED } from 'constants/app'; import ROUTES from 'constants/routes'; import history from 'lib/history'; import setTheme from 'lib/theme/setTheme'; -import React, { useCallback, useState } from 'react'; -import { connect, useSelector } from 'react-redux'; +import React, { useCallback, useLayoutEffect, useState } from 'react'; +import { connect, useDispatch, useSelector } from 'react-redux'; import { NavLink, useLocation } from 'react-router-dom'; import { bindActionCreators } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { ToggleDarkMode } from 'store/actions'; +import { SideBarCollapse } from 'store/actions/app'; import { AppState } from 'store/reducers'; import AppActions from 'types/actions'; import AppReducer from 'types/reducer/app'; @@ -24,7 +27,10 @@ import { } from './styles'; function SideNav({ toggleDarkMode }: Props): JSX.Element { - const [collapsed, setCollapsed] = useState(false); + const dispatch = useDispatch(); + const [collapsed, setCollapsed] = useState( + getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true', + ); const { pathname } = useLocation(); const { isDarkMode } = useSelector((state) => state.app); @@ -53,6 +59,10 @@ function SideNav({ toggleDarkMode }: Props): JSX.Element { setCollapsed((collapsed) => !collapsed); }, []); + useLayoutEffect(() => { + dispatch(SideBarCollapse(collapsed)); + }, [collapsed]); + const onClickHandler = useCallback( (to: string) => { if (pathname !== to) { @@ -62,7 +72,7 @@ function SideNav({ toggleDarkMode }: Props): JSX.Element { [pathname], ); - const onClickSlackHandler = () => { + const onClickSlackHandler = (): void => { window.open('https://signoz.io/slack', '_blank'); }; diff --git a/frontend/src/container/Trace/Graph/index.tsx b/frontend/src/container/Trace/Graph/index.tsx index 0181907901..a41332c125 100644 --- a/frontend/src/container/Trace/Graph/index.tsx +++ b/frontend/src/container/Trace/Graph/index.tsx @@ -3,6 +3,7 @@ import Graph from 'components/Graph'; import Spinner from 'components/Spinner'; import React, { useMemo } from 'react'; import { useSelector } from 'react-redux'; +import { useMeasure } from 'react-use'; import { AppState } from 'store/reducers'; import { TraceReducer } from 'types/reducer/trace'; @@ -10,6 +11,8 @@ import { getChartData, getChartDataforGroupBy } from './config'; import { Container } from './styles'; function TraceGraph(): JSX.Element { + const [ref, { width }] = useMeasure(); + const { spansGraph, selectedGroupBy, yAxisUnit } = useSelector< AppState, TraceReducer @@ -21,7 +24,7 @@ function TraceGraph(): JSX.Element { return selectedGroupBy.length === 0 ? getChartData(payload) : getChartDataforGroupBy(payload); - }, [payload]); + }, [payload, selectedGroupBy.length]); if (error) { return ( @@ -40,12 +43,14 @@ function TraceGraph(): JSX.Element { } return ( - + ); diff --git a/frontend/src/container/Trace/Graph/styles.ts b/frontend/src/container/Trace/Graph/styles.ts index 51a3e72ffc..617a7837d7 100644 --- a/frontend/src/container/Trace/Graph/styles.ts +++ b/frontend/src/container/Trace/Graph/styles.ts @@ -1,13 +1,17 @@ +import React from 'react'; import styled, { css } from 'styled-components'; interface Props { center?: boolean; + ref?: React.RefObject | null; // The ref type provided by react-use is incorrect -> https://github.com/streamich/react-use/issues/1264 Open Issue } export const Container = styled.div` - height: 25vh; + height: 25vh !important; margin-top: 1rem; margin-bottom: 1rem; + overflow: auto; + width: 100% !important; ${({ center }) => center && diff --git a/frontend/src/container/Trace/TraceGraphFilter/config.ts b/frontend/src/container/Trace/TraceGraphFilter/config.ts index 50769235c8..882ccc2e96 100644 --- a/frontend/src/container/Trace/TraceGraphFilter/config.ts +++ b/frontend/src/container/Trace/TraceGraphFilter/config.ts @@ -67,35 +67,35 @@ export const functions: Dropdown[] = [ key: 'ratePerSec', yAxisUnit: 'reqps', }, - { displayValue: 'Sum(duration in ns)', key: 'sum', yAxisUnit: 'ns' }, - { displayValue: 'Avg(duration in ns)', key: 'avg', yAxisUnit: 'ns' }, + { displayValue: 'Sum (duration)', key: 'sum', yAxisUnit: 'ns' }, + { displayValue: 'Avg (duration)', key: 'avg', yAxisUnit: 'ns' }, { - displayValue: 'Max(duration in ns)', + displayValue: 'Max (duration)', key: 'max', yAxisUnit: 'ns', }, { - displayValue: 'Min(duration in ns)', + displayValue: 'Min (duration)', key: 'min', yAxisUnit: 'ns', }, { - displayValue: '50th percentile(duration in ns)', + displayValue: '50th percentile (duration)', key: 'p50', yAxisUnit: 'ns', }, { - displayValue: '90th percentile(duration in ns)', + displayValue: '90th percentile (duration)', key: 'p90', yAxisUnit: 'ns', }, { - displayValue: '95th percentile(duration in ns)', + displayValue: '95th percentile (duration)', key: 'p95', yAxisUnit: 'ns', }, { - displayValue: '99th percentile(duration in ns)', + displayValue: '99th percentile (duration)', key: 'p99', yAxisUnit: 'ns', }, diff --git a/frontend/src/container/Trace/TraceGraphFilter/styles.ts b/frontend/src/container/Trace/TraceGraphFilter/styles.ts index 2acd767d8c..5fb2a7cfad 100644 --- a/frontend/src/container/Trace/TraceGraphFilter/styles.ts +++ b/frontend/src/container/Trace/TraceGraphFilter/styles.ts @@ -3,6 +3,6 @@ import styled from 'styled-components'; export const SelectComponent = styled(Select)` &&& { - min-width: 10rem; + min-width: 12rem; } `; diff --git a/frontend/src/container/Trace/TraceTable/index.tsx b/frontend/src/container/Trace/TraceTable/index.tsx index 309ed9a374..a305009cc8 100644 --- a/frontend/src/container/Trace/TraceTable/index.tsx +++ b/frontend/src/container/Trace/TraceTable/index.tsx @@ -43,7 +43,7 @@ function TraceTable({ getSpansAggregate }: TraceProps): JSX.Element { sorter: true, render: (value: TableType['timestamp']): JSX.Element => { const day = dayjs(value); - return
{day.format('DD/MM/YYYY hh:mm:ss A')}
; + return
{day.format('YYYY/MM/DD HH:mm:ss')}
; }, }, { diff --git a/frontend/src/store/actions/app/index.ts b/frontend/src/store/actions/app/index.ts index 036d1024cf..3fb993105f 100644 --- a/frontend/src/store/actions/app/index.ts +++ b/frontend/src/store/actions/app/index.ts @@ -1 +1,2 @@ +export * from './sideBarCollapse'; export * from './toggleDarkMode'; diff --git a/frontend/src/store/actions/app/sideBarCollapse.ts b/frontend/src/store/actions/app/sideBarCollapse.ts new file mode 100644 index 0000000000..dc2fde6108 --- /dev/null +++ b/frontend/src/store/actions/app/sideBarCollapse.ts @@ -0,0 +1,16 @@ +import setLocalStorageKey from 'api/browser/localstorage/set'; +import { IS_SIDEBAR_COLLAPSED } from 'constants/app'; +import { Dispatch } from 'redux'; +import AppActions from 'types/actions'; + +export const SideBarCollapse = ( + collapseState: boolean, +): ((dispatch: Dispatch) => void) => { + setLocalStorageKey(IS_SIDEBAR_COLLAPSED, `${collapseState}`); + return (dispatch: Dispatch): void => { + dispatch({ + type: 'SIDEBAR_COLLAPSE', + payload: collapseState, + }); + }; +}; diff --git a/frontend/src/store/reducers/app.ts b/frontend/src/store/reducers/app.ts index b1753dd1a8..2f45bee614 100644 --- a/frontend/src/store/reducers/app.ts +++ b/frontend/src/store/reducers/app.ts @@ -1,12 +1,19 @@ import getLocalStorageKey from 'api/browser/localstorage/get'; +import { IS_SIDEBAR_COLLAPSED } from 'constants/app'; import { IS_LOGGED_IN } from 'constants/auth'; import getTheme from 'lib/theme/getTheme'; -import { AppAction, LOGGED_IN, SWITCH_DARK_MODE } from 'types/actions/app'; +import { + AppAction, + LOGGED_IN, + SIDEBAR_COLLAPSE, + SWITCH_DARK_MODE, +} from 'types/actions/app'; import InitialValueTypes from 'types/reducer/app'; const InitialValue: InitialValueTypes = { isDarkMode: getTheme() === 'darkMode', isLoggedIn: getLocalStorageKey(IS_LOGGED_IN) === 'yes', + isSideBarCollapsed: getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true', }; const appReducer = ( @@ -28,6 +35,13 @@ const appReducer = ( }; } + case SIDEBAR_COLLAPSE: { + return { + ...state, + isSideBarCollapsed: action.payload, + }; + } + default: return state; } diff --git a/frontend/src/types/actions/app.ts b/frontend/src/types/actions/app.ts index 4a8495aafe..f58b589a3d 100644 --- a/frontend/src/types/actions/app.ts +++ b/frontend/src/types/actions/app.ts @@ -1,5 +1,6 @@ export const SWITCH_DARK_MODE = 'SWITCH_DARK_MODE'; export const LOGGED_IN = 'LOGGED_IN'; +export const SIDEBAR_COLLAPSE = 'SIDEBAR_COLLAPSE'; export interface SwitchDarkMode { type: typeof SWITCH_DARK_MODE; @@ -9,4 +10,9 @@ export interface LoggedInUser { type: typeof LOGGED_IN; } -export type AppAction = SwitchDarkMode | LoggedInUser; +export interface SideBarCollapse { + type: typeof SIDEBAR_COLLAPSE; + payload: boolean; +} + +export type AppAction = SwitchDarkMode | LoggedInUser | SideBarCollapse; diff --git a/frontend/src/types/reducer/app.ts b/frontend/src/types/reducer/app.ts index 2ec974c399..36fa886ec9 100644 --- a/frontend/src/types/reducer/app.ts +++ b/frontend/src/types/reducer/app.ts @@ -1,4 +1,5 @@ export default interface AppReducer { isDarkMode: boolean; isLoggedIn: boolean; + isSideBarCollapsed: boolean; }