Compare commits

..

13 Commits

Author SHA1 Message Date
Abhi kumar
e2b8b56591 Merge branch 'main' into enh/external-api-charts 2026-03-05 16:19:15 +05:30
Yunus M
16761bc574 Merge branch 'main' into enh/external-api-charts 2026-03-05 14:01:48 +05:30
Abhi kumar
91ee0fb06f Merge branch 'main' into enh/external-api-charts 2026-03-03 15:12:59 +05:30
Abhi Kumar
6a138fa422 fix: tests 2026-03-03 15:10:10 +05:30
Abhi Kumar
28b21f6c48 Merge branch 'main' of https://github.com/SigNoz/signoz into enh/external-api-charts 2026-03-03 14:25:32 +05:30
Abhi Kumar
7974f4fb08 feat: replaced external apis barchart with the new bar chart 2026-03-01 19:16:45 +05:30
Abhi kumar
f11153cdec Merge branch 'main' into chore/uplot-builder-restructure 2026-02-28 18:55:41 +05:30
Abhi Kumar
a380c4d6be chore: fixed tsc + test 2026-02-28 18:08:39 +05:30
Abhi Kumar
a0f576e5fb chore: fixed tsc + test 2026-02-28 17:53:44 +05:30
Abhi Kumar
98013ee3b9 chore: fixed tsc + test 2026-02-28 15:51:58 +05:30
Abhi Kumar
97b94fc4f5 chore: updated timezone types 2026-02-28 15:20:24 +05:30
Abhi Kumar
0f3f49b96a chore: updated baseconfigbuilder test 2026-02-28 15:15:21 +05:30
Abhi Kumar
0928a30863 chore: made baseconfigbuilder generic to be used across different charts 2026-02-28 15:10:16 +05:30
91 changed files with 1098 additions and 26455 deletions

View File

@@ -7,14 +7,10 @@ on:
pull_request_target:
types:
- labeled
merge_group:
types:
- checks_requested
jobs:
refcheck:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest

View File

@@ -7,14 +7,10 @@ on:
pull_request_target:
types:
- labeled
merge_group:
types:
- checks_requested
jobs:
test:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/go-test.yaml@main
@@ -25,7 +21,6 @@ jobs:
GO_VERSION: 1.24
fmt:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/go-fmt.yaml@main
@@ -35,7 +30,6 @@ jobs:
GO_VERSION: 1.24
lint:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/go-lint.yaml@main
@@ -45,7 +39,6 @@ jobs:
GO_VERSION: 1.24
deps:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/go-deps.yaml@main
@@ -55,7 +48,6 @@ jobs:
GO_VERSION: 1.24
build:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest
@@ -87,7 +79,6 @@ jobs:
make docker-build-enterprise
openapi:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest

View File

@@ -7,14 +7,10 @@ on:
pull_request_target:
types:
- labeled
merge_group:
types:
- checks_requested
jobs:
tsc:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest
@@ -31,7 +27,6 @@ jobs:
run: cd frontend && yarn tsc
tsc2:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/js-tsc.yaml@main
@@ -41,7 +36,6 @@ jobs:
JS_SRC: frontend
test:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/js-test.yaml@main
@@ -51,7 +45,6 @@ jobs:
JS_SRC: frontend
fmt:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/js-fmt.yaml@main
@@ -61,7 +54,6 @@ jobs:
JS_SRC: frontend
lint:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
uses: signoz/primus.workflows/.github/workflows/js-lint.yaml@main
@@ -69,53 +61,8 @@ jobs:
with:
PRIMUS_REF: main
JS_SRC: frontend
lint-pnpm:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: setup node
uses: actions/setup-node@v6
with:
node-version: "22"
- name: install
run: cd frontend && pnpm install
- name: lint
run: echo 'done'
lint-pnpm-cache:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4
- name: setup pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: setup node
uses: actions/setup-node@v6
with:
node-version: "22"
cache: 'pnpm'
cache-dependency-path: frontend/pnpm-lock.yaml
- name: install
run: cd frontend && pnpm install
- name: lint
run: echo 'done'
md-languages:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest
@@ -126,7 +73,6 @@ jobs:
run: bash frontend/scripts/validate-md-languages.sh
authz:
if: |
github.event_name == 'merge_group' ||
(github.event_name == 'pull_request' && ! github.event.pull_request.head.repo.fork && github.event.pull_request.user.login != 'dependabot[bot]' && ! contains(github.event.pull_request.labels.*.name, 'safe-to-test')) ||
(github.event_name == 'pull_request_target' && contains(github.event.pull_request.labels.*.name, 'safe-to-test'))
runs-on: ubuntu-latest

View File

@@ -190,7 +190,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:v0.114.1
image: signoz/signoz:v0.114.0
ports:
- "8080:8080" # signoz port
# - "6060:6060" # pprof port

View File

@@ -117,7 +117,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:v0.114.1
image: signoz/signoz:v0.114.0
ports:
- "8080:8080" # signoz port
volumes:

View File

@@ -181,7 +181,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:${VERSION:-v0.114.1}
image: signoz/signoz:${VERSION:-v0.114.0}
container_name: signoz
ports:
- "8080:8080" # signoz port

View File

@@ -109,7 +109,7 @@ services:
# - ../common/clickhouse/storage.xml:/etc/clickhouse-server/config.d/storage.xml
signoz:
!!merge <<: *db-depend
image: signoz/signoz:${VERSION:-v0.114.1}
image: signoz/signoz:${VERSION:-v0.114.0}
container_name: signoz
ports:
- "8080:8080" # signoz port

View File

@@ -8,8 +8,6 @@ import (
"github.com/SigNoz/signoz/pkg/querier"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
)
@@ -69,10 +67,6 @@ func (p *BaseSeasonalProvider) toTSResults(ctx context.Context, resp *qbtypes.Qu
}
func (p *BaseSeasonalProvider) getResults(ctx context.Context, orgID valuer.UUID, params *anomalyQueryParams) (*anomalyQueryResults, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "anomaly",
instrumentationtypes.CodeFunctionName: "getResults",
})
// TODO(srikanthccv): parallelize this?
p.logger.InfoContext(ctx, "fetching results for current period", "anomaly_current_period_query", params.CurrentPeriodQuery)
currentPeriodResults, err := p.querier.QueryRange(ctx, orgID, &params.CurrentPeriodQuery)

View File

@@ -15,9 +15,7 @@ import (
"github.com/SigNoz/signoz/pkg/queryparser"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/roletypes"
"github.com/SigNoz/signoz/pkg/valuer"
@@ -107,10 +105,6 @@ func (module *module) GetPublicDashboardSelectorsAndOrg(ctx context.Context, id
}
func (module *module) GetPublicWidgetQueryRange(ctx context.Context, id valuer.UUID, widgetIdx, startTime, endTime uint64) (*querybuildertypesv5.QueryRangeResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "dashboard",
instrumentationtypes.CodeFunctionName: "GetPublicWidgetQueryRange",
})
dashboard, err := module.GetDashboardByPublicID(ctx, id)
if err != nil {
return nil, err

View File

@@ -10,8 +10,6 @@ import (
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/query-service/utils/labels"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"go.uber.org/zap"
)
@@ -63,10 +61,6 @@ func (p *BaseSeasonalProvider) getQueryParams(req *GetAnomaliesRequest) *anomaly
}
func (p *BaseSeasonalProvider) getResults(ctx context.Context, orgID valuer.UUID, params *anomalyQueryParams) (*anomalyQueryResults, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "anomaly",
instrumentationtypes.CodeFunctionName: "getResults",
})
zap.L().Info("fetching results for current period", zap.Any("currentPeriodQuery", params.CurrentPeriodQuery))
currentPeriodResults, _, err := p.querierV2.QueryRange(ctx, orgID, params.CurrentPeriodQuery)
if err != nil {

View File

@@ -37,10 +37,10 @@
"@dnd-kit/modifiers": "7.0.0",
"@dnd-kit/sortable": "8.0.0",
"@dnd-kit/utilities": "3.2.2",
"@grafana/data": "11.2.3",
"@grafana/data": "^11.2.3",
"@mdx-js/loader": "2.3.0",
"@mdx-js/react": "2.3.0",
"@monaco-editor/react": "4.3.1",
"@monaco-editor/react": "^4.3.1",
"@playwright/test": "1.55.1",
"@radix-ui/react-tabs": "1.0.4",
"@radix-ui/react-tooltip": "1.0.7",
@@ -54,7 +54,7 @@
"@signozhq/combobox": "0.0.2",
"@signozhq/command": "0.0.0",
"@signozhq/design-tokens": "2.1.1",
"@signozhq/dialog": "0.0.2",
"@signozhq/dialog": "^0.0.2",
"@signozhq/icons": "0.1.0",
"@signozhq/input": "0.0.2",
"@signozhq/popover": "0.0.0",
@@ -63,7 +63,7 @@
"@signozhq/sonner": "0.1.0",
"@signozhq/switch": "0.0.2",
"@signozhq/table": "0.3.7",
"@signozhq/toggle-group": "0.0.1",
"@signozhq/toggle-group": "^0.0.1",
"@signozhq/tooltip": "0.0.2",
"@tanstack/react-table": "8.20.6",
"@tanstack/react-virtual": "3.11.2",
@@ -76,28 +76,28 @@
"@visx/shape": "3.5.0",
"@visx/tooltip": "3.3.0",
"@vitejs/plugin-react": "5.1.4",
"@xstate/react": "3.0.0",
"@xstate/react": "^3.0.0",
"ansi-to-html": "0.7.2",
"antd": "5.11.0",
"antd-table-saveas-excel": "2.2.1",
"antlr4": "4.13.2",
"axios": "1.12.0",
"babel-eslint": "10.1.0",
"babel-jest": "29.6.4",
"babel-eslint": "^10.1.0",
"babel-jest": "^29.6.4",
"babel-loader": "9.1.3",
"babel-plugin-named-asset-import": "0.3.7",
"babel-preset-minify": "0.5.1",
"babel-preset-react-app": "10.0.1",
"babel-plugin-named-asset-import": "^0.3.7",
"babel-preset-minify": "^0.5.1",
"babel-preset-react-app": "^10.0.1",
"chart.js": "3.9.1",
"chartjs-adapter-date-fns": "2.0.0",
"chartjs-plugin-annotation": "1.4.0",
"chartjs-adapter-date-fns": "^2.0.0",
"chartjs-plugin-annotation": "^1.4.0",
"classnames": "2.3.2",
"color": "4.2.1",
"color": "^4.2.1",
"color-alpha": "2.0.0",
"cross-env": "7.0.3",
"cross-env": "^7.0.3",
"crypto-js": "4.2.0",
"d3-hierarchy": "3.1.2",
"dayjs": "1.10.7",
"dayjs": "^1.10.7",
"dompurify": "3.2.4",
"dotenv": "8.2.0",
"event-source-polyfill": "1.0.31",
@@ -106,19 +106,19 @@
"history": "4.10.1",
"http-proxy-middleware": "3.0.5",
"http-status-codes": "2.3.0",
"i18next": "21.6.12",
"i18next-browser-languagedetector": "6.1.3",
"i18next-http-backend": "1.3.2",
"i18next": "^21.6.12",
"i18next-browser-languagedetector": "^6.1.3",
"i18next-http-backend": "^1.3.2",
"immer": "11.1.3",
"jest": "30.2.0",
"js-base64": "3.7.2",
"lodash-es": "4.17.21",
"js-base64": "^3.7.2",
"lodash-es": "^4.17.21",
"lucide-react": "0.498.0",
"mini-css-extract-plugin": "2.4.5",
"motion": "12.4.13",
"nuqs": "2.8.8",
"overlayscrollbars": "2.8.1",
"overlayscrollbars-react": "0.5.6",
"overlayscrollbars": "^2.8.1",
"overlayscrollbars-react": "^0.5.6",
"papaparse": "5.4.1",
"posthog-js": "1.298.0",
"rc-tween-one": "3.0.6",
@@ -130,36 +130,36 @@
"react-dom": "18.2.0",
"react-drag-listview": "2.0.0",
"react-error-boundary": "4.0.11",
"react-force-graph-2d": "1.29.1",
"react-force-graph-2d": "^1.29.1",
"react-full-screen": "1.1.1",
"react-grid-layout": "1.3.4",
"react-grid-layout": "^1.3.4",
"react-helmet-async": "1.3.0",
"react-i18next": "11.16.1",
"react-i18next": "^11.16.1",
"react-lottie": "1.2.10",
"react-markdown": "8.0.7",
"react-query": "3.39.3",
"react-redux": "7.2.2",
"react-router-dom": "5.2.0",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
"react-router-dom-v5-compat": "6.27.0",
"react-syntax-highlighter": "15.5.0",
"react-use": "17.3.2",
"react-use": "^17.3.2",
"react-virtuoso": "4.0.3",
"redux": "4.0.5",
"redux-thunk": "2.3.0",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"rehype-raw": "7.0.0",
"rollup-plugin-visualizer": "7.0.0",
"rrule": "2.8.1",
"stream": "0.0.2",
"styled-components": "5.3.11",
"timestamp-nano": "1.0.0",
"ts-node": "10.2.1",
"stream": "^0.0.2",
"styled-components": "^5.3.11",
"timestamp-nano": "^1.0.0",
"ts-node": "^10.2.1",
"typescript": "5.9.3",
"uplot": "1.6.31",
"uuid": "8.3.2",
"uuid": "^8.3.2",
"vite": "npm:rolldown-vite@7.3.1",
"vite-plugin-html": "3.2.2",
"web-vitals": "0.2.4",
"xstate": "4.31.0",
"web-vitals": "^0.2.4",
"xstate": "^4.31.0",
"zustand": "5.0.11"
},
"browserslist": {
@@ -175,70 +175,69 @@
]
},
"devDependencies": {
"@babel/core": "7.22.11",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-syntax-jsx": "7.12.13",
"@babel/preset-env": "7.22.14",
"@babel/preset-react": "7.12.13",
"@babel/preset-typescript": "7.21.4",
"@commitlint/cli": "20.4.2",
"@commitlint/config-conventional": "20.4.2",
"@babel/core": "^7.22.11",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-syntax-jsx": "^7.12.13",
"@babel/preset-env": "^7.22.14",
"@babel/preset-react": "^7.12.13",
"@babel/preset-typescript": "^7.21.4",
"@commitlint/cli": "^20.4.2",
"@commitlint/config-conventional": "^20.4.2",
"@faker-js/faker": "9.3.0",
"@jest/globals": "30.2.0",
"@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/color": "^3.0.3",
"@types/crypto-js": "4.2.2",
"@types/dompurify": "2.4.0",
"@types/event-source-polyfill": "1.0.0",
"@types/dompurify": "^2.4.0",
"@types/event-source-polyfill": "^1.0.0",
"@types/fontfaceobserver": "2.1.0",
"@types/jest": "30.0.0",
"@types/lodash-es": "4.17.4",
"@types/mini-css-extract-plugin": "2.5.1",
"@types/node": "16.10.3",
"@types/lodash-es": "^4.17.4",
"@types/mini-css-extract-plugin": "^2.5.1",
"@types/node": "^16.10.3",
"@types/papaparse": "5.3.7",
"@types/react": "18.0.26",
"@types/react-addons-update": "0.14.21",
"@types/react-beautiful-dnd": "13.1.8",
"@types/react-dom": "18.0.10",
"@types/react-grid-layout": "1.1.2",
"@types/react-grid-layout": "^1.1.2",
"@types/react-helmet-async": "1.0.3",
"@types/react-lottie": "1.2.10",
"@types/react-redux": "7.1.11",
"@types/react-redux": "^7.1.11",
"@types/react-resizable": "3.0.3",
"@types/react-router-dom": "5.1.6",
"@types/react-router-dom": "^5.1.6",
"@types/react-syntax-highlighter": "15.5.13",
"@types/redux-mock-store": "1.0.4",
"@types/styled-components": "5.1.4",
"@types/uuid": "8.3.1",
"@typescript-eslint/eslint-plugin": "4.33.0",
"@typescript-eslint/parser": "4.33.0",
"@types/styled-components": "^5.1.4",
"@types/uuid": "^8.3.1",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"autoprefixer": "10.4.19",
"babel-plugin-styled-components": "1.12.0",
"eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jest": "29.15.0",
"eslint-plugin-jsx-a11y": "6.5.1",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-react": "7.24.0",
"eslint-plugin-react-hooks": "4.3.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"eslint-plugin-sonarjs": "0.12.0",
"glob": "13.0.6",
"husky": "7.0.4",
"imagemin": "8.0.1",
"imagemin-svgo": "10.0.1",
"is-ci": "3.0.1",
"babel-plugin-styled-components": "^1.12.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.28.1",
"eslint-plugin-jest": "^29.15.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"eslint-plugin-sonarjs": "^0.12.0",
"husky": "^7.0.4",
"imagemin": "^8.0.1",
"imagemin-svgo": "^10.0.1",
"is-ci": "^3.0.1",
"jest-environment-jsdom": "29.7.0",
"jest-environment-node": "29.7.0",
"jest-styled-components": "7.2.0",
"lint-staged": "12.5.0",
"jest-styled-components": "^7.2.0",
"lint-staged": "^12.5.0",
"msw": "1.3.2",
"npm-run-all": "latest",
"orval": "7.18.0",
"portfinder-sync": "0.0.2",
"portfinder-sync": "^0.0.2",
"postcss": "8.5.6",
"prettier": "2.2.1",
"prop-types": "15.8.1",
@@ -250,7 +249,7 @@
"svgo": "4.0.0",
"ts-api-utils": "2.4.0",
"ts-jest": "29.4.6",
"ts-node": "10.2.1",
"ts-node": "^10.2.1",
"typescript-plugin-css-modules": "5.2.0",
"vite-plugin-checker": "0.12.0",
"vite-plugin-compression": "0.5.1",
@@ -269,40 +268,18 @@
"debug": "4.3.4",
"semver": "7.5.4",
"xml2js": "0.5.0",
"phin": "3.7.1",
"phin": "^3.7.1",
"body-parser": "1.20.3",
"http-proxy-middleware": "3.0.5",
"cross-spawn": "7.0.5",
"cookie": "0.7.1",
"cookie": "^0.7.1",
"serialize-javascript": "6.0.2",
"prismjs": "1.30.0",
"got": "11.8.5",
"form-data": "4.0.4",
"brace-expansion": "2.0.2",
"on-headers": "1.1.0",
"brace-expansion": "^2.0.2",
"on-headers": "^1.1.0",
"tmp": "0.2.4",
"vite": "npm:rolldown-vite@7.3.1"
},
"pnpm": {
"overrides": {
"@types/react": "18.0.26",
"@types/react-dom": "18.0.10",
"debug": "4.3.4",
"semver": "7.5.4",
"xml2js": "0.5.0",
"phin": "3.7.1",
"body-parser": "1.20.3",
"http-proxy-middleware": "3.0.5",
"cross-spawn": "7.0.5",
"cookie": "0.7.1",
"serialize-javascript": "6.0.2",
"prismjs": "1.30.0",
"got": "11.8.5",
"form-data": "4.0.4",
"brace-expansion": "2.0.2",
"on-headers": "1.1.0",
"tmp": "0.2.4",
"vite": "npm:rolldown-vite@7.3.1"
}
}
}

