diff --git a/.github/config.yml b/.github/config.yml index d31bb878b4..ecbab95fd7 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -17,7 +17,7 @@ newPRWelcomeComment: > # Comment to be posted to on pull requests merged by a first time user firstPRMergeComment: > Congrats on merging your first pull request! - + ![minion-party](https://i.imgur.com/Xlg59lP.gif) We here at SigNoz are proud of you! 🥳 diff --git a/.github/workflows/e2e-k3s.yaml b/.github/workflows/e2e-k3s.yaml index da3db01917..a1a307a9d9 100644 --- a/.github/workflows/e2e-k3s.yaml +++ b/.github/workflows/e2e-k3s.yaml @@ -57,7 +57,7 @@ jobs: --set frontend.service.type=LoadBalancer \ --set queryService.image.tag=$DOCKER_TAG \ --set frontend.image.tag=$DOCKER_TAG - + # get pods, services and the container images kubectl get pods -n platform kubectl get svc -n platform diff --git a/.github/workflows/pr_verify_linked_issue.yml b/.github/workflows/pr_verify_linked_issue.yml index adf2718a46..3fd5abd2ec 100644 --- a/.github/workflows/pr_verify_linked_issue.yml +++ b/.github/workflows/pr_verify_linked_issue.yml @@ -17,4 +17,3 @@ jobs: uses: hattan/verify-linked-issue-action@v1.1.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 751b9053f2..c19c4f5452 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -24,4 +24,3 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - \ No newline at end of file diff --git a/deploy/README.md b/deploy/README.md index a67aa0b168..f226c79d4c 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -27,12 +27,6 @@ For x86 chip (amd): docker-compose -f docker/clickhouse-setup/docker-compose.yaml up -d ``` -For Mac with Apple chip (arm): - -```sh -docker-compose -f docker/clickhouse-setup/docker-compose.arm.yaml up -d -``` - Open http://localhost:3301 in your favourite browser. In couple of minutes, you should see the data generated from hotrod in SigNoz UI. diff --git a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml index 90888be3c3..1ad46cf057 100644 --- a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml @@ -137,7 +137,7 @@ services: condition: on-failure query-service: - image: signoz/query-service:0.15.0 + image: signoz/query-service:0.16.0 command: ["-config=/root/config/prometheus.yml"] # ports: # - "6060:6060" # pprof port @@ -166,7 +166,7 @@ services: <<: *clickhouse-depend frontend: - image: signoz/frontend:0.15.0 + image: signoz/frontend:0.16.0 deploy: restart_policy: condition: on-failure @@ -179,7 +179,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector: - image: signoz/signoz-otel-collector:0.66.3 + image: signoz/signoz-otel-collector:0.66.4 command: ["--config=/etc/otel-collector-config.yaml"] user: root # required for reading docker container logs volumes: @@ -188,6 +188,7 @@ services: environment: - OTEL_RESOURCE_ATTRIBUTES=host.name={{.Node.Hostname}},os.type={{.Node.Platform.OS}},dockerswarm.service.name={{.Service.Name}},dockerswarm.task.name={{.Task.Name}} - DOCKER_MULTI_NODE_CLUSTER=false + - LOW_CARDINAL_EXCEPTION_GROUPING=false ports: # - "1777:1777" # pprof extension - "4317:4317" # OTLP gRPC receiver @@ -207,7 +208,7 @@ services: <<: *clickhouse-depend otel-collector-metrics: - image: signoz/signoz-otel-collector:0.66.3 + image: signoz/signoz-otel-collector:0.66.4 command: ["--config=/etc/otel-collector-metrics-config.yaml"] volumes: - ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml diff --git a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml index f51f70c55c..61b937ea4b 100644 --- a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml @@ -110,6 +110,7 @@ exporters: clickhousetraces: datasource: tcp://clickhouse:9000/?database=signoz_traces docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} + low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING} clickhousemetricswrite: endpoint: tcp://clickhouse:9000/?database=signoz_metrics resource_to_telemetry_conversion: diff --git a/deploy/docker/clickhouse-setup/docker-compose-core.yaml b/deploy/docker/clickhouse-setup/docker-compose-core.yaml index bacf87e1a6..febd11a13d 100644 --- a/deploy/docker/clickhouse-setup/docker-compose-core.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose-core.yaml @@ -41,7 +41,7 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` otel-collector: container_name: otel-collector - image: signoz/signoz-otel-collector:0.66.3 + image: signoz/signoz-otel-collector:0.66.4 command: ["--config=/etc/otel-collector-config.yaml"] # user: root # required for reading docker container logs volumes: @@ -67,7 +67,7 @@ services: otel-collector-metrics: container_name: otel-collector-metrics - image: signoz/signoz-otel-collector:0.66.3 + image: signoz/signoz-otel-collector:0.66.4 command: ["--config=/etc/otel-collector-metrics-config.yaml"] volumes: - ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml diff --git a/deploy/docker/clickhouse-setup/docker-compose.yaml b/deploy/docker/clickhouse-setup/docker-compose.yaml index 3a6478e5ec..e507dd1645 100644 --- a/deploy/docker/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose.yaml @@ -153,7 +153,7 @@ services: # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` query-service: - image: signoz/query-service:${DOCKER_TAG:-0.15.0} + image: signoz/query-service:${DOCKER_TAG:-0.16.0} container_name: query-service command: ["-config=/root/config/prometheus.yml"] # ports: @@ -181,7 +181,7 @@ services: <<: *clickhouse-depend frontend: - image: signoz/frontend:${DOCKER_TAG:-0.15.0} + image: signoz/frontend:${DOCKER_TAG:-0.16.0} container_name: frontend restart: on-failure depends_on: @@ -193,7 +193,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.3} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.4} command: ["--config=/etc/otel-collector-config.yaml"] user: root # required for reading docker container logs volumes: @@ -202,6 +202,7 @@ services: environment: - OTEL_RESOURCE_ATTRIBUTES=host.name=signoz-host,os.type=linux - DOCKER_MULTI_NODE_CLUSTER=false + - LOW_CARDINAL_EXCEPTION_GROUPING=false ports: # - "1777:1777" # pprof extension - "4317:4317" # OTLP gRPC receiver @@ -218,7 +219,7 @@ services: <<: *clickhouse-depend otel-collector-metrics: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.3} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.4} command: ["--config=/etc/otel-collector-metrics-config.yaml"] volumes: - ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml @@ -231,15 +232,15 @@ services: <<: *clickhouse-depend hotrod: - image: jaegertracing/example-hotrod:1.30 - container_name: hotrod - logging: - options: - max-size: 50m - max-file: "3" - command: ["all"] - environment: - - JAEGER_ENDPOINT=http://otel-collector:14268/api/traces + image: jaegertracing/example-hotrod:1.30 + container_name: hotrod + logging: + options: + max-size: 50m + max-file: "3" + command: ["all"] + environment: + - JAEGER_ENDPOINT=http://otel-collector:14268/api/traces load-hotrod: image: "grubykarol/locust:1.2.3-python3.9-alpine3.12" diff --git a/deploy/docker/clickhouse-setup/otel-collector-config.yaml b/deploy/docker/clickhouse-setup/otel-collector-config.yaml index 00d9546867..409580696a 100644 --- a/deploy/docker/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker/clickhouse-setup/otel-collector-config.yaml @@ -119,6 +119,7 @@ exporters: clickhousetraces: datasource: tcp://clickhouse:9000/?database=signoz_traces docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} + low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING} clickhousemetricswrite: endpoint: tcp://clickhouse:9000/?database=signoz_metrics resource_to_telemetry_conversion: diff --git a/deploy/install.sh b/deploy/install.sh index ba69553b50..ef4e75171a 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -81,6 +81,11 @@ check_os() { os="centos" package_manager="yum" ;; + Rocky*) + desired_os=1 + os="centos" + package_manager="yum" + ;; SLES*) desired_os=1 os="sles" diff --git a/frontend/jest.config.ts b/frontend/jest.config.ts index f85772a0e8..9021421c78 100644 --- a/frontend/jest.config.ts +++ b/frontend/jest.config.ts @@ -25,6 +25,7 @@ const config: Config.InitialOptions = { setupFilesAfterEnv: ['jest.setup.ts'], testPathIgnorePatterns: ['/node_modules/', '/public/'], moduleDirectories: ['node_modules', 'src'], + testEnvironment: 'jest-environment-jsdom', testEnvironmentOptions: { 'jest-playwright': { browsers: ['chromium', 'firefox', 'webkit'], diff --git a/frontend/package.json b/frontend/package.json index bd06d4893f..b0aec96f2b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,10 +31,6 @@ "@ant-design/icons": "4.8.0", "@grafana/data": "^8.4.3", "@monaco-editor/react": "^4.3.1", - "@testing-library/jest-dom": "^5.11.4", - "@testing-library/react": "^11.1.0", - "@testing-library/user-event": "^12.1.10", - "@welldone-software/why-did-you-render": "^6.2.1", "@xstate/react": "^3.0.0", "antd": "5.0.5", "axios": "^0.21.0", @@ -82,7 +78,6 @@ "react-router-dom": "^5.2.0", "react-use": "^17.3.2", "react-virtuoso": "4.0.3", - "react-vis": "^1.11.7", "redux": "^4.0.5", "redux-thunk": "^2.3.0", "stream": "^0.0.2", @@ -122,7 +117,9 @@ "@commitlint/config-conventional": "^16.2.4", "@jest/globals": "^27.5.1", "@playwright/test": "^1.22.0", - "@testing-library/react-hooks": "^7.0.2", + "@testing-library/jest-dom": "5.16.5", + "@testing-library/react": "13.4.0", + "@testing-library/user-event": "14.4.3", "@types/color": "^3.0.3", "@types/compression-webpack-plugin": "^9.0.0", "@types/copy-webpack-plugin": "^8.0.1", @@ -138,6 +135,7 @@ "@types/react-dom": "18.0.10", "@types/react-grid-layout": "^1.1.2", "@types/react-redux": "^7.1.11", + "@types/react-resizable": "3.0.3", "@types/react-router-dom": "^5.1.6", "@types/redux": "^3.6.0", "@types/styled-components": "^5.1.4", @@ -147,6 +145,7 @@ "@types/webpack-dev-server": "^4.3.0", "@typescript-eslint/eslint-plugin": "^4.28.2", "@typescript-eslint/parser": "^4.28.2", + "@welldone-software/why-did-you-render": "6.2.1", "autoprefixer": "^9.0.0", "babel-plugin-styled-components": "^1.12.0", "compression-webpack-plugin": "9.0.0", @@ -176,6 +175,7 @@ "portfinder-sync": "^0.0.2", "prettier": "2.2.1", "react-hot-loader": "^4.13.0", + "react-resizable": "3.0.4", "ts-jest": "^27.1.4", "ts-node": "^10.2.1", "typescript-plugin-css-modules": "^3.4.0", diff --git a/frontend/src/AppRoutes/Private.tsx b/frontend/src/AppRoutes/Private.tsx index 436b184ca4..754b6cbf40 100644 --- a/frontend/src/AppRoutes/Private.tsx +++ b/frontend/src/AppRoutes/Private.tsx @@ -47,6 +47,8 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { const dispatch = useDispatch>(); + const [notifications, NotificationElement] = notification.useNotification(); + const currentRoute = mapRoutes.get('current'); const navigateToLoginIfNotLoggedIn = (isLoggedIn = isLoggedInState): void => { @@ -106,7 +108,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { } else { Logout(); - notification.error({ + notifications.error({ message: response.error || t('something_went_wrong'), }); } @@ -155,7 +157,12 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { // NOTE: disabling this rule as there is no need to have div // eslint-disable-next-line react/jsx-no-useless-fragment - return <>{children}; + return ( + <> + {NotificationElement} + {children} + + ); } interface PrivateRouteProps { diff --git a/frontend/src/api/trace/getSpans.ts b/frontend/src/api/trace/getSpans.ts index c3bb5e0bf1..55fa677e38 100644 --- a/frontend/src/api/trace/getSpans.ts +++ b/frontend/src/api/trace/getSpans.ts @@ -37,7 +37,7 @@ const getSpans = async ( start: String(props.start), end: String(props.end), function: props.function, - groupBy: props.groupBy, + groupBy: props.groupBy === 'none' ? '' : props.groupBy, step: props.step, tags: updatedSelectedTags, ...nonDuration, diff --git a/frontend/src/components/Graph/index.tsx b/frontend/src/components/Graph/index.tsx index b51772d62d..8bc8ee4109 100644 --- a/frontend/src/components/Graph/index.tsx +++ b/frontend/src/components/Graph/index.tsx @@ -23,8 +23,10 @@ import { } from 'chart.js'; import * as chartjsAdapter from 'chartjs-adapter-date-fns'; import annotationPlugin from 'chartjs-plugin-annotation'; +import dayjs from 'dayjs'; import { useIsDarkMode } from 'hooks/useDarkMode'; -import React, { useCallback, useEffect, useRef } from 'react'; +import isEqual from 'lodash-es/isEqual'; +import React, { memo, useCallback, useEffect, useRef } from 'react'; import { hasData } from './hasData'; import { getAxisLabelColor } from './helpers'; @@ -80,6 +82,7 @@ function Graph({ onDragSelect, dragSelectColor, }: GraphProps): JSX.Element { + const nearestDatasetIndex = useRef(null); const chartRef = useRef(null); const isDarkMode = useIsDarkMode(); @@ -150,6 +153,10 @@ function Graph({ }, tooltip: { callbacks: { + title(context) { + const date = dayjs(context[0].parsed.x); + return date.format('MMM DD, YYYY, HH:mm:ss'); + }, label(context) { let label = context.dataset.label || ''; @@ -159,8 +166,16 @@ function Graph({ if (context.parsed.y !== null) { label += getToolTipValue(context.parsed.y.toString(), yAxisUnit); } + return label; }, + labelTextColor(labelData) { + if (labelData.datasetIndex === nearestDatasetIndex.current) { + return 'rgba(255, 255, 255, 1)'; + } + + return 'rgba(255, 255, 255, 0.75)'; + }, }, }, [dragSelectPluginId]: createDragSelectPluginOptions( @@ -226,12 +241,38 @@ function Graph({ tension: 0, cubicInterpolationMode: 'monotone', }, + point: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + hoverBackgroundColor: (ctx: any) => { + if (ctx?.element?.options?.borderColor) { + return ctx.element.options.borderColor; + } + return 'rgba(0,0,0,0.1)'; + }, + hoverRadius: 5, + }, }, onClick: (event, element, chart) => { if (onClickHandler) { onClickHandler(event, element, chart, data); } }, + onHover: (event, _, chart) => { + if (event.native) { + const interactions = chart.getElementsAtEventForMode( + event.native, + 'nearest', + { + intersect: false, + }, + true, + ); + + if (interactions[0]) { + nearestDatasetIndex.current = interactions[0].datasetIndex; + } + } + }, }; const chartHasData = hasData(data); @@ -334,4 +375,7 @@ Graph.defaultProps = { onDragSelect: undefined, dragSelectColor: undefined, }; -export default Graph; + +export default memo(Graph, (prevProps, nextProps) => + isEqual(prevProps.data, nextProps.data), +); diff --git a/frontend/src/components/Logs/AddToQueryHOC.tsx b/frontend/src/components/Logs/AddToQueryHOC.tsx index ea517fa003..d8aee19708 100644 --- a/frontend/src/components/Logs/AddToQueryHOC.tsx +++ b/frontend/src/components/Logs/AddToQueryHOC.tsx @@ -2,7 +2,9 @@ import { Button, Popover } from 'antd'; import { generateFilterQuery } from 'lib/logs/generateFilterQuery'; import React, { memo, useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { Dispatch } from 'redux'; import { AppState } from 'store/reducers'; +import AppActions from 'types/actions'; import { SET_SEARCH_QUERY_STRING } from 'types/actions/logs'; import { ILogsReducer } from 'types/reducer/logs'; @@ -14,7 +16,7 @@ function AddToQueryHOC({ const { searchFilter: { queryString }, } = useSelector((store) => store.logs); - const dispatch = useDispatch(); + const dispatch = useDispatch>(); const generatedQuery = useMemo( () => generateFilterQuery({ fieldKey, fieldValue, type: 'IN' }), @@ -31,7 +33,9 @@ function AddToQueryHOC({ } dispatch({ type: SET_SEARCH_QUERY_STRING, - payload: updatedQueryString, + payload: { + searchQueryString: updatedQueryString, + }, }); }, [dispatch, generatedQuery, queryString]); diff --git a/frontend/src/components/Logs/CopyClipboardHOC.tsx b/frontend/src/components/Logs/CopyClipboardHOC.tsx index bac9dca86a..f7aa461d88 100644 --- a/frontend/src/components/Logs/CopyClipboardHOC.tsx +++ b/frontend/src/components/Logs/CopyClipboardHOC.tsx @@ -7,14 +7,14 @@ function CopyClipboardHOC({ children, }: CopyClipboardHOCProps): JSX.Element { const [value, setCopy] = useCopyToClipboard(); - + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (value.value) { - notification.success({ + notifications.success({ message: 'Copied to clipboard', }); } - }, [value]); + }, [value, notifications]); const onClick = useCallback((): void => { setCopy(textToCopy); @@ -22,6 +22,7 @@ function CopyClipboardHOC({ return ( + {NotificationElement} Copy to clipboard} diff --git a/frontend/src/components/Logs/LogItem/index.tsx b/frontend/src/components/Logs/LogItem/index.tsx index aa24cd7414..bc061651e7 100644 --- a/frontend/src/components/Logs/LogItem/index.tsx +++ b/frontend/src/components/Logs/LogItem/index.tsx @@ -79,6 +79,7 @@ function LogItem({ logData }: LogItemProps): JSX.Element { const dispatch = useDispatch(); const flattenLogData = useMemo(() => FlatLogData(logData), [logData]); const [, setCopy] = useCopyToClipboard(); + const [notifications, NotificationElement] = notification.useNotification(); const handleDetailedView = useCallback(() => { dispatch({ @@ -89,27 +90,22 @@ function LogItem({ logData }: LogItemProps): JSX.Element { const handleCopyJSON = (): void => { setCopy(JSON.stringify(logData, null, 2)); - notification.success({ + notifications.success({ message: 'Copied to clipboard', }); }; return ( + {NotificationElement}
{'{'} <> - + {flattenLogData.stream && ( - + )} ( + e.stopPropagation()} + /> + ), + [], + ); + + const draggableOpts = useMemo( + () => ({ + enableUserSelectHack, + }), + [], + ); + + if (!width) { + // eslint-disable-next-line react/jsx-props-no-spreading + return ; + } + + return ( + + {/* eslint-disable-next-line react/jsx-props-no-spreading */} + + + ); +} + +interface ResizableHeaderProps { + onResize: (e: React.SyntheticEvent, data: ResizeCallbackData) => void; + width: number; +} + +export default ResizableHeader; diff --git a/frontend/src/components/ResizeTable/ResizeTable.tsx b/frontend/src/components/ResizeTable/ResizeTable.tsx new file mode 100644 index 0000000000..b7aee770c9 --- /dev/null +++ b/frontend/src/components/ResizeTable/ResizeTable.tsx @@ -0,0 +1,51 @@ +import { Table } from 'antd'; +import type { TableProps } from 'antd/es/table'; +import { ColumnsType } from 'antd/lib/table'; +import React, { useCallback, useMemo, useState } from 'react'; +import { ResizeCallbackData } from 'react-resizable'; + +import ResizableHeader from './ResizableHeader'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function ResizeTable({ columns, ...restprops }: TableProps): JSX.Element { + const [columnsData, setColumns] = useState(columns || []); + + const handleResize = useCallback( + (index: number) => ( + _e: React.SyntheticEvent, + { size }: ResizeCallbackData, + ): void => { + const newColumns = [...columnsData]; + newColumns[index] = { + ...newColumns[index], + width: size.width, + }; + setColumns(newColumns); + }, + [columnsData], + ); + + const mergeColumns = useMemo( + () => + columnsData.map((col, index) => ({ + ...col, + onHeaderCell: (column: ColumnsType[number]): unknown => ({ + width: column.width, + onResize: handleResize(index), + }), + })), + [columnsData, handleResize], + ); + + return ( + } + /> + ); +} + +export default ResizeTable; diff --git a/frontend/src/components/ResizeTable/config.ts b/frontend/src/components/ResizeTable/config.ts new file mode 100644 index 0000000000..0186ddd1a3 --- /dev/null +++ b/frontend/src/components/ResizeTable/config.ts @@ -0,0 +1 @@ +export const enableUserSelectHack = { enableUserSelectHack: false }; diff --git a/frontend/src/components/ResizeTable/index.ts b/frontend/src/components/ResizeTable/index.ts new file mode 100644 index 0000000000..ec177d06eb --- /dev/null +++ b/frontend/src/components/ResizeTable/index.ts @@ -0,0 +1,4 @@ +import ResizableHeader from './ResizableHeader'; +import ResizeTable from './ResizeTable'; + +export { ResizableHeader, ResizeTable }; diff --git a/frontend/src/components/ResizeTable/styles.ts b/frontend/src/components/ResizeTable/styles.ts new file mode 100644 index 0000000000..acb0c28219 --- /dev/null +++ b/frontend/src/components/ResizeTable/styles.ts @@ -0,0 +1,11 @@ +import styled from 'styled-components'; + +export const SpanStyle = styled.span` + position: absolute; + right: -5px; + bottom: 0; + z-index: 1; + width: 10px; + height: 100%; + cursor: col-resize; +`; diff --git a/frontend/src/constants/theme.ts b/frontend/src/constants/theme.ts index 7e3bb042f8..36dfe4bd87 100644 --- a/frontend/src/constants/theme.ts +++ b/frontend/src/constants/theme.ts @@ -37,6 +37,7 @@ const themeColors = { matterhornGrey: '#555555', whiteCream: '#ffffffd5', black: '#000000', + lightgrey: '#ddd', }; export { themeColors }; diff --git a/frontend/src/container/AllAlertChannels/AlertChannels.tsx b/frontend/src/container/AllAlertChannels/AlertChannels.tsx index 762304a871..03a9e8a40e 100644 --- a/frontend/src/container/AllAlertChannels/AlertChannels.tsx +++ b/frontend/src/container/AllAlertChannels/AlertChannels.tsx @@ -1,6 +1,7 @@ /* eslint-disable react/display-name */ -import { Button, notification, Table } from 'antd'; +import { Button, notification } from 'antd'; import { ColumnsType } from 'antd/lib/table'; +import { ResizeTable } from 'components/ResizeTable'; import ROUTES from 'constants/routes'; import useComponentPermission from 'hooks/useComponentPermission'; import history from 'lib/history'; @@ -34,11 +35,13 @@ function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element { title: t('column_channel_name'), dataIndex: 'name', key: 'name', + width: 100, }, { title: t('column_channel_type'), dataIndex: 'type', key: 'type', + width: 80, }, ]; @@ -48,6 +51,7 @@ function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element { dataIndex: 'id', key: 'action', align: 'center', + width: 80, render: (id: string): JSX.Element => ( <>
+ ); } diff --git a/frontend/src/container/AllError/index.tsx b/frontend/src/container/AllError/index.tsx index 78db55123e..4ab3e7c100 100644 --- a/frontend/src/container/AllError/index.tsx +++ b/frontend/src/container/AllError/index.tsx @@ -5,7 +5,6 @@ import { Input, notification, Space, - Table, TableProps, Tooltip, Typography, @@ -16,6 +15,7 @@ import { ColumnsType } from 'antd/lib/table'; import { FilterConfirmProps } from 'antd/lib/table/interface'; import getAll from 'api/errors/getAll'; import getErrorCounts from 'api/errors/getErrorCounts'; +import { ResizeTable } from 'components/ResizeTable'; import ROUTES from 'constants/routes'; import dayjs from 'dayjs'; import useUrlQuery from 'hooks/useUrlQuery'; @@ -127,14 +127,15 @@ function AllErrors(): JSX.Element { enabled: !loading, }, ]); + const [notifications, NotificationElement] = notification.useNotification(); useEffect(() => { if (data?.error) { - notification.error({ + notifications.error({ message: data.error || t('something_went_wrong'), }); } - }, [data?.error, data?.payload, t]); + }, [data?.error, data?.payload, t, notifications]); const getDateValue = (value: string): JSX.Element => ( {dayjs(value).format('DD/MM/YYYY HH:mm:ss A')} @@ -258,6 +259,7 @@ function AllErrors(): JSX.Element { const columns: ColumnsType = [ { title: 'Exception Type', + width: 100, dataIndex: 'exceptionType', key: 'exceptionType', ...getFilter(onExceptionTypeFilter, 'Search By Exception', 'exceptionType'), @@ -283,6 +285,7 @@ function AllErrors(): JSX.Element { title: 'Error Message', dataIndex: 'exceptionMessage', key: 'exceptionMessage', + width: 100, render: (value): JSX.Element => ( value}> + <> + {NotificationElement} + + ); } diff --git a/frontend/src/container/AppLayout/index.tsx b/frontend/src/container/AppLayout/index.tsx index 3ff1cfe6c4..189aac2e33 100644 --- a/frontend/src/container/AppLayout/index.tsx +++ b/frontend/src/container/AppLayout/index.tsx @@ -91,6 +91,8 @@ function AppLayout(props: AppLayoutProps): JSX.Element { const latestVersionCounter = useRef(0); const latestConfigCounter = useRef(0); + const [notifications, NotificationElement] = notification.useNotification(); + useEffect(() => { if ( getUserLatestVersionResponse.isFetched && @@ -105,7 +107,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element { isError: true, }, }); - notification.error({ + notifications.error({ message: t('oops_something_went_wrong_version'), }); } @@ -123,7 +125,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element { isError: true, }, }); - notification.error({ + notifications.error({ message: t('oops_something_went_wrong_version'), }); } @@ -219,12 +221,14 @@ function AppLayout(props: AppLayoutProps): JSX.Element { getDynamicConfigsResponse.data, getDynamicConfigsResponse.isFetched, getDynamicConfigsResponse.isSuccess, + notifications, ]); const isToDisplayLayout = isLoggedIn; return ( + {NotificationElement} {isToDisplayLayout &&
} {isToDisplayLayout && } diff --git a/frontend/src/container/CreateAlertRule/defaults.ts b/frontend/src/container/CreateAlertRule/defaults.ts index c12233bb13..5ce07a03be 100644 --- a/frontend/src/container/CreateAlertRule/defaults.ts +++ b/frontend/src/container/CreateAlertRule/defaults.ts @@ -6,6 +6,16 @@ import { defaultMatchType, } from 'types/api/alerts/def'; +const defaultAlertDescription = + 'This alert is fired when the defined metric (current value: {{$value}}) crosses the threshold ({{$threshold}})'; +const defaultAlertSummary = + 'The rule threshold is set to {{$threshold}}, and the observed metric value is {{$value}}'; + +const defaultAnnotations = { + description: defaultAlertDescription, + summary: defaultAlertSummary, +}; + export const alertDefaults: AlertDef = { alertType: AlertTypes.METRICS_BASED_ALERT, condition: { @@ -38,9 +48,7 @@ export const alertDefaults: AlertDef = { labels: { severity: 'warning', }, - annotations: { - description: 'A new alert', - }, + annotations: defaultAnnotations, evalWindow: defaultEvalWindow, }; @@ -85,9 +93,7 @@ export const logAlertDefaults: AlertDef = { severity: 'warning', details: `${window.location.protocol}//${window.location.host}/logs`, }, - annotations: { - description: 'A new log-based alert', - }, + annotations: defaultAnnotations, evalWindow: defaultEvalWindow, }; @@ -132,9 +138,7 @@ export const traceAlertDefaults: AlertDef = { severity: 'warning', details: `${window.location.protocol}//${window.location.host}/traces`, }, - annotations: { - description: 'A new trace-based alert', - }, + annotations: defaultAnnotations, evalWindow: defaultEvalWindow, }; @@ -179,8 +183,6 @@ export const exceptionAlertDefaults: AlertDef = { severity: 'warning', details: `${window.location.protocol}//${window.location.host}/exceptions`, }, - annotations: { - description: 'A new exceptions-based alert', - }, + annotations: defaultAnnotations, evalWindow: defaultEvalWindow, }; diff --git a/frontend/src/container/ErrorDetails/index.tsx b/frontend/src/container/ErrorDetails/index.tsx index d42d2e4a3e..57a8c92906 100644 --- a/frontend/src/container/ErrorDetails/index.tsx +++ b/frontend/src/container/ErrorDetails/index.tsx @@ -1,6 +1,7 @@ -import { Button, Divider, notification, Space, Table, Typography } from 'antd'; +import { Button, Divider, notification, Space, Typography } from 'antd'; import getNextPrevId from 'api/errors/getNextPrevId'; import Editor from 'components/Editor'; +import { ResizeTable } from 'components/ResizeTable'; import { getNanoSeconds } from 'container/AllError/utils'; import dayjs from 'dayjs'; import history from 'lib/history'; @@ -53,12 +54,14 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { () => [ { title: 'Key', + width: 100, dataIndex: 'key', key: 'key', }, { title: 'Value', dataIndex: 'value', + width: 100, key: 'value', }, ], @@ -77,13 +80,15 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { [], ); + const [notifications, NotificationElement] = notification.useNotification(); + const onClickErrorIdHandler = async ( id: string, timestamp: string, ): Promise => { try { if (id.length === 0) { - notification.error({ + notifications.error({ message: 'Error Id cannot be empty', }); return; @@ -95,7 +100,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { }×tamp=${getNanoSeconds(timestamp)}&errorId=${id}`, ); } catch (error) { - notification.error({ + notifications.error({ message: t('something_went_wrong'), }); } @@ -116,6 +121,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { return ( <> + {NotificationElement} {errorDetail.exceptionType} {errorDetail.exceptionMessage} @@ -167,7 +173,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element { -
+ diff --git a/frontend/src/container/FormAlertChannels/Settings/LabelFilter.tsx b/frontend/src/container/FormAlertChannels/Settings/LabelFilter.tsx index 2d71c520ce..21311e416d 100644 --- a/frontend/src/container/FormAlertChannels/Settings/LabelFilter.tsx +++ b/frontend/src/container/FormAlertChannels/Settings/LabelFilter.tsx @@ -1,5 +1,4 @@ -import { Input, Select } from 'antd'; -import FormItem from 'antd/lib/form/FormItem'; +import { Form, Input, Select } from 'antd'; import { LabelFilterStatement } from 'container/CreateAlertChannels/config'; import React from 'react'; @@ -10,7 +9,7 @@ const { Option } = Select; // point function LabelFilterForm({ setFilter }: LabelFilterProps): JSX.Element { return ( - + { setSelectedConfig((value) => ({ @@ -20,9 +19,9 @@ function PagerForm({ setSelectedConfig }: PagerFormProps): JSX.Element { })); }} /> - + - - + - - + - - + - - + - - + - - - + - + - - + ); } diff --git a/frontend/src/container/FormAlertChannels/Settings/Slack.tsx b/frontend/src/container/FormAlertChannels/Settings/Slack.tsx index 89ea3d62f9..9415a500d7 100644 --- a/frontend/src/container/FormAlertChannels/Settings/Slack.tsx +++ b/frontend/src/container/FormAlertChannels/Settings/Slack.tsx @@ -1,5 +1,4 @@ -import { Input } from 'antd'; -import FormItem from 'antd/lib/form/FormItem'; +import { Form, Input } from 'antd'; import React from 'react'; import { useTranslation } from 'react-i18next'; @@ -12,7 +11,7 @@ function Slack({ setSelectedConfig }: SlackProps): JSX.Element { return ( <> - + { setSelectedConfig((value) => ({ @@ -21,9 +20,9 @@ function Slack({ setSelectedConfig }: SlackProps): JSX.Element { })); }} /> - + - - + - +