diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c1aa885b6a..fd42658745 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -2,6 +2,6 @@ # Owners are automatically requested for review for PRs that changes code # that they own. * @ankitnayan -/frontend/ @palashgdev @pranshuchittora +/frontend/ @palashgdev /deploy/ @prashant-shahi **/query-service/ @srikanthccv diff --git a/.github/workflows/staging-deployment.yaml b/.github/workflows/staging-deployment.yaml index c655d69df2..6de51f4733 100644 --- a/.github/workflows/staging-deployment.yaml +++ b/.github/workflows/staging-deployment.yaml @@ -11,21 +11,23 @@ jobs: environment: staging steps: - name: Executing remote ssh commands using ssh key - uses: appleboy/ssh-action@v0.1.6 + uses: appleboy/ssh-action@v0.1.8 env: GITHUB_BRANCH: develop GITHUB_SHA: ${{ github.sha }} with: host: ${{ secrets.HOST_DNS }} username: ${{ secrets.USERNAME }} - key: ${{ secrets.EC2_SSH_KEY }} + key: ${{ secrets.SSH_KEY }} envs: GITHUB_BRANCH,GITHUB_SHA command_timeout: 60m script: | echo "GITHUB_BRANCH: ${GITHUB_BRANCH}" echo "GITHUB_SHA: ${GITHUB_SHA}" export DOCKER_TAG="${GITHUB_SHA:0:7}" # needed for child process to access it + export OTELCOL_TAG="main" docker system prune --force + docker pull signoz/signoz-otel-collector:main cd ~/signoz git status git add . diff --git a/.github/workflows/testing-deployment.yaml b/.github/workflows/testing-deployment.yaml index d122291d42..d65a4e8bbc 100644 --- a/.github/workflows/testing-deployment.yaml +++ b/.github/workflows/testing-deployment.yaml @@ -11,14 +11,14 @@ jobs: if: ${{ github.event.label.name == 'testing-deploy' }} steps: - name: Executing remote ssh commands using ssh key - uses: appleboy/ssh-action@v0.1.6 + uses: appleboy/ssh-action@v0.1.8 env: GITHUB_BRANCH: ${{ github.head_ref || github.ref_name }} GITHUB_SHA: ${{ github.sha }} with: host: ${{ secrets.HOST_DNS }} username: ${{ secrets.USERNAME }} - key: ${{ secrets.EC2_SSH_KEY }} + key: ${{ secrets.SSH_KEY }} envs: GITHUB_BRANCH,GITHUB_SHA command_timeout: 60m script: | diff --git a/README.de-de.md b/README.de-de.md index 55dd7f4c22..6587756b9b 100644 --- a/README.de-de.md +++ b/README.de-de.md @@ -85,9 +85,9 @@ Hier findest du die vollständige Liste von unterstützten Programmiersprachen - ### Bereitstellung mit Docker -Bitte folge den [hier](https://signoz.io/docs/deployment/docker/) aufgelisteten Schritten um deine Anwendung mit Docker bereitzustellen. +Bitte folge den [hier](https://signoz.io/docs/install/docker/) aufgelisteten Schritten um deine Anwendung mit Docker bereitzustellen. -Die [Anleitungen zur Fehlerbehebung](https://signoz.io/docs/deployment/troubleshooting) könnten hilfreich sein, falls du auf irgendwelche Schwierigkeiten stößt. +Die [Anleitungen zur Fehlerbehebung](https://signoz.io/docs/install/troubleshooting/) könnten hilfreich sein, falls du auf irgendwelche Schwierigkeiten stößt.

 

diff --git a/README.md b/README.md index 70779f3de5..4920ca9a26 100644 --- a/README.md +++ b/README.md @@ -130,9 +130,9 @@ You can find the complete list of languages here - https://opentelemetry.io/docs ### Deploy using Docker -Please follow the steps listed [here](https://signoz.io/docs/deployment/docker/) to install using docker +Please follow the steps listed [here](https://signoz.io/docs/install/docker/) to install using docker -The [troubleshooting instructions](https://signoz.io/docs/deployment/troubleshooting) may be helpful if you face any issues. +The [troubleshooting instructions](https://signoz.io/docs/install/troubleshooting/) may be helpful if you face any issues.

 

