diff --git a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml index c198c2f57c..0636b518cf 100644 --- a/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker-swarm/clickhouse-setup/otel-collector-config.yaml @@ -78,7 +78,7 @@ processors: signozspanmetrics/prometheus: metrics_exporter: prometheus latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s ] - dimensions_cache_size: 10000 + dimensions_cache_size: 100000 dimensions: - name: service.namespace default: default diff --git a/deploy/docker/clickhouse-setup/otel-collector-config.yaml b/deploy/docker/clickhouse-setup/otel-collector-config.yaml index 2829bf966f..c6773d187d 100644 --- a/deploy/docker/clickhouse-setup/otel-collector-config.yaml +++ b/deploy/docker/clickhouse-setup/otel-collector-config.yaml @@ -74,7 +74,7 @@ processors: signozspanmetrics/prometheus: metrics_exporter: prometheus latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s ] - dimensions_cache_size: 10000 + dimensions_cache_size: 100000 dimensions: - name: service.namespace default: default diff --git a/frontend/src/api/logs/livetail.ts b/frontend/src/api/logs/livetail.ts index f1cec5472a..150f63d193 100644 --- a/frontend/src/api/logs/livetail.ts +++ b/frontend/src/api/logs/livetail.ts @@ -4,14 +4,16 @@ import { ENVIRONMENT } from 'constants/env'; import { LOCALSTORAGE } from 'constants/localStorage'; import { EventSourcePolyfill } from 'event-source-polyfill'; -export const LiveTail = (queryParams: string): EventSourcePolyfill => { - const dict = { - headers: { - Authorization: `Bearer ${getLocalStorageKey(LOCALSTORAGE.AUTH_TOKEN)}`, - }, - }; - return new EventSourcePolyfill( +// 10 min in ms +const TIMEOUT_IN_MS = 10 * 60 * 1000; + +export const LiveTail = (queryParams: string): EventSourcePolyfill => + new EventSourcePolyfill( `${ENVIRONMENT.baseURL}${apiV1}logs/tail?${queryParams}`, - dict, + { + headers: { + Authorization: `Bearer ${getLocalStorageKey(LOCALSTORAGE.AUTH_TOKEN)}`, + }, + heartbeatTimeout: TIMEOUT_IN_MS, + }, ); -}; diff --git a/frontend/src/container/LogsSearchFilter/index.tsx b/frontend/src/container/LogsSearchFilter/index.tsx index c7e79b14ca..b5cb71faa9 100644 --- a/frontend/src/container/LogsSearchFilter/index.tsx +++ b/frontend/src/container/LogsSearchFilter/index.tsx @@ -127,7 +127,7 @@ function SearchFilter({ useEffect(() => { debouncedHandleSearch(urlQueryString || ''); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [urlQueryString, maxTime, minTime, idEnd, idStart]); + }, [urlQueryString, maxTime, minTime, idEnd, idStart, logLinesPerPage]); return ( diff --git a/frontend/src/container/Version/index.tsx b/frontend/src/container/Version/index.tsx index e36a0c6d18..cad08351e3 100644 --- a/frontend/src/container/Version/index.tsx +++ b/frontend/src/container/Version/index.tsx @@ -1,6 +1,6 @@ import { WarningFilled } from '@ant-design/icons'; import { Button, Card, Form, Space, Typography } from 'antd'; -import React, { useCallback } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { AppState } from 'store/reducers'; @@ -14,10 +14,6 @@ function Version(): JSX.Element { const [form] = Form.useForm(); const { t } = useTranslation(); - const onClickUpgradeHandler = useCallback((link: string) => { - window.open(link, '_blank'); - }, []); - const { currentVersion, latestVersion, @@ -60,9 +56,8 @@ function Version(): JSX.Element { placeholder={t('latest_version')} /> diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go index 0711382acf..a9626d887b 100644 --- a/pkg/query-service/app/clickhouseReader/reader.go +++ b/pkg/query-service/app/clickhouseReader/reader.go @@ -1178,33 +1178,54 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode traceFilterReponse.Status = map[string]uint64{"ok": 0, "error": 0} } case constants.Duration: - finalQuery := fmt.Sprintf("SELECT durationNano as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.durationTable) - finalQuery += query - finalQuery += " ORDER BY durationNano LIMIT 1" - var dBResponse []model.DBResponseTotal - err := r.db.Select(ctx, &dBResponse, finalQuery, args...) - zap.S().Info(finalQuery) + err := r.featureFlags.CheckFeature(constants.DurationSort) + durationSortEnabled := err == nil + finalQuery := "" + if !durationSortEnabled { + // if duration sort is not enabled, we need to get the min and max duration from the index table + finalQuery = fmt.Sprintf("SELECT min(durationNano) as min, max(durationNano) as max FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.indexTable) + finalQuery += query + var dBResponse []model.DBResponseMinMax + err = r.db.Select(ctx, &dBResponse, finalQuery, args...) + zap.S().Info(finalQuery) + if err != nil { + zap.S().Debug("Error in processing sql query: ", err) + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + } + if len(dBResponse) > 0 { + traceFilterReponse.Duration = map[string]uint64{"minDuration": dBResponse[0].Min, "maxDuration": dBResponse[0].Max} + } + } else { + // when duration sort is enabled, we need to get the min and max duration from the duration table + finalQuery = fmt.Sprintf("SELECT durationNano as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.durationTable) + finalQuery += query + finalQuery += " ORDER BY durationNano LIMIT 1" + var dBResponse []model.DBResponseTotal + err = r.db.Select(ctx, &dBResponse, finalQuery, args...) + zap.S().Info(finalQuery) - if err != nil { - zap.S().Debug("Error in processing sql query: ", err) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} - } - finalQuery = fmt.Sprintf("SELECT durationNano as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.durationTable) - finalQuery += query - finalQuery += " ORDER BY durationNano DESC LIMIT 1" - var dBResponse2 []model.DBResponseTotal - err = r.db.Select(ctx, &dBResponse2, finalQuery, args...) - zap.S().Info(finalQuery) + if err != nil { + zap.S().Debug("Error in processing sql query: ", err) + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + } - if err != nil { - zap.S().Debug("Error in processing sql query: ", err) - return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} - } - if len(dBResponse) > 0 { - traceFilterReponse.Duration["minDuration"] = dBResponse[0].NumTotal - } - if len(dBResponse2) > 0 { - traceFilterReponse.Duration["maxDuration"] = dBResponse2[0].NumTotal + finalQuery = fmt.Sprintf("SELECT durationNano as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.durationTable) + finalQuery += query + finalQuery += " ORDER BY durationNano DESC LIMIT 1" + var dBResponse2 []model.DBResponseTotal + err = r.db.Select(ctx, &dBResponse2, finalQuery, args...) + zap.S().Info(finalQuery) + + if err != nil { + zap.S().Debug("Error in processing sql query: ", err) + return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)} + } + if len(dBResponse) > 0 { + traceFilterReponse.Duration["minDuration"] = dBResponse[0].NumTotal + } + if len(dBResponse2) > 0 { + traceFilterReponse.Duration["maxDuration"] = dBResponse2[0].NumTotal + } } case constants.RPCMethod: finalQuery := fmt.Sprintf("SELECT rpcMethod, count() as count FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.indexTable) diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go index 927b825792..6bb3a21999 100644 --- a/pkg/query-service/app/http_handler.go +++ b/pkg/query-service/app/http_handler.go @@ -1333,7 +1333,7 @@ func (aH *APIHandler) getServices(w http.ResponseWriter, r *http.Request) { } telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_NUMBER_OF_SERVICES, data) - if (data["number"] != 0) || (data["number"] != telemetry.DEFAULT_NUMBER_OF_SERVICES) { + if (data["number"] != 0) && (data["number"] != telemetry.DEFAULT_NUMBER_OF_SERVICES) { telemetry.GetInstance().AddActiveTracesUser() } diff --git a/pkg/query-service/model/response.go b/pkg/query-service/model/response.go index 0f1d60d9c2..5441f894b2 100644 --- a/pkg/query-service/model/response.go +++ b/pkg/query-service/model/response.go @@ -399,6 +399,11 @@ type DBResponseTotal struct { NumTotal uint64 `ch:"numTotal"` } +type DBResponseMinMax struct { + Min uint64 `ch:"min"` + Max uint64 `ch:"max"` +} + type SpanFiltersResponse struct { ServiceName map[string]uint64 `json:"serviceName"` Status map[string]uint64 `json:"status"` diff --git a/pkg/query-service/tests/test-deploy/otel-collector-config.yaml b/pkg/query-service/tests/test-deploy/otel-collector-config.yaml index 9f7ee3fd18..517c7bc643 100644 --- a/pkg/query-service/tests/test-deploy/otel-collector-config.yaml +++ b/pkg/query-service/tests/test-deploy/otel-collector-config.yaml @@ -74,7 +74,7 @@ processors: signozspanmetrics/prometheus: metrics_exporter: prometheus latency_histogram_buckets: [100us, 1ms, 2ms, 6ms, 10ms, 50ms, 100ms, 250ms, 500ms, 1000ms, 1400ms, 2000ms, 5s, 10s, 20s, 40s, 60s ] - dimensions_cache_size: 10000 + dimensions_cache_size: 100000 dimensions: - name: service.namespace default: default