24227
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
import axios from 'api';
import { AxiosResponse } from 'axios';
import store from 'store';
import {
QueryKeyRequestProps,
QueryKeySuggestionsResponseProps,
@@ -17,6 +18,12 @@ export const getKeySuggestions = (
signalSource = '',
} = props;
const { globalTime } = store.getState();
const resolvedTimeRange = {
startUnixMilli: Math.floor(globalTime.minTime / 1000000),
endUnixMilli: Math.floor(globalTime.maxTime / 1000000),
};
const encodedSignal = encodeURIComponent(signal);
const encodedSearchText = encodeURIComponent(searchText);
const encodedMetricName = encodeURIComponent(metricName);
@@ -24,7 +31,14 @@ export const getKeySuggestions = (
const encodedFieldDataType = encodeURIComponent(fieldDataType);
const encodedSource = encodeURIComponent(signalSource);
return axios.get(
`/fields/keys?signal=${encodedSignal}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&fieldContext=${encodedFieldContext}&fieldDataType=${encodedFieldDataType}&source=${encodedSource}`,
);
let url = `/fields/keys?signal=${encodedSignal}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&fieldContext=${encodedFieldContext}&fieldDataType=${encodedFieldDataType}&source=${encodedSource}`;
if (resolvedTimeRange.startUnixMilli !== undefined) {
url += `&startUnixMilli=${resolvedTimeRange.startUnixMilli}`;
}
if (resolvedTimeRange.endUnixMilli !== undefined) {
url += `&endUnixMilli=${resolvedTimeRange.endUnixMilli}`;
}
return axios.get(url);
};

View File

@@ -1,5 +1,6 @@
import axios from 'api';
import { AxiosResponse } from 'axios';
import store from 'store';
import {
QueryKeyValueRequestProps,
QueryKeyValueSuggestionsResponseProps,
@@ -8,7 +9,20 @@ import {
export const getValueSuggestions = (
props: QueryKeyValueRequestProps,
): Promise<AxiosResponse<QueryKeyValueSuggestionsResponseProps>> => {
const { signal, key, searchText, signalSource, metricName } = props;
const {
signal,
key,
searchText,
signalSource,
metricName,
existingQuery,
} = props;
const { globalTime } = store.getState();
const resolvedTimeRange = {
startUnixMilli: Math.floor(globalTime.minTime / 1000000),
endUnixMilli: Math.floor(globalTime.maxTime / 1000000),
};
const encodedSignal = encodeURIComponent(signal);
const encodedKey = encodeURIComponent(key);
@@ -16,7 +30,17 @@ export const getValueSuggestions = (
const encodedSearchText = encodeURIComponent(searchText);
const encodedSource = encodeURIComponent(signalSource || '');
return axios.get(
`/fields/values?signal=${encodedSignal}&name=${encodedKey}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&source=${encodedSource}`,
);
let url = `/fields/values?signal=${encodedSignal}&name=${encodedKey}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&source=${encodedSource}`;
if (resolvedTimeRange.startUnixMilli !== undefined) {
url += `&startUnixMilli=${resolvedTimeRange.startUnixMilli}`;
}
if (resolvedTimeRange.endUnixMilli !== undefined) {
url += `&endUnixMilli=${resolvedTimeRange.endUnixMilli}`;
}
if (existingQuery) {
url += `&existingQuery=${encodeURIComponent(existingQuery)}`;
}
return axios.get(url);
};

View File

@@ -272,7 +272,6 @@ function QuerySearch({
metricName: debouncedMetricName ?? undefined,
signalSource: signalSource as 'meter' | '',
});
if (response.data.data) {
const { keys } = response.data.data;
const options = generateOptions(keys);
@@ -432,6 +431,7 @@ function QuerySearch({
}
const sanitizedSearchText = searchText ? searchText?.trim() : '';
const existingQuery = queryData.filter?.expression || '';
try {
const response = await getValueSuggestions({
@@ -440,9 +440,9 @@ function QuerySearch({
signal: dataSource,
signalSource: signalSource as 'meter' | '',
metricName: debouncedMetricName ?? undefined,
});
existingQuery,
}); // Skip updates if component unmounted or key changed
// Skip updates if component unmounted or key changed
if (
!isMountedRef.current ||
lastKeyRef.current !== key ||
@@ -454,7 +454,9 @@ function QuerySearch({
// Process the response data
const responseData = response.data as any;
const values = responseData.data?.values || {};
const stringValues = values.stringValues || [];
const relatedValues = values.relatedValues || [];
const stringValues =
relatedValues.length > 0 ? relatedValues : values.stringValues || [];
const numberValues = values.numberValues || [];
// Generate options from string values - explicitly handle empty strings
@@ -529,11 +531,12 @@ function QuerySearch({
},
[
activeKey,
dataSource,
isLoadingSuggestions,
debouncedMetricName,
signalSource,
queryData.filter?.expression,
toggleSuggestions,
dataSource,
signalSource,
debouncedMetricName,
],
);
@@ -1240,19 +1243,17 @@ function QuerySearch({
if (!queryContext) {
return;
}
// Trigger suggestions based on context
if (editorRef.current) {
// Only trigger suggestions and fetch if editor is focused (i.e., user is interacting)
if (isFocused && editorRef.current) {
toggleSuggestions(10);
}
// Handle value suggestions for value context
if (queryContext.isInValue) {
const { keyToken, currentToken } = queryContext;
const key = keyToken || currentToken;
// Only fetch if needed and if we have a valid key
if (key && key !== activeKey && !isLoadingSuggestions) {
fetchValueSuggestions({ key });
// Handle value suggestions for value context
if (queryContext.isInValue) {
const { keyToken, currentToken } = queryContext;
const key = keyToken || currentToken;
// Only fetch if needed and if we have a valid key
if (key && key !== activeKey && !isLoadingSuggestions) {
fetchValueSuggestions({ key });
}
}
}
}, [
@@ -1261,6 +1262,7 @@ function QuerySearch({
isLoadingSuggestions,
activeKey,
fetchValueSuggestions,
isFocused,
]);
const getTooltipContent = (): JSX.Element => (

View File

@@ -48,7 +48,12 @@
.filter-separator {
height: 1px;
background-color: var(--bg-slate-400);
margin: 4px 0;
margin: 7px 0;
&.related-separator {
opacity: 0.5;
margin: 0.5px 0;
}
}
.value {
@@ -138,6 +143,93 @@
cursor: pointer;
}
}
.search-prompt {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 10px 12px;
margin-top: 4px;
border: 1px dashed var(--bg-amber-500);
border-radius: 10px;
color: var(--bg-amber-200);
background: linear-gradient(
90deg,
var(--bg-ink-500) 0%,
var(--bg-ink-400) 100%
);
cursor: pointer;
transition: all 0.16s ease, transform 0.12s ease;
text-align: left;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
&:hover {
background: linear-gradient(
90deg,
var(--bg-ink-400) 0%,
var(--bg-ink-300) 100%
);
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.45);
}
&:active {
transform: translateY(1px);
}
&__icon {
color: var(--bg-amber-400);
flex-shrink: 0;
}
&__text {
display: flex;
flex-direction: column;
gap: 2px;
}
&__title {
color: var(--bg-amber-200);
}
&__subtitle {
color: var(--bg-amber-300);
font-size: 12px;
}
}
.lightMode & {
.search-prompt {
border: 1px dashed var(--bg-amber-500);
color: var(--bg-amber-800);
background: linear-gradient(
90deg,
var(--bg-vanilla-200) 0%,
var(--bg-vanilla-100) 100%
);
box-shadow: 0 2px 12px rgba(184, 107, 0, 0.08);
&:hover {
background: linear-gradient(
90deg,
var(--bg-vanilla-100) 0%,
var(--bg-vanilla-50) 100%
);
box-shadow: 0 4px 16px rgba(184, 107, 0, 0.15);
}
&__icon {
color: var(--bg-amber-600);
}
&__title {
color: var(--bg-amber-800);
}
&__subtitle {
color: var(--bg-amber-800);
}
}
}
.go-to-docs {
display: flex;
flex-direction: column;

View File

@@ -150,7 +150,8 @@ describe('CheckboxFilter - User Flows', () => {
// User should see the filter is automatically opened (not collapsed)
expect(screen.getByText('Service Name')).toBeInTheDocument();
await waitFor(() => {
expect(screen.getByPlaceholderText('Filter values')).toBeInTheDocument();
// eslint-disable-next-line sonarjs/no-duplicate-string
expect(screen.getByPlaceholderText('Search values')).toBeInTheDocument();
});
// User should see visual separator between checked and unchecked items
@@ -184,7 +185,7 @@ describe('CheckboxFilter - User Flows', () => {
// Initially auto-opened due to active filters
await waitFor(() => {
expect(screen.getByPlaceholderText('Filter values')).toBeInTheDocument();
expect(screen.getByPlaceholderText('Search values')).toBeInTheDocument();
});
// User manually closes the filter
@@ -192,7 +193,7 @@ describe('CheckboxFilter - User Flows', () => {
// User should see filter is now closed (respecting user preference)
expect(
screen.queryByPlaceholderText('Filter values'),
screen.queryByPlaceholderText('Search values'),
).not.toBeInTheDocument();
// User manually opens the filter again
@@ -200,7 +201,7 @@ describe('CheckboxFilter - User Flows', () => {
// User should see filter is now open (respecting user preference)
await waitFor(() => {
expect(screen.getByPlaceholderText('Filter values')).toBeInTheDocument();
expect(screen.getByPlaceholderText('Search values')).toBeInTheDocument();
});
});

View File

@@ -1,6 +1,15 @@
/* eslint-disable sonarjs/no-identical-functions */
import { Fragment, useMemo, useState } from 'react';
import { Button, Checkbox, Input, Skeleton, Typography } from 'antd';
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/click-events-have-key-events */
import {
Fragment,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { Button, Checkbox, Input, InputRef, Skeleton, Typography } from 'antd';
import cx from 'classnames';
import { removeKeysFromExpression } from 'components/QueryBuilderV2/utils';
import {
@@ -8,19 +17,14 @@ import {
QuickFiltersSource,
} from 'components/QuickFilters/types';
import { OPERATORS } from 'constants/antlrQueryConstants';
import {
DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY,
PANEL_TYPES,
} from 'constants/queryBuilder';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import { getOperatorValue } from 'container/QueryBuilder/filters/QueryBuilderSearch/utils';
import { useGetAggregateValues } from 'hooks/queryBuilder/useGetAggregateValues';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useGetQueryKeyValueSuggestions } from 'hooks/querySuggestions/useGetQueryKeyValueSuggestions';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import { cloneDeep, isArray, isEqual, isFunction } from 'lodash-es';
import { ChevronDown, ChevronRight } from 'lucide-react';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { AlertTriangle, ChevronDown, ChevronRight } from 'lucide-react';
import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { v4 as uuid } from 'uuid';
@@ -57,6 +61,7 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
// null = no user action, true = user opened, false = user closed
const [userToggleState, setUserToggleState] = useState<boolean | null>(null);
const [visibleItemsCount, setVisibleItemsCount] = useState<number>(10);
const [visibleUncheckedCount, setVisibleUncheckedCount] = useState<number>(5);
const {
lastUsedQuery,
@@ -78,6 +83,12 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
return lastUsedQuery || 0;
}, [isListView, source, lastUsedQuery]);
// Extract current filter expression for the active query
const currentFilterExpression = useMemo(() => {
const queryData = currentQuery.builder.queryData?.[activeQueryIndex];
return queryData?.filter?.expression || '';
}, [currentQuery.builder.queryData, activeQueryIndex]);
// Check if this filter has active filters in the query
const isSomeFilterPresentForCurrentAttribute = useMemo(
() =>
@@ -109,54 +120,125 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
filter.defaultOpen,
]);
const { data, isLoading } = useGetAggregateValues(
{
aggregateOperator: filter.aggregateOperator || 'noop',
dataSource: filter.dataSource || DataSource.LOGS,
aggregateAttribute: filter.aggregateAttribute || '',
attributeKey: filter.attributeKey.key,
filterAttributeKeyDataType: filter.attributeKey.dataType || DataTypes.EMPTY,
tagType: filter.attributeKey.type || '',
searchText: searchText ?? '',
},
{
enabled: isOpen && source !== QuickFiltersSource.METER_EXPLORER,
keepPreviousData: true,
},
);
const {
data: keyValueSuggestions,
isLoading: isLoadingKeyValueSuggestions,
refetch: refetchKeyValueSuggestions,
} = useGetQueryKeyValueSuggestions({
key: filter.attributeKey.key,
signal: filter.dataSource || DataSource.LOGS,
signalSource: 'meter',
searchText: searchText || '',
existingQuery: currentFilterExpression,
options: {
enabled: isOpen && source === QuickFiltersSource.METER_EXPLORER,
enabled: isOpen,
keepPreviousData: true,
},
});
const attributeValues: string[] = useMemo(() => {
const dataType = filter.attributeKey.dataType || DataTypes.String;
const searchInputRef = useRef<InputRef | null>(null);
const searchContainerRef = useRef<HTMLDivElement | null>(null);
const previousFiltersItemsRef = useRef(
currentQuery.builder.queryData?.[activeQueryIndex]?.filters?.items,
);
if (source === QuickFiltersSource.METER_EXPLORER && keyValueSuggestions) {
// Process the response data
// Refetch when other filters change (not this filter)
// Watch for when filters.items is different from previous value, indicating other filters changed
useEffect(() => {
const currentFiltersItems =
currentQuery.builder.queryData?.[activeQueryIndex]?.filters?.items;
const previousFiltersItems = previousFiltersItemsRef.current;
// Check if filters items have changed (not the same)
const filtersChanged = !isEqual(previousFiltersItems, currentFiltersItems);
if (isOpen && filtersChanged) {
// Check if OTHER filters (not this filter) have changed
const currentOtherFilters = currentFiltersItems?.filter(
(item) => !isEqual(item.key?.key, filter.attributeKey.key),
);
const previousOtherFilters = previousFiltersItems?.filter(
(item) => !isEqual(item.key?.key, filter.attributeKey.key),
);
// Refetch if other filters changed (not just this filter's values)
const otherFiltersChanged = !isEqual(
currentOtherFilters,
previousOtherFilters,
);
// Only update ref if we have valid API data or if filters actually changed
// Don't update if search returned 0 results to preserve unchecked values
const hasValidData = keyValueSuggestions && !isLoadingKeyValueSuggestions;
if (otherFiltersChanged || hasValidData) {
previousFiltersItemsRef.current = currentFiltersItems;
}
if (otherFiltersChanged) {
refetchKeyValueSuggestions();
}
} else {
previousFiltersItemsRef.current = currentFiltersItems;
}
}, [
activeQueryIndex,
isOpen,
refetchKeyValueSuggestions,
filter.attributeKey.key,
currentQuery.builder.queryData,
keyValueSuggestions,
isLoadingKeyValueSuggestions,
]);
const handleSearchPromptClick = useCallback((): void => {
if (searchContainerRef.current) {
searchContainerRef.current.scrollIntoView({
behavior: 'smooth',
block: 'center',
});
}
if (searchInputRef.current) {
setTimeout(() => searchInputRef.current?.focus({ cursor: 'end' }), 120);
}
}, []);
const isDataComplete = useMemo(() => {
if (keyValueSuggestions) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const responseData = keyValueSuggestions?.data as any;
return responseData.data?.complete || false;
}
return false;
}, [keyValueSuggestions]);
const previousUncheckedValuesRef = useRef<string[]>([]);
const { attributeValues, relatedValuesSet } = useMemo(() => {
if (keyValueSuggestions) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const responseData = keyValueSuggestions?.data as any;
const values = responseData.data?.values || {};
const stringValues = values.stringValues || [];
const numberValues = values.numberValues || [];
const relatedValues: string[] = values.relatedValues || [];
const stringValues: string[] = values.stringValues || [];
const numberValues: number[] = values.numberValues || [];
// Generate options from string values - explicitly handle empty strings
const stringOptions = stringValues
// Strict filtering for empty string - we'll handle it as a special case if needed
.filter(
(value: string | null | undefined): value is string =>
value !== null && value !== undefined && value !== '',
);
const valuesToUse = [
...relatedValues,
...stringValues.filter(
(value: string | null | undefined) =>
value !== null &&
value !== undefined &&
value !== '' &&
!relatedValues.includes(value),
),
];
const stringOptions = valuesToUse.filter(
(value: string | null | undefined): value is string =>
value !== null && value !== undefined && value !== '',
);
// Generate options from number values
const numberOptions = numberValues
.filter(
(value: number | null | undefined): value is number =>
@@ -164,15 +246,27 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
)
.map((value: number) => value.toString());
// Combine all options and make sure we don't have duplicate labels
return [...stringOptions, ...numberOptions];
}
const filteredRelated = new Set(
relatedValues.filter(
(v): v is string => v !== null && v !== undefined && v !== '',
),
);
const key = DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY[dataType];
return (data?.payload?.[key] || []).filter(
(val) => val !== undefined && val !== null,
);
}, [data?.payload, filter.attributeKey.dataType, keyValueSuggestions, source]);
const baseValues = [...stringOptions, ...numberOptions];
const previousUnchecked = previousUncheckedValuesRef.current || [];
const preservedUnchecked = previousUnchecked.filter(
(value) => !baseValues.includes(value),
);
return {
attributeValues: [...baseValues, ...preservedUnchecked],
relatedValuesSet: filteredRelated,
};
}
return {
attributeValues: [] as string[],
relatedValuesSet: new Set<string>(),
};
}, [keyValueSuggestions]);
const setSearchTextDebounced = useDebouncedFn((...args) => {
setSearchText(args[0] as string);
@@ -246,22 +340,51 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
const isMultipleValuesTrueForTheKey =
Object.values(currentFilterState).filter((val) => val).length > 1;
// Sort checked items to the top, then unchecked items
const currentAttributeKeys = useMemo(() => {
// Sort checked items to the top; always show unchecked items beneath, regardless of pagination
const {
visibleCheckedValues,
uncheckedValues,
visibleUncheckedValues,
visibleCheckedCount,
hasMoreChecked,
hasMoreUnchecked,
checkedSeparatorIndex,
} = useMemo(() => {
const checkedValues = attributeValues.filter(
(val) => currentFilterState[val],
);
const uncheckedValues = attributeValues.filter(
(val) => !currentFilterState[val],
);
return [...checkedValues, ...uncheckedValues].slice(0, visibleItemsCount);
}, [attributeValues, currentFilterState, visibleItemsCount]);
const unchecked = attributeValues.filter((val) => !currentFilterState[val]);
const visibleChecked = checkedValues.slice(0, visibleItemsCount);
const visibleUnchecked = unchecked.slice(0, visibleUncheckedCount);
// Count of checked values in the currently visible items
const checkedValuesCount = useMemo(
() => currentAttributeKeys.filter((val) => currentFilterState[val]).length,
[currentAttributeKeys, currentFilterState],
);
const findSeparatorIndex = (list: string[]): number => {
if (relatedValuesSet.size === 0) {
return -1;
}
const firstNonRelated = list.findIndex((v) => !relatedValuesSet.has(v));
return firstNonRelated > 0 ? firstNonRelated : -1;
};
return {
visibleCheckedValues: visibleChecked,
uncheckedValues: unchecked,
visibleUncheckedValues: visibleUnchecked,
visibleCheckedCount: visibleChecked.length,
hasMoreChecked: checkedValues.length > visibleChecked.length,
hasMoreUnchecked: unchecked.length > visibleUnchecked.length,
checkedSeparatorIndex: findSeparatorIndex(visibleChecked),
};
}, [
attributeValues,
currentFilterState,
visibleItemsCount,
visibleUncheckedCount,
relatedValuesSet,
]);
useEffect(() => {
previousUncheckedValuesRef.current = uncheckedValues;
}, [uncheckedValues]);
const handleClearFilterAttribute = (): void => {
const preparedQuery: Query = {
@@ -302,6 +425,7 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
isOnlyOrAllClicked: boolean,
// eslint-disable-next-line sonarjs/cognitive-complexity
): void => {
setVisibleUncheckedCount(5);
const query = cloneDeep(currentQuery.builder.queryData?.[activeQueryIndex]);
// if only or all are clicked we do not need to worry about anything just override whatever we have
@@ -562,6 +686,7 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
if (isOpen) {
setUserToggleState(false);
setVisibleItemsCount(10);
setVisibleUncheckedCount(5);
} else {
setUserToggleState(true);
}
@@ -590,35 +715,93 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
)}
</section>
</section>
{isOpen &&
(isLoading || isLoadingKeyValueSuggestions) &&
!attributeValues.length && (
<section className="loading">
<Skeleton paragraph={{ rows: 4 }} />
</section>
)}
{isOpen && !isLoading && !isLoadingKeyValueSuggestions && (
{isOpen && isLoadingKeyValueSuggestions && !attributeValues.length && (
<section className="loading">
<Skeleton paragraph={{ rows: 4 }} />
</section>
)}
{isOpen && !isLoadingKeyValueSuggestions && (
<>
{!isEmptyStateWithDocsEnabled && (
<section className="search">
<section className="search" ref={searchContainerRef}>
<Input
placeholder="Filter values"
placeholder="Search values"
onChange={(e): void => setSearchTextDebounced(e.target.value)}
disabled={isFilterDisabled}
ref={searchInputRef}
/>
</section>
)}
{attributeValues.length > 0 ? (
<section className="values">
{currentAttributeKeys.map((value: string, index: number) => (
{visibleCheckedValues.map((value: string, index: number) => (
<Fragment key={value}>
{index === checkedValuesCount && checkedValuesCount > 0 && (
<div
key="separator"
className="filter-separator"
data-testid="filter-separator"
/>
{index === checkedSeparatorIndex && (
<div className="filter-separator related-separator" />
)}
<div className="value">
<Checkbox
onChange={(e): void => onChange(value, e.target.checked, false)}
checked={currentFilterState[value]}
disabled={isFilterDisabled}
rootClassName="check-box"
/>
<div
className={cx(
'checkbox-value-section',
isFilterDisabled ? 'filter-disabled' : '',
)}
onClick={(): void => {
if (isFilterDisabled) {
return;
}
onChange(value, currentFilterState[value], true);
}}
>
<div className={`${filter.title} label-${value}`} />
{filter.customRendererForValue ? (
filter.customRendererForValue(value)
) : (
<Typography.Text
className="value-string"
ellipsis={{ tooltip: { placement: 'top' } }}
>
{String(value)}
</Typography.Text>
)}
<Button type="text" className="only-btn">
{isSomeFilterPresentForCurrentAttribute
? currentFilterState[value] && !isMultipleValuesTrueForTheKey
? 'All'
: 'Only'
: 'Only'}
</Button>
<Button type="text" className="toggle-btn">
Toggle
</Button>
</div>
</div>
</Fragment>
))}
{hasMoreChecked && (
<section className="show-more">
<Typography.Text
className="show-more-text"
onClick={(): void => setVisibleItemsCount((prev) => prev + 10)}
>
Show More...
</Typography.Text>
</section>
)}
{visibleCheckedCount > 0 && uncheckedValues.length > 0 && (
<div className="filter-separator" data-testid="filter-separator" />
)}
{visibleUncheckedValues.map((value: string) => (
<Fragment key={value}>
<div className="value">
<Checkbox
onChange={(e): void => onChange(value, e.target.checked, false)}
@@ -670,6 +853,17 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
</div>
</Fragment>
))}
{hasMoreUnchecked && (
<section className="show-more">
<Typography.Text
className="show-more-text"
onClick={(): void => setVisibleUncheckedCount((prev) => prev + 5)}
>
Show More...
</Typography.Text>
</section>
)}
</section>
) : isEmptyStateWithDocsEnabled ? (
<LogsQuickFilterEmptyState attributeKey={filter.attributeKey.key} />
@@ -678,16 +872,18 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
<Typography.Text>No values found</Typography.Text>{' '}
</section>
)}
{visibleItemsCount < attributeValues?.length && (
<section className="show-more">
<Typography.Text
className="show-more-text"
onClick={(): void => setVisibleItemsCount((prev) => prev + 10)}
>
Show More...
</Typography.Text>
</section>
)}
{visibleItemsCount >= attributeValues?.length &&
attributeValues?.length > 0 &&
!isDataComplete && (
<section className="search-prompt" onClick={handleSearchPromptClick}>
<AlertTriangle size={16} className="search-prompt__icon" />
<span className="search-prompt__text">
<Typography.Text className="search-prompt__subtitle">
Tap to search and load more suggestions.
</Typography.Text>
</span>
</section>
)}
</>
)}
</div>

View File

@@ -127,6 +127,34 @@
align-items: center;
padding: 8px;
}
.filters-info {
display: flex;
align-items: center;
padding: 6px 10px 0 10px;
color: var(--bg-vanilla-400);
gap: 6px;
flex-wrap: wrap;
.filters-info-toggle {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 0;
height: auto;
color: var(--bg-vanilla-400);
&:hover {
color: var(--bg-robin-500);
}
}
.filters-info-text {
color: var(--bg-vanilla-400);
font-size: 13px;
line-height: 16px;
}
}
}
.perilin-bg {
@@ -180,5 +208,30 @@
}
}
}
.filters-info {
color: var(--bg-ink-400);
.filters-info-toggle {
color: var(--bg-ink-400);
&:hover {
color: var(--bg-ink-300);
}
}
.filters-info-text {
color: var(--bg-ink-400);
}
}
}
}
.filters-info-tooltip-title {
font-weight: var(--font-weight-bold);
margin-bottom: 4px;
}
.filters-info-tooltip-detail {
margin-top: 4px;
}

View File

@@ -23,7 +23,7 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
import { useApiMonitoringParams } from 'container/ApiMonitoring/queryParams';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { isFunction, isNull } from 'lodash-es';
import { Frown, Settings2 as SettingsIcon } from 'lucide-react';
import { Frown, Lightbulb, Settings2 as SettingsIcon } from 'lucide-react';
import { useAppContext } from 'providers/App/App';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { USER_ROLES } from 'types/roles';
@@ -291,6 +291,27 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
/>
</div>
)}
<section className="filters-info">
<Tooltip
title={
<div className="filters-info-tooltip">
<div className="filters-info-tooltip-title">Adaptive Filters</div>
<div>Values update automatically as you apply filters.</div>
<div className="filters-info-tooltip-detail">
The most relevant values are shown first, followed by all other
available options.
</div>
</div>
}
placement="right"
mouseEnterDelay={0.3}
>
<Typography.Text className="filters-info-toggle">
<Lightbulb size={15} />
Adaptive filters
</Typography.Text>
</Tooltip>
</section>
<section className="filters">
{filterConfig.map((filter) => {
switch (filter.type) {

View File

@@ -4,6 +4,7 @@ import {
useApiMonitoringParams,
} from 'container/ApiMonitoring/queryParams';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useGetQueryKeyValueSuggestions } from 'hooks/querySuggestions/useGetQueryKeyValueSuggestions';
import {
otherFiltersResponse,
quickFiltersAttributeValuesResponse,
@@ -24,6 +25,8 @@ jest.mock('hooks/queryBuilder/useQueryBuilder', () => ({
}));
jest.mock('container/ApiMonitoring/queryParams');
jest.mock('hooks/querySuggestions/useGetQueryKeyValueSuggestions');
const handleFilterVisibilityChange = jest.fn();
const redirectWithQueryBuilderData = jest.fn();
const putHandler = jest.fn();
@@ -32,13 +35,15 @@ const mockSetApiMonitoringParams = jest.fn() as jest.MockedFunction<
>;
const mockUseApiMonitoringParams = jest.mocked(useApiMonitoringParams);
const mockUseGetQueryKeyValueSuggestions = jest.mocked(
useGetQueryKeyValueSuggestions,
);
const BASE_URL = ENVIRONMENT.baseURL;
const SIGNAL = SignalType.LOGS;
const quickFiltersListURL = `${BASE_URL}/api/v1/orgs/me/filters/${SIGNAL}`;
const saveQuickFiltersURL = `${BASE_URL}/api/v1/orgs/me/filters`;
const quickFiltersSuggestionsURL = `${BASE_URL}/api/v3/filter_suggestions`;
const quickFiltersAttributeValuesURL = `${BASE_URL}/api/v3/autocomplete/attribute_values`;
const fieldsValuesURL = `${BASE_URL}/api/v1/fields/values`;
const FILTER_OS_DESCRIPTION = 'os.description';
const FILTER_K8S_DEPLOYMENT_NAME = 'k8s.deployment.name';
@@ -62,10 +67,7 @@ const setupServer = (): void => {
putHandler(await req.json());
return res(ctx.status(200), ctx.json({}));
}),
rest.get(quickFiltersAttributeValuesURL, (_req, res, ctx) =>
res(ctx.status(200), ctx.json(quickFiltersAttributeValuesResponse)),
),
rest.get(fieldsValuesURL, (_req, res, ctx) =>
rest.get('*/api/v1/fields/values*', (_req, res, ctx) =>
res(ctx.status(200), ctx.json(quickFiltersAttributeValuesResponse)),
),
);
@@ -135,18 +137,28 @@ beforeEach(() => {
queryData: [
{
queryName: QUERY_NAME,
filters: { items: [{ key: 'test', value: 'value' }] },
filters: { items: [], op: 'AND' },
filter: { expression: '' },
},
],
},
},
lastUsedQuery: 0,
panelType: 'logs',
redirectWithQueryBuilderData,
});
mockUseApiMonitoringParams.mockReturnValue([
{ showIP: true } as ApiMonitoringParams,
mockSetApiMonitoringParams,
]);
// Mock the hook to return data with mq-kafka
mockUseGetQueryKeyValueSuggestions.mockReturnValue({
data: quickFiltersAttributeValuesResponse,
isLoading: false,
refetch: jest.fn(),
} as any);
setupServer();
});
@@ -259,8 +271,9 @@ describe('Quick Filters', () => {
render(<TestQuickFilters />);
// Prefer role if possible; if label text isnt wired to input, clicking the label text is OK
const target = await screen.findByText('mq-kafka');
// Wait for the filter to load with data
const target = await screen.findByText('mq-kafka', {}, { timeout: 5000 });
await user.click(target);
await waitFor(() => {

View File

@@ -14,6 +14,8 @@ import cx from 'classnames';
import { dragColumnParams } from 'hooks/useDragColumns/configs';
import { getColumnWidth, RowData } from 'lib/query/createTableColumnsFromQuery';
import { debounce, set } from 'lodash-es';
import { useDashboard } from 'providers/Dashboard/Dashboard';
import { Widgets } from 'types/api/dashboard/getAll';
import ResizableHeader from './ResizableHeader';
import { DragSpanStyle } from './styles';
@@ -24,26 +26,31 @@ function ResizeTable({
columns,
onDragColumn,
pagination,
columnWidths,
onColumnWidthsChange,
widgetId,
shouldPersistColumnWidths = false,
...restProps
}: ResizeTableProps): JSX.Element {
const [columnsData, setColumns] = useState<ColumnsType>([]);
const onColumnWidthsChangeRef = useRef(onColumnWidthsChange);
const { setColumnWidths, selectedDashboard } = useDashboard();
const columnWidths = shouldPersistColumnWidths
? (selectedDashboard?.data?.widgets?.find(
(widget) => widget.id === widgetId,
) as Widgets)?.columnWidths
: undefined;
const updateAllColumnWidths = useRef(
debounce((widthsConfig: Record<string, number>) => {
if (!onColumnWidthsChangeRef.current) {
if (!widgetId || !shouldPersistColumnWidths) {
return;
}
onColumnWidthsChangeRef.current(widthsConfig);
setColumnWidths?.((prev) => ({
...prev,
[widgetId]: widthsConfig,
}));
}, 1000),
).current;
useEffect(() => {
onColumnWidthsChangeRef.current = onColumnWidthsChange;
}, [onColumnWidthsChange]);
const handleResize = useCallback(
(index: number) => (
e: SyntheticEvent<Element>,
@@ -68,7 +75,7 @@ function ResizeTable({
...col,
...(onDragColumn && {
title: (
<DragSpanStyle className="dragHandler" data-testid="drag-column-title">
<DragSpanStyle className="dragHandler">
{col?.title?.toString() || ''}
</DragSpanStyle>
),
@@ -99,31 +106,31 @@ function ResizeTable({
}, [mergedColumns, pagination, restProps]);
useEffect(() => {
if (!columns) {
return;
}
const columnsWithStoredWidths = columns.map((col) => {
const dataIndex = (col as RowData).dataIndex as string;
if (dataIndex && columnWidths) {
const width = getColumnWidth(dataIndex, columnWidths);
if (width) {
return { ...col, width };
if (columns) {
// Apply stored column widths from widget configuration
const columnsWithStoredWidths = columns.map((col) => {
const dataIndex = (col as RowData).dataIndex as string;
if (dataIndex && columnWidths) {
const width = getColumnWidth(dataIndex, columnWidths);
if (width) {
return {
...col,
width, // Apply stored width
};
}
}
}
return col;
});
return col;
});
setColumns(columnsWithStoredWidths);
setColumns(columnsWithStoredWidths);
}
}, [columns, columnWidths]);
const lastReportedWidthsRef = useRef<Record<string, number>>({});
useEffect(() => {
if (!onColumnWidthsChange) {
if (!shouldPersistColumnWidths) {
return;
}
// Collect all column widths in a single object
const newColumnWidths: Record<string, number> = {};
mergedColumns.forEach((col) => {
@@ -133,20 +140,11 @@ function ResizeTable({
}
});
if (Object.keys(newColumnWidths).length === 0) {
return;
}
const last = lastReportedWidthsRef.current;
const hasChange =
Object.keys(newColumnWidths).length !== Object.keys(last).length ||
Object.keys(newColumnWidths).some((k) => newColumnWidths[k] !== last[k]);
if (hasChange) {
lastReportedWidthsRef.current = newColumnWidths;
// Only update if there are actual widths to set
if (Object.keys(newColumnWidths).length > 0) {
updateAllColumnWidths(newColumnWidths);
}
}, [mergedColumns, updateAllColumnWidths, onColumnWidthsChange]);
}, [mergedColumns, updateAllColumnWidths, shouldPersistColumnWidths]);
return onDragColumn ? (
<ReactDragListView.DragColumn {...dragColumnParams} onDragEnd={onDragColumn}>

View File

@@ -1,244 +0,0 @@
import { act } from '@testing-library/react';
import { render, screen, userEvent } from 'tests/test-utils';
import ResizeTable from '../ResizeTable';
jest.mock('react-resizable', () => ({
Resizable: ({
children,
onResize,
width,
}: {
children: React.ReactNode;
onResize: (
e: React.SyntheticEvent,
data: { size: { width: number } },
) => void;
width: number;
}): JSX.Element => (
<div>
{children}
<button
data-testid="resize-trigger"
type="button"
onClick={(e): void => onResize(e, { size: { width: width + 50 } })}
/>
</div>
),
}));
// Make debounce synchronous so onColumnWidthsChange fires immediately
jest.mock('lodash-es', () => ({
...jest.requireActual('lodash-es'),
debounce: (fn: (...args: any[]) => any): ((...args: any[]) => any) => fn,
}));
const baseColumns = [
{ dataIndex: 'name', title: 'Name', width: 100 },
{ dataIndex: 'value', title: 'Value', width: 100 },
];
const baseDataSource = [
{ key: '1', name: 'Alice', value: 42 },
{ key: '2', name: 'Bob', value: 99 },
];
describe('ResizeTable', () => {
it('renders column headers and data rows', () => {
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
/>,
);
expect(screen.getByText('Name')).toBeInTheDocument();
expect(screen.getByText('Value')).toBeInTheDocument();
expect(screen.getByText('Alice')).toBeInTheDocument();
expect(screen.getByText('Bob')).toBeInTheDocument();
});
it('overrides column widths from columnWidths prop and reports them via onColumnWidthsChange', () => {
const onColumnWidthsChange = jest.fn();
act(() => {
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
columnWidths={{ name: 250, value: 180 }}
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
});
expect(onColumnWidthsChange).toHaveBeenCalledWith(
expect.objectContaining({ name: 250, value: 180 }),
);
});
it('reports original column widths via onColumnWidthsChange when columnWidths prop is not provided', () => {
const onColumnWidthsChange = jest.fn();
act(() => {
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
});
expect(onColumnWidthsChange).toHaveBeenCalledWith(
expect.objectContaining({ name: 100, value: 100 }),
);
});
it('does not call onColumnWidthsChange when it is not provided', () => {
// Should render without errors and without attempting to call an undefined callback
expect(() => {
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
/>,
);
}).not.toThrow();
});
it('only overrides the column that has a stored width, leaving others at their original width', () => {
const onColumnWidthsChange = jest.fn();
act(() => {
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
columnWidths={{ name: 250 }}
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
});
expect(onColumnWidthsChange).toHaveBeenCalledWith(
expect.objectContaining({ name: 250, value: 100 }),
);
});
it('does not call onColumnWidthsChange on re-render when widths have not changed', () => {
const onColumnWidthsChange = jest.fn();
const { rerender } = render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
expect(onColumnWidthsChange).toHaveBeenCalledTimes(1);
onColumnWidthsChange.mockClear();
rerender(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
expect(onColumnWidthsChange).not.toHaveBeenCalled();
});
it('does not call onColumnWidthsChange when no column has a defined width', () => {
const onColumnWidthsChange = jest.fn();
render(
<ResizeTable
columns={[
{ dataIndex: 'name', title: 'Name' },
{ dataIndex: 'value', title: 'Value' },
]}
dataSource={baseDataSource}
rowKey="key"
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
expect(onColumnWidthsChange).not.toHaveBeenCalled();
});
it('calls onColumnWidthsChange with the new width after a column is resized', async () => {
const user = userEvent.setup();
const onColumnWidthsChange = jest.fn();
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
onColumnWidthsChange.mockClear();
// Click the first column's resize trigger — mock adds 50px to the current width (100 → 150)
const [firstResizeTrigger] = screen.getAllByTestId('resize-trigger');
await user.click(firstResizeTrigger);
expect(onColumnWidthsChange).toHaveBeenCalledWith(
expect.objectContaining({ name: 150, value: 100 }),
);
});
it('does not affect other columns when only one column is resized', async () => {
const user = userEvent.setup();
const onColumnWidthsChange = jest.fn();
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
onColumnWidthsChange={onColumnWidthsChange}
/>,
);
onColumnWidthsChange.mockClear();
// Resize only the second column (value: 100 → 150), name should stay at 100
const resizeTriggers = screen.getAllByTestId('resize-trigger');
await user.click(resizeTriggers[1]);
expect(onColumnWidthsChange).toHaveBeenCalledWith(
expect.objectContaining({ name: 100, value: 150 }),
);
});
it('wraps column titles in drag handler spans when onDragColumn is provided', () => {
const onDragColumn = jest.fn();
render(
<ResizeTable
columns={baseColumns}
dataSource={baseDataSource}
rowKey="key"
onDragColumn={onDragColumn}
/>,
);
const dragTitles = screen.getAllByTestId('drag-column-title');
expect(dragTitles).toHaveLength(baseColumns.length);
expect(dragTitles[0]).toHaveTextContent('Name');
expect(dragTitles[1]).toHaveTextContent('Value');
});
});

View File

@@ -6,25 +6,10 @@ import { LaunchChatSupportProps } from 'components/LaunchChatSupport/LaunchChatS
import { TableDataSource } from './contants';
type ColumnWidths = Record<string, number>;
export interface ResizeTableProps extends TableProps<any> {
onDragColumn?: (fromIndex: number, toIndex: number) => void;
/**
* Pre-resolved column widths for this table, keyed by column dataIndex.
* Use this to apply persisted widths on mount (e.g. from widget.columnWidths).
* Do NOT pass a value that updates reactively on every resize — that creates a
* feedback loop. Pass only stable / persisted values.
*/
columnWidths?: ColumnWidths;
/**
* Called (debounced) whenever the user finishes resizing a column.
* The widths object contains all current column widths keyed by dataIndex.
* Intended for persisting widths to an external store (e.g. dashboard context
* staging buffer). The caller owns the storage; ResizeTable does not read back
* whatever is written here.
*/
onColumnWidthsChange?: (widths: ColumnWidths) => void;
widgetId?: string;
shouldPersistColumnWidths?: boolean;
}
export interface DynamicColumnTableProps extends TableProps<any> {
tablesource: typeof TableDataSource[keyof typeof TableDataSource];

View File

@@ -3,16 +3,14 @@ import { UseQueryResult } from 'react-query';
import { Color } from '@signozhq/design-tokens';
import { Button, Card, Skeleton, Typography } from 'antd';
import cx from 'classnames';
import { useGetGraphCustomSeries } from 'components/CeleryTask/useGetGraphCustomSeries';
import { useNavigateToExplorer } from 'components/CeleryTask/useNavigateToExplorer';
import Uplot from 'components/Uplot';
import { PANEL_TYPES } from 'constants/queryBuilder';
import {
getCustomFiltersForBarChart,
getFormattedEndPointStatusCodeChartData,
getStatusCodeBarChartWidgetData,
statusCodeWidgetInfo,
} from 'container/ApiMonitoring/utils';
import BarChart from 'container/DashboardContainer/visualization/charts/BarChart/BarChart';
import { handleGraphClick } from 'container/GridCardLayout/GridCard/utils';
import { useGraphClickToShowButton } from 'container/GridCardLayout/useGraphClickToShowButton';
import useNavigateToExplorerPages from 'container/GridCardLayout/useNavigateToExplorerPages';
@@ -20,15 +18,16 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { useResizeObserver } from 'hooks/useDimensions';
import { useNotifications } from 'hooks/useNotifications';
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
import { LegendPosition } from 'lib/uPlotV2/components/types';
import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { useTimezone } from 'providers/Timezone';
import { SuccessResponse } from 'types/api';
import { Widgets } from 'types/api/dashboard/getAll';
import { IBuilderQuery } from 'types/api/queryBuilder/queryBuilderData';
import { Options } from 'uplot';
import ErrorState from './ErrorState';
import { prepareStatusCodeBarChartsConfig } from './utils';
function StatusCodeBarCharts({
endPointStatusCodeBarChartsDataQuery,
@@ -67,13 +66,6 @@ function StatusCodeBarCharts({
} = endPointStatusCodeLatencyBarChartsDataQuery;
const { startTime: minTime, endTime: maxTime } = timeRange;
const legendScrollPositionRef = useRef<{
scrollTop: number;
scrollLeft: number;
}>({
scrollTop: 0,
scrollLeft: 0,
});
const graphRef = useRef<HTMLDivElement>(null);
const dimensions = useResizeObserver(graphRef);
@@ -119,6 +111,7 @@ function StatusCodeBarCharts({
const navigateToExplorer = useNavigateToExplorer();
const { currentQuery } = useQueryBuilder();
const { timezone } = useTimezone();
const navigateToExplorerPages = useNavigateToExplorerPages();
const { notifications } = useNotifications();
@@ -134,12 +127,6 @@ function StatusCodeBarCharts({
[],
);
const { getCustomSeries } = useGetGraphCustomSeries({
isDarkMode,
drawStyle: 'bars',
colorMapping,
});
const widget = useMemo<Widgets>(
() =>
getStatusCodeBarChartWidgetData(domainName, {
@@ -193,49 +180,36 @@ function StatusCodeBarCharts({
],
);
const options = useMemo(
() =>
getUPlotChartOptions({
apiResponse:
currentWidgetInfoIndex === 0
? formattedEndPointStatusCodeBarChartsDataPayload
: formattedEndPointStatusCodeLatencyBarChartsDataPayload,
isDarkMode,
dimensions,
yAxisUnit: statusCodeWidgetInfo[currentWidgetInfoIndex].yAxisUnit,
softMax: null,
softMin: null,
minTimeScale: minTime,
maxTimeScale: maxTime,
panelType: PANEL_TYPES.BAR,
onClickHandler: graphClickHandler,
customSeries: getCustomSeries,
onDragSelect,
colorMapping,
query: currentQuery,
legendScrollPosition: legendScrollPositionRef.current,
setLegendScrollPosition: (position: {
scrollTop: number;
scrollLeft: number;
}) => {
legendScrollPositionRef.current = position;
},
}),
[
minTime,
maxTime,
currentWidgetInfoIndex,
dimensions,
formattedEndPointStatusCodeBarChartsDataPayload,
formattedEndPointStatusCodeLatencyBarChartsDataPayload,
const config = useMemo(() => {
const apiResponse =
currentWidgetInfoIndex === 0
? formattedEndPointStatusCodeBarChartsDataPayload
: formattedEndPointStatusCodeLatencyBarChartsDataPayload;
return prepareStatusCodeBarChartsConfig({
timezone,
isDarkMode,
graphClickHandler,
getCustomSeries,
query: currentQuery,
onDragSelect,
onClick: graphClickHandler,
apiResponse,
minTimeScale: minTime,
maxTimeScale: maxTime,
yAxisUnit: statusCodeWidgetInfo[currentWidgetInfoIndex].yAxisUnit,
colorMapping,
currentQuery,
],
);
});
}, [
currentQuery,
isDarkMode,
minTime,
maxTime,
graphClickHandler,
onDragSelect,
formattedEndPointStatusCodeBarChartsDataPayload,
formattedEndPointStatusCodeLatencyBarChartsDataPayload,
timezone,
currentWidgetInfoIndex,
colorMapping,
]);
const renderCardContent = useCallback(
(query: UseQueryResult<SuccessResponse<any>, unknown>): JSX.Element => {
@@ -253,11 +227,20 @@ function StatusCodeBarCharts({
!query.isLoading && !query?.data?.payload?.data?.result?.length,
})}
>
<Uplot options={options as Options} data={chartData} />
<BarChart
config={config}
data={chartData}
width={dimensions.width}
height={dimensions.height}
timezone={timezone}
legendConfig={{
position: LegendPosition.BOTTOM,
}}
/>
</div>
);
},
[options, chartData],
[config, chartData, dimensions, timezone],
);
return (

View File

@@ -0,0 +1,83 @@
import { ExecStats } from 'api/v5/v5';
import { Timezone } from 'components/CustomTimePicker/timezoneUtils';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { buildBaseConfig } from 'container/DashboardContainer/visualization/panels/utils/baseConfigBuilder';
import { getLegend } from 'lib/dashboard/getQueryResults';
import getLabelName from 'lib/getLabelName';
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
import { DrawStyle } from 'lib/uPlotV2/config/types';
import { UPlotConfigBuilder } from 'lib/uPlotV2/config/UPlotConfigBuilder';
import { get } from 'lodash-es';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { QueryData } from 'types/api/widgets/getQuery';
import { v4 as uuid } from 'uuid';
export const prepareStatusCodeBarChartsConfig = ({
timezone,
isDarkMode,
query,
onDragSelect,
onClick,
apiResponse,
minTimeScale,
maxTimeScale,
yAxisUnit,
colorMapping,
}: {
timezone: Timezone;
isDarkMode: boolean;
query: Query;
onDragSelect: (startTime: number, endTime: number) => void;
onClick?: OnClickPluginOpts['onClick'];
minTimeScale?: number;
maxTimeScale?: number;
apiResponse: MetricRangePayloadProps;
yAxisUnit?: string;
colorMapping?: Record<string, string>;
}): UPlotConfigBuilder => {
const stepIntervals: ExecStats['stepIntervals'] = get(
apiResponse,
'data.newResult.meta.stepIntervals',
{},
);
const minStepInterval = Math.min(...Object.values(stepIntervals));
const config = buildBaseConfig({
id: uuid(),
yAxisUnit: yAxisUnit,
apiResponse,
isDarkMode,
onDragSelect,
timezone,
onClick,
minTimeScale,
maxTimeScale,
stepInterval: minStepInterval,
panelType: PANEL_TYPES.BAR,
});
const seriesList: QueryData[] = apiResponse?.data?.result || [];
seriesList.forEach((series) => {
const baseLabelName = getLabelName(
series.metric,
series.queryName || '', // query
series.legend || '',
);
const label = query ? getLegend(series, query, baseLabelName) : baseLabelName;
const currentStepInterval = get(stepIntervals, series.queryName, undefined);
config.addSeries({
scaleKey: 'y',
drawStyle: DrawStyle.Bar,
label: label,
colorMapping: colorMapping ?? {},
isDarkMode,
stepInterval: currentStepInterval,
});
});
return config;
};

View File

@@ -21,10 +21,15 @@ interface MockQueryResult {
}
// Mocks
jest.mock('components/Uplot', () => ({
__esModule: true,
default: jest.fn().mockImplementation(() => <div data-testid="uplot-mock" />),
}));
jest.mock(
'container/DashboardContainer/visualization/charts/BarChart/BarChart',
() => ({
__esModule: true,
default: jest
.fn()
.mockImplementation(() => <div data-testid="bar-chart-mock" />),
}),
);
jest.mock('components/CeleryTask/useGetGraphCustomSeries', () => ({
useGetGraphCustomSeries: (): { getCustomSeries: jest.Mock } => ({
@@ -70,6 +75,24 @@ jest.mock('hooks/useNotifications', () => ({
useNotifications: (): { notifications: [] } => ({ notifications: [] }),
}));
jest.mock('providers/Timezone', () => ({
useTimezone: (): {
timezone: {
name: string;
value: string;
offset: string;
searchIndex: string;
};
} => ({
timezone: {
name: 'UTC',
value: 'UTC',
offset: '+00:00',
searchIndex: 'UTC',
},
}),
}));
jest.mock('lib/uPlotLib/getUplotChartOptions', () => ({
getUPlotChartOptions: jest.fn().mockReturnValue({}),
}));
@@ -319,7 +342,7 @@ describe('StatusCodeBarCharts', () => {
mockData.payload,
'sum',
);
expect(screen.getByTestId('uplot-mock')).toBeInTheDocument();
expect(screen.getByTestId('bar-chart-mock')).toBeInTheDocument();
expect(screen.getByText('Number of calls')).toBeInTheDocument();
expect(screen.getByText('Latency')).toBeInTheDocument();
});

View File

@@ -674,7 +674,7 @@ function GeneralSettings({
return (
<div className="general-settings-page">
<div className="general-settings-header">
<span className="general-settings-title">Workspace</span>
<span className="general-settings-title">General</span>
<span className="general-settings-subtitle">
Manage your workspace settings.
</span>

View File

@@ -81,18 +81,7 @@ function FullView({
setCurrentGraphRef(fullViewRef);
}, [setCurrentGraphRef]);
const {
selectedDashboard,
isDashboardLocked,
setColumnWidths,
} = useDashboard();
const onColumnWidthsChange = useCallback(
(widths: Record<string, number>) => {
setColumnWidths((prev) => ({ ...prev, [widget.id]: widths }));
},
[setColumnWidths, widget.id],
);
const { selectedDashboard, isDashboardLocked } = useDashboard();
const { dashboardVariables } = useDashboardVariables();
const { user } = useAppContext();
@@ -392,7 +381,6 @@ function FullView({
onClickHandler={onClickHandler}
enableDrillDown={enableDrillDown}
selectedGraph={selectedPanelType}
onColumnWidthsChange={onColumnWidthsChange}
/>
</GraphContainer>
</div>

View File

@@ -168,9 +168,6 @@ jest.mock('providers/Dashboard/Dashboard', () => ({
variables: [],
},
},
setLayouts: jest.fn(),
setSelectedDashboard: jest.fn(),
setColumnWidths: jest.fn(),
}),
}));

View File

@@ -101,19 +101,7 @@ function WidgetGraphComponent({
const navigateToExplorerPages = useNavigateToExplorerPages();
const {
setLayouts,
selectedDashboard,
setSelectedDashboard,
setColumnWidths,
} = useDashboard();
const onColumnWidthsChange = useCallback(
(widths: Record<string, number>) => {
setColumnWidths((prev) => ({ ...prev, [widget.id]: widths }));
},
[setColumnWidths, widget.id],
);
const { setLayouts, selectedDashboard, setSelectedDashboard } = useDashboard();
const onToggleModal = useCallback(
(func: Dispatch<SetStateAction<boolean>>) => {
@@ -436,7 +424,6 @@ function WidgetGraphComponent({
customSeries={customSeries}
customOnRowClick={customOnRowClick}
enableDrillDown={enableDrillDown}
onColumnWidthsChange={onColumnWidthsChange}
/>
</div>
)}

View File

@@ -45,8 +45,6 @@ function GridTableComponent({
onOpenTraceBtnClick,
customOnRowClick,
widgetId,
columnWidths,
onColumnWidthsChange,
panelType,
queryRangeRequest,
decimalPrecision,
@@ -286,8 +284,6 @@ function GridTableComponent({
dataSource={dataSource}
sticky={sticky}
widgetId={widgetId}
columnWidths={columnWidths}
onColumnWidthsChange={onColumnWidthsChange}
panelType={panelType}
queryRangeRequest={queryRangeRequest}
onRow={

View File

@@ -24,8 +24,6 @@ export type GridTableComponentProps = {
onOpenTraceBtnClick?: (record: RowData) => void;
customOnRowClick?: (record: RowData) => void;
widgetId?: string;
columnWidths?: Record<string, number>;
onColumnWidthsChange?: (widths: Record<string, number>) => void;
renderColumnCell?: QueryTableProps['renderColumnCell'];
customColTitles?: Record<string, string>;
enableDrillDown?: boolean;

View File

@@ -33,7 +33,6 @@ function LogsPanelComponent({
widget,
setRequestData,
queryResponse,
onColumnWidthsChange,
}: LogsPanelComponentProps): JSX.Element {
const [pageSize, setPageSize] = useState<number>(10);
const [offset, setOffset] = useState<number>(0);
@@ -146,8 +145,8 @@ function LogsPanelComponent({
columns={columns}
onRow={handleRow}
rowKey={(record): string => record.id}
columnWidths={widget.columnWidths}
onColumnWidthsChange={onColumnWidthsChange}
widgetId={widget.id}
shouldPersistColumnWidths
/>
</OverlayScrollbar>
</div>
@@ -190,7 +189,6 @@ export type LogsPanelComponentProps = {
Error
>;
widget: Widgets;
onColumnWidthsChange?: (widths: Record<string, number>) => void;
};
export default LogsPanelComponent;

View File

@@ -161,7 +161,7 @@ function MySettings(): JSX.Element {
<div className="my-settings-container">
<div className="user-info-section">
<div className="user-info-section-header">
<div className="user-info-section-title">Account </div>
<div className="user-info-section-title">General </div>
<div className="user-info-section-subtitle">
Manage your account settings.

View File

@@ -8,7 +8,6 @@ function ListPanelWrapper({
widget,
queryResponse,
setRequestData,
onColumnWidthsChange,
}: PanelWrapperProps): JSX.Element {
const dataSource = widget.query.builder?.queryData[0]?.dataSource;
@@ -22,7 +21,6 @@ function ListPanelWrapper({
widget={widget}
queryResponse={queryResponse}
setRequestData={setRequestData}
onColumnWidthsChange={onColumnWidthsChange}
/>
);
}
@@ -31,7 +29,6 @@ function ListPanelWrapper({
widget={widget}
queryResponse={queryResponse}
setRequestData={setRequestData}
onColumnWidthsChange={onColumnWidthsChange}
/>
);
}

View File

@@ -24,7 +24,6 @@ function PanelWrapper({
customOnRowClick,
panelMode,
enableDrillDown = false,
onColumnWidthsChange,
}: PanelWrapperProps): JSX.Element {
const Component = PanelTypeVsPanelWrapper[
selectedGraph || widget.panelTypes
@@ -59,7 +58,6 @@ function PanelWrapper({
customOnRowClick={customOnRowClick}
customSeries={customSeries}
enableDrillDown={enableDrillDown}
onColumnWidthsChange={onColumnWidthsChange}
/>
);
}

View File

@@ -14,7 +14,6 @@ function TablePanelWrapper({
onOpenTraceBtnClick,
customOnRowClick,
enableDrillDown = false,
onColumnWidthsChange,
}: PanelWrapperProps): JSX.Element {
const panelData =
(queryResponse.data?.payload?.data?.result?.[0] as any)?.table || [];
@@ -35,8 +34,6 @@ function TablePanelWrapper({
onOpenTraceBtnClick={onOpenTraceBtnClick}
customOnRowClick={customOnRowClick}
widgetId={widget.id}
columnWidths={widget.columnWidths}
onColumnWidthsChange={onColumnWidthsChange}
renderColumnCell={widget.renderColumnCell}
customColTitles={widget.customColTitles}
contextLinks={widget.contextLinks}

View File

@@ -29,7 +29,6 @@ export type PanelWrapperProps = {
customSeries?: (data: QueryData[]) => uPlot.Series[];
enableDrillDown?: boolean;
panelMode: PanelMode;
onColumnWidthsChange?: (widths: Record<string, number>) => void;
};
export type TooltipData = {

View File

@@ -24,8 +24,6 @@ export type QueryTableProps = Omit<
sticky?: TableProps<RowData>['sticky'];
searchTerm?: string;
widgetId?: string;
columnWidths?: Record<string, number>;
onColumnWidthsChange?: (widths: Record<string, number>) => void;
enableDrillDown?: boolean;
contextLinks?: ContextLinksData;
panelType?: PANEL_TYPES;

View File

@@ -28,8 +28,6 @@ export function QueryTable({
sticky,
searchTerm,
widgetId,
columnWidths,
onColumnWidthsChange,
panelType,
...props
}: QueryTableProps): JSX.Element {
@@ -177,8 +175,8 @@ export function QueryTable({
dataSource={filterTable === null ? newDataSource : filterTable}
scroll={{ x: 'max-content' }}
pagination={paginationConfig}
columnWidths={columnWidths}
onColumnWidthsChange={onColumnWidthsChange}
widgetId={widgetId}
shouldPersistColumnWidths
sticky={sticky}
{...props}
/>

View File

@@ -1057,20 +1057,21 @@
gap: 8px;
.user-settings-dropdown-label-text {
color: var(--l3-foreground);
color: var(--bg-slate-50, #62687c);
font-family: Inter;
font-size: var(--uppercase-small-500-font-size);
font-weight: var(--uppercase-small-500-font-weight);
font-size: 10px;
font-family: Inter;
font-weight: 600;
font-style: normal;
line-height: 18px;
line-height: 18px; /* 163.636% */
letter-spacing: 0.88px;
text-transform: uppercase;
}
.user-settings-dropdown-label-email {
color: var(--l1-foreground);
color: var(--bg-vanilla-400, #c0c1c3);
font-family: Inter;
font-size: var(--font-size-xs);
font-size: 12px;
font-style: normal;
line-height: normal;
letter-spacing: 0.14px;
@@ -1078,7 +1079,7 @@
}
.ant-dropdown-menu-item-divider {
background-color: var(--secondary) !important;
background-color: var(--bg-slate-500, #161922) !important;
}
.ant-dropdown-menu-item-disabled {
@@ -1094,14 +1095,6 @@
.help-support-dropdown {
.ant-dropdown-menu-item {
min-height: 32px;
.ant-dropdown-menu-title-content {
color: var(--l1-foreground) !important;
}
.user-settings-dropdown-logout-section {
color: var(--danger-background);
}
}
}
@@ -1278,7 +1271,7 @@
}
.help-support-dropdown li.ant-dropdown-menu-item-divider {
background-color: var(--secondary) !important;
background-color: var(--bg-slate-500, #161922) !important;
}
.lightMode {
@@ -1438,6 +1431,22 @@
}
}
.settings-dropdown {
.user-settings-dropdown-logged-in-section {
.user-settings-dropdown-label-text {
color: var(--bg-ink-400);
}
.user-settings-dropdown-label-email {
color: var(--bg-ink-300);
}
}
.ant-dropdown-menu-item-divider {
background-color: var(--bg-vanilla-300) !important;
}
}
.reorder-shortcut-nav-items-modal {
.ant-modal-content {
border: 1px solid var(--bg-vanilla-300);
@@ -1494,6 +1503,10 @@
color: var(--bg-ink-400);
}
}
.help-support-dropdown li.ant-dropdown-menu-item-divider {
background-color: var(--bg-vanilla-300) !important;
}
}
.version-tooltip-overlay {

View File

@@ -69,7 +69,6 @@ import { routeConfig } from './config';
import { getQueryString } from './helper';
import {
defaultMoreMenuItems,
getUserSettingsDropdownMenuItems,
helpSupportDropdownMenuItems as DefaultHelpSupportDropdownMenuItems,
helpSupportMenuItem,
primaryMenuItems,
@@ -486,12 +485,48 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element {
const userSettingsDropdownMenuItems: MenuProps['items'] = useMemo(
() =>
getUserSettingsDropdownMenuItems({
userEmail: user.email,
isWorkspaceBlocked,
isEnterpriseSelfHostedUser,
isCommunityEnterpriseUser,
}),
[
{
key: 'label',
label: (
<div className="user-settings-dropdown-logged-in-section">
<span className="user-settings-dropdown-label-text">LOGGED IN AS</span>
<span className="user-settings-dropdown-label-email">{user.email}</span>
</div>
),
disabled: true,
dataTestId: 'logged-in-as-nav-item',
},
{ type: 'divider' as const },
{
key: 'account',
label: 'Account Settings',
dataTestId: 'account-settings-nav-item',
},
{
key: 'workspace',
label: 'Workspace Settings',
disabled: isWorkspaceBlocked,
dataTestId: 'workspace-settings-nav-item',
},
...(isEnterpriseSelfHostedUser || isCommunityEnterpriseUser
? [
{
key: 'license',
label: 'Manage License',
dataTestId: 'manage-license-nav-item',
},
]
: []),
{ type: 'divider' as const },
{
key: 'logout',
label: (
<span className="user-settings-dropdown-logout-section">Sign out</span>
),
dataTestId: 'logout-nav-item',
},
].filter(Boolean),
[
isEnterpriseSelfHostedUser,
isCommunityEnterpriseUser,
@@ -821,6 +856,9 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element {
});
switch (item.key) {
case ROUTES.SHORTCUTS:
history.push(ROUTES.SHORTCUTS);
break;
case 'invite-collaborators':
history.push(`${ROUTES.ORG_SETTINGS}#invite-team-members`);
break;
@@ -840,7 +878,7 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element {
};
const handleSettingsMenuItemClick = (info: SidebarItem): void => {
const item = (userSettingsDropdownMenuItems ?? []).find(
const item = userSettingsDropdownMenuItems.find(
(item) => item?.key === info.key,
);
let menuLabel = '';
@@ -866,9 +904,6 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element {
case 'license':
history.push(ROUTES.LIST_LICENSES);
break;
case 'keyboard-shortcuts':
history.push(ROUTES.SHORTCUTS);
break;
case 'logout':
Logout();
break;

View File

@@ -1,74 +0,0 @@
import { getUserSettingsDropdownMenuItems } from 'container/SideNav/menuItems';
const BASE_PARAMS = {
userEmail: 'test@signoz.io',
isWorkspaceBlocked: false,
isEnterpriseSelfHostedUser: false,
isCommunityEnterpriseUser: false,
};
describe('getUserSettingsDropdownMenuItems', () => {
it('always includes logged-in-as label, workspace, account, keyboard shortcuts, and sign out', () => {
const items = getUserSettingsDropdownMenuItems(BASE_PARAMS);
const keys = items?.map((item) => item?.key);
expect(keys).toContain('label');
expect(keys).toContain('workspace');
expect(keys).toContain('account');
expect(keys).toContain('keyboard-shortcuts');
expect(keys).toContain('logout');
// workspace item is enabled when workspace is not blocked
const workspaceItem = items?.find(
(item: any) => item.key === 'workspace',
) as any;
expect(workspaceItem?.disabled).toBe(false);
// does not include license item for regular cloud user
expect(keys).not.toContain('license');
});
it('includes manage license item for enterprise self-hosted users', () => {
const items = getUserSettingsDropdownMenuItems({
...BASE_PARAMS,
isEnterpriseSelfHostedUser: true,
});
const keys = items?.map((item) => item?.key);
expect(keys).toContain('license');
});
it('includes manage license item for community enterprise users', () => {
const items = getUserSettingsDropdownMenuItems({
...BASE_PARAMS,
isCommunityEnterpriseUser: true,
});
const keys = items?.map((item) => item?.key);
expect(keys).toContain('license');
});
it('workspace item is disabled when workspace is blocked', () => {
const items = getUserSettingsDropdownMenuItems({
...BASE_PARAMS,
isWorkspaceBlocked: true,
});
const workspaceItem = items?.find(
(item: any) => item.key === 'workspace',
) as any;
expect(workspaceItem?.disabled).toBe(true);
});
it('returns items in correct order: label, divider, workspace, account, ..., shortcuts, divider, logout', () => {
const items = getUserSettingsDropdownMenuItems(BASE_PARAMS) ?? [];
const keys = items.map((item: any) => item.key ?? item.type);
expect(keys[0]).toBe('label');
expect(keys[1]).toBe('divider');
expect(keys[2]).toBe('workspace');
expect(keys[3]).toBe('account');
expect(keys[keys.length - 1]).toBe('logout');
});
});

View File

@@ -1,6 +1,4 @@
import { RocketOutlined } from '@ant-design/icons';
import { Style } from '@signozhq/design-tokens';
import { MenuProps } from 'antd';
import ROUTES from 'constants/routes';
import {
ArrowUpRight,
@@ -10,7 +8,6 @@ import {
Book,
Boxes,
BugIcon,
Building2,
ChartArea,
Cloudy,
DraftingCompass,
@@ -23,12 +20,12 @@ import {
Layers2,
LayoutGrid,
ListMinus,
LogOut,
MessageSquareText,
Plus,
Receipt,
Route,
ScrollText,
Search,
Settings,
Shield,
Slack,
@@ -37,11 +34,7 @@ import {
UserPlus,
} from 'lucide-react';
import {
SecondaryMenuItemKey,
SettingsNavSection,
SidebarItem,
} from './sideNav.types';
import { SecondaryMenuItemKey, SidebarItem } from './sideNav.types';
export const getStartedMenuItem = {
key: ROUTES.GET_STARTED,
@@ -195,6 +188,12 @@ export const primaryMenuItems: SidebarItem[] = [
icon: <Home size={16} />,
itemKey: 'home',
},
{
key: 'quick-search',
label: 'Search',
icon: <Search size={16} />,
itemKey: 'quick-search',
},
{
key: ROUTES.LIST_ALL_ALERT,
label: 'Alerts',
@@ -297,100 +296,77 @@ export const defaultMoreMenuItems: SidebarItem[] = [
},
];
export const settingsNavSections: SettingsNavSection[] = [
export const settingsMenuItems: SidebarItem[] = [
{
key: 'general',
items: [
{
key: ROUTES.SETTINGS,
label: 'Workspace',
icon: <Settings size={16} />,
isEnabled: true,
itemKey: 'workspace',
},
{
key: ROUTES.MY_SETTINGS,
label: 'Account',
icon: <User size={16} />,
isEnabled: true,
itemKey: 'account',
},
{
key: ROUTES.ALL_CHANNELS,
label: 'Notification Channels',
icon: <FileKey2 size={16} />,
isEnabled: true,
itemKey: 'notification-channels',
},
{
key: ROUTES.BILLING,
label: 'Billing',
icon: <Receipt size={16} />,
isEnabled: false,
itemKey: 'billing',
},
{
key: ROUTES.INTEGRATIONS,
label: 'Integrations',
icon: <Unplug size={16} />,
isEnabled: false,
itemKey: 'integrations',
},
],
key: ROUTES.SETTINGS,
label: 'General',
icon: <Settings size={16} />,
isEnabled: true,
itemKey: 'general',
},
{
key: ROUTES.BILLING,
label: 'Billing',
icon: <Receipt size={16} />,
isEnabled: false,
itemKey: 'billing',
},
{
key: ROUTES.ROLES_SETTINGS,
label: 'Roles',
icon: <Shield size={16} />,
isEnabled: false,
itemKey: 'roles',
},
{
key: ROUTES.ORG_SETTINGS,
label: 'Members & SSO',
icon: <User size={16} />,
isEnabled: false,
itemKey: 'members-sso',
},
{
key: 'identity-access',
title: 'Identity & Access',
items: [
{
key: ROUTES.ROLES_SETTINGS,
label: 'Roles',
icon: <Shield size={16} />,
isEnabled: false,
itemKey: 'roles',
},
{
key: ROUTES.API_KEYS,
label: 'API Keys',
icon: <Key size={16} />,
isEnabled: false,
itemKey: 'api-keys',
},
{
key: ROUTES.INGESTION_SETTINGS,
label: 'Ingestion',
icon: <RocketOutlined rotate={45} />,
isEnabled: false,
itemKey: 'ingestion',
},
],
key: ROUTES.INTEGRATIONS,
label: 'Integrations',
icon: <Unplug size={16} />,
isEnabled: false,
itemKey: 'integrations',
},
{
key: 'authentication',
title: 'Authentication',
items: [
{
key: ROUTES.ORG_SETTINGS,
label: 'Members & SSO',
icon: <User size={16} />,
isEnabled: false,
itemKey: 'members-sso',
},
],
key: ROUTES.ALL_CHANNELS,
label: 'Notification Channels',
icon: <FileKey2 size={16} />,
isEnabled: true,
itemKey: 'notification-channels',
},
{
key: 'shortcuts',
hasDivider: true,
items: [
{
key: ROUTES.SHORTCUTS,
label: 'Keyboard Shortcuts',
icon: <Keyboard size={16} />,
isEnabled: true,
itemKey: 'keyboard-shortcuts',
},
],
key: ROUTES.API_KEYS,
label: 'API Keys',
icon: <Key size={16} />,
isEnabled: false,
itemKey: 'api-keys',
},
{
key: ROUTES.INGESTION_SETTINGS,
label: 'Ingestion',
icon: <RocketOutlined rotate={45} />,
isEnabled: false,
itemKey: 'ingestion',
},
{
key: ROUTES.MY_SETTINGS,
label: 'Account Settings',
icon: <User size={16} />,
isEnabled: true,
itemKey: 'account-settings',
},
{
key: ROUTES.SHORTCUTS,
label: 'Keyboard Shortcuts',
icon: <Layers2 size={16} />,
isEnabled: true,
itemKey: 'keyboard-shortcuts',
},
];
@@ -441,6 +417,12 @@ export const helpSupportDropdownMenuItems: SidebarItem[] = [
icon: <MessageSquareText size={14} />,
itemKey: 'chat-support',
},
{
key: ROUTES.SHORTCUTS,
label: 'Keyboard Shortcuts',
icon: <Keyboard size={14} />,
itemKey: 'keyboard-shortcuts',
},
{
key: 'invite-collaborators',
label: 'Invite a Team Member',
@@ -449,78 +431,6 @@ export const helpSupportDropdownMenuItems: SidebarItem[] = [
},
];
export interface UserSettingsMenuItemsParams {
userEmail: string;
isWorkspaceBlocked: boolean;
isEnterpriseSelfHostedUser: boolean;
isCommunityEnterpriseUser: boolean;
}
export const getUserSettingsDropdownMenuItems = ({
userEmail,
isWorkspaceBlocked,
isEnterpriseSelfHostedUser,
isCommunityEnterpriseUser,
}: UserSettingsMenuItemsParams): MenuProps['items'] =>
[
{
key: 'label',
label: (
<div className="user-settings-dropdown-logged-in-section">
<span className="user-settings-dropdown-label-text">LOGGED IN AS</span>
<span className="user-settings-dropdown-label-email">{userEmail}</span>
</div>
),
disabled: true,
dataTestId: 'logged-in-as-nav-item',
},
{ type: 'divider' as const },
{
key: 'workspace',
label: 'Workspace Settings',
icon: <Building2 size={14} color={Style.L1_FOREGROUND} />,
disabled: isWorkspaceBlocked,
dataTestId: 'workspace-settings-nav-item',
},
{
key: 'account',
label: 'Account Settings',
icon: <User size={14} color={Style.L1_FOREGROUND} />,
dataTestId: 'account-settings-nav-item',
},
...(isEnterpriseSelfHostedUser || isCommunityEnterpriseUser
? [
{
key: 'license',
label: 'Manage License',
icon: <Shield size={14} color={Style.L1_FOREGROUND} />,
dataTestId: 'manage-license-nav-item',
},
]
: []),
{
key: 'keyboard-shortcuts',
label: 'Keyboard Shortcuts',
icon: <Keyboard size={14} color={Style.L1_FOREGROUND} />,
dataTestId: 'keyboard-shortcuts-nav-item',
},
{ type: 'divider' as const },
{
key: 'logout',
label: (
<span className="user-settings-dropdown-logout-section">Sign out</span>
),
icon: (
<LogOut
size={14}
className="user-settings-dropdown-logout-section"
color={Style.DANGER_BACKGROUND}
/>
),
dataTestId: 'logout-nav-item',
},
].filter(Boolean);
/** Mapping of some newly added routes and their corresponding active sidebar menu key */
export const NEW_ROUTES_MENU_ITEM_KEY_MAP: Record<string, string> = {
[ROUTES.TRACE]: ROUTES.TRACES_EXPLORER,

View File

@@ -24,13 +24,6 @@ export interface SidebarItem {
export const CHANGELOG_LABEL = 'Full Changelog';
export interface SettingsNavSection {
title?: string;
items: SidebarItem[];
key: string;
hasDivider?: boolean;
}
export interface DropdownSeparator {
type: 'divider' | 'group';
label?: ReactNode;

View File

@@ -35,7 +35,6 @@ function TracesTableComponent({
widget,
queryResponse,
setRequestData,
onColumnWidthsChange,
}: TracesTableComponentProps): JSX.Element {
const [pagination, setPagination] = useState<Pagination>({
offset: 0,
@@ -132,8 +131,8 @@ function TracesTableComponent({
columns={columns}
onRow={handleRow}
sticky
columnWidths={widget.columnWidths}
onColumnWidthsChange={onColumnWidthsChange}
widgetId={widget.id}
shouldPersistColumnWidths
/>
</OverlayScrollbar>
</div>
@@ -176,7 +175,6 @@ export type TracesTableComponentProps = {
>;
widget: Widgets;
setRequestData: Dispatch<SetStateAction<GetQueryResultsProps>>;
onColumnWidthsChange?: (widths: Record<string, number>) => void;
};
export default TracesTableComponent;

View File

@@ -1,7 +1,11 @@
/* eslint-disable no-restricted-imports */
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
import { useSelector } from 'react-redux';
import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion';
import { AxiosError, AxiosResponse } from 'axios';
import { AppState } from 'store/reducers';
import { QueryKeyValueSuggestionsResponseProps } from 'types/api/querySuggestions/types';
import { GlobalReducer } from 'types/reducer/globalTime';
export const useGetQueryKeyValueSuggestions = ({
key,
@@ -9,6 +13,7 @@ export const useGetQueryKeyValueSuggestions = ({
searchText,
signalSource,
metricName,
existingQuery,
options,
}: {
key: string;
@@ -20,11 +25,24 @@ export const useGetQueryKeyValueSuggestions = ({
AxiosError
>;
metricName?: string;
existingQuery?: string;
}): UseQueryResult<
AxiosResponse<QueryKeyValueSuggestionsResponseProps>,
AxiosError
> =>
useQuery<AxiosResponse<QueryKeyValueSuggestionsResponseProps>, AxiosError>({
> => {
const { minTime, maxTime } = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
);
const timeRangeKey =
minTime != null && maxTime != null
? `${Math.floor(minTime / 1e9)}-${Math.floor(maxTime / 1e9)}`
: null;
return useQuery<
AxiosResponse<QueryKeyValueSuggestionsResponseProps>,
AxiosError
>({
queryKey: [
'queryKeyValueSuggestions',
key,
@@ -32,6 +50,7 @@ export const useGetQueryKeyValueSuggestions = ({
searchText,
signalSource,
metricName,
timeRangeKey,
],
queryFn: () =>
getValueSuggestions({
@@ -40,6 +59,8 @@ export const useGetQueryKeyValueSuggestions = ({
searchText: searchText || '',
signalSource: signalSource as 'meter' | '',
metricName: metricName || '',
existingQuery,
}),
...options,
});
};

View File

@@ -1,4 +1,4 @@
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import cx from 'classnames';
import { getFocusedSeriesAtPosition } from 'lib/uPlotLib/plugins/onClickPlugin';
@@ -44,14 +44,12 @@ export default function TooltipPlugin({
canPinTooltip = false,
}: TooltipPluginProps): JSX.Element | null {
const containerRef = useRef<HTMLDivElement>(null);
const portalRoot = useRef<HTMLElement>(document.body);
const rafId = useRef<number | null>(null);
const dismissTimeoutId = useRef<ReturnType<typeof setTimeout> | null>(null);
const layoutRef = useRef<TooltipLayoutInfo>();
const renderRef = useRef(render);
renderRef.current = render;
const [portalRoot, setPortalRoot] = useState<HTMLElement>(
(document.fullscreenElement as HTMLElement) ?? document.body,
);
// React-managed snapshot of what should be rendered. The controller
// owns the interaction state and calls `updateState` when a visible
@@ -391,19 +389,6 @@ export default function TooltipPlugin({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [config]);
const resolvePortalRoot = useCallback((): void => {
setPortalRoot((document.fullscreenElement as HTMLElement) ?? document.body);
}, []);
useLayoutEffect((): (() => void) => {
resolvePortalRoot();
document.addEventListener('fullscreenchange', resolvePortalRoot);
return (): void => {
document.removeEventListener('fullscreenchange', resolvePortalRoot);
};
}, [resolvePortalRoot]);
useLayoutEffect((): void => {
if (!hasPlot || !layoutRef.current) {
return;
@@ -464,6 +449,6 @@ export default function TooltipPlugin({
>
{tooltipBody}
</div>,
portalRoot,
portalRoot.current,
);
}

View File

@@ -188,58 +188,6 @@ describe('TooltipPlugin', () => {
expect(container).not.toBeNull();
expect(container.parentElement).toBe(document.body);
});
it('moves tooltip portal root to fullscreen element and back on exit', async () => {
const config = createConfigMock();
let mockedFullscreenElement: Element | null = null;
const originalFullscreenElementDescriptor = Object.getOwnPropertyDescriptor(
Document.prototype,
'fullscreenElement',
);
Object.defineProperty(Document.prototype, 'fullscreenElement', {
configurable: true,
get: () => mockedFullscreenElement,
});
renderAndActivateHover(config);
const container = document.querySelector(
'.tooltip-plugin-container',
) as HTMLElement;
expect(container.parentElement).toBe(document.body);
const fullscreenRoot = document.createElement('div');
document.body.appendChild(fullscreenRoot);
act(() => {
mockedFullscreenElement = fullscreenRoot;
document.dispatchEvent(new Event('fullscreenchange'));
});
await waitFor(() => {
const updatedContainer = screen.getByTestId('tooltip-plugin-container');
expect(updatedContainer.parentElement).toBe(fullscreenRoot);
});
act(() => {
mockedFullscreenElement = null;
document.dispatchEvent(new Event('fullscreenchange'));
});
await waitFor(() => {
const updatedContainer = screen.getByTestId('tooltip-plugin-container');
expect(updatedContainer.parentElement).toBe(document.body);
});
if (originalFullscreenElementDescriptor) {
Object.defineProperty(
Document.prototype,
'fullscreenElement',
originalFullscreenElementDescriptor,
);
}
fullscreenRoot.remove();
});
});
// ---- Pin behaviour ----------------------------------------------------------

View File

@@ -118,13 +118,13 @@ export const otherFiltersResponse = {
export const quickFiltersAttributeValuesResponse = {
status: 'success',
data: {
stringAttributeValues: [
'mq-kafka',
'otel-demo',
'otlp-python',
'sample-flask',
],
numberAttributeValues: null,
boolAttributeValues: null,
data: {
values: {
relatedValues: ['mq-kafka', 'otel-demo', 'otlp-python', 'sample-flask'],
stringValues: ['mq-kafka', 'otel-demo', 'otlp-python', 'sample-flask'],
numberValues: [],
},
complete: true,
},
},
};

View File

@@ -31,33 +31,9 @@
.settings-page-sidenav {
width: 240px;
height: calc(100vh - 48px);
border-right: 1px solid var(--secondary);
background: var(--sidebar-primary-foreground);
padding-top: var(--padding-1);
display: flex;
flex-direction: column;
gap: var(--spacing-12);
overflow-y: auto;
.settings-nav-section {
display: flex;
flex-direction: column;
}
.settings-nav-section--with-divider {
border-top: 1px solid var(--secondary);
padding-top: var(--padding-4);
}
.settings-nav-section-title {
font-size: var(--uppercase-small-600-font-size);
font-weight: var(--uppercase-small-600-font-weight);
letter-spacing: 0.88px;
text-transform: uppercase;
color: var(--l3-foreground);
margin-bottom: var(--margin-2);
padding: var(--padding-1) var(--padding-3);
}
border-right: 1px solid var(--Slate-500, #161922);
background: var(--Ink-500, #0b0c0e);
margin-top: 4px;
.nav-item {
.nav-item-data {

View File

@@ -7,7 +7,7 @@ import { FeatureKeys } from 'constants/features';
import ROUTES from 'constants/routes';
import { routeConfig } from 'container/SideNav/config';
import { getQueryString } from 'container/SideNav/helper';
import { settingsNavSections } from 'container/SideNav/menuItems';
import { settingsMenuItems as defaultSettingsMenuItems } from 'container/SideNav/menuItems';
import NavItem from 'container/SideNav/NavItem/NavItem';
import { SidebarItem } from 'container/SideNav/sideNav.types';
import useComponentPermission from 'hooks/useComponentPermission';
@@ -33,7 +33,7 @@ function SettingsPage(): JSX.Element {
const { isCloudUser, isEnterpriseSelfHostedUser } = useGetTenantLicense();
const [settingsMenuItems, setSettingsMenuItems] = useState<SidebarItem[]>(
settingsNavSections.flatMap((section) => section.items),
defaultSettingsMenuItems,
);
const isAdmin = user.role === USER_ROLES.ADMIN;
@@ -252,45 +252,25 @@ function SettingsPage(): JSX.Element {
<div className="settings-page-content-container">
<div className="settings-page-sidenav" data-testid="settings-page-sidenav">
{settingsNavSections.map((section) => {
const enabledItems = section.items.filter((sectionItem) =>
settingsMenuItems.some(
(item) => item.key === sectionItem.key && item.isEnabled,
),
);
if (enabledItems.length === 0) {
return null;
}
return (
<div
key={section.key}
className={`settings-nav-section${
section.hasDivider ? ' settings-nav-section--with-divider' : ''
}`}
>
{section.title && (
<div className="settings-nav-section-title">{section.title}</div>
)}
{enabledItems.map((item) => (
<NavItem
key={item.key}
item={item}
isActive={isActiveNavItem(item.key as string)}
isDisabled={false}
showIcon={false}
onClick={(event): void => {
logEvent('Settings V2: Menu clicked', {
menuLabel: item.label,
menuRoute: item.key,
});
handleMenuItemClick((event as unknown) as MouseEvent, item);
}}
dataTestId={item.itemKey}
/>
))}
</div>
);
})}
{settingsMenuItems
.filter((item) => item.isEnabled)
.map((item) => (
<NavItem
key={item.key}
item={item}
isActive={isActiveNavItem(item.key as string)}
isDisabled={false}
showIcon={false}
onClick={(event): void => {
logEvent('Settings V2: Menu clicked', {
menuLabel: item.label,
menuRoute: item.key,
});
handleMenuItemClick((event as unknown) as MouseEvent, item);
}}
dataTestId={item.itemKey}
/>
))}
</div>
<div className="settings-page-content">

View File

@@ -1,137 +0,0 @@
import React from 'react';
import SettingsPage from 'pages/Settings/Settings';
import { render, screen, within } from 'tests/test-utils';
import { LicensePlatform } from 'types/api/licensesV3/getActive';
import { USER_ROLES } from 'types/roles';
jest.mock('components/MarkdownRenderer/MarkdownRenderer', () => ({
__esModule: true,
default: ({ children }: { children: React.ReactNode }): React.ReactNode =>
children,
}));
jest.mock('api/common/logEvent', () => ({
__esModule: true,
default: jest.fn(),
}));
jest.mock('lib/history', () => ({
push: jest.fn(),
listen: jest.fn(() => jest.fn()),
location: { pathname: '/settings', search: '' },
}));
const getCloudAdminOverrides = (): any => ({
activeLicense: {
key: 'test-key',
platform: LicensePlatform.CLOUD,
},
});
const getSelfHostedAdminOverrides = (): any => ({
activeLicense: {
key: 'test-key',
platform: LicensePlatform.SELF_HOSTED,
},
});
describe('SettingsPage nav sections', () => {
describe('Cloud Admin', () => {
beforeEach(() => {
render(<SettingsPage />, undefined, {
role: USER_ROLES.ADMIN,
appContextOverrides: getCloudAdminOverrides(),
initialRoute: '/settings',
});
});
it.each([
'settings-page-sidenav',
'workspace',
'account',
'notification-channels',
'billing',
'roles',
'api-keys',
'members-sso',
'integrations',
'ingestion',
])('renders "%s" element', (id) => {
expect(screen.getByTestId(id)).toBeInTheDocument();
});
it.each(['Identity & Access', 'Authentication'])(
'renders "%s" section title',
(text) => {
expect(screen.getByText(text)).toBeInTheDocument();
},
);
});
describe('Cloud Viewer', () => {
beforeEach(() => {
render(<SettingsPage />, undefined, {
role: USER_ROLES.VIEWER,
appContextOverrides: getCloudAdminOverrides(),
initialRoute: '/settings',
});
});
it.each(['workspace', 'account'])('renders "%s" element', (id) => {
expect(screen.getByTestId(id)).toBeInTheDocument();
});
it.each(['billing', 'roles', 'api-keys'])(
'does not render "%s" element',
(id) => {
expect(screen.queryByTestId(id)).not.toBeInTheDocument();
},
);
});
describe('Self-hosted Admin', () => {
beforeEach(() => {
render(<SettingsPage />, undefined, {
role: USER_ROLES.ADMIN,
appContextOverrides: getSelfHostedAdminOverrides(),
initialRoute: '/settings',
});
});
it.each(['roles', 'api-keys', 'integrations', 'members-sso', 'ingestion'])(
'renders "%s" element',
(id) => {
expect(screen.getByTestId(id)).toBeInTheDocument();
},
);
});
describe('section structure', () => {
it('renders items in correct sections for cloud admin', () => {
const { container } = render(<SettingsPage />, undefined, {
role: USER_ROLES.ADMIN,
appContextOverrides: getCloudAdminOverrides(),
initialRoute: '/settings',
});
const sidenav = within(container).getByTestId('settings-page-sidenav');
const sections = sidenav.querySelectorAll('.settings-nav-section');
// Should have at least 2 sections (general + identity-access) for cloud admin
expect(sections.length).toBeGreaterThanOrEqual(2);
});
it('hides section entirely when all items in it are disabled', () => {
// Community user has very limited access — identity section should be hidden
render(<SettingsPage />, undefined, {
role: USER_ROLES.VIEWER,
appContextOverrides: {
activeLicense: null,
},
initialRoute: '/settings',
});
expect(screen.queryByText('IDENTITY & ACCESS')).not.toBeInTheDocument();
});
});
});

View File

@@ -592,6 +592,39 @@ body {
}
}
.ant-btn-text:hover,
.ant-btn-text:focus-visible {
background-color: var(--bg-vanilla-200) !important;
}
.ant-btn-link:hover,
.ant-btn-link:focus-visible {
background-color: transparent !important;
}
.ant-btn-default:hover,
.ant-btn-default:focus-visible,
.ant-btn-text:not(.ant-btn-primary):hover,
.ant-btn-text:not(.ant-btn-primary):focus-visible,
.ant-btn:not(.ant-btn-primary):not(.ant-btn-dangerous):hover,
.ant-btn:not(.ant-btn-primary):not(.ant-btn-dangerous):focus-visible {
background-color: var(--bg-vanilla-200) !important;
}
.ant-typography:hover,
.ant-typography:focus-visible {
background-color: transparent !important;
}
.ant-tooltip {
--antd-arrow-background-color: var(--bg-vanilla-300);
.ant-tooltip-inner {
background-color: var(--bg-vanilla-200);
color: var(--bg-ink-500);
}
}
// Enhanced legend light mode styles
.u-legend-enhanced {
// Light mode scrollbar styling

View File

@@ -47,6 +47,7 @@ export interface QueryKeyValueRequestProps {
searchText: string;
signalSource?: 'meter' | '';
metricName?: string;
existingQuery?: string;
}
export type SignalType = 'traces' | 'logs' | 'metrics';

View File

@@ -18,7 +18,6 @@ import (
"github.com/SigNoz/signoz/pkg/telemetrymetrics"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/metricsexplorertypes"
"github.com/SigNoz/signoz/pkg/types/metrictypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
@@ -60,8 +59,6 @@ func NewModule(ts telemetrystore.TelemetryStore, telemetryMetadataStore telemetr
// TODO(srikanthccv): use metadata store to fetch metric metadata
func (m *module) ListMetrics(ctx context.Context, orgID valuer.UUID, params *metricsexplorertypes.ListMetricsParams) (*metricsexplorertypes.ListMetricsResponse, error) {
ctx = m.withMetricsExplorerContext(ctx, "ListMetrics")
if err := params.Validate(); err != nil {
return nil, err
}
@@ -291,7 +288,6 @@ func (m *module) GetTreemap(ctx context.Context, orgID valuer.UUID, req *metrics
}
func (m *module) GetMetricMetadataMulti(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string]*metricsexplorertypes.MetricMetadata, error) {
if len(metricNames) == 0 {
return map[string]*metricsexplorertypes.MetricMetadata{}, nil
}
@@ -480,8 +476,6 @@ func (m *module) GetMetricAttributes(ctx context.Context, orgID valuer.UUID, req
}
func (m *module) CheckMetricExists(ctx context.Context, orgID valuer.UUID, metricName string) (bool, error) {
ctx = m.withMetricsExplorerContext(ctx, "CheckMetricExists")
sb := sqlbuilder.NewSelectBuilder()
sb.Select("count(*) > 0 as metricExists")
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, telemetrymetrics.AttributesMetadataTableName))
@@ -518,8 +512,6 @@ func (m *module) fetchMetadataFromCache(ctx context.Context, orgID valuer.UUID,
}
func (m *module) fetchUpdatedMetadata(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string]*metricsexplorertypes.MetricMetadata, error) {
ctx = m.withMetricsExplorerContext(ctx, "fetchUpdatedMetadata")
if len(metricNames) == 0 {
return map[string]*metricsexplorertypes.MetricMetadata{}, nil
}
@@ -578,8 +570,6 @@ func (m *module) fetchUpdatedMetadata(ctx context.Context, orgID valuer.UUID, me
}
func (m *module) fetchTimeseriesMetadata(ctx context.Context, orgID valuer.UUID, metricNames []string) (map[string]*metricsexplorertypes.MetricMetadata, error) {
ctx = m.withMetricsExplorerContext(ctx, "fetchTimeseriesMetadata")
if len(metricNames) == 0 {
return map[string]*metricsexplorertypes.MetricMetadata{}, nil
}
@@ -708,8 +698,6 @@ func (m *module) validateMetricLabels(ctx context.Context, req *metricsexplorert
}
func (m *module) checkForLabelInMetric(ctx context.Context, metricName string, label string) (bool, error) {
ctx = m.withMetricsExplorerContext(ctx, "checkForLabelInMetric")
sb := sqlbuilder.NewSelectBuilder()
sb.Select("count(*) > 0 AS has_label")
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, telemetrymetrics.AttributesMetadataTableName))
@@ -731,7 +719,6 @@ func (m *module) checkForLabelInMetric(ctx context.Context, metricName string, l
}
func (m *module) insertMetricsMetadata(ctx context.Context, orgID valuer.UUID, req *metricsexplorertypes.UpdateMetricMetadataRequest) error {
ctx = m.withMetricsExplorerContext(ctx, "insertMetricsMetadata")
createdAt := time.Now().UnixMilli()
ib := sqlbuilder.NewInsertBuilder()
@@ -825,7 +812,6 @@ func (m *module) fetchMetricsStatsWithSamples(
normalized bool,
orderBy *qbtypes.OrderBy,
) ([]metricsexplorertypes.Stat, uint64, error) {
ctx = m.withMetricsExplorerContext(ctx, "fetchMetricsStatsWithSamples")
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
samplesTable := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
@@ -933,8 +919,6 @@ func (m *module) fetchMetricsStatsWithSamples(
}
func (m *module) computeTimeseriesTreemap(ctx context.Context, req *metricsexplorertypes.TreemapRequest, filterWhereClause *sqlbuilder.WhereClause) ([]metricsexplorertypes.TreemapEntry, error) {
ctx = m.withMetricsExplorerContext(ctx, "computeTimeseriesTreemap")
start, end, distributedTsTable, _ := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
totalTSBuilder := sqlbuilder.NewSelectBuilder()
@@ -999,8 +983,6 @@ func (m *module) computeTimeseriesTreemap(ctx context.Context, req *metricsexplo
}
func (m *module) computeSamplesTreemap(ctx context.Context, req *metricsexplorertypes.TreemapRequest, filterWhereClause *sqlbuilder.WhereClause) ([]metricsexplorertypes.TreemapEntry, error) {
ctx = m.withMetricsExplorerContext(ctx, "computeSamplesTreemap")
start, end, distributedTsTable, localTsTable := telemetrymetrics.WhichTSTableToUse(uint64(req.Start), uint64(req.End), nil)
samplesTable := telemetrymetrics.WhichSamplesTableToUse(uint64(req.Start), uint64(req.End), metrictypes.UnspecifiedType, metrictypes.TimeAggregationUnspecified, nil)
countExp := telemetrymetrics.CountExpressionForSamplesTable(samplesTable)
@@ -1102,8 +1084,6 @@ func (m *module) computeSamplesTreemap(ctx context.Context, req *metricsexplorer
// getMetricDataPoints returns the total number of data points (samples) for a metric.
func (m *module) getMetricDataPoints(ctx context.Context, metricName string) (uint64, error) {
ctx = m.withMetricsExplorerContext(ctx, "getMetricDataPoints")
sb := sqlbuilder.NewSelectBuilder()
sb.Select("sum(count) AS data_points")
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, telemetrymetrics.SamplesV4Agg30mTableName))
@@ -1124,8 +1104,6 @@ func (m *module) getMetricDataPoints(ctx context.Context, metricName string) (ui
// getMetricLastReceived returns the last received timestamp for a metric.
func (m *module) getMetricLastReceived(ctx context.Context, metricName string) (uint64, error) {
ctx = m.withMetricsExplorerContext(ctx, "getMetricLastReceived")
sb := sqlbuilder.NewSelectBuilder()
sb.Select("MAX(last_reported_unix_milli) AS last_received_time")
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, telemetrymetrics.AttributesMetadataTableName))
@@ -1149,8 +1127,6 @@ func (m *module) getMetricLastReceived(ctx context.Context, metricName string) (
// getTotalTimeSeriesForMetricName returns the total number of unique time series for a metric.
func (m *module) getTotalTimeSeriesForMetricName(ctx context.Context, metricName string) (uint64, error) {
ctx = m.withMetricsExplorerContext(ctx, "getTotalTimeSeriesForMetricName")
sb := sqlbuilder.NewSelectBuilder()
sb.Select("uniq(fingerprint) AS time_series_count")
sb.From(fmt.Sprintf("%s.%s", telemetrymetrics.DBName, telemetrymetrics.TimeseriesV41weekTableName))
@@ -1171,8 +1147,6 @@ func (m *module) getTotalTimeSeriesForMetricName(ctx context.Context, metricName
// getActiveTimeSeriesForMetricName returns the number of active time series for a metric within the given duration.
func (m *module) getActiveTimeSeriesForMetricName(ctx context.Context, metricName string, duration time.Duration) (uint64, error) {
ctx = m.withMetricsExplorerContext(ctx, "getActiveTimeSeriesForMetricName")
milli := time.Now().Add(-duration).UnixMilli()
sb := sqlbuilder.NewSelectBuilder()
@@ -1194,8 +1168,6 @@ func (m *module) getActiveTimeSeriesForMetricName(ctx context.Context, metricNam
}
func (m *module) fetchMetricAttributes(ctx context.Context, metricName string, start, end *int64) ([]metricsexplorertypes.MetricAttribute, error) {
ctx = m.withMetricsExplorerContext(ctx, "fetchMetricAttributes")
// Build query using sqlbuilder
sb := sqlbuilder.NewSelectBuilder()
sb.Select(
@@ -1244,12 +1216,3 @@ func (m *module) fetchMetricAttributes(ctx context.Context, metricName string, s
return attributes, nil
}
func (m *module) withMetricsExplorerContext(ctx context.Context, functionName string) context.Context {
comments := map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metrics-explorer",
instrumentationtypes.CodeFunctionName: functionName,
}
return ctxtypes.NewContextWithCommentVals(ctx, comments)
}

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/modules/promote"
"github.com/SigNoz/signoz/pkg/telemetrylogs"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/promotetypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
)
@@ -107,11 +105,6 @@ func (m *module) PromotePaths(ctx context.Context, paths []string) error {
// createIndexes creates string ngram + token filter indexes on JSON path subcolumns for LIKE queries.
func (m *module) createIndexes(ctx context.Context, indexes []schemamigrator.Index) error {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "promote",
instrumentationtypes.CodeFunctionName: "createIndexes",
})
if len(indexes) == 0 {
return nil
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/SigNoz/signoz/pkg/modules/rawdataexport"
"github.com/SigNoz/signoz/pkg/querier"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/valuer"
)
@@ -23,10 +22,6 @@ func NewModule(querier querier.Querier) rawdataexport.Module {
}
func (m *Module) ExportRawData(ctx context.Context, orgID valuer.UUID, rangeRequest *qbtypes.QueryRangeRequest, doneChan chan any) (chan *qbtypes.RawRow, chan error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "rawdataexport",
instrumentationtypes.CodeFunctionName: "ExportRawData",
})
spec := rangeRequest.CompositeQuery.Queries[0].Spec.(qbtypes.QueryBuilderQuery[qbtypes.LogAggregation])
rowCountLimit := spec.Limit

View File

@@ -13,8 +13,6 @@ import (
"github.com/SigNoz/signoz/pkg/querier"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/telemetrytraces"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/servicetypes/servicetypesv1"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
@@ -36,8 +34,6 @@ func NewModule(q querier.Querier, ts telemetrystore.TelemetryStore) services.Mod
// FetchTopLevelOperations returns top-level operations per service using db query
func (m *module) FetchTopLevelOperations(ctx context.Context, start time.Time, services []string) (map[string][]string, error) {
ctx = m.withServicesContext(ctx, "FetchTopLevelOperations")
db := m.TelemetryStore.ClickhouseDB()
query := fmt.Sprintf("SELECT name, serviceName, max(time) as ts FROM %s.%s WHERE time >= @start", telemetrytraces.DBName, telemetrytraces.TopLevelOperationsTableName)
args := []any{clickhouse.Named("start", start)}
@@ -74,7 +70,6 @@ func (m *module) FetchTopLevelOperations(ctx context.Context, start time.Time, s
// Get implements services.Module
// Builds a QBv5 traces aggregation grouped by service.name and maps results to ResponseItem.
func (m *module) Get(ctx context.Context, orgUUID valuer.UUID, req *servicetypesv1.Request) ([]*servicetypesv1.ResponseItem, error) {
ctx = m.withServicesContext(ctx, "Get")
if req == nil {
return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "request is nil")
}
@@ -109,7 +104,6 @@ func (m *module) Get(ctx context.Context, orgUUID valuer.UUID, req *servicetypes
// GetTopOperations implements services.Module for QBV5 based top ops
func (m *module) GetTopOperations(ctx context.Context, orgUUID valuer.UUID, req *servicetypesv1.OperationsRequest) ([]servicetypesv1.OperationItem, error) {
ctx = m.withServicesContext(ctx, "GetTopOperations")
if req == nil {
return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "request is nil")
}
@@ -130,7 +124,6 @@ func (m *module) GetTopOperations(ctx context.Context, orgUUID valuer.UUID, req
// GetEntryPointOperations implements services.Module for QBV5 based entry point ops
func (m *module) GetEntryPointOperations(ctx context.Context, orgUUID valuer.UUID, req *servicetypesv1.OperationsRequest) ([]servicetypesv1.OperationItem, error) {
ctx = m.withServicesContext(ctx, "GetEntryPointOperations")
if req == nil {
return nil, errors.NewInvalidInputf(errors.CodeInvalidInput, "request is nil")
}
@@ -524,12 +517,3 @@ func (m *module) mapEntryPointOpsQueryRangeResp(resp *qbtypes.QueryRangeResponse
}
return out
}
func (m *module) withServicesContext(ctx context.Context, functionName string) context.Context {
comments := map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "services",
instrumentationtypes.CodeFunctionName: functionName,
}
return ctxtypes.NewContextWithCommentVals(ctx, comments)
}

View File

@@ -8,8 +8,6 @@ import (
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/modules/spanpercentile"
"github.com/SigNoz/signoz/pkg/querier"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/spanpercentiletypes"
"github.com/SigNoz/signoz/pkg/valuer"
@@ -29,10 +27,6 @@ func NewModule(
}
func (m *module) GetSpanPercentile(ctx context.Context, orgID valuer.UUID, userID valuer.UUID, req *spanpercentiletypes.SpanPercentileRequest) (*spanpercentiletypes.SpanPercentileResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "spanpercentile",
instrumentationtypes.CodeFunctionName: "GetSpanPercentile",
})
queryRangeRequest, err := buildSpanPercentileQuery(ctx, req)
if err != nil {
return nil, err

View File

@@ -11,9 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/query-service/constants"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
promValue "github.com/prometheus/prometheus/model/value"
"github.com/prometheus/prometheus/prompb"
"github.com/prometheus/prometheus/storage"
@@ -140,7 +137,6 @@ func (client *client) queryToClickhouseQuery(_ context.Context, query *prompb.Qu
}
func (client *client) getFingerprintsFromClickhouseQuery(ctx context.Context, query string, args []any) (map[uint64][]prompb.Label, error) {
ctx = client.withClickhousePrometheusContext(ctx, "getFingerprintsFromClickhouseQuery")
rows, err := client.telemetryStore.ClickhouseDB().Query(ctx, query, args...)
if err != nil {
return nil, err
@@ -172,7 +168,6 @@ func (client *client) getFingerprintsFromClickhouseQuery(ctx context.Context, qu
}
func (client *client) querySamples(ctx context.Context, start int64, end int64, fingerprints map[uint64][]prompb.Label, metricName string, subQuery string, args []any) ([]*prompb.TimeSeries, error) {
ctx = client.withClickhousePrometheusContext(ctx, "querySamples")
argCount := len(args)
query := fmt.Sprintf(`
@@ -249,8 +244,6 @@ func (client *client) querySamples(ctx context.Context, start int64, end int64,
}
func (client *client) queryRaw(ctx context.Context, query string, ts int64) (*prompb.QueryResult, error) {
ctx = client.withClickhousePrometheusContext(ctx, "queryRaw")
rows, err := client.telemetryStore.ClickhouseDB().Query(ctx, query)
if err != nil {
return nil, err
@@ -298,12 +291,3 @@ func (client *client) queryRaw(ctx context.Context, query string, ts int64) (*pr
return &res, nil
}
func (client *client) withClickhousePrometheusContext(ctx context.Context, functionName string) context.Context {
comments := map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-prometheus",
instrumentationtypes.CodeFunctionName: functionName,
}
return ctxtypes.NewContextWithCommentVals(ctx, comments)
}

View File

@@ -15,7 +15,6 @@ import (
"github.com/SigNoz/signoz/pkg/http/render"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
@@ -34,10 +33,6 @@ func NewHandler(set factory.ProviderSettings, querier Querier, analytics analyti
func (handler *handler) QueryRange(rw http.ResponseWriter, req *http.Request) {
ctx := req.Context()
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "querier",
instrumentationtypes.CodeFunctionName: "QueryRange",
})
claims, err := authtypes.ClaimsFromContext(ctx)
if err != nil {

View File

@@ -12,8 +12,6 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/telemetrylogs"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/bytedance/sonic"
@@ -214,11 +212,6 @@ func (q *builderQuery[T]) Execute(ctx context.Context) (*qbtypes.Result, error)
// executeWithContext executes the query with query window and step context for partial value detection
func (q *builderQuery[T]) executeWithContext(ctx context.Context, query string, args []any) (*qbtypes.Result, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: q.spec.Signal.StringValue(),
instrumentationtypes.QueryDuration: instrumentationtypes.DurationBucket(q.fromMS, q.toMS),
})
totalRows := uint64(0)
totalBytes := uint64(0)
elapsed := time.Duration(0)

View File

@@ -14,8 +14,6 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/querybuilder"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
)
@@ -100,9 +98,6 @@ func (q *chSQLQuery) renderVars(query string, vars map[string]qbtypes.VariableIt
}
func (q *chSQLQuery) Execute(ctx context.Context) (*qbtypes.Result, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.QueryDuration: instrumentationtypes.DurationBucket(q.fromMS, q.toMS),
})
totalRows := uint64(0)
totalBytes := uint64(0)

View File

@@ -14,8 +14,6 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/prometheus"
"github.com/SigNoz/signoz/pkg/querybuilder"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbv5 "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/prometheus/prometheus/promql"
@@ -189,11 +187,6 @@ func (q *promqlQuery) renderVars(query string, vars map[string]qbv5.VariableItem
func (q *promqlQuery) Execute(ctx context.Context) (*qbv5.Result, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.QueryDuration: instrumentationtypes.DurationBucket(q.tr.From, q.tr.To),
})
start := int64(querybuilder.ToNanoSecs(q.tr.From))
end := int64(querybuilder.ToNanoSecs(q.tr.To))

View File

@@ -16,8 +16,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/utils"
"github.com/SigNoz/signoz/pkg/querybuilder"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/metrictypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"golang.org/x/exp/maps"
@@ -528,11 +526,6 @@ func (q *querier) run(
steps map[string]qbtypes.Step,
qbEvent *qbtypes.QBEvent,
) (*qbtypes.QueryRangeResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.PanelType: qbEvent.PanelType,
instrumentationtypes.QueryType: qbEvent.QueryType,
})
results := make(map[string]any)
warnings := make([]string, 0)
warningsDocURL := ""

View File

@@ -6,10 +6,7 @@ import (
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
)
type traceOperatorQuery struct {
@@ -55,11 +52,6 @@ func (q *traceOperatorQuery) Execute(ctx context.Context) (*qbtypes.Result, erro
}
func (q *traceOperatorQuery) executeWithContext(ctx context.Context, query string, args []any) (*qbtypes.Result, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.QueryDuration: instrumentationtypes.DurationBucket(q.fromMS, q.toMS),
})
totalRows := uint64(0)
totalBytes := uint64(0)
elapsed := time.Duration(0)

View File

@@ -20,9 +20,6 @@ import (
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/uptrace/bun"
@@ -272,12 +269,6 @@ func (r *ClickHouseReader) GetQueryRangeResult(ctx context.Context, query *model
}
func (r *ClickHouseReader) GetServicesList(ctx context.Context) (*[]string, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetServicesList",
})
services := []string{}
rows, err := r.db.Query(ctx, fmt.Sprintf(`SELECT DISTINCT resource_string_service$$name FROM %s.%s WHERE ts_bucket_start > (toUnixTimestamp(now() - INTERVAL 1 DAY) - 1800) AND toDate(timestamp) > now() - INTERVAL 1 DAY`, r.TraceDB, r.traceTableName))
if err != nil {
@@ -297,12 +288,6 @@ func (r *ClickHouseReader) GetServicesList(ctx context.Context) (*[]string, erro
}
func (r *ClickHouseReader) GetTopLevelOperations(ctx context.Context, start, end time.Time, services []string) (*map[string][]string, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTopLevelOperations",
})
start = start.In(time.UTC)
// The `top_level_operations` that have `time` >= start
@@ -398,12 +383,6 @@ func (r *ClickHouseReader) buildResourceSubQuery(tags []model.TagQueryParam, svc
func (r *ClickHouseReader) GetServices(ctx context.Context, queryParams *model.GetServicesParams) (*[]model.ServiceItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetServices",
})
if r.indexTable == "" {
return nil, &model.ApiError{Typ: model.ErrorExec, Err: ErrNoIndexTable}
}
@@ -760,11 +739,6 @@ func (r *ClickHouseReader) GetEntryPointOperations(ctx context.Context, queryPar
func (r *ClickHouseReader) GetTopOperations(ctx context.Context, queryParams *model.GetTopOperationsParams) (*[]model.TopOperationsItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTopOperations",
})
namedArgs := []interface{}{
clickhouse.Named("start", strconv.FormatInt(queryParams.Start.UnixNano(), 10)),
clickhouse.Named("end", strconv.FormatInt(queryParams.End.UnixNano(), 10)),
@@ -820,11 +794,6 @@ func (r *ClickHouseReader) GetTopOperations(ctx context.Context, queryParams *mo
func (r *ClickHouseReader) GetUsage(ctx context.Context, queryParams *model.GetUsageParams) (*[]model.UsageItem, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetUsage",
})
var usageItems []model.UsageItem
namedArgs := []interface{}{
clickhouse.Named("interval", queryParams.StepHour),
@@ -860,13 +829,6 @@ func (r *ClickHouseReader) GetUsage(ctx context.Context, queryParams *model.GetU
}
func (r *ClickHouseReader) GetSpansForTrace(ctx context.Context, traceID string, traceDetailsQuery string) ([]model.SpanItemV2, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetSpansForTrace",
})
var traceSummary model.TraceSummary
summaryQuery := fmt.Sprintf("SELECT trace_id, min(start) AS start, max(end) AS end, sum(num_spans) AS num_spans FROM %s.%s WHERE trace_id=$1 GROUP BY trace_id", r.TraceDB, r.traceSummaryTable)
err := r.db.QueryRow(ctx, summaryQuery, traceID).Scan(&traceSummary.TraceID, &traceSummary.Start, &traceSummary.End, &traceSummary.NumSpans)
@@ -1265,11 +1227,6 @@ func (r *ClickHouseReader) GetFlamegraphSpansForTrace(ctx context.Context, orgID
func (r *ClickHouseReader) GetDependencyGraph(ctx context.Context, queryParams *model.GetServicesParams) (*[]model.ServiceMapDependencyResponseItem, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetDependencyGraph",
})
response := []model.ServiceMapDependencyResponseItem{}
args := []interface{}{}
@@ -1324,11 +1281,6 @@ func getLocalTableName(tableName string) string {
}
func (r *ClickHouseReader) setTTLLogs(ctx context.Context, orgID string, params *model.TTLParams) (*model.SetTTLResponseItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "setTTLLogs",
})
hasCustomRetention, err := r.hasCustomRetentionColumn(ctx)
if hasCustomRetention {
return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("SetTTLV2 only supported")}
@@ -1492,11 +1444,6 @@ func (r *ClickHouseReader) setTTLLogs(ctx context.Context, orgID string, params
}
func (r *ClickHouseReader) setTTLTraces(ctx context.Context, orgID string, params *model.TTLParams) (*model.SetTTLResponseItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "setTTLTraces",
})
// uuid is used as transaction id
uuidWithHyphen := uuid.New()
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
@@ -1642,12 +1589,6 @@ func (r *ClickHouseReader) setTTLTraces(ctx context.Context, orgID string, param
}
func (r *ClickHouseReader) hasCustomRetentionColumn(ctx context.Context) (bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "hasCustomRetentionColumn",
})
// Directly query for the _retention_days column existence
query := fmt.Sprintf("SELECT 1 FROM system.columns WHERE database = '%s' AND table = '%s' AND name = '_retention_days' LIMIT 1", r.logsDB, r.logsLocalTableV2)
@@ -1669,11 +1610,6 @@ func (r *ClickHouseReader) hasCustomRetentionColumn(ctx context.Context) (bool,
func (r *ClickHouseReader) SetTTLV2(ctx context.Context, orgID string, params *model.CustomRetentionTTLParams) (*model.CustomRetentionTTLResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "SetTTLV2",
})
hasCustomRetention, err := r.hasCustomRetentionColumn(ctx)
if err != nil {
return nil, errorsV2.Wrapf(err, errorsV2.TypeInternal, errorsV2.CodeInternal, "custom retention not supported")
@@ -2063,10 +1999,6 @@ func (r *ClickHouseReader) updateCustomRetentionTTLStatus(ctx context.Context, o
// Enhanced validation function with duplicate detection and efficient key validation
func (r *ClickHouseReader) validateTTLConditions(ctx context.Context, ttlConditions []model.CustomRetentionRule) error {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "validateTTLConditions",
})
if len(ttlConditions) == 0 {
return nil
}
@@ -2184,11 +2116,6 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context, orgID string, params *mod
}
func (r *ClickHouseReader) setTTLMetrics(ctx context.Context, orgID string, params *model.TTLParams) (*model.SetTTLResponseItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "setTTLMetrics",
})
// uuid is used as transaction id
uuidWithHyphen := uuid.New()
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
@@ -2397,10 +2324,6 @@ func (r *ClickHouseReader) getTTLQueryStatus(ctx context.Context, orgID string,
func (r *ClickHouseReader) setColdStorage(ctx context.Context, tableName string, coldStorageVolume string) *model.ApiError {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "setColdStorage",
})
// Set the storage policy for the required table. If it is already set, then setting it again
// will not a problem.
if len(coldStorageVolume) > 0 {
@@ -2417,10 +2340,6 @@ func (r *ClickHouseReader) setColdStorage(ctx context.Context, tableName string,
// GetDisks returns a list of disks {name, type} configured in clickhouse DB.
func (r *ClickHouseReader) GetDisks(ctx context.Context) (*[]model.DiskItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetDisks",
})
diskItems := []model.DiskItem{}
query := "SELECT name,type FROM system.disks"
@@ -2444,10 +2363,6 @@ func getLocalTableNameArray(tableNames []string) []string {
// GetTTL returns current ttl, expected ttl and past setTTL status for metrics/traces.
func (r *ClickHouseReader) GetTTL(ctx context.Context, orgID string, ttlParams *model.GetTTLParams) (*model.GetTTLResponseItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTTL",
})
parseTTL := func(queryResp string) (int, int) {
zap.L().Info("Parsing TTL from: ", zap.String("queryResp", queryResp))
@@ -2617,11 +2532,6 @@ func (r *ClickHouseReader) GetTTL(ctx context.Context, orgID string, ttlParams *
func (r *ClickHouseReader) ListErrors(ctx context.Context, queryParams *model.ListErrorsParams) (*[]model.Error, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "ListErrors",
})
var getErrorResponses []model.Error
query := "SELECT any(exceptionMessage) as exceptionMessage, count() AS exceptionCount, min(timestamp) as firstSeen, max(timestamp) as lastSeen, groupID"
@@ -2694,12 +2604,6 @@ func (r *ClickHouseReader) ListErrors(ctx context.Context, queryParams *model.Li
func (r *ClickHouseReader) CountErrors(ctx context.Context, queryParams *model.CountErrorsParams) (uint64, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "CountErrors",
})
var errorCount uint64
query := fmt.Sprintf("SELECT count(distinct(groupID)) FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.errorTable)
@@ -2737,11 +2641,6 @@ func (r *ClickHouseReader) CountErrors(ctx context.Context, queryParams *model.C
func (r *ClickHouseReader) GetErrorFromErrorID(ctx context.Context, queryParams *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetErrorFromErrorID",
})
if queryParams.ErrorID == "" {
zap.L().Error("errorId missing from params")
return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("ErrorID missing from params")}
@@ -2769,11 +2668,6 @@ func (r *ClickHouseReader) GetErrorFromErrorID(ctx context.Context, queryParams
func (r *ClickHouseReader) GetErrorFromGroupID(ctx context.Context, queryParams *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetErrorFromGroupID",
})
var getErrorWithSpanReponse []model.ErrorWithSpan
query := fmt.Sprintf("SELECT errorID, exceptionType, exceptionStacktrace, exceptionEscaped, exceptionMessage, timestamp, spanID, traceID, serviceName, groupID FROM %s.%s WHERE timestamp = @timestamp AND groupID = @groupID LIMIT 1", r.TraceDB, r.errorTable)
@@ -2822,11 +2716,6 @@ func (r *ClickHouseReader) GetNextPrevErrorIDs(ctx context.Context, queryParams
func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *model.GetErrorParams) (string, time.Time, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "getNextErrorID",
})
var getNextErrorIDReponse []model.NextPrevErrorIDsDBResponse
query := fmt.Sprintf("SELECT errorID as nextErrorID, timestamp as nextTimestamp FROM %s.%s WHERE groupID = @groupID AND timestamp >= @timestamp AND errorID != @errorID ORDER BY timestamp ASC LIMIT 2", r.TraceDB, r.errorTable)
@@ -2896,11 +2785,6 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode
func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *model.GetErrorParams) (string, time.Time, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "getPrevErrorID",
})
var getPrevErrorIDReponse []model.NextPrevErrorIDsDBResponse
query := fmt.Sprintf("SELECT errorID as prevErrorID, timestamp as prevTimestamp FROM %s.%s WHERE groupID = @groupID AND timestamp <= @timestamp AND errorID != @errorID ORDER BY timestamp DESC LIMIT 2", r.TraceDB, r.errorTable)
@@ -2992,11 +2876,6 @@ func (r *ClickHouseReader) FetchTemporality(ctx context.Context, orgID valuer.UU
}
func (r *ClickHouseReader) GetLogFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLogFields",
})
// response will contain top level fields from the otel log model
response := model.GetFieldsResponse{
Selected: constants.StaticSelectedLogFields,
@@ -3033,11 +2912,6 @@ func (r *ClickHouseReader) GetLogFields(ctx context.Context) (*model.GetFieldsRe
}
func (r *ClickHouseReader) GetLogFieldsFromNames(ctx context.Context, fieldNames []string) (*model.GetFieldsResponse, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLogFieldsFromNames",
})
// response will contain top level fields from the otel log model
response := model.GetFieldsResponse{
Selected: constants.StaticSelectedLogFields,
@@ -3088,10 +2962,6 @@ func (r *ClickHouseReader) extractSelectedAndInterestingFields(tableStatement st
}
func (r *ClickHouseReader) UpdateLogField(ctx context.Context, field *model.UpdateField) *model.ApiError {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "UpdateLogField",
})
if !field.Selected {
return model.ForbiddenError(errors.New("removing a selected field is not allowed, please reach out to support."))
}
@@ -3158,10 +3028,6 @@ func (r *ClickHouseReader) UpdateLogField(ctx context.Context, field *model.Upda
}
func (r *ClickHouseReader) GetTraceFields(ctx context.Context) (*model.GetFieldsResponse, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTraceFields",
})
// response will contain top level fields from the otel trace model
response := model.GetFieldsResponse{
Selected: []model.Field{},
@@ -3217,11 +3083,6 @@ func (r *ClickHouseReader) GetTraceFields(ctx context.Context) (*model.GetFields
}
func (r *ClickHouseReader) UpdateTraceField(ctx context.Context, field *model.UpdateField) *model.ApiError {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "UpdateTraceField",
})
if !field.Selected {
return model.ForbiddenError(errors.New("removing a selected field is not allowed, please reach out to support."))
}
@@ -3313,10 +3174,6 @@ func (r *ClickHouseReader) UpdateTraceField(ctx context.Context, field *model.Up
return nil
}
func (r *ClickHouseReader) QueryDashboardVars(ctx context.Context, query string) (*model.DashboardVar, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "QueryDashboardVars",
})
var result = model.DashboardVar{VariableValues: make([]interface{}, 0)}
rows, err := r.db.Query(ctx, query)
@@ -3353,11 +3210,6 @@ func (r *ClickHouseReader) QueryDashboardVars(ctx context.Context, query string)
}
func (r *ClickHouseReader) GetMetricAggregateAttributes(ctx context.Context, orgID valuer.UUID, req *v3.AggregateAttributeRequest, skipSignozMetrics bool) (*v3.AggregateAttributeResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricAggregateAttributes",
})
var response v3.AggregateAttributeResponse
normalized := true
if constants.IsDotMetricsEnabled {
@@ -3436,11 +3288,6 @@ func (r *ClickHouseReader) GetMetricAggregateAttributes(ctx context.Context, org
}
func (r *ClickHouseReader) GetMeterAggregateAttributes(ctx context.Context, orgID valuer.UUID, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMeterAggregateAttributes",
})
var response v3.AggregateAttributeResponse
// Query all relevant metric names from time_series_v4, but leave metadata retrieval to cache/db
query := fmt.Sprintf(
@@ -3489,11 +3336,6 @@ func (r *ClickHouseReader) GetMeterAggregateAttributes(ctx context.Context, orgI
}
func (r *ClickHouseReader) GetMetricAttributeKeys(ctx context.Context, req *v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricAttributeKeys",
})
var query string
var err error
var rows driver.Rows
@@ -3534,11 +3376,6 @@ func (r *ClickHouseReader) GetMetricAttributeKeys(ctx context.Context, req *v3.F
}
func (r *ClickHouseReader) GetMeterAttributeKeys(ctx context.Context, req *v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMeterAttributeKeys",
})
var query string
var err error
var rows driver.Rows
@@ -3575,11 +3412,6 @@ func (r *ClickHouseReader) GetMeterAttributeKeys(ctx context.Context, req *v3.Fi
func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricAttributeValues",
})
var query string
var err error
var rows driver.Rows
@@ -3620,11 +3452,6 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, req *v3
func (r *ClickHouseReader) GetMetricMetadata(ctx context.Context, orgID valuer.UUID, metricName, serviceName string) (*v3.MetricMetadataResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricMetadata",
})
unixMilli := common.PastDayRoundOff()
// 1. Fetch metadata from cache/db using unified function
@@ -3706,10 +3533,6 @@ func (r *ClickHouseReader) GetMetricMetadata(ctx context.Context, orgID valuer.U
// GetCountOfThings returns the count of things in the query
// This is a generic function that can be used to check if any data exists for a given query
func (r *ClickHouseReader) GetCountOfThings(ctx context.Context, query string) (uint64, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetCountOfThings",
})
var count uint64
err := r.db.QueryRow(ctx, query).Scan(&count)
if err != nil {
@@ -3760,11 +3583,6 @@ func (r *ClickHouseReader) GetActiveHostsFromMetricMetadata(ctx context.Context,
func (r *ClickHouseReader) GetLatestReceivedMetric(
ctx context.Context, metricNames []string, labelValues map[string]string,
) (*model.MetricStatus, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLatestReceivedMetric",
})
// at least 1 metric name must be specified.
// this query can be too slow otherwise.
if len(metricNames) < 1 {
@@ -3849,11 +3667,6 @@ func isColumn(tableStatement, attrType, field, datType string) bool {
func (r *ClickHouseReader) GetLogAggregateAttributes(ctx context.Context, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLogAggregateAttributes",
})
var query string
var err error
var rows driver.Rows
@@ -3938,11 +3751,6 @@ func (r *ClickHouseReader) GetLogAggregateAttributes(ctx context.Context, req *v
}
func (r *ClickHouseReader) GetLogAttributeKeys(ctx context.Context, req *v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLogAttributeKeys",
})
var query string
var err error
var rows driver.Rows
@@ -4009,10 +3817,6 @@ func (r *ClickHouseReader) GetLogAttributeKeys(ctx context.Context, req *v3.Filt
}
func (r *ClickHouseReader) FetchRelatedValues(ctx context.Context, req *v3.FilterAttributeValueRequest) ([]string, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "FetchRelatedValues",
})
var andConditions []string
andConditions = append(andConditions, fmt.Sprintf("unix_milli >= %d", req.StartTimeMillis))
@@ -4104,11 +3908,6 @@ func (r *ClickHouseReader) FetchRelatedValues(ctx context.Context, req *v3.Filte
}
func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLogAttributeValues",
})
var err error
var filterValueColumn string
var rows driver.Rows
@@ -4426,10 +4225,6 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam
// GetTimeSeriesResultV3 runs the query and returns list of time series
func (r *ClickHouseReader) GetTimeSeriesResultV3(ctx context.Context, query string) ([]*v3.Series, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTimeSeriesResultV3",
})
// Hook up query progress reporting if requested.
queryId := ctx.Value("queryId")
if queryId != nil {
@@ -4493,10 +4288,6 @@ func (r *ClickHouseReader) GetTimeSeriesResultV3(ctx context.Context, query stri
// GetListResultV3 runs the query and returns list of rows
func (r *ClickHouseReader) GetListResultV3(ctx context.Context, query string) ([]*v3.Row, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetListResultV3",
})
rows, err := r.db.Query(ctx, query)
if err != nil {
zap.L().Error("error while reading time series result", zap.Error(err))
@@ -4559,11 +4350,6 @@ func (r *ClickHouseReader) GetListResultV3(ctx context.Context, query string) ([
// GetHostMetricsExistenceAndEarliestTime returns (count, minFirstReportedUnixMilli, error) for the given host metric names
// from distributed_metadata. When count is 0, minFirstReportedUnixMilli is 0.
func (r *ClickHouseReader) GetMetricsExistenceAndEarliestTime(ctx context.Context, metricNames []string) (uint64, uint64, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricsExistenceAndEarliestTime",
})
if len(metricNames) == 0 {
return 0, 0, nil
}
@@ -4599,10 +4385,6 @@ func getPersonalisedError(err error) error {
}
func (r *ClickHouseReader) CheckClickHouse(ctx context.Context) error {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "CheckClickHouse",
})
rows, err := r.db.Query(ctx, "SELECT 1")
if err != nil {
return err
@@ -4613,11 +4395,6 @@ func (r *ClickHouseReader) CheckClickHouse(ctx context.Context) error {
}
func (r *ClickHouseReader) GetTraceAggregateAttributes(ctx context.Context, req *v3.AggregateAttributeRequest) (*v3.AggregateAttributeResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTraceAggregateAttributes",
})
var query string
var err error
var rows driver.Rows
@@ -4711,11 +4488,6 @@ func (r *ClickHouseReader) GetTraceAggregateAttributes(ctx context.Context, req
func (r *ClickHouseReader) GetTraceAttributeKeys(ctx context.Context, req *v3.FilterAttributeKeyRequest) (*v3.FilterAttributeKeyResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTraceAttributeKeys",
})
var query string
var err error
var rows driver.Rows
@@ -4784,11 +4556,6 @@ func (r *ClickHouseReader) GetTraceAttributeKeys(ctx context.Context, req *v3.Fi
}
func (r *ClickHouseReader) GetTraceAttributeValues(ctx context.Context, req *v3.FilterAttributeValueRequest) (*v3.FilterAttributeValueResponse, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTraceAttributeValues",
})
var query string
var filterValueColumn string
var err error
@@ -4882,11 +4649,6 @@ func (r *ClickHouseReader) GetTraceAttributeValues(ctx context.Context, req *v3.
}
func (r *ClickHouseReader) GetSpanAttributeKeysByNames(ctx context.Context, names []string) (map[string]v3.AttributeKey, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetSpanAttributeKeysByNames",
})
var query string
var err error
var rows driver.Rows
@@ -4935,10 +4697,6 @@ func (r *ClickHouseReader) GetSpanAttributeKeysByNames(ctx context.Context, name
}
func (r *ClickHouseReader) AddRuleStateHistory(ctx context.Context, ruleStateHistory []model.RuleStateHistory) error {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "AddRuleStateHistory",
})
var statement driver.Batch
var err error
@@ -4970,10 +4728,6 @@ func (r *ClickHouseReader) AddRuleStateHistory(ctx context.Context, ruleStateHis
}
func (r *ClickHouseReader) GetLastSavedRuleStateHistory(ctx context.Context, ruleID string) ([]model.RuleStateHistory, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetLastSavedRuleStateHistory",
})
query := fmt.Sprintf("SELECT * FROM %s.%s WHERE rule_id = '%s' AND state_changed = true ORDER BY unix_milli DESC LIMIT 1 BY fingerprint",
signozHistoryDBName, ruleStateHistoryTableName, ruleID)
@@ -4988,10 +4742,6 @@ func (r *ClickHouseReader) GetLastSavedRuleStateHistory(ctx context.Context, rul
func (r *ClickHouseReader) ReadRuleStateHistoryByRuleID(
ctx context.Context, ruleID string, params *model.QueryRuleStateHistory) (*model.RuleStateTimeline, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "ReadRuleStateHistoryByRuleID",
})
var conditions []string
conditions = append(conditions, fmt.Sprintf("rule_id = '%s'", ruleID))
@@ -5106,10 +4856,6 @@ func (r *ClickHouseReader) ReadRuleStateHistoryByRuleID(
func (r *ClickHouseReader) ReadRuleStateHistoryTopContributorsByRuleID(
ctx context.Context, ruleID string, params *model.QueryRuleStateHistory) ([]model.RuleStateHistoryContributor, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "ReadRuleStateHistoryTopContributorsByRuleID",
})
query := fmt.Sprintf(`SELECT
fingerprint,
any(labels) as labels,
@@ -5134,10 +4880,6 @@ func (r *ClickHouseReader) ReadRuleStateHistoryTopContributorsByRuleID(
func (r *ClickHouseReader) GetOverallStateTransitions(ctx context.Context, ruleID string, params *model.QueryRuleStateHistory) ([]model.ReleStateItem, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetOverallStateTransitions",
})
tmpl := `WITH firing_events AS (
SELECT
rule_id,
@@ -5265,10 +5007,6 @@ ORDER BY firing_time ASC;`
func (r *ClickHouseReader) GetAvgResolutionTime(ctx context.Context, ruleID string, params *model.QueryRuleStateHistory) (float64, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAvgResolutionTime",
})
tmpl := `
WITH firing_events AS (
SELECT
@@ -5380,10 +5118,6 @@ ORDER BY ts ASC;`
}
func (r *ClickHouseReader) GetTotalTriggers(ctx context.Context, ruleID string, params *model.QueryRuleStateHistory) (uint64, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTotalTriggers",
})
query := fmt.Sprintf("SELECT count(*) FROM %s.%s WHERE rule_id = '%s' AND (state_changed = true) AND (state = '%s') AND unix_milli >= %d AND unix_milli <= %d",
signozHistoryDBName, ruleStateHistoryTableName, ruleID, model.StateFiring.String(), params.Start, params.End)
@@ -5412,11 +5146,6 @@ func (r *ClickHouseReader) GetTriggersByInterval(ctx context.Context, ruleID str
}
func (r *ClickHouseReader) GetMinAndMaxTimestampForTraceID(ctx context.Context, traceID []string) (int64, int64, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMinAndMaxTimestampForTraceID",
})
var minTime, maxTime time.Time
query := fmt.Sprintf("SELECT min(timestamp), max(timestamp) FROM %s.%s WHERE traceID IN ('%s')",
@@ -5454,11 +5183,6 @@ func (r *ClickHouseReader) SubscribeToQueryProgress(
}
func (r *ClickHouseReader) GetAllMetricFilterAttributeKeys(ctx context.Context, req *metrics_explorer.FilterKeyRequest) (*[]v3.AttributeKey, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAllMetricFilterAttributeKeys",
})
var rows driver.Rows
var response []v3.AttributeKey
normalized := true
@@ -5496,11 +5220,6 @@ func (r *ClickHouseReader) GetAllMetricFilterAttributeKeys(ctx context.Context,
}
func (r *ClickHouseReader) GetAllMetricFilterAttributeValues(ctx context.Context, req *metrics_explorer.FilterValueRequest) ([]string, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAllMetricFilterAttributeValues",
})
var query string
var err error
var rows driver.Rows
@@ -5537,11 +5256,6 @@ func (r *ClickHouseReader) GetAllMetricFilterAttributeValues(ctx context.Context
}
func (r *ClickHouseReader) GetAllMetricFilterUnits(ctx context.Context, req *metrics_explorer.FilterValueRequest) ([]string, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAllMetricFilterUnits",
})
var rows driver.Rows
var response []string
query := fmt.Sprintf("SELECT DISTINCT unit FROM %s.%s WHERE unit ILIKE $1 AND unit IS NOT NULL ORDER BY unit", signozMetricDBName, signozTSTableNameV41Day)
@@ -5569,11 +5283,6 @@ func (r *ClickHouseReader) GetAllMetricFilterUnits(ctx context.Context, req *met
return response, nil
}
func (r *ClickHouseReader) GetAllMetricFilterTypes(ctx context.Context, req *metrics_explorer.FilterValueRequest) ([]string, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAllMetricFilterTypes",
})
var rows driver.Rows
var response []string
query := fmt.Sprintf("SELECT DISTINCT type FROM %s.%s WHERE type ILIKE $1 AND type IS NOT NULL ORDER BY type", signozMetricDBName, signozTSTableNameV41Day)
@@ -5601,11 +5310,6 @@ func (r *ClickHouseReader) GetAllMetricFilterTypes(ctx context.Context, req *met
}
func (r *ClickHouseReader) GetMetricsDataPoints(ctx context.Context, metricName string) (uint64, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricsDataPoints",
})
query := fmt.Sprintf(`SELECT
sum(count) as data_points
FROM %s.%s
@@ -5621,11 +5325,6 @@ WHERE metric_name = ?
}
func (r *ClickHouseReader) GetMetricsLastReceived(ctx context.Context, metricName string) (int64, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricsLastReceived",
})
query := fmt.Sprintf(`SELECT
MAX(unix_milli) AS last_received_time
FROM %s.%s
@@ -5651,11 +5350,6 @@ WHERE metric_name = ? and unix_milli > ?
}
func (r *ClickHouseReader) GetTotalTimeSeriesForMetricName(ctx context.Context, metricName string) (uint64, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetTotalTimeSeriesForMetricName",
})
query := fmt.Sprintf(`SELECT
uniq(fingerprint) AS timeSeriesCount
FROM %s.%s
@@ -5670,11 +5364,6 @@ WHERE metric_name = ?;`, signozMetricDBName, signozTSTableNameV41Week)
}
func (r *ClickHouseReader) GetAttributesForMetricName(ctx context.Context, metricName string, start, end *int64, filters *v3.FilterSet) (*[]metrics_explorer.Attribute, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAttributesForMetricName",
})
whereClause := ""
if filters != nil {
conditions, _ := utils.BuildFilterConditions(filters, "t")
@@ -5742,11 +5431,6 @@ WHERE metric_name = ? AND __normalized=? %s`
}
func (r *ClickHouseReader) GetActiveTimeSeriesForMetricName(ctx context.Context, metricName string, duration time.Duration) (uint64, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetActiveTimeSeriesForMetricName",
})
milli := time.Now().Add(-duration).UnixMilli()
query := fmt.Sprintf("SELECT uniq(fingerprint) FROM %s.%s WHERE metric_name = '%s' and unix_milli >= ?", signozMetricDBName, signozTSTableNameV4, metricName)
var timeSeries uint64
@@ -5760,11 +5444,6 @@ func (r *ClickHouseReader) GetActiveTimeSeriesForMetricName(ctx context.Context,
}
func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.UUID, req *metrics_explorer.SummaryListMetricsRequest) (*metrics_explorer.SummaryListMetricsResponse, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "ListSummaryMetrics",
})
var args []interface{}
// Build filter conditions (if any)
@@ -5983,11 +5662,6 @@ func (r *ClickHouseReader) ListSummaryMetrics(ctx context.Context, orgID valuer.
}
func (r *ClickHouseReader) GetMetricsTimeSeriesPercentage(ctx context.Context, req *metrics_explorer.TreeMapMetricsRequest) (*[]metrics_explorer.TreeMapResponseItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricsTimeSeriesPercentage",
})
var args []interface{}
normalized := true
@@ -6068,11 +5742,6 @@ func (r *ClickHouseReader) GetMetricsTimeSeriesPercentage(ctx context.Context, r
func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req *metrics_explorer.TreeMapMetricsRequest) (*[]metrics_explorer.TreeMapResponseItem, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricsSamplesPercentage",
})
conditions, _ := utils.BuildFilterConditions(&req.Filters, "ts")
whereClause := ""
if conditions != nil {
@@ -6232,11 +5901,6 @@ func (r *ClickHouseReader) GetMetricsSamplesPercentage(ctx context.Context, req
}
func (r *ClickHouseReader) GetNameSimilarity(ctx context.Context, req *metrics_explorer.RelatedMetricsRequest) (map[string]metrics_explorer.RelatedMetricsScore, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetNameSimilarity",
})
start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End)
normalized := true
@@ -6290,11 +5954,6 @@ func (r *ClickHouseReader) GetNameSimilarity(ctx context.Context, req *metrics_e
}
func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metrics_explorer.RelatedMetricsRequest) (map[string]metrics_explorer.RelatedMetricsScore, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetAttributeSimilarity",
})
start, end, tsTable, _ := utils.WhichTSTableToUse(req.Start, req.End)
normalized := true
@@ -6453,11 +6112,6 @@ func (r *ClickHouseReader) GetAttributeSimilarity(ctx context.Context, req *metr
}
func (r *ClickHouseReader) GetMetricsAllResourceAttributes(ctx context.Context, start int64, end int64) (map[string]uint64, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetMetricsAllResourceAttributes",
})
start, end, attTable, _ := utils.WhichAttributesTableToUse(start, end)
query := fmt.Sprintf(`SELECT
key,
@@ -6494,11 +6148,6 @@ ORDER BY distinct_value_count DESC;`, signozMetadataDbName, attTable)
}
func (r *ClickHouseReader) GetInspectMetrics(ctx context.Context, req *metrics_explorer.InspectMetricsRequest, fingerprints []string) (*metrics_explorer.InspectMetricsResponse, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetInspectMetrics",
})
start, end, _, localTsTable := utils.WhichTSTableToUse(req.Start, req.End)
fingerprintsString := strings.Join(fingerprints, ",")
query := fmt.Sprintf(`SELECT
@@ -6593,11 +6242,6 @@ func (r *ClickHouseReader) GetInspectMetrics(ctx context.Context, req *metrics_e
}
func (r *ClickHouseReader) GetInspectMetricsFingerprints(ctx context.Context, attributes []string, req *metrics_explorer.InspectMetricsRequest) ([]string, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetInspectMetricsFingerprints",
})
// Build dynamic key selections and JSON extracts
var jsonExtracts []string
var groupBys []string
@@ -6679,11 +6323,6 @@ LIMIT 40`, // added rand to get diff value every time we run this query
}
func (r *ClickHouseReader) UpdateMetricsMetadata(ctx context.Context, orgID valuer.UUID, req *model.UpdateMetricsMetadata) *model.ApiError {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "UpdateMetricsMetadata",
})
if req.MetricType == v3.MetricTypeHistogram {
labels := []string{"le"}
hasLabels, apiError := r.CheckForLabelsInMetric(ctx, req.MetricName, labels)
@@ -6728,11 +6367,6 @@ VALUES ( ?, ?, ?, ?, ?, ?, ?);`, signozMetricDBName, signozUpdatedMetricsMetadat
}
func (r *ClickHouseReader) CheckForLabelsInMetric(ctx context.Context, metricName string, labels []string) (bool, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "CheckForLabelsInMetric",
})
if len(labels) == 0 {
return true, nil
}
@@ -6767,11 +6401,6 @@ func (r *ClickHouseReader) CheckForLabelsInMetric(ctx context.Context, metricNam
}
func (r *ClickHouseReader) GetUpdatedMetricsMetadata(ctx context.Context, orgID valuer.UUID, metricNames ...string) (map[string]*model.UpdateMetricsMetadata, *model.ApiError) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetUpdatedMetricsMetadata",
})
cachedMetadata := make(map[string]*model.UpdateMetricsMetadata)
var missingMetrics []string
@@ -6881,11 +6510,6 @@ func (r *ClickHouseReader) GetUpdatedMetricsMetadata(ctx context.Context, orgID
}
func (r *ClickHouseReader) SearchTraces(ctx context.Context, params *model.SearchTracesParams) (*[]model.SearchSpansResult, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "SearchTraces",
})
searchSpansResult := []model.SearchSpansResult{
{
Columns: []string{"__time", "SpanId", "TraceId", "ServiceName", "Name", "Kind", "DurationNano", "TagsKeys", "TagsValues", "References", "Events", "HasError", "StatusMessage", "StatusCodeString", "SpanKind"},
@@ -6997,11 +6621,6 @@ func (r *ClickHouseReader) GetNormalizedStatus(
metricNames []string,
) (map[string]bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "clickhouse-reader",
instrumentationtypes.CodeFunctionName: "GetNormalizedStatus",
})
if len(metricNames) == 0 {
return map[string]bool{}, nil
}

View File

@@ -62,10 +62,8 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
"github.com/SigNoz/signoz/pkg/types/featuretypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/licensetypes"
"github.com/SigNoz/signoz/pkg/types/opamptypes"
"github.com/SigNoz/signoz/pkg/types/pipelinetypes"
@@ -2414,12 +2412,7 @@ func (aH *APIHandler) onboardKafka(w http.ResponseWriter, r *http.Request) {
return
}
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "onboardKafka",
})
results, errQueriesByName, err := aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
results, errQueriesByName, err := aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2531,12 +2524,7 @@ func (aH *APIHandler) getNetworkData(w http.ResponseWriter, r *http.Request) {
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getNetworkData",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2572,7 +2560,7 @@ func (aH *APIHandler) getNetworkData(w http.ResponseWriter, r *http.Request) {
return
}
resultFetchLatency, errQueriesByNameFetchLatency, err := aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
resultFetchLatency, errQueriesByNameFetchLatency, err := aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByNameFetchLatency)
@@ -2628,11 +2616,7 @@ func (aH *APIHandler) getProducerData(w http.ResponseWriter, r *http.Request) {
}
evalCtx := featuretypes.NewFlaggerEvaluationContext(orgID)
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getProducerData",
})
kafkaSpanEval := aH.Signoz.Flagger.BooleanOrEmpty(ctx, flagger.FeatureKafkaSpanEval, evalCtx)
kafkaSpanEval := aH.Signoz.Flagger.BooleanOrEmpty(r.Context(), flagger.FeatureKafkaSpanEval, evalCtx)
queryRangeParams, err := kafka.BuildQueryRangeParams(messagingQueue, "producer", kafkaSpanEval)
if err != nil {
@@ -2650,7 +2634,7 @@ func (aH *APIHandler) getProducerData(w http.ResponseWriter, r *http.Request) {
var result []*v3.Result
var errQueriesByName map[string]error
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2703,11 +2687,7 @@ func (aH *APIHandler) getConsumerData(w http.ResponseWriter, r *http.Request) {
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getConsumerData",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2761,11 +2741,7 @@ func (aH *APIHandler) getPartitionOverviewLatencyData(w http.ResponseWriter, r *
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getPartitionOverviewLatencyData",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2819,11 +2795,7 @@ func (aH *APIHandler) getConsumerPartitionLatencyData(w http.ResponseWriter, r *
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getConsumerPartitionLatencyData",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2880,11 +2852,7 @@ func (aH *APIHandler) getProducerThroughputOverview(w http.ResponseWriter, r *ht
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getProducerThroughputOverview",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, producerQueryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, producerQueryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -2918,7 +2886,7 @@ func (aH *APIHandler) getProducerThroughputOverview(w http.ResponseWriter, r *ht
return
}
resultFetchLatency, errQueriesByNameFetchLatency, err := aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
resultFetchLatency, errQueriesByNameFetchLatency, err := aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByNameFetchLatency)
@@ -2995,11 +2963,7 @@ func (aH *APIHandler) getProducerThroughputDetails(w http.ResponseWriter, r *htt
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getProducerThroughputDetails",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -3053,11 +3017,7 @@ func (aH *APIHandler) getConsumerThroughputOverview(w http.ResponseWriter, r *ht
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getConsumerThroughputOverview",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -3111,11 +3071,7 @@ func (aH *APIHandler) getConsumerThroughputDetails(w http.ResponseWriter, r *htt
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getConsumerThroughputDetails",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -3175,11 +3131,7 @@ func (aH *APIHandler) getProducerConsumerEval(w http.ResponseWriter, r *http.Req
var result []*v3.Result
var errQueriesByName map[string]error
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getProducerConsumerEval",
})
result, errQueriesByName, err = aH.querierV2.QueryRange(ctx, orgID, queryRangeParams)
result, errQueriesByName, err = aH.querierV2.QueryRange(r.Context(), orgID, queryRangeParams)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
RespondError(w, apiErrObj, errQueriesByName)
@@ -3440,10 +3392,6 @@ func (aH *APIHandler) calculateLogsConnectionStatus(ctx context.Context, orgID v
},
},
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "calculateLogsConnectionStatus",
})
queryRes, _, err := aH.querier.QueryRange(ctx, orgID, qrParams)
if err != nil {
return nil, model.InternalError(fmt.Errorf(
@@ -3996,10 +3944,6 @@ func (aH *APIHandler) calculateAWSIntegrationSvcLogsConnectionStatus(
},
},
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "calculateLogsConnectionStatus",
})
queryRes, _, err := aH.querier.QueryRange(
ctx, orgID, qrParams,
)
@@ -4548,10 +4492,6 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "QueryRange",
})
result, errQueriesByName, err = aH.querier.QueryRange(ctx, orgID, queryRangeParams)
if err != nil {
@@ -4946,11 +4886,7 @@ func (aH *APIHandler) QueryRangeV4(w http.ResponseWriter, r *http.Request) {
return
}
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "QueryRangeV4",
})
aH.queryRangeV4(ctx, queryRangeParams, w, r)
aH.queryRangeV4(r.Context(), queryRangeParams, w, r)
}
func (aH *APIHandler) traceFields(w http.ResponseWriter, r *http.Request) {
@@ -5043,12 +4979,8 @@ func (aH *APIHandler) getDomainList(w http.ResponseWriter, r *http.Request) {
return
}
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getDomainList",
})
// Execute the query using the v5 querier
result, err := aH.Signoz.Querier.QueryRange(ctx, orgID, queryRangeRequest)
result, err := aH.Signoz.Querier.QueryRange(r.Context(), orgID, queryRangeRequest)
if err != nil {
zap.L().Error("Query execution failed", zap.Error(err))
apiErrObj := errorsV2.New(errorsV2.TypeInvalidInput, errorsV2.CodeInvalidInput, err.Error())
@@ -5103,12 +5035,8 @@ func (aH *APIHandler) getDomainInfo(w http.ResponseWriter, r *http.Request) {
return
}
ctx := ctxtypes.NewContextWithCommentVals(r.Context(), map[string]string{
instrumentationtypes.CodeNamespace: "app",
instrumentationtypes.CodeFunctionName: "getDomainInfo",
})
// Execute the query using the v5 querier
result, err := aH.Signoz.Querier.QueryRange(ctx, orgID, queryRangeRequest)
result, err := aH.Signoz.Querier.QueryRange(r.Context(), orgID, queryRangeRequest)
if err != nil {
zap.L().Error("Query execution failed", zap.Error(err))
apiErrObj := errorsV2.New(errorsV2.TypeInvalidInput, errorsV2.CodeInvalidInput, err.Error())

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -165,10 +163,6 @@ func (p *ClustersRepo) getTopClusterGroups(ctx context.Context, orgID valuer.UUI
topClusterGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopClusterGroups",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, topClusterGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -284,10 +278,6 @@ func (p *ClustersRepo) GetClusterList(ctx context.Context, orgID valuer.UUID, re
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetClusterList",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -232,10 +230,6 @@ func (d *DaemonSetsRepo) getTopDaemonSetGroups(ctx context.Context, orgID valuer
topDaemonSetGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopDaemonSetGroups",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, topDaemonSetGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -361,10 +355,6 @@ func (d *DaemonSetsRepo) GetDaemonSetList(ctx context.Context, orgID valuer.UUID
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetDaemonSetList",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -232,10 +230,6 @@ func (d *DeploymentsRepo) getTopDeploymentGroups(ctx context.Context, orgID valu
topDeploymentGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopDeploymentGroups",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, topDeploymentGroupsQueryRangeParams)
if err != nil {
return nil, nil, err

View File

@@ -16,8 +16,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"go.uber.org/zap"
"golang.org/x/exp/maps"
@@ -274,10 +272,6 @@ func (h *HostsRepo) getTopHostGroups(ctx context.Context, orgID valuer.UUID, req
topHostGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopHostGroups",
})
queryResponse, _, err := h.querierV2.QueryRange(ctx, orgID, topHostGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -488,10 +482,6 @@ func (h *HostsRepo) GetHostList(ctx context.Context, orgID valuer.UUID, req mode
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetHostList",
})
queryResponse, _, err := h.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -276,10 +274,6 @@ func (d *JobsRepo) getTopJobGroups(ctx context.Context, orgID valuer.UUID, req m
topJobGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopJobGroups",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, topJobGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -405,10 +399,6 @@ func (d *JobsRepo) GetJobList(ctx context.Context, orgID valuer.UUID, req model.
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetJobList",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -159,10 +157,6 @@ func (p *NamespacesRepo) getTopNamespaceGroups(ctx context.Context, orgID valuer
topNamespaceGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopNamespaceGroups",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, topNamespaceGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -283,10 +277,6 @@ func (p *NamespacesRepo) GetNamespaceList(ctx context.Context, orgID valuer.UUID
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetNamespaceList",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -14,8 +14,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -189,10 +187,6 @@ func (p *NodesRepo) getTopNodeGroups(ctx context.Context, orgID valuer.UUID, req
topNodeGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopNodeGroups",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, topNodeGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -308,10 +302,6 @@ func (p *NodesRepo) GetNodeList(ctx context.Context, orgID valuer.UUID, req mode
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetNodeList",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -14,8 +14,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -334,10 +332,6 @@ func (p *PodsRepo) getTopPodGroups(ctx context.Context, orgID valuer.UUID, req m
topPodGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopPodGroups",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, topPodGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -453,10 +447,6 @@ func (p *PodsRepo) GetPodList(ctx context.Context, orgID valuer.UUID, req model.
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetPodList",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -173,10 +171,6 @@ func (p *ProcessesRepo) getTopProcessGroups(ctx context.Context, orgID valuer.UU
topProcessGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopProcessGroups",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, topProcessGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -290,10 +284,6 @@ func (p *ProcessesRepo) GetProcessList(ctx context.Context, orgID valuer.UUID, r
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetProcessList",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -192,10 +190,6 @@ func (p *PvcsRepo) getTopVolumeGroups(ctx context.Context, orgID valuer.UUID, re
topVolumeGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopVolumeGroups",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, topVolumeGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -311,10 +305,6 @@ func (p *PvcsRepo) GetPvcList(ctx context.Context, orgID valuer.UUID, req model.
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetPvcList",
})
queryResponse, _, err := p.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -11,8 +11,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/slices"
)
@@ -232,10 +230,6 @@ func (d *StatefulSetsRepo) getTopStatefulSetGroups(ctx context.Context, orgID va
topStatefulSetGroupsQueryRangeParams.CompositeQuery.BuilderQueries[queryName] = query
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "getTopStatefulSetGroups",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, topStatefulSetGroupsQueryRangeParams)
if err != nil {
return nil, nil, err
@@ -361,10 +355,6 @@ func (d *StatefulSetsRepo) GetStatefulSetList(ctx context.Context, orgID valuer.
}
}
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "inframetrics",
instrumentationtypes.CodeFunctionName: "GetStatefulSetList",
})
queryResponse, _, err := d.querierV2.QueryRange(ctx, orgID, query)
if err != nil {
return resp, err

View File

@@ -17,8 +17,6 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
"github.com/SigNoz/signoz/pkg/query-service/postprocess"
"github.com/SigNoz/signoz/pkg/transition"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/ruletypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/SigNoz/signoz/pkg/valuer"
@@ -435,10 +433,7 @@ func (r *ThresholdRule) buildAndRunQuery(ctx context.Context, orgID valuer.UUID,
var results []*v3.Result
var queryErrors map[string]error
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "rules",
instrumentationtypes.CodeFunctionName: "buildAndRunQuery",
})
if r.version == "v4" {
results, queryErrors, err = r.querierV2.QueryRange(ctx, orgID, params)
} else {
@@ -506,11 +501,6 @@ func (r *ThresholdRule) buildAndRunQueryV5(ctx context.Context, orgID valuer.UUI
var results []*v3.Result
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "rules",
instrumentationtypes.CodeFunctionName: "buildAndRunQueryV5",
})
v5Result, err := r.querierV5.QueryRange(ctx, orgID, params)
if err != nil {
r.logger.ErrorContext(ctx, "failed to get alert query result", "rule_name", r.Name(), "error", err)

View File

@@ -176,10 +176,9 @@ func NewSQLMigrationProviderFactories(
func NewTelemetryStoreProviderFactories() factory.NamedMap[factory.ProviderFactory[telemetrystore.TelemetryStore, telemetrystore.Config]] {
return factory.MustNewNamedMap(
clickhousetelemetrystore.NewFactory(
telemetrystorehook.NewLoggingFactory(),
// adding instrumentation factory before settings as we are starting the query span here
telemetrystorehook.NewInstrumentationFactory(),
telemetrystorehook.NewSettingsFactory(),
telemetrystorehook.NewLoggingFactory(),
telemetrystorehook.NewInstrumentationFactory(),
),
)
}

View File

@@ -14,8 +14,6 @@ import (
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/tokenizer"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/SigNoz/signoz/pkg/version"
"go.opentelemetry.io/otel/attribute"
@@ -203,10 +201,6 @@ func (provider *provider) Stop(ctx context.Context) error {
}
func (provider *provider) collectOrg(ctx context.Context, orgID valuer.UUID) map[string]any {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.CodeNamespace: "statsreporter",
instrumentationtypes.CodeFunctionName: "collectOrg",
})
var wg sync.WaitGroup
wg.Add(len(provider.collectors))

View File

@@ -13,8 +13,6 @@ import (
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/querybuilder"
"github.com/SigNoz/signoz/pkg/telemetrylogs"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
"github.com/huandu/go-sqlbuilder"
)
@@ -49,11 +47,6 @@ var (
// searchOperator: LIKE for pattern matching, EQUAL for exact match
func (t *telemetryMetaStore) fetchBodyJSONPaths(ctx context.Context,
fieldKeySelectors []*telemetrytypes.FieldKeySelector) ([]*telemetrytypes.TelemetryFieldKey, []string, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "fetchBodyJSONPaths",
})
query, args, limit := buildGetBodyJSONPathsQuery(fieldKeySelectors)
rows, err := t.telemetrystore.ClickhouseDB().Query(ctx, query, args...)
if err != nil {
@@ -274,7 +267,6 @@ func buildListLogsJSONIndexesQuery(cluster string, filters ...string) (string, [
}
func (t *telemetryMetaStore) ListLogsJSONIndexes(ctx context.Context, filters ...string) (map[string][]schemamigrator.Index, error) {
ctx = withTelemetryContext(ctx, "ListLogsJSONIndexes")
query, args := buildListLogsJSONIndexesQuery(t.telemetrystore.Cluster(), filters...)
rows, err := t.telemetrystore.ClickhouseDB().Query(ctx, query, args...)
if err != nil {
@@ -304,7 +296,6 @@ func (t *telemetryMetaStore) ListLogsJSONIndexes(ctx context.Context, filters ..
// TODO(Piyush): Remove this if not used in future
func (t *telemetryMetaStore) ListJSONValues(ctx context.Context, path string, limit int) (*telemetrytypes.TelemetryFieldValues, bool, error) {
ctx = withTelemetryContext(ctx, "ListJSONValues")
path = CleanPathPrefixes(path)
if strings.Contains(path, telemetrytypes.ArraySep) || strings.Contains(path, telemetrytypes.ArrayAnyIndex) {
@@ -467,7 +458,6 @@ func derefValue(v any) any {
// IsPathPromoted checks if a specific path is promoted (Column Evolution table: field_name for logs body).
func (t *telemetryMetaStore) IsPathPromoted(ctx context.Context, path string) (bool, error) {
ctx = withTelemetryContext(ctx, "IsPathPromoted")
split := strings.Split(path, telemetrytypes.ArraySep)
pathSegment := split[0]
query := fmt.Sprintf("SELECT 1 FROM %s.%s WHERE signal = ? AND column_name = ? AND field_context = ? AND field_name = ? LIMIT 1", DBName, PromotedPathsTableName)
@@ -482,7 +472,6 @@ func (t *telemetryMetaStore) IsPathPromoted(ctx context.Context, path string) (b
// GetPromotedPaths returns promoted paths from the Column Evolution table (field_name for logs body).
func (t *telemetryMetaStore) GetPromotedPaths(ctx context.Context, paths ...string) (map[string]bool, error) {
ctx = withTelemetryContext(ctx, "GetPromotedPaths")
sb := sqlbuilder.Select("field_name").From(fmt.Sprintf("%s.%s", DBName, PromotedPathsTableName))
conditions := []string{
sb.Equal("signal", telemetrytypes.SignalLogs),
@@ -529,7 +518,6 @@ func CleanPathPrefixes(path string) string {
// PromotePaths inserts promoted paths into the Column Evolution table (same schema as signoz-otel-collector metadata_migrations).
func (t *telemetryMetaStore) PromotePaths(ctx context.Context, paths ...string) error {
ctx = withTelemetryContext(ctx, "PromotePaths")
batch, err := t.telemetrystore.ClickhouseDB().PrepareBatch(ctx,
fmt.Sprintf("INSERT INTO %s.%s (signal, column_name, column_type, field_context, field_name, version, release_time) VALUES", DBName,
PromotedPathsTableName))
@@ -554,11 +542,3 @@ func (t *telemetryMetaStore) PromotePaths(ctx context.Context, paths ...string)
}
return nil
}
func withTelemetryContext(ctx context.Context, functionName string) context.Context {
return ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: functionName,
})
}

View File

@@ -13,8 +13,6 @@ import (
"github.com/SigNoz/signoz/pkg/telemetrymetrics"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/telemetrytraces"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/metrictypes"
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
@@ -120,11 +118,6 @@ func NewTelemetryMetaStore(
// tracesTblStatementToFieldKeys returns materialised attribute/resource/scope keys from the traces table
func (t *telemetryMetaStore) tracesTblStatementToFieldKeys(ctx context.Context) ([]*telemetrytypes.TelemetryFieldKey, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "tracesTblStatementToFieldKeys",
})
query := fmt.Sprintf("SHOW CREATE TABLE %s.%s", t.tracesDBName, t.indexV3TblName)
statements := []telemetrytypes.ShowCreateTableStatement{}
err := t.telemetrystore.ClickhouseDB().Select(ctx, &statements, query)
@@ -146,12 +139,6 @@ func (t *telemetryMetaStore) tracesTblStatementToFieldKeys(ctx context.Context)
// getTracesKeys returns the keys from the spans that match the field selection criteria
func (t *telemetryMetaStore) getTracesKeys(ctx context.Context, fieldKeySelectors []*telemetrytypes.FieldKeySelector) ([]*telemetrytypes.TelemetryFieldKey, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getTracesKeys",
})
if len(fieldKeySelectors) == 0 {
return nil, true, nil
}
@@ -326,11 +313,6 @@ func (t *telemetryMetaStore) getTracesKeys(ctx context.Context, fieldKeySelector
// logsTblStatementToFieldKeys returns materialised attribute/resource/scope keys from the logs table
func (t *telemetryMetaStore) logsTblStatementToFieldKeys(ctx context.Context) ([]*telemetrytypes.TelemetryFieldKey, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "logsTblStatementToFieldKeys",
})
query := fmt.Sprintf("SHOW CREATE TABLE %s.%s", t.logsDBName, t.logsV2TblName)
statements := []telemetrytypes.ShowCreateTableStatement{}
err := t.telemetrystore.ClickhouseDB().Select(ctx, &statements, query)
@@ -352,12 +334,6 @@ func (t *telemetryMetaStore) logsTblStatementToFieldKeys(ctx context.Context) ([
// getLogsKeys returns the keys from the spans that match the field selection criteria
func (t *telemetryMetaStore) getLogsKeys(ctx context.Context, fieldKeySelectors []*telemetrytypes.FieldKeySelector) ([]*telemetrytypes.TelemetryFieldKey, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getLogsKeys",
})
if len(fieldKeySelectors) == 0 {
return nil, true, nil
}
@@ -607,11 +583,6 @@ func getPriorityForContext(ctx telemetrytypes.FieldContext) int {
// getMetricsKeys returns the keys from the metrics that match the field selection criteria
func (t *telemetryMetaStore) getMetricsKeys(ctx context.Context, fieldKeySelectors []*telemetrytypes.FieldKeySelector) ([]*telemetrytypes.TelemetryFieldKey, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getMetricsKeys",
})
if len(fieldKeySelectors) == 0 {
return nil, true, nil
}
@@ -714,12 +685,6 @@ func (t *telemetryMetaStore) getMetricsKeys(ctx context.Context, fieldKeySelecto
// getMeterKeys returns the keys from the meter metrics that match the field selection criteria
func (t *telemetryMetaStore) getMeterSourceMetricKeys(ctx context.Context, fieldKeySelectors []*telemetrytypes.FieldKeySelector) ([]*telemetrytypes.TelemetryFieldKey, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getMeterSourceMetricKeys",
})
if len(fieldKeySelectors) == 0 {
return nil, true, nil
}
@@ -1008,11 +973,6 @@ func (t *telemetryMetaStore) GetKey(ctx context.Context, fieldKeySelector *telem
}
func (t *telemetryMetaStore) getRelatedValues(ctx context.Context, fieldValueSelector *telemetrytypes.FieldValueSelector) ([]string, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: fieldValueSelector.Signal.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getRelatedValues",
})
// nothing to return as "related" value if there is nothing to filter on
if fieldValueSelector.ExistingQuery == "" {
@@ -1158,11 +1118,6 @@ func (t *telemetryMetaStore) GetRelatedValues(ctx context.Context, fieldValueSel
}
func (t *telemetryMetaStore) getSpanFieldValues(ctx context.Context, fieldValueSelector *telemetrytypes.FieldValueSelector) (*telemetrytypes.TelemetryFieldValues, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getSpanFieldValues",
})
// build the query to get the keys from the spans that match the field selection criteria
limit := fieldValueSelector.Limit
if limit == 0 {
@@ -1247,11 +1202,6 @@ func (t *telemetryMetaStore) getSpanFieldValues(ctx context.Context, fieldValueS
}
func (t *telemetryMetaStore) getLogFieldValues(ctx context.Context, fieldValueSelector *telemetrytypes.FieldValueSelector) (*telemetrytypes.TelemetryFieldValues, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalLogs.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getLogFieldValues",
})
// build the query to get the keys from the spans that match the field selection criteria
limit := fieldValueSelector.Limit
if limit == 0 {
@@ -1335,11 +1285,6 @@ func (t *telemetryMetaStore) getLogFieldValues(ctx context.Context, fieldValueSe
// getMetricFieldValues returns field values and whether the result is complete
func (t *telemetryMetaStore) getMetricFieldValues(ctx context.Context, fieldValueSelector *telemetrytypes.FieldValueSelector) (*telemetrytypes.TelemetryFieldValues, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getMetricFieldValues",
})
limit := fieldValueSelector.Limit
if limit == 0 {
limit = 50
@@ -1428,11 +1373,6 @@ func (t *telemetryMetaStore) getMetricFieldValues(ctx context.Context, fieldValu
// getIntrinsicMetricFieldValues returns values, isSearchComplete, error
func (t *telemetryMetaStore) getIntrinsicMetricFieldValues(ctx context.Context, fieldValueSelector *telemetrytypes.FieldValueSelector, limit int) (*telemetrytypes.TelemetryFieldValues, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getIntrinsicMetricFieldValues",
})
key, ok := telemetrymetrics.IntrinsicMetricFieldDefinitions[fieldValueSelector.Name]
if !ok {
return &telemetrytypes.TelemetryFieldValues{}, nil
@@ -1506,11 +1446,6 @@ func (t *telemetryMetaStore) getIntrinsicMetricFieldValues(ctx context.Context,
}
func (t *telemetryMetaStore) getMeterSourceMetricFieldValues(ctx context.Context, fieldValueSelector *telemetrytypes.FieldValueSelector) (*telemetrytypes.TelemetryFieldValues, bool, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "getMeterSourceMetricFieldValues",
})
sb := sqlbuilder.Select("DISTINCT arrayJoin(JSONExtractKeysAndValues(labels, 'String')) AS attr").
From(t.meterDBName + "." + t.meterFieldsTblName)
@@ -1727,11 +1662,6 @@ func (t *telemetryMetaStore) FetchTemporalityAndTypeMulti(ctx context.Context, q
}
func (t *telemetryMetaStore) fetchMetricsTemporalityAndType(ctx context.Context, queryTimeRangeStartTs, queryTimeRangeEndTs uint64, metricNames ...string) (map[string][]metrictypes.Temporality, map[string]metrictypes.Type, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "fetchMetricsTemporalityAndType",
})
temporalities := make(map[string][]metrictypes.Temporality)
types := make(map[string]metrictypes.Type)
@@ -1793,11 +1723,6 @@ func (t *telemetryMetaStore) fetchMetricsTemporalityAndType(ctx context.Context,
}
func (t *telemetryMetaStore) fetchMeterSourceMetricsTemporalityAndType(ctx context.Context, metricNames ...string) (map[string]metrictypes.Temporality, map[string]metrictypes.Type, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "fetchMeterSourceMetricsTemporalityAndType",
})
temporalities := make(map[string]metrictypes.Temporality)
types := make(map[string]metrictypes.Type)
@@ -1864,11 +1789,6 @@ const chunkSizeFirstSeenMetricMetadata = 1600
// for each metric-attribute-value combination.
// Returns a map where key is `telemetrytypes.MetricMetadataLookupKey` and value is first_seen in milliseconds.
func (t *telemetryMetaStore) GetFirstSeenFromMetricMetadata(ctx context.Context, lookupKeys []telemetrytypes.MetricMetadataLookupKey) (map[telemetrytypes.MetricMetadataLookupKey]int64, error) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalMetrics.StringValue(),
instrumentationtypes.CodeNamespace: "metadata",
instrumentationtypes.CodeFunctionName: "GetFirstSeenFromMetricMetadata",
})
result := make(map[telemetrytypes.MetricMetadataLookupKey]int64)
for i := 0; i < len(lookupKeys); i += chunkSizeFirstSeenMetricMetadata {

View File

@@ -5,7 +5,6 @@ import (
"github.com/SigNoz/signoz/pkg/factory"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/metric"
@@ -36,14 +35,7 @@ func NewInstrumentation(ctx context.Context, providerSettings factory.ProviderSe
}
func (hook *instrumentation) BeforeQuery(ctx context.Context, event *telemetrystore.QueryEvent) context.Context {
ctx, span := hook.tracer.Start(ctx, "", trace.WithSpanKind(trace.SpanKindClient))
// add trace_id and span_id to the log_comment
comment := ctxtypes.CommentFromContext(ctx)
comment.Set("trace_id", span.SpanContext().TraceID().String())
comment.Set("span_id", span.SpanContext().SpanID().String())
ctx = ctxtypes.NewContextWithComment(ctx, comment)
ctx, _ = hook.tracer.Start(ctx, "", trace.WithSpanKind(trace.SpanKindClient))
return ctx
}

View File

@@ -6,9 +6,6 @@ import (
"strings"
"github.com/SigNoz/signoz/pkg/telemetrystore"
"github.com/SigNoz/signoz/pkg/types/ctxtypes"
"github.com/SigNoz/signoz/pkg/types/instrumentationtypes"
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
)
type TraceTimeRangeFinder struct {
@@ -27,11 +24,6 @@ func (f *TraceTimeRangeFinder) GetTraceTimeRange(ctx context.Context, traceID st
}
func (f *TraceTimeRangeFinder) GetTraceTimeRangeMulti(ctx context.Context, traceIDs []string) (startNano, endNano int64, ok bool) {
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
instrumentationtypes.TelemetrySignal: telemetrytypes.SignalTraces.StringValue(),
instrumentationtypes.CodeNamespace: "trace-time-range",
instrumentationtypes.CodeFunctionName: "GetTraceTimeRangeMulti",
})
if len(traceIDs) == 0 {
return 0, 0, false
}

View File

@@ -104,13 +104,6 @@ func CommentFromHTTPRequest(req *http.Request) map[string]string {
return comments
}
// AddCommentsToContext returns a new context with all key-value pairs merged into the Comment in the context.
func NewContextWithCommentVals(ctx context.Context, vals map[string]string) context.Context {
comment := CommentFromContext(ctx)
comment.Merge(vals)
return NewContextWithComment(ctx, comment)
}
// NewComment creates a new Comment with an empty map. It is safe to use concurrently.
func NewComment() *Comment {
return &Comment{vals: map[string]string{}}

View File

@@ -1,53 +0,0 @@
package instrumentationtypes
import (
"math"
"time"
)
// DurationBucket returns a human-readable bucket label for the duration between fromMS and toMS.
// fromMS and toMS are Unix timestamps (same unit as used by time.Unix).
// Returns labels like "<1h", "<6h", "<24h", "<3D", "<1W", "<2W", "<1M", or ">=1M".
func DurationBucket(from, to uint64) string {
// make sure it's nanoseconds regardless of the unit
fromNS := ToNanoSecs(from)
toNS := ToNanoSecs(to)
diff := time.Unix(0, int64(toNS)).Sub(time.Unix(0, int64(fromNS)))
buckets := []struct {
d time.Duration
l string
}{
{1 * time.Hour, "<1h"},
{6 * time.Hour, "<6h"},
{24 * time.Hour, "<24h"},
{3 * 24 * time.Hour, "<3D"},
{7 * 24 * time.Hour, "<1W"},
{14 * 24 * time.Hour, "<2W"},
{30 * 24 * time.Hour, "<1M"},
}
for _, b := range buckets {
if diff < b.d {
return b.l
}
}
return ">=1M"
}
// ToNanoSecs takes epoch and returns it in ns
func ToNanoSecs(epoch uint64) uint64 {
temp := epoch
count := 0
if epoch == 0 {
count = 1
} else {
for epoch != 0 {
epoch /= 10
count++
}
}
return temp * uint64(math.Pow(10, float64(19-count)))
}

View File

@@ -1,21 +0,0 @@
package instrumentationtypes
import semconv "go.opentelemetry.io/collector/semconv/v1.6.1"
// Log comment / context keys for query observability.
// Names align with OpenTelemetry semantic conventions where applicable
// (https://pkg.go.dev/go.opentelemetry.io/otel/semconv); custom keys are namespaced.
const (
// CodeFunctionName is the fully-qualified function or method name (OTel code.function.name).
CodeFunctionName = semconv.AttributeCodeFunction
// CodeNamespace is the logical module or component name (e.g. "dashboard", "anomaly").
CodeNamespace = semconv.AttributeCodeNamespace
// TelemetrySignal is the telemetry signal type: "traces", "logs", or "metrics".
TelemetrySignal = "telemetry.signal"
// QueryDuration is the query time-range bucket label (e.g. "<1h", "<24h").
QueryDuration = "query.duration"
// PanelType is the panel type: "timeseries", "list", "value"
PanelType = "panel.type"
// QueryType is the query type: "promql", "clickhouse_sql", "builder_query".
QueryType = "query.type"
)