diff --git a/README.pt-br.md b/README.pt-br.md index ce168b4101..c817e8afb9 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -84,9 +84,9 @@ Você pode encontrar a lista completa de linguagens aqui - https://opentelemetry ### Implantar usando Docker -Siga as etapas listadas [aqui](https://signoz.io/docs/deployment/docker/) para instalar usando o Docker. +Siga as etapas listadas [aqui](https://signoz.io/docs/install/docker/) para instalar usando o Docker. -Esse [guia para solução de problemas](https://signoz.io/docs/deployment/troubleshooting) pode ser útil se você enfrentar quaisquer problemas. +Esse [guia para solução de problemas](https://signoz.io/docs/install/troubleshooting/) pode ser útil se você enfrentar quaisquer problemas.

 

diff --git a/README.zh-cn.md b/README.zh-cn.md index 3658eeb520..aaa89551bf 100644 --- a/README.zh-cn.md +++ b/README.zh-cn.md @@ -80,9 +80,9 @@ SigNoz帮助开发人员监控应用并排查已部署应用中的问题。SigNo ### 使用Docker部署 -请按照[这里](https://signoz.io/docs/deployment/docker/)列出的步骤使用Docker来安装 +请按照[这里](https://signoz.io/docs/install/docker/)列出的步骤使用Docker来安装 -如果你遇到任何问题,这个[排查指南](https://signoz.io/docs/deployment/troubleshooting)会对你有帮助。 +如果你遇到任何问题,这个[排查指南](https://signoz.io/docs/install/troubleshooting/)会对你有帮助。

 

