diff --git a/.github/workflows/staging-deployment.yaml b/.github/workflows/staging-deployment.yaml index 21ea7a3c75..b201eb9f64 100644 --- a/.github/workflows/staging-deployment.yaml +++ b/.github/workflows/staging-deployment.yaml @@ -29,6 +29,7 @@ jobs: export PATH="/usr/local/go/bin/:$PATH" # needed for Golang to work docker system prune --force docker pull signoz/signoz-otel-collector:main + docker pull signoz/signoz/signoz-schema-migrator:main cd ~/signoz git status git add . diff --git a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml index debe370026..5658db11a1 100644 --- a/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker-swarm/clickhouse-setup/docker-compose.yaml @@ -146,7 +146,7 @@ services: condition: on-failure query-service: - image: signoz/query-service:0.32.1 + image: signoz/query-service:0.33.0 command: [ "-config=/root/config/prometheus.yml", @@ -186,7 +186,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:0.32.1 + image: signoz/frontend:0.33.0 deploy: restart_policy: condition: on-failure @@ -199,7 +199,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector: - image: signoz/signoz-otel-collector:0.79.12 + image: signoz/signoz-otel-collector:0.79.13 command: [ "--config=/etc/otel-collector-config.yaml", @@ -237,7 +237,7 @@ services: - query-service otel-collector-migrator: - image: signoz/signoz-schema-migrator:0.79.12 + image: signoz/signoz-schema-migrator:0.79.13 deploy: restart_policy: condition: on-failure @@ -250,7 +250,7 @@ services: # - clickhouse-3 otel-collector-metrics: - image: signoz/signoz-otel-collector:0.79.12 + image: signoz/signoz-otel-collector:0.79.13 command: [ "--config=/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 74df932c0f..bc4fa3d3a8 100644 --- a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml @@ -63,38 +63,33 @@ receivers: processors: logstransform/internal: operators: + - type: regex_parser + id: traceid + # https://regex101.com/r/MMfNjk/1 + regex: '(?i)(trace(-|_||)id("|=| |-|:)*)(?P[A-Fa-f0-9]+)' + parse_from: body + parse_to: attributes.temp_trace + if: 'body matches "(?i)(trace(-|_||)id(\"|=| |-|:)*)(?P[A-Fa-f0-9]+)"' + output: spanid + - type: regex_parser + id: spanid + # https://regex101.com/r/uXSwLc/1 + regex: '(?i)(span(-|_||)id("|=| |-|:)*)(?P[A-Fa-f0-9]+)' + parse_from: body + parse_to: attributes.temp_trace + if: 'body matches "(?i)(span(-|_||)id(\"|=| |-|:)*)(?P[A-Fa-f0-9]+)"' + output: trace_parser - type: trace_parser - if: '"trace_id" in attributes or "span_id" in attributes' + id: trace_parser trace_id: - parse_from: attributes.trace_id + parse_from: attributes.temp_trace.trace_id span_id: - parse_from: attributes.span_id - output: remove_trace_id - - type: trace_parser - if: '"traceId" in attributes or "spanId" in attributes' - trace_id: - parse_from: attributes.traceId - span_id: - parse_from: attributes.spanId - output: remove_traceId - - id: remove_traceId - type: remove - if: '"traceId" in attributes' - field: attributes.traceId - output: remove_spanId - - id: remove_spanId - type: remove - if: '"spanId" in attributes' - field: attributes.spanId - - id: remove_trace_id - type: remove - if: '"trace_id" in attributes' - field: attributes.trace_id - output: remove_span_id - - id: remove_span_id - type: remove - if: '"span_id" in attributes' - field: attributes.span_id + parse_from: attributes.temp_trace.span_id + output: remove_temp + - type: remove + id: remove_temp + field: attributes.temp_trace + if: '"temp_trace" in attributes' batch: send_batch_size: 10000 send_batch_max_size: 11000 diff --git a/deploy/docker/clickhouse-setup/docker-compose-core.yaml b/deploy/docker/clickhouse-setup/docker-compose-core.yaml index 6d97d9c266..c24bd1870d 100644 --- a/deploy/docker/clickhouse-setup/docker-compose-core.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose-core.yaml @@ -66,7 +66,7 @@ services: - --storage.path=/data otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.79.12} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.79.13} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -81,7 +81,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: signoz-otel-collector - image: signoz/signoz-otel-collector:0.79.12 + image: signoz/signoz-otel-collector:0.79.13 command: [ "--config=/etc/otel-collector-config.yaml", @@ -118,7 +118,7 @@ services: otel-collector-metrics: container_name: signoz-otel-collector-metrics - image: signoz/signoz-otel-collector:0.79.12 + image: signoz/signoz-otel-collector:0.79.13 command: [ "--config=/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 8ed943ad3c..702720237c 100644 --- a/deploy/docker/clickhouse-setup/docker-compose.yaml +++ b/deploy/docker/clickhouse-setup/docker-compose.yaml @@ -164,7 +164,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.32.1} + image: signoz/query-service:${DOCKER_TAG:-0.33.0} container_name: signoz-query-service command: [ @@ -203,7 +203,7 @@ services: <<: *db-depend frontend: - image: signoz/frontend:${DOCKER_TAG:-0.32.1} + image: signoz/frontend:${DOCKER_TAG:-0.33.0} container_name: signoz-frontend restart: on-failure depends_on: @@ -215,7 +215,7 @@ services: - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf otel-collector-migrator: - image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.79.12} + image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.79.13} container_name: otel-migrator command: - "--dsn=tcp://clickhouse:9000" @@ -229,7 +229,7 @@ services: otel-collector: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.79.12} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.79.13} container_name: signoz-otel-collector command: [ @@ -269,7 +269,7 @@ services: condition: service_healthy otel-collector-metrics: - image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.79.12} + image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.79.13} container_name: signoz-otel-collector-metrics command: [ diff --git a/deploy/docker/clickhouse-setup/otel-collector-config.yaml b/deploy/docker/clickhouse-setup/otel-collector-config.yaml index 1604ae38a1..fe6da5f126 100644 --- a/deploy/docker/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker/clickhouse-setup/otel-collector-config.yaml @@ -64,38 +64,33 @@ receivers: processors: logstransform/internal: operators: + - type: regex_parser + id: traceid + # https://regex101.com/r/MMfNjk/1 + regex: '(?i)(trace(-|_||)id("|=| |-|:)*)(?P[A-Fa-f0-9]+)' + parse_from: body + parse_to: attributes.temp_trace + if: 'body matches "(?i)(trace(-|_||)id(\"|=| |-|:)*)(?P[A-Fa-f0-9]+)"' + output: spanid + - type: regex_parser + id: spanid + # https://regex101.com/r/uXSwLc/1 + regex: '(?i)(span(-|_||)id("|=| |-|:)*)(?P[A-Fa-f0-9]+)' + parse_from: body + parse_to: attributes.temp_trace + if: 'body matches "(?i)(span(-|_||)id(\"|=| |-|:)*)(?P[A-Fa-f0-9]+)"' + output: trace_parser - type: trace_parser - if: '"trace_id" in attributes or "span_id" in attributes' + id: trace_parser trace_id: - parse_from: attributes.trace_id + parse_from: attributes.temp_trace.trace_id span_id: - parse_from: attributes.span_id - output: remove_trace_id - - type: trace_parser - if: '"traceId" in attributes or "spanId" in attributes' - trace_id: - parse_from: attributes.traceId - span_id: - parse_from: attributes.spanId - output: remove_traceId - - id: remove_traceId - type: remove - if: '"traceId" in attributes' - field: attributes.traceId - output: remove_spanId - - id: remove_spanId - type: remove - if: '"spanId" in attributes' - field: attributes.spanId - - id: remove_trace_id - type: remove - if: '"trace_id" in attributes' - field: attributes.trace_id - output: remove_span_id - - id: remove_span_id - type: remove - if: '"span_id" in attributes' - field: attributes.span_id + parse_from: attributes.temp_trace.span_id + output: remove_temp + - type: remove + id: remove_temp + field: attributes.temp_trace + if: '"temp_trace" in attributes' batch: send_batch_size: 10000 send_batch_max_size: 11000 diff --git a/ee/query-service/Dockerfile b/ee/query-service/Dockerfile index 46b2186ec4..dad09b3cbd 100644 --- a/ee/query-service/Dockerfile +++ b/ee/query-service/Dockerfile @@ -1,5 +1,5 @@ # use a minimal alpine image -FROM alpine:3.17 +FROM alpine:3.18.3 # Add Maintainer Info LABEL maintainer="signoz" diff --git a/frontend/public/locales/en/pipeline.json b/frontend/public/locales/en/pipeline.json index 77989fdfc5..3b0f7d8bda 100644 --- a/frontend/public/locales/en/pipeline.json +++ b/frontend/public/locales/en/pipeline.json @@ -37,9 +37,9 @@ "processor_field_placeholder": "Field", "processor_value_placeholder": "Value", "processor_description_placeholder": "example rule: %{word:first}", - "processor_trace_id_placeholder": "Trace Id Parce From", - "processor_span_id_placeholder": "Span id Parse From", - "processor_trace_flags_placeholder": "Trace flags parse from", + "processor_trace_id_placeholder": "Parse Trace ID from", + "processor_span_id_placeholder": "Parse Span ID from", + "processor_trace_flags_placeholder": "Parse Trace flags from", "processor_from_placeholder": "From", "processor_to_placeholder": "To" } diff --git a/frontend/public/locales/en/titles.json b/frontend/public/locales/en/titles.json index bea44d8a18..24b0f45269 100644 --- a/frontend/public/locales/en/titles.json +++ b/frontend/public/locales/en/titles.json @@ -32,6 +32,7 @@ "LOGS": "SigNoz | Logs", "LOGS_EXPLORER": "SigNoz | Logs Explorer", "LIVE_LOGS": "SigNoz | Live Logs", + "LOGS_PIPELINES": "SigNoz | Logs Pipelines", "HOME_PAGE": "Open source Observability Platform | SigNoz", "PASSWORD_RESET": "SigNoz | Password Reset", "LIST_LICENSES": "SigNoz | List of Licenses", diff --git a/frontend/src/AppRoutes/Private.tsx b/frontend/src/AppRoutes/Private.tsx index 70f8cccf04..f559dc633f 100644 --- a/frontend/src/AppRoutes/Private.tsx +++ b/frontend/src/AppRoutes/Private.tsx @@ -39,10 +39,12 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { [pathname], ); - const { data: licensesData } = useLicense(); + const { + data: licensesData, + isFetching: isFetchingLicensesData, + } = useLicense(); const { - user, isUserFetching, isUserFetchingError, isLoggedIn: isLoggedInState, @@ -116,7 +118,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { if ( localStorageUserAuthToken && localStorageUserAuthToken.refreshJwt && - user?.userId === '' + isUserFetching ) { handleUserLoginIfTokenPresent(key); } else { @@ -131,28 +133,34 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { if (path && path !== ROUTES.WORKSPACE_LOCKED) { history.push(ROUTES.WORKSPACE_LOCKED); - } - dispatch({ - type: UPDATE_USER_IS_FETCH, - payload: { - isUserFetching: false, - }, - }); + dispatch({ + type: UPDATE_USER_IS_FETCH, + payload: { + isUserFetching: false, + }, + }); + } }; + useEffect(() => { + if (!isFetchingLicensesData) { + const shouldBlockWorkspace = licensesData?.payload?.workSpaceBlock; + + if (shouldBlockWorkspace) { + navigateToWorkSpaceBlocked(currentRoute); + } + } + }, [isFetchingLicensesData]); + // eslint-disable-next-line sonarjs/cognitive-complexity useEffect(() => { (async (): Promise => { try { - const shouldBlockWorkspace = licensesData?.payload?.workSpaceBlock; - if (currentRoute) { const { isPrivate, key } = currentRoute; - if (shouldBlockWorkspace) { - navigateToWorkSpaceBlocked(currentRoute); - } else if (isPrivate) { + if (isPrivate && key !== ROUTES.WORKSPACE_LOCKED) { handlePrivateRoutes(key); } else { // no need to fetch the user and make user fetching false diff --git a/frontend/src/AppRoutes/index.tsx b/frontend/src/AppRoutes/index.tsx index 62ed0946be..deff831a36 100644 --- a/frontend/src/AppRoutes/index.tsx +++ b/frontend/src/AppRoutes/index.tsx @@ -13,6 +13,7 @@ import useLicense, { LICENSE_PLAN_KEY } from 'hooks/useLicense'; import { NotificationProvider } from 'hooks/useNotifications'; import { ResourceProvider } from 'hooks/useResourceAttribute'; import history from 'lib/history'; +import { identity, pickBy } from 'lodash-es'; import { DashboardProvider } from 'providers/Dashboard/Dashboard'; import { QueryBuilderProvider } from 'providers/QueryBuilder'; import { Suspense, useEffect, useState } from 'react'; @@ -90,13 +91,19 @@ function App(): JSX.Element { const orgName = org && Array.isArray(org) && org.length > 0 ? org[0].name : ''; + const { name, email } = user; + const identifyPayload = { - email: user?.email, - name: user?.name, + email, + name, company_name: orgName, role, + source: 'signoz-ui', }; - const domain = extractDomain(user?.email); + + const sanitizedIdentifyPayload = pickBy(identifyPayload, identity); + + const domain = extractDomain(email); const hostNameParts = hostname.split('.'); @@ -106,13 +113,14 @@ function App(): JSX.Element { data_region: hostNameParts[1], tenant_url: hostname, company_domain: domain, + source: 'signoz-ui', }; - window.analytics.identify(user?.email, identifyPayload); + window.analytics.identify(email, sanitizedIdentifyPayload); window.analytics.group(domain, groupTraits); - window.clarity('identify', user.email, user.name); + window.clarity('identify', email, name); }; useEffect(() => { diff --git a/frontend/src/AppRoutes/routes.ts b/frontend/src/AppRoutes/routes.ts index b764d609b3..2f4142c809 100644 --- a/frontend/src/AppRoutes/routes.ts +++ b/frontend/src/AppRoutes/routes.ts @@ -282,10 +282,10 @@ const routes: AppRoutes[] = [ isPrivate: false, }, { - path: ROUTES.PIPELINES, + path: ROUTES.LOGS_PIPELINES, exact: true, component: PipelinePage, - key: 'PIPELINES', + key: 'LOGS_PIPELINES', isPrivate: true, }, { @@ -299,7 +299,7 @@ const routes: AppRoutes[] = [ path: ROUTES.WORKSPACE_LOCKED, exact: true, component: WorkspaceBlocked, - isPrivate: false, + isPrivate: true, key: 'WORKSPACE_LOCKED', }, ]; diff --git a/frontend/src/components/DropDown/DropDown.styles.scss b/frontend/src/components/DropDown/DropDown.styles.scss new file mode 100644 index 0000000000..232b349545 --- /dev/null +++ b/frontend/src/components/DropDown/DropDown.styles.scss @@ -0,0 +1,11 @@ +.dropdown-button { + color: #fff; +} + +.dropdown-button--dark { + color: #000; +} + +.dropdown-icon { + font-size: 1.2rem; +} \ No newline at end of file diff --git a/frontend/src/components/DropDown/DropDown.tsx b/frontend/src/components/DropDown/DropDown.tsx new file mode 100644 index 0000000000..c29fbdd15b --- /dev/null +++ b/frontend/src/components/DropDown/DropDown.tsx @@ -0,0 +1,30 @@ +import './DropDown.styles.scss'; + +import { EllipsisOutlined } from '@ant-design/icons'; +import { Button, Dropdown, MenuProps } from 'antd'; +import { useIsDarkMode } from 'hooks/useDarkMode'; + +function DropDown({ element }: { element: JSX.Element[] }): JSX.Element { + const isDarkMode = useIsDarkMode(); + + const items: MenuProps['items'] = element.map( + (e: JSX.Element, index: number) => ({ + label: e, + key: index, + }), + ); + + return ( + + + + ); +} + +export default DropDown; diff --git a/frontend/src/components/ResizeTable/DynamicColumnTable.syles.scss b/frontend/src/components/ResizeTable/DynamicColumnTable.syles.scss new file mode 100644 index 0000000000..2bd0606abd --- /dev/null +++ b/frontend/src/components/ResizeTable/DynamicColumnTable.syles.scss @@ -0,0 +1,25 @@ +.DynamicColumnTable { + display: flex; + flex-direction: column; + width: 100%; + + .dynamicColumnTable-button { + align-self: flex-end; + margin: 10px 0; + } +} + +.dynamicColumnsTable-items { + display: flex; + width: 10.625rem; + justify-content: space-between; + align-items: center; +} + +@media (max-width: 768px) { + .dynamicColumnsTable-items { + flex-direction: column; + width: auto; + text-align: center; + } +} \ No newline at end of file diff --git a/frontend/src/components/ResizeTable/DynamicColumnTable.tsx b/frontend/src/components/ResizeTable/DynamicColumnTable.tsx new file mode 100644 index 0000000000..385734f11d --- /dev/null +++ b/frontend/src/components/ResizeTable/DynamicColumnTable.tsx @@ -0,0 +1,112 @@ +/* eslint-disable react/jsx-props-no-spreading */ +import './DynamicColumnTable.syles.scss'; + +import { SettingOutlined } from '@ant-design/icons'; +import { Button, Dropdown, MenuProps, Switch } from 'antd'; +import { ColumnsType } from 'antd/lib/table'; +import { memo, useEffect, useState } from 'react'; +import { popupContainer } from 'utils/selectPopupContainer'; + +import ResizeTable from './ResizeTable'; +import { DynamicColumnTableProps } from './types'; +import { + getNewColumnData, + getVisibleColumns, + setVisibleColumns, +} from './utils'; + +function DynamicColumnTable({ + tablesource, + columns, + dynamicColumns, + onDragColumn, + ...restProps +}: DynamicColumnTableProps): JSX.Element { + const [columnsData, setColumnsData] = useState( + columns, + ); + + useEffect(() => { + const visibleColumns = getVisibleColumns({ + tablesource, + columnsData: columns, + dynamicColumns, + }); + setColumnsData((prevColumns) => + prevColumns + ? [ + ...prevColumns.slice(0, prevColumns.length - 1), + ...visibleColumns, + prevColumns[prevColumns.length - 1], + ] + : undefined, + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const onToggleHandler = (index: number) => ( + checked: boolean, + event: React.MouseEvent, + ): void => { + event.stopPropagation(); + setVisibleColumns({ + tablesource, + dynamicColumns, + index, + checked, + }); + setColumnsData((prevColumns) => + getNewColumnData({ + checked, + index, + prevColumns, + dynamicColumns, + }), + ); + }; + + const items: MenuProps['items'] = + dynamicColumns?.map((column, index) => ({ + label: ( +
+
{column.title?.toString()}
+ c.key === column.key) !== -1} + onChange={onToggleHandler(index)} + /> +
+ ), + key: index, + type: 'checkbox', + })) || []; + + return ( +
+ {dynamicColumns && ( + +
+ ); +} + +DynamicColumnTable.defaultProps = { + onDragColumn: undefined, +}; + +export default memo(DynamicColumnTable); diff --git a/frontend/src/components/ResizeTable/TableComponent/DateComponent.tsx b/frontend/src/components/ResizeTable/TableComponent/DateComponent.tsx new file mode 100644 index 0000000000..87c5c57420 --- /dev/null +++ b/frontend/src/components/ResizeTable/TableComponent/DateComponent.tsx @@ -0,0 +1,15 @@ +import { Typography } from 'antd'; + +import Time from './Time'; + +function DateComponent( + CreatedOrUpdateTime: string | number | Date, +): JSX.Element { + if (CreatedOrUpdateTime === null) { + return - ; + } + + return