diff --git a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml index a0c2ba8105..42dbd5afc6 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.17.0 + image: signoz/query-service:0.18.1 command: ["-config=/root/config/prometheus.yml"] # ports: # - "6060:6060" # pprof port @@ -166,7 +166,7 @@ services: <<: *clickhouse-depend frontend: - image: signoz/frontend:0.17.0 + image: signoz/frontend:0.18.1 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.6 + image: signoz/signoz-otel-collector:0.66.7 command: ["--config=/etc/otel-collector-config.yaml"] user: root # required for reading docker container logs volumes: @@ -208,7 +208,7 @@ services: <<: *clickhouse-depend otel-collector-metrics: - image: signoz/signoz-otel-collector:0.66.6 + image: signoz/signoz-otel-collector:0.66.7 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-core.yaml b/deploy/docker/clickhouse-setup/docker-compose-core.yaml index e7c9360879..80bd4a9890 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.6 + image: signoz/signoz-otel-collector:0.66.7 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.6 + image: signoz/signoz-otel-collector:0.66.7 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 4906ba4c10..9a967cc800 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.17.0} + image: signoz/query-service:${DOCKER_TAG:-0.18.1} 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.17.0} + image: signoz/frontend:${DOCKER_TAG:-0.18.1} 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.6} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.7} command: ["--config=/etc/otel-collector-config.yaml"] user: root # required for reading docker container logs volumes: @@ -219,7 +219,7 @@ services: <<: *clickhouse-depend otel-collector-metrics: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.6} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.66.7} command: ["--config=/etc/otel-collector-metrics-config.yaml"] volumes: - ./otel-collector-metrics-config.yaml:/etc/otel-collector-metrics-config.yaml diff --git a/deploy/install.sh b/deploy/install.sh index e8a14a5821..e908dd8952 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -125,7 +125,7 @@ check_ports_occupied() { echo "+++++++++++ ERROR ++++++++++++++++++++++" echo "SigNoz requires ports 3301 & 4317 to be open. Please shut down any other service(s) that may be running on these ports." - echo "You can run SigNoz on another port following this guide https://signoz.io/docs/deployment/docker#troubleshooting" + echo "You can run SigNoz on another port following this guide https://signoz.io/docs/install/troubleshooting/" echo "++++++++++++++++++++++++++++++++++++++++" echo "" exit 1 @@ -249,7 +249,7 @@ bye() { # Prints a friendly good bye message and exits the script. echo "" echo -e "$sudo_cmd docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml ps -a" - # echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker#troubleshooting" + echo "Please read our troubleshooting guide https://signoz.io/docs/install/troubleshooting/" echo "or reach us for support in #help channel in our Slack Community https://signoz.io/slack" echo "++++++++++++++++++++++++++++++++++++++++" @@ -500,7 +500,7 @@ if [[ $status_code -ne 200 ]]; then echo -e "$sudo_cmd docker-compose -f ./docker/clickhouse-setup/docker-compose.yaml ps -a" - echo "Please read our troubleshooting guide https://signoz.io/docs/deployment/docker/#troubleshooting-of-common-issues" + echo "Please read our troubleshooting guide https://signoz.io/docs/install/troubleshooting/" echo "or reach us on SigNoz for support https://signoz.io/slack" echo "++++++++++++++++++++++++++++++++++++++++" diff --git a/frontend/jest.setup.ts b/frontend/jest.setup.ts index b3b8061422..c9441402d9 100644 --- a/frontend/jest.setup.ts +++ b/frontend/jest.setup.ts @@ -1,5 +1,20 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +/* eslint-disable object-shorthand */ +/* eslint-disable func-names */ + /** * Adds custom matchers from the react testing library to all tests */ import '@testing-library/jest-dom'; import 'jest-styled-components'; + +// Mock window.matchMedia +window.matchMedia = + window.matchMedia || + function (): any { + return { + matches: false, + addListener: function () {}, + removeListener: function () {}, + }; + }; diff --git a/frontend/src/AppRoutes/index.tsx b/frontend/src/AppRoutes/index.tsx index 832e557e49..edfe843882 100644 --- a/frontend/src/AppRoutes/index.tsx +++ b/frontend/src/AppRoutes/index.tsx @@ -4,6 +4,7 @@ import Spinner from 'components/Spinner'; import AppLayout from 'container/AppLayout'; import { useThemeConfig } from 'hooks/useDarkMode'; import { NotificationProvider } from 'hooks/useNotifications'; +import { ResourceProvider } from 'hooks/useResourceAttribute'; import history from 'lib/history'; import { QueryBuilderProvider } from 'providers/QueryBuilder'; import React, { Suspense } from 'react'; @@ -17,30 +18,32 @@ function App(): JSX.Element { return ( - - + + - - - }> - - {routes.map(({ path, component, exact }) => ( - - ))} + + + + }> + + {routes.map(({ path, component, exact }) => ( + + ))} - - - - - + + + + + + - - + + ); } diff --git a/frontend/src/api/apiV1.ts b/frontend/src/api/apiV1.ts index 5145443b2a..2e7df02395 100644 --- a/frontend/src/api/apiV1.ts +++ b/frontend/src/api/apiV1.ts @@ -1,6 +1,7 @@ const apiV1 = '/api/v1/'; export const apiV2 = '/api/v2/'; +export const apiV3 = '/api/v3/'; export const apiAlertManager = '/api/alertmanager'; export default apiV1; diff --git a/frontend/src/api/errors/getAll.ts b/frontend/src/api/errors/getAll.ts index 7014e52a56..8d6793ee87 100644 --- a/frontend/src/api/errors/getAll.ts +++ b/frontend/src/api/errors/getAll.ts @@ -1,7 +1,6 @@ import axios from 'api'; import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; import { AxiosError } from 'axios'; -import createQueryParams from 'lib/createQueryParams'; import { ErrorResponse, SuccessResponse } from 'types/api'; import { PayloadProps, Props } from 'types/api/errors/getAll'; @@ -9,11 +8,17 @@ const getAll = async ( props: Props, ): Promise | ErrorResponse> => { try { - const response = await axios.get( - `/listErrors?${createQueryParams({ - ...props, - })}`, - ); + const response = await axios.post(`/listErrors`, { + start: `${props.start}`, + end: `${props.end}`, + order: props.order, + orderParam: props.orderParam, + limit: props.limit, + offset: props.offset, + exceptionType: props.exceptionType, + serviceName: props.serviceName, + tags: props.tags, + }); return { statusCode: 200, diff --git a/frontend/src/api/errors/getErrorCounts.ts b/frontend/src/api/errors/getErrorCounts.ts index 4992a6d391..977eeb226f 100644 --- a/frontend/src/api/errors/getErrorCounts.ts +++ b/frontend/src/api/errors/getErrorCounts.ts @@ -1,7 +1,6 @@ import axios from 'api'; import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; import { AxiosError } from 'axios'; -import createQueryParams from 'lib/createQueryParams'; import { ErrorResponse, SuccessResponse } from 'types/api'; import { PayloadProps, Props } from 'types/api/errors/getErrorCounts'; @@ -9,11 +8,13 @@ const getErrorCounts = async ( props: Props, ): Promise | ErrorResponse> => { try { - const response = await axios.get( - `/countErrors?${createQueryParams({ - ...props, - })}`, - ); + const response = await axios.post(`/countErrors`, { + start: `${props.start}`, + end: `${props.end}`, + exceptionType: props.exceptionType, + serviceName: props.serviceName, + tags: props.tags, + }); return { statusCode: 200, diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 2a48730f04..584e3b4868 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -9,7 +9,7 @@ import { ENVIRONMENT } from 'constants/env'; import { LOCALSTORAGE } from 'constants/localStorage'; import store from 'store'; -import apiV1, { apiAlertManager, apiV2 } from './apiV1'; +import apiV1, { apiAlertManager, apiV2, apiV3 } from './apiV1'; import { Logout } from './utils'; const interceptorsResponse = ( @@ -109,6 +109,17 @@ ApiV2Instance.interceptors.response.use( ); ApiV2Instance.interceptors.request.use(interceptorsRequestResponse); +// axios V3 +export const ApiV3Instance = axios.create({ + baseURL: `${ENVIRONMENT.baseURL}${apiV3}`, +}); +ApiV3Instance.interceptors.response.use( + interceptorsResponse, + interceptorRejected, +); +ApiV3Instance.interceptors.request.use(interceptorsRequestResponse); +// + AxiosAlertManagerInstance.interceptors.response.use( interceptorsResponse, interceptorRejected, diff --git a/frontend/src/api/queryBuilder/getAggregateAttribute.ts b/frontend/src/api/queryBuilder/getAggregateAttribute.ts new file mode 100644 index 0000000000..15e221d975 --- /dev/null +++ b/frontend/src/api/queryBuilder/getAggregateAttribute.ts @@ -0,0 +1,33 @@ +import { ApiV3Instance } from 'api'; +import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; +import { AxiosError, AxiosResponse } from 'axios'; +// ** Helpers +import { ErrorResponse, SuccessResponse } from 'types/api'; +// ** Types +import { IGetAggregateAttributePayload } from 'types/api/queryBuilder/getAggregatorAttribute'; +import { IQueryAutocompleteResponse } from 'types/api/queryBuilder/queryAutocompleteResponse'; + +export const getAggregateAttribute = async ({ + aggregateOperator, + searchText, + dataSource, +}: IGetAggregateAttributePayload): Promise< + SuccessResponse | ErrorResponse +> => { + try { + const response: AxiosResponse<{ + data: IQueryAutocompleteResponse; + }> = await ApiV3Instance.get( + `autocomplete/aggregate_attributes?aggregateOperator=${aggregateOperator}&dataSource=${dataSource}&searchText=${searchText}`, + ); + + return { + statusCode: 200, + error: null, + message: response.statusText, + payload: response.data.data, + }; + } catch (e) { + return ErrorResponseHandler(e as AxiosError); + } +}; diff --git a/frontend/src/api/queryBuilder/getAttributeKeys.ts b/frontend/src/api/queryBuilder/getAttributeKeys.ts new file mode 100644 index 0000000000..439c20f132 --- /dev/null +++ b/frontend/src/api/queryBuilder/getAttributeKeys.ts @@ -0,0 +1,34 @@ +import { ApiV3Instance } from 'api'; +import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; +import { AxiosError, AxiosResponse } from 'axios'; +import { ErrorResponse, SuccessResponse } from 'types/api'; +// ** Types +import { IGetAttributeKeysPayload } from 'types/api/queryBuilder/getAttributeKeys'; +import { IQueryAutocompleteResponse } from 'types/api/queryBuilder/queryAutocompleteResponse'; + +export const getAggregateKeys = async ({ + aggregateOperator, + searchText, + dataSource, + aggregateAttribute, + tagType, +}: IGetAttributeKeysPayload): Promise< + SuccessResponse | ErrorResponse +> => { + try { + const response: AxiosResponse<{ + data: IQueryAutocompleteResponse; + }> = await ApiV3Instance.get( + `autocomplete/attribute_keys?aggregateOperator=${aggregateOperator}&dataSource=${dataSource}&aggregateAttribute=${aggregateAttribute}&tagType=${tagType}&searchText=${searchText}`, + ); + + return { + statusCode: 200, + error: null, + message: response.statusText, + payload: response.data.data, + }; + } catch (e) { + return ErrorResponseHandler(e as AxiosError); + } +}; diff --git a/frontend/src/api/queryBuilder/getAttributesKeysValues.ts b/frontend/src/api/queryBuilder/getAttributesKeysValues.ts new file mode 100644 index 0000000000..f5b938a345 --- /dev/null +++ b/frontend/src/api/queryBuilder/getAttributesKeysValues.ts @@ -0,0 +1,63 @@ +import { ApiV3Instance } from 'api'; +import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; +import { AxiosError } from 'axios'; +import { ErrorResponse, SuccessResponse } from 'types/api'; + +export type TagKeyValueProps = { + dataSource: string; + aggregateOperator?: string; + aggregateAttribute?: string; + searchText?: string; + attributeKey?: string; +}; + +export interface AttributeKeyOptions { + key: string; + type: string; + dataType: 'string' | 'boolean' | 'number'; + isColumn: boolean; +} + +export const getAttributesKeys = async ( + props: TagKeyValueProps, +): Promise | ErrorResponse> => { + try { + const response = await ApiV3Instance.get( + `/autocomplete/attribute_keys?aggregateOperator=${props.aggregateOperator}&dataSource=${props.dataSource}&aggregateAttribute=${props.aggregateAttribute}&searchText=${props.searchText}`, + ); + + return { + statusCode: 200, + error: null, + message: response.data.status, + payload: response.data.data.attributeKeys, + }; + } catch (error) { + return ErrorResponseHandler(error as AxiosError); + } +}; + +export interface TagValuePayloadProps { + boolAttributeValues: null | string[]; + numberAttributeValues: null | string[]; + stringAttributeValues: null | string[]; +} + +export const getAttributesValues = async ( + props: TagKeyValueProps, +): Promise | ErrorResponse> => { + try { + const response = await ApiV3Instance.get( + `/autocomplete/attribute_values?aggregateOperator=${props.aggregateOperator}&dataSource=${props.dataSource}&aggregateAttribute=${props.aggregateAttribute}&searchText=${props.searchText}&attributeKey=${props.attributeKey}`, + ); + + return { + statusCode: 200, + error: null, + message: response.data.status, + payload: response.data.data, + }; + } catch (error) { + return ErrorResponseHandler(error as AxiosError); + } +}; diff --git a/frontend/src/api/trace/getSpans.ts b/frontend/src/api/trace/getSpans.ts index 8b56caa46d..261b2652c6 100644 --- a/frontend/src/api/trace/getSpans.ts +++ b/frontend/src/api/trace/getSpans.ts @@ -10,7 +10,7 @@ const getSpans = async ( ): Promise | ErrorResponse> => { try { const updatedSelectedTags = props.selectedTags.map((e) => ({ - Key: e.Key, + Key: `${e.Key}.(string)`, Operator: e.Operator, StringValues: e.StringValues, NumberValues: e.NumberValues, diff --git a/frontend/src/api/trace/getSpansAggregate.ts b/frontend/src/api/trace/getSpansAggregate.ts index cfa1f7e31f..7f245605fc 100644 --- a/frontend/src/api/trace/getSpansAggregate.ts +++ b/frontend/src/api/trace/getSpansAggregate.ts @@ -28,7 +28,7 @@ const getSpanAggregate = async ( }); const updatedSelectedTags = props.selectedTags.map((e) => ({ - Key: e.Key, + Key: `${e.Key}.(string)`, Operator: e.Operator, StringValues: e.StringValues, NumberValues: e.NumberValues, diff --git a/frontend/src/components/Logs/TableView/styles.ts b/frontend/src/components/Logs/TableView/styles.ts index cd361b9c5e..951404afec 100644 --- a/frontend/src/components/Logs/TableView/styles.ts +++ b/frontend/src/components/Logs/TableView/styles.ts @@ -16,6 +16,4 @@ export const TableBodyContent = styled.div` font-size: 0.875rem; line-height: 2rem; - - cursor: pointer; `; diff --git a/frontend/src/components/TextToolTip/index.tsx b/frontend/src/components/TextToolTip/index.tsx index 7e6c04c6f1..64a9cd053a 100644 --- a/frontend/src/components/TextToolTip/index.tsx +++ b/frontend/src/components/TextToolTip/index.tsx @@ -1,23 +1,40 @@ -/* eslint-disable react/no-unstable-nested-components */ +import { grey } from '@ant-design/colors'; import { QuestionCircleFilled } from '@ant-design/icons'; import { Tooltip } from 'antd'; -import React from 'react'; +import { themeColors } from 'constants/theme'; +import { useIsDarkMode } from 'hooks/useDarkMode'; +import React, { useMemo } from 'react'; + +import { style } from './styles'; function TextToolTip({ text, url }: TextToolTipProps): JSX.Element { + const isDarkMode = useIsDarkMode(); + + const overlay = useMemo( + () => ( +
+ {`${text} `} + {url && ( + + here + + )} +
+ ), + [text, url], + ); + + const iconStyle = useMemo( + () => ({ + ...style, + color: isDarkMode ? themeColors.whiteCream : grey[0], + }), + [isDarkMode], + ); + return ( - ( -
- {`${text} `} - {url && ( - - here - - )} -
- )} - > - + + ); } diff --git a/frontend/src/components/TextToolTip/styles.ts b/frontend/src/components/TextToolTip/styles.ts new file mode 100644 index 0000000000..bb2532182d --- /dev/null +++ b/frontend/src/components/TextToolTip/styles.ts @@ -0,0 +1 @@ +export const style = { fontSize: '1.3125rem' }; diff --git a/frontend/src/constants/query.ts b/frontend/src/constants/query.ts index 29221e9f9c..35c1e2c2ca 100644 --- a/frontend/src/constants/query.ts +++ b/frontend/src/constants/query.ts @@ -1,5 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/naming-convention -export enum METRICS_PAGE_QUERY_PARAM { +export enum QueryParams { interval = 'interval', startTime = 'startTime', endTime = 'endTime', @@ -12,4 +11,5 @@ export enum METRICS_PAGE_QUERY_PARAM { selectedTags = 'selectedTags', aggregationOption = 'aggregationOption', entity = 'entity', + resourceAttributes = 'resourceAttribute', } diff --git a/frontend/src/constants/queryBuilder.ts b/frontend/src/constants/queryBuilder.ts new file mode 100644 index 0000000000..5c81778742 --- /dev/null +++ b/frontend/src/constants/queryBuilder.ts @@ -0,0 +1,177 @@ +// ** Helpers +import { createNewBuilderItemName } from 'lib/newQueryBuilder/createNewBuilderItemName'; +import { LocalDataType } from 'types/api/queryBuilder/queryAutocompleteResponse'; +import { + Having, + IBuilderFormula, + IBuilderQueryForm, +} from 'types/api/queryBuilder/queryBuilderData'; +import { + BoolOperators, + DataSource, + LogsAggregatorOperator, + MetricAggregateOperator, + NumberOperators, + StringOperators, + TracesAggregatorOperator, +} from 'types/common/queryBuilder'; + +export const MAX_FORMULAS = 20; +export const MAX_QUERIES = 26; + +export const formulasNames: string[] = Array.from( + Array(MAX_FORMULAS), + (_, i) => `F${i + 1}`, +); +const alpha: number[] = Array.from(Array(MAX_QUERIES), (_, i) => i + 65); +export const alphabet: string[] = alpha.map((str) => String.fromCharCode(str)); + +export enum QueryBuilderKeys { + GET_AGGREGATE_ATTRIBUTE = 'GET_AGGREGATE_ATTRIBUTE', + GET_AGGREGATE_KEYS = 'GET_AGGREGATE_KEYS', +} + +export const mapOfOperators: Record = { + metrics: Object.values(MetricAggregateOperator), + logs: Object.values(LogsAggregatorOperator), + traces: Object.values(TracesAggregatorOperator), +}; + +export const mapOfFilters: Record = { + // eslint-disable-next-line sonarjs/no-duplicate-string + metrics: ['Aggregation interval', 'Having'], + logs: ['Order by', 'Limit', 'Having', 'Aggregation interval'], + traces: ['Order by', 'Limit', 'Having', 'Aggregation interval'], +}; + +export const initialHavingValues: Having = { + columnName: '', + op: '', + value: [], +}; + +export const initialAggregateAttribute: IBuilderQueryForm['aggregateAttribute'] = { + dataType: null, + key: '', + isColumn: null, + type: null, +}; + +export const initialQueryBuilderFormValues: IBuilderQueryForm = { + dataSource: DataSource.METRICS, + queryName: createNewBuilderItemName({ existNames: [], sourceNames: alphabet }), + aggregateOperator: Object.values(MetricAggregateOperator)[0], + aggregateAttribute: initialAggregateAttribute, + tagFilters: { items: [], op: 'AND' }, + expression: '', + disabled: false, + having: [], + stepInterval: 30, + limit: 10, + orderBy: [], + groupBy: [], + legend: '', + reduceTo: '', +}; + +export const initialFormulaBuilderFormValues: IBuilderFormula = { + label: createNewBuilderItemName({ + existNames: [], + sourceNames: formulasNames, + }), + expression: '', + disabled: false, + legend: '', +}; + +export const operatorsByTypes: Record = { + string: Object.values(StringOperators), + number: Object.values(NumberOperators), + bool: Object.values(BoolOperators), +}; + +export type IQueryBuilderState = 'search'; + +export const QUERY_BUILDER_SEARCH_VALUES = { + MULTIPLY: 'MULTIPLY_VALUE', + SINGLE: 'SINGLE_VALUE', + NON: 'NON_VALUE', + NOT_VALID: 'NOT_VALID', +}; + +export const OPERATORS = { + IN: 'IN', + NIN: 'NOT_IN', + LIKE: 'LIKE', + NLIKE: 'NOT_LIKE', + EQUALS: '=', + NOT_EQUALS: '!=', + EXISTS: 'EXISTS', + NOT_EXISTS: 'NOT_EXISTS', + CONTAINS: 'CONTAINS', + NOT_CONTAINS: 'NOT_CONTAINS', + GTE: '>=', + GT: '>', + LTE: '<=', + LT: '<', +}; + +export const QUERY_BUILDER_OPERATORS_BY_TYPES = { + string: [ + OPERATORS.EQUALS, + OPERATORS.NOT_EQUALS, + OPERATORS.IN, + OPERATORS.NIN, + OPERATORS.LIKE, + OPERATORS.NLIKE, + OPERATORS.CONTAINS, + OPERATORS.NOT_CONTAINS, + OPERATORS.EXISTS, + OPERATORS.NOT_EXISTS, + ], + number: [ + OPERATORS.EQUALS, + OPERATORS.NOT_EQUALS, + OPERATORS.IN, + OPERATORS.NIN, + OPERATORS.EXISTS, + OPERATORS.NOT_EXISTS, + OPERATORS.GTE, + OPERATORS.GT, + OPERATORS.LTE, + OPERATORS.LT, + ], + boolean: [ + OPERATORS.EQUALS, + OPERATORS.NOT_EQUALS, + OPERATORS.EXISTS, + OPERATORS.NOT_EXISTS, + ], + universal: [ + OPERATORS.EQUALS, + OPERATORS.NOT_EQUALS, + OPERATORS.IN, + OPERATORS.NIN, + OPERATORS.EXISTS, + OPERATORS.NOT_EXISTS, + OPERATORS.LIKE, + OPERATORS.NLIKE, + OPERATORS.GTE, + OPERATORS.GT, + OPERATORS.LTE, + OPERATORS.LT, + OPERATORS.CONTAINS, + OPERATORS.NOT_CONTAINS, + ], +}; + +export const HAVING_OPERATORS: string[] = [ + OPERATORS.EQUALS, + OPERATORS.NOT_EQUALS, + OPERATORS.IN, + OPERATORS.NIN, + OPERATORS.GTE, + OPERATORS.GT, + OPERATORS.LTE, + OPERATORS.LT, +]; diff --git a/frontend/src/container/AllError/index.tsx b/frontend/src/container/AllError/index.tsx index 64d83e70ec..c3b0580f44 100644 --- a/frontend/src/container/AllError/index.tsx +++ b/frontend/src/container/AllError/index.tsx @@ -18,6 +18,8 @@ import { ResizeTable } from 'components/ResizeTable'; import ROUTES from 'constants/routes'; import dayjs from 'dayjs'; import { useNotifications } from 'hooks/useNotifications'; +import useResourceAttribute from 'hooks/useResourceAttribute'; +import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils'; import useUrlQuery from 'hooks/useUrlQuery'; import createQueryParams from 'lib/createQueryParams'; import history from 'lib/history'; @@ -93,9 +95,11 @@ function AllErrors(): JSX.Element { ], ); + const { queries } = useResourceAttribute(); + const [{ isLoading, data }, errorCountResponse] = useQueries([ { - queryKey: ['getAllErrors', updatedPath, maxTime, minTime], + queryKey: ['getAllErrors', updatedPath, maxTime, minTime, queries], queryFn: (): Promise | ErrorResponse> => getAll({ end: maxTime, @@ -106,6 +110,7 @@ function AllErrors(): JSX.Element { orderParam: getUpdatedParams, exceptionType: getUpdatedExceptionType, serviceName: getUpdatedServiceName, + tags: convertRawQueriesToTraceSelectedTags(queries), }), enabled: !loading, }, @@ -116,6 +121,7 @@ function AllErrors(): JSX.Element { minTime, getUpdatedExceptionType, getUpdatedServiceName, + queries, ], queryFn: (): Promise> => getErrorCounts({ @@ -123,6 +129,7 @@ function AllErrors(): JSX.Element { start: minTime, exceptionType: getUpdatedExceptionType, serviceName: getUpdatedServiceName, + tags: convertRawQueriesToTraceSelectedTags(queries), }), enabled: !loading, }, diff --git a/frontend/src/container/LogsSearchFilter/SearchFields/ActionBar.tsx b/frontend/src/container/LogsSearchFilter/SearchFields/ActionBar.tsx index a8d5c777c9..05ba17b8f6 100644 --- a/frontend/src/container/LogsSearchFilter/SearchFields/ActionBar.tsx +++ b/frontend/src/container/LogsSearchFilter/SearchFields/ActionBar.tsx @@ -1,23 +1,15 @@ import { Button, Row } from 'antd'; import React from 'react'; -import { QueryFields } from './utils'; - interface SearchFieldsActionBarProps { - fieldsQuery: QueryFields[][]; - applyUpdate: () => void; - clearFilters: () => void; + applyUpdate: VoidFunction; + clearFilters: VoidFunction; } export function SearchFieldsActionBar({ - fieldsQuery, applyUpdate, clearFilters, }: SearchFieldsActionBarProps): JSX.Element | null { - if (fieldsQuery.length === 0) { - return null; - } - return (