mirror of
https://github.com/hanzoai/o11y.git
synced 2026-10-15 12:58:33 +00:00
Salvage blue-wt-o11y-readers worktree
This commit is contained in:
+182
-182
@@ -36,128 +36,128 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "6.0.0",
|
||||
"@ant-design/v5-patch-for-react-19": "1.0.3",
|
||||
"@codemirror/autocomplete": "6.18.6",
|
||||
"@codemirror/lang-javascript": "6.2.3",
|
||||
"@codemirror/state": "6.5.2",
|
||||
"@codemirror/view": "6.36.6",
|
||||
"@dnd-kit/core": "6.1.0",
|
||||
"@dnd-kit/modifiers": "7.0.0",
|
||||
"@dnd-kit/sortable": "8.0.0",
|
||||
"@dnd-kit/utilities": "3.2.2",
|
||||
"@grafana/data": "^11.6.14",
|
||||
"@hanzo/insights": "^1.357.1",
|
||||
"@hanzo/ui": "^5.3.41",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@radix-ui/react-avatar": "1.1.11",
|
||||
"@radix-ui/react-checkbox": "1.3.3",
|
||||
"@radix-ui/react-dialog": "1.1.15",
|
||||
"@radix-ui/react-dropdown-menu": "2.1.16",
|
||||
"@radix-ui/react-popover": "1.1.15",
|
||||
"@radix-ui/react-progress": "1.1.8",
|
||||
"@radix-ui/react-radio-group": "1.3.8",
|
||||
"@radix-ui/react-select": "2.2.6",
|
||||
"@radix-ui/react-slider": "1.3.6",
|
||||
"@radix-ui/react-slot": "1.2.3",
|
||||
"@radix-ui/react-switch": "1.2.6",
|
||||
"@radix-ui/react-tabs": "1.1.13",
|
||||
"@radix-ui/react-toggle-group": "1.1.11",
|
||||
"@radix-ui/react-tooltip": "1.2.8",
|
||||
"@sentry/react": "8.41.0",
|
||||
"@sentry/vite-plugin": "2.22.6",
|
||||
"@tanstack/react-table": "8.20.6",
|
||||
"@tanstack/react-virtual": "3.11.2",
|
||||
"@uiw/codemirror-theme-copilot": "4.23.11",
|
||||
"@uiw/codemirror-theme-github": "4.24.1",
|
||||
"@uiw/react-codemirror": "4.23.10",
|
||||
"@visx/group": "4.0.0",
|
||||
"@visx/hierarchy": "4.0.0",
|
||||
"@visx/shape": "4.0.0",
|
||||
"@visx/tooltip": "4.0.0",
|
||||
"@visx/vendor": "4.0.0",
|
||||
"@vitejs/plugin-react": "5.1.4",
|
||||
"ansi-to-html": "0.7.2",
|
||||
"antd": "5.29.3",
|
||||
"antd-table-saveas-excel": "2.2.1",
|
||||
"antlr4": "4.13.2",
|
||||
"axios": "1.16.0",
|
||||
"babel-jest": "^29.6.4",
|
||||
"chart.js": "3.9.1",
|
||||
"chartjs-adapter-date-fns": "^2.0.0",
|
||||
"chartjs-plugin-annotation": "^1.4.0",
|
||||
"class-variance-authority": "0.7.1",
|
||||
"classnames": "2.3.2",
|
||||
"clsx": "2.1.1",
|
||||
"cmdk": "1.1.1",
|
||||
"color": "^4.2.1",
|
||||
"crypto-js": "4.2.0",
|
||||
"d3-hierarchy": "3.1.2",
|
||||
"dayjs": "^1.10.7",
|
||||
"dompurify": "3.4.0",
|
||||
"event-source-polyfill": "1.0.31",
|
||||
"eventemitter3": "5.0.1",
|
||||
"geist": "1.3.1",
|
||||
"history": "4.10.1",
|
||||
"http-proxy-middleware": "4.0.0",
|
||||
"http-status-codes": "2.3.0",
|
||||
"i18next": "^21.6.12",
|
||||
"i18next-browser-languagedetector": "^6.1.3",
|
||||
"i18next-http-backend": "^4.0.0",
|
||||
"immer": "11.1.3",
|
||||
"jest": "30.2.0",
|
||||
"js-base64": "^3.7.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-react": "0.498.0",
|
||||
"monaco-editor": "0.55.1",
|
||||
"motion": "12.4.13",
|
||||
"nuqs": "2.8.8",
|
||||
"overlayscrollbars": "^2.8.1",
|
||||
"overlayscrollbars-react": "^0.5.6",
|
||||
"papaparse": "5.4.1",
|
||||
"rc-tween-one": "3.0.6",
|
||||
"react": "19.2.7",
|
||||
"react-addons-update": "15.6.3",
|
||||
"react-day-picker": "^9.0.0",
|
||||
"react-dnd": "16.0.1",
|
||||
"react-dnd-html5-backend": "16.0.1",
|
||||
"react-dom": "19.2.7",
|
||||
"react-drag-listview": "2.0.0",
|
||||
"react-force-graph-2d": "^1.29.1",
|
||||
"react-full-screen": "1.1.1",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-helmet-async": "3.0.0",
|
||||
"react-hook-form": "7.71.2",
|
||||
"react-i18next": "^11.16.1",
|
||||
"react-json-tree": "^0.20.0",
|
||||
"react-markdown": "9.0.3",
|
||||
"react-query": "3.39.3",
|
||||
"react-redux": "9.3.0",
|
||||
"react-resizable-panels": "^4.0.0",
|
||||
"react-rnd": "^10.5.3",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-router-dom-v5-compat": "6.30.3",
|
||||
"react-syntax-highlighter": "15.5.0",
|
||||
"react-use": "^17.3.2",
|
||||
"react-virtuoso": "4.0.3",
|
||||
"redux": "^4.0.5",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"rehype-raw": "7.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
"rollup-plugin-visualizer": "7.0.0",
|
||||
"rrule": "2.8.1",
|
||||
"sonner": "2.0.7",
|
||||
"styled-components": "^5.3.11",
|
||||
"tailwind-merge": "3.5.0",
|
||||
"timestamp-nano": "^1.0.0",
|
||||
"typescript": "5.9.3",
|
||||
"uplot": "1.6.31",
|
||||
"uuid": "^8.3.2",
|
||||
"vaul": "1.1.2",
|
||||
"@ant-design/colors": "catalog:",
|
||||
"@ant-design/v5-patch-for-react-19": "catalog:",
|
||||
"@codemirror/autocomplete": "catalog:",
|
||||
"@codemirror/lang-javascript": "catalog:",
|
||||
"@codemirror/state": "catalog:",
|
||||
"@codemirror/view": "catalog:",
|
||||
"@dnd-kit/core": "catalog:",
|
||||
"@dnd-kit/modifiers": "catalog:",
|
||||
"@dnd-kit/sortable": "catalog:",
|
||||
"@dnd-kit/utilities": "catalog:",
|
||||
"@grafana/data": "catalog:",
|
||||
"@hanzo/insights": "catalog:",
|
||||
"@hanzo/ui": "catalog:",
|
||||
"@monaco-editor/react": "catalog:",
|
||||
"@radix-ui/react-avatar": "catalog:",
|
||||
"@radix-ui/react-checkbox": "catalog:",
|
||||
"@radix-ui/react-dialog": "catalog:",
|
||||
"@radix-ui/react-dropdown-menu": "catalog:",
|
||||
"@radix-ui/react-popover": "catalog:",
|
||||
"@radix-ui/react-progress": "catalog:",
|
||||
"@radix-ui/react-radio-group": "catalog:",
|
||||
"@radix-ui/react-select": "catalog:",
|
||||
"@radix-ui/react-slider": "catalog:",
|
||||
"@radix-ui/react-slot": "catalog:",
|
||||
"@radix-ui/react-switch": "catalog:",
|
||||
"@radix-ui/react-tabs": "catalog:",
|
||||
"@radix-ui/react-toggle-group": "catalog:",
|
||||
"@radix-ui/react-tooltip": "catalog:",
|
||||
"@sentry/react": "catalog:",
|
||||
"@sentry/vite-plugin": "catalog:",
|
||||
"@tanstack/react-table": "catalog:",
|
||||
"@tanstack/react-virtual": "catalog:",
|
||||
"@uiw/codemirror-theme-copilot": "catalog:",
|
||||
"@uiw/codemirror-theme-github": "catalog:",
|
||||
"@uiw/react-codemirror": "catalog:",
|
||||
"@visx/group": "catalog:",
|
||||
"@visx/hierarchy": "catalog:",
|
||||
"@visx/shape": "catalog:",
|
||||
"@visx/tooltip": "catalog:",
|
||||
"@visx/vendor": "catalog:",
|
||||
"@vitejs/plugin-react": "catalog:",
|
||||
"ansi-to-html": "catalog:",
|
||||
"antd": "catalog:",
|
||||
"antd-table-saveas-excel": "catalog:",
|
||||
"antlr4": "catalog:",
|
||||
"axios": "catalog:",
|
||||
"babel-jest": "catalog:",
|
||||
"chart.js": "catalog:",
|
||||
"chartjs-adapter-date-fns": "catalog:",
|
||||
"chartjs-plugin-annotation": "catalog:",
|
||||
"class-variance-authority": "catalog:",
|
||||
"classnames": "catalog:",
|
||||
"clsx": "catalog:",
|
||||
"cmdk": "catalog:",
|
||||
"color": "catalog:",
|
||||
"crypto-js": "catalog:",
|
||||
"d3-hierarchy": "catalog:",
|
||||
"dayjs": "catalog:",
|
||||
"dompurify": "catalog:",
|
||||
"event-source-polyfill": "catalog:",
|
||||
"eventemitter3": "catalog:",
|
||||
"geist": "catalog:",
|
||||
"history": "catalog:",
|
||||
"http-proxy-middleware": "catalog:",
|
||||
"http-status-codes": "catalog:",
|
||||
"i18next": "catalog:",
|
||||
"i18next-browser-languagedetector": "catalog:",
|
||||
"i18next-http-backend": "catalog:",
|
||||
"immer": "catalog:",
|
||||
"jest": "catalog:",
|
||||
"js-base64": "catalog:",
|
||||
"lodash-es": "catalog:",
|
||||
"lucide-react": "catalog:",
|
||||
"monaco-editor": "catalog:",
|
||||
"motion": "catalog:",
|
||||
"nuqs": "catalog:",
|
||||
"overlayscrollbars": "catalog:",
|
||||
"overlayscrollbars-react": "catalog:",
|
||||
"papaparse": "catalog:",
|
||||
"rc-tween-one": "catalog:",
|
||||
"react": "catalog:",
|
||||
"react-addons-update": "catalog:",
|
||||
"react-day-picker": "catalog:",
|
||||
"react-dnd": "catalog:",
|
||||
"react-dnd-html5-backend": "catalog:",
|
||||
"react-dom": "catalog:",
|
||||
"react-drag-listview": "catalog:",
|
||||
"react-force-graph-2d": "catalog:",
|
||||
"react-full-screen": "catalog:",
|
||||
"react-grid-layout": "catalog:",
|
||||
"react-helmet-async": "catalog:",
|
||||
"react-hook-form": "catalog:",
|
||||
"react-i18next": "catalog:",
|
||||
"react-json-tree": "catalog:",
|
||||
"react-markdown": "catalog:",
|
||||
"react-query": "catalog:",
|
||||
"react-redux": "catalog:",
|
||||
"react-resizable-panels": "catalog:",
|
||||
"react-rnd": "catalog:",
|
||||
"react-router-dom": "catalog:",
|
||||
"react-router-dom-v5-compat": "catalog:",
|
||||
"react-syntax-highlighter": "catalog:",
|
||||
"react-use": "catalog:",
|
||||
"react-virtuoso": "catalog:",
|
||||
"redux": "catalog:",
|
||||
"redux-thunk": "catalog:",
|
||||
"rehype-raw": "catalog:",
|
||||
"remark-gfm": "catalog:",
|
||||
"rollup-plugin-visualizer": "catalog:",
|
||||
"rrule": "catalog:",
|
||||
"sonner": "catalog:",
|
||||
"styled-components": "catalog:",
|
||||
"tailwind-merge": "catalog:",
|
||||
"timestamp-nano": "catalog:",
|
||||
"typescript": "catalog:",
|
||||
"uplot": "catalog:",
|
||||
"uuid": "catalog:",
|
||||
"vaul": "catalog:",
|
||||
"vite": "npm:[email protected]",
|
||||
"vite-plugin-html": "3.2.2",
|
||||
"zod": "4.3.6",
|
||||
"zustand": "5.0.11"
|
||||
"vite-plugin-html": "catalog:",
|
||||
"zod": "catalog:",
|
||||
"zustand": "catalog:"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
@@ -172,67 +172,67 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.22.11",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/preset-env": "^7.22.14",
|
||||
"@babel/preset-react": "^7.12.13",
|
||||
"@babel/preset-typescript": "^7.21.4",
|
||||
"@commitlint/cli": "20.4.4",
|
||||
"@commitlint/config-conventional": "20.4.4",
|
||||
"@jest/globals": "30.4.1",
|
||||
"@jest/types": "30.2.0",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/react": "16.3.2",
|
||||
"@testing-library/user-event": "14.4.3",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/d3-hierarchy": "1.1.11",
|
||||
"@types/event-source-polyfill": "^1.0.0",
|
||||
"@types/history": "4.7.11",
|
||||
"@types/jest": "30.0.0",
|
||||
"@types/lodash-es": "^4.17.4",
|
||||
"@types/node": "^16.10.3",
|
||||
"@types/papaparse": "5.3.7",
|
||||
"@types/react": "19.2.17",
|
||||
"@types/react-addons-update": "0.14.21",
|
||||
"@types/react-dom": "19.2.3",
|
||||
"@types/react-grid-layout": "^1.1.2",
|
||||
"@types/react-resizable": "3.0.3",
|
||||
"@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/testing-library__jest-dom": "^5.14.5",
|
||||
"@types/uuid": "^8.3.1",
|
||||
"@typescript/native-preview": "7.0.0-dev.20260430.1",
|
||||
"eslint-plugin-sonarjs": "4.0.2",
|
||||
"glob": "^13.0.6",
|
||||
"husky": "^7.0.4",
|
||||
"is-ci": "^3.0.1",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"jest-styled-components": "^7.2.0",
|
||||
"json-schema-to-typescript": "^15.0.4",
|
||||
"lint-staged": "^17.0.4",
|
||||
"msw": "1.3.2",
|
||||
"orval": "8.9.1",
|
||||
"oxfmt": "0.47.0",
|
||||
"oxlint": "1.62.0",
|
||||
"oxlint-tsgolint": "0.22.1",
|
||||
"postcss": "8.5.14",
|
||||
"postcss-scss": "4.0.9",
|
||||
"react-resizable": "3.0.4",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"sass": "1.97.3",
|
||||
"sharp": "0.34.5",
|
||||
"stylelint": "17.7.0",
|
||||
"svgo": "4.0.1",
|
||||
"ts-jest": "29.4.9",
|
||||
"typescript-plugin-css-modules": "5.2.0",
|
||||
"use-sync-external-store": "1.6.0",
|
||||
"vite-plugin-checker": "0.12.0",
|
||||
"vite-plugin-compression": "0.5.1",
|
||||
"vite-plugin-image-optimizer": "2.0.3",
|
||||
"vite-tsconfig-paths": "6.1.1"
|
||||
"@babel/core": "catalog:",
|
||||
"@babel/plugin-proposal-class-properties": "catalog:",
|
||||
"@babel/preset-env": "catalog:",
|
||||
"@babel/preset-react": "catalog:",
|
||||
"@babel/preset-typescript": "catalog:",
|
||||
"@commitlint/cli": "catalog:",
|
||||
"@commitlint/config-conventional": "catalog:",
|
||||
"@jest/globals": "catalog:",
|
||||
"@jest/types": "catalog:",
|
||||
"@testing-library/jest-dom": "catalog:",
|
||||
"@testing-library/react": "catalog:",
|
||||
"@testing-library/user-event": "catalog:",
|
||||
"@types/color": "catalog:",
|
||||
"@types/crypto-js": "catalog:",
|
||||
"@types/d3-hierarchy": "catalog:",
|
||||
"@types/event-source-polyfill": "catalog:",
|
||||
"@types/history": "catalog:",
|
||||
"@types/jest": "catalog:",
|
||||
"@types/lodash-es": "catalog:",
|
||||
"@types/node": "catalog:",
|
||||
"@types/papaparse": "catalog:",
|
||||
"@types/react": "catalog:",
|
||||
"@types/react-addons-update": "catalog:",
|
||||
"@types/react-dom": "catalog:",
|
||||
"@types/react-grid-layout": "catalog:",
|
||||
"@types/react-resizable": "catalog:",
|
||||
"@types/react-router-dom": "catalog:",
|
||||
"@types/react-syntax-highlighter": "catalog:",
|
||||
"@types/redux-mock-store": "catalog:",
|
||||
"@types/styled-components": "catalog:",
|
||||
"@types/testing-library__jest-dom": "catalog:",
|
||||
"@types/uuid": "catalog:",
|
||||
"@typescript/native-preview": "catalog:",
|
||||
"eslint-plugin-sonarjs": "catalog:",
|
||||
"glob": "catalog:",
|
||||
"husky": "catalog:",
|
||||
"is-ci": "catalog:",
|
||||
"jest-environment-jsdom": "catalog:",
|
||||
"jest-styled-components": "catalog:",
|
||||
"json-schema-to-typescript": "catalog:",
|
||||
"lint-staged": "catalog:",
|
||||
"msw": "catalog:",
|
||||
"orval": "catalog:",
|
||||
"oxfmt": "catalog:",
|
||||
"oxlint": "catalog:",
|
||||
"oxlint-tsgolint": "catalog:",
|
||||
"postcss": "catalog:",
|
||||
"postcss-scss": "catalog:",
|
||||
"react-resizable": "catalog:",
|
||||
"redux-mock-store": "catalog:",
|
||||
"sass": "catalog:",
|
||||
"sharp": "catalog:",
|
||||
"stylelint": "catalog:",
|
||||
"svgo": "catalog:",
|
||||
"ts-jest": "catalog:",
|
||||
"typescript-plugin-css-modules": "catalog:",
|
||||
"use-sync-external-store": "catalog:",
|
||||
"vite-plugin-checker": "catalog:",
|
||||
"vite-plugin-compression": "catalog:",
|
||||
"vite-plugin-image-optimizer": "catalog:",
|
||||
"vite-tsconfig-paths": "catalog:"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.(js|jsx|ts|tsx)": [
|
||||
|
||||
@@ -4,3 +4,279 @@ minimumReleaseAge: 2880 # 2d
|
||||
minimumReleaseAgeStrict: true
|
||||
minimumReleaseAgeExclude:
|
||||
blockExoticSubdeps: true
|
||||
overrides:
|
||||
'@noble/hashes': '1.8.0'
|
||||
'zod': '^4.5.2'
|
||||
'@hanzogui/adapt': '8.3.1'
|
||||
'@hanzogui/animate': '8.3.1'
|
||||
'@hanzogui/animate-presence': '8.3.1'
|
||||
'@hanzogui/animations-css': '8.3.1'
|
||||
'@hanzogui/animations-moti': '8.3.1'
|
||||
'@hanzogui/animations-react-native': '8.3.1'
|
||||
'@hanzogui/babel-plugin': '8.3.1'
|
||||
'@hanzogui/build': '8.3.1'
|
||||
'@hanzogui/button': '8.3.1'
|
||||
'@hanzogui/checkbox-headless': '8.3.1'
|
||||
'@hanzogui/cli': '8.3.1'
|
||||
'@hanzogui/collapsible': '8.3.1'
|
||||
'@hanzogui/collection': '8.3.1'
|
||||
'@hanzogui/colors': '8.3.1'
|
||||
'@hanzogui/component-helpers': '8.3.1'
|
||||
'@hanzogui/compose-refs': '8.3.1'
|
||||
'@hanzogui/config': '8.3.1'
|
||||
'@hanzogui/config-default': '8.3.1'
|
||||
'@hanzogui/constants': '8.3.1'
|
||||
'@hanzogui/core': '8.3.1'
|
||||
'@hanzogui/create-context': '8.3.1'
|
||||
'@hanzogui/create-menu': '8.3.1'
|
||||
'@hanzogui/dialog': '8.3.1'
|
||||
'@hanzogui/dismissable': '8.3.1'
|
||||
'@hanzogui/element': '8.3.1'
|
||||
'@hanzogui/floating': '8.3.1'
|
||||
'@hanzogui/focus-guard': '8.3.1'
|
||||
'@hanzogui/focus-scope': '8.3.1'
|
||||
'@hanzogui/focusable': '8.3.1'
|
||||
'@hanzogui/font-size': '8.3.1'
|
||||
'@hanzogui/get-button-sized': '8.3.1'
|
||||
'@hanzogui/get-font-sized': '8.3.1'
|
||||
'@hanzogui/get-token': '8.3.1'
|
||||
'@hanzogui/group': '8.3.1'
|
||||
'@hanzogui/helpers': '8.3.1'
|
||||
'@hanzogui/helpers-icon': '8.3.1'
|
||||
'@hanzogui/image': '8.3.1'
|
||||
'@hanzogui/input': '8.3.1'
|
||||
'@hanzogui/label': '8.3.1'
|
||||
'@hanzogui/list-item': '8.3.1'
|
||||
'@hanzogui/loader': '8.3.1'
|
||||
'@hanzogui/lucide-icons-2': '8.3.1'
|
||||
'@hanzogui/native': '8.3.1'
|
||||
'@hanzogui/next-plugin': '8.3.1'
|
||||
'@hanzogui/next-theme': '8.3.1'
|
||||
'@hanzogui/polyfill-dev': '8.3.1'
|
||||
'@hanzogui/popover': '8.3.1'
|
||||
'@hanzogui/popper': '8.3.1'
|
||||
'@hanzogui/portal': '8.3.1'
|
||||
'@hanzogui/radio-headless': '8.3.1'
|
||||
'@hanzogui/react-native-media-driver': '8.3.1'
|
||||
'@hanzogui/react-native-svg': '8.3.1'
|
||||
'@hanzogui/react-native-use-pressable': '8.3.1'
|
||||
'@hanzogui/react-native-use-responder-events': '8.3.1'
|
||||
'@hanzogui/react-native-web-lite': '8.3.1'
|
||||
'@hanzogui/remove-scroll': '8.3.1'
|
||||
'@hanzogui/roving-focus': '8.3.1'
|
||||
'@hanzogui/scroll-view': '8.3.1'
|
||||
'@hanzogui/separator': '8.3.1'
|
||||
'@hanzogui/shapes': '8.3.1'
|
||||
'@hanzogui/sheet': '8.3.1'
|
||||
'@hanzogui/shell': '8.3.1'
|
||||
'@hanzogui/sizable-context': '8.3.1'
|
||||
'@hanzogui/spacer': '8.3.1'
|
||||
'@hanzogui/stacks': '8.3.1'
|
||||
'@hanzogui/start-transition': '8.3.1'
|
||||
'@hanzogui/switch-headless': '8.3.1'
|
||||
'@hanzogui/telemetry': '8.3.1'
|
||||
'@hanzogui/text': '8.3.1'
|
||||
'@hanzogui/theme': '8.3.1'
|
||||
'@hanzogui/theme-base': '8.3.1'
|
||||
'@hanzogui/themes': '8.3.1'
|
||||
'@hanzogui/toast': '8.3.1'
|
||||
'@hanzogui/use-async': '8.3.1'
|
||||
'@hanzogui/use-callback-ref': '8.3.1'
|
||||
'@hanzogui/use-constant': '8.3.1'
|
||||
'@hanzogui/use-controllable-state': '8.3.1'
|
||||
'@hanzogui/use-debounce': '8.3.1'
|
||||
'@hanzogui/use-did-finish-ssr': '8.3.1'
|
||||
'@hanzogui/use-direction': '8.3.1'
|
||||
'@hanzogui/use-escape-keydown': '8.3.1'
|
||||
'@hanzogui/use-event': '8.3.1'
|
||||
'@hanzogui/use-force-update': '8.3.1'
|
||||
'@hanzogui/use-keyboard-visible': '8.3.1'
|
||||
'@hanzogui/use-presence': '8.3.1'
|
||||
'@hanzogui/use-previous': '8.3.1'
|
||||
'@hanzogui/visually-hidden': '8.3.1'
|
||||
'@hanzogui/vite-plugin': '8.3.1'
|
||||
'@hanzogui/web': '8.3.1'
|
||||
'@hanzogui/z-index-stack': '8.3.1'
|
||||
catalog:
|
||||
'@ant-design/colors': '^8.0.1'
|
||||
'@ant-design/v5-patch-for-react-19': '^1.0.3'
|
||||
'@babel/core': '^8.0.1'
|
||||
'@babel/plugin-proposal-class-properties': '^7.18.6'
|
||||
'@babel/preset-env': '^8.0.2'
|
||||
'@babel/preset-react': '^8.0.1'
|
||||
'@babel/preset-typescript': '^8.0.1'
|
||||
'@codemirror/autocomplete': '^6.20.3'
|
||||
'@codemirror/lang-javascript': '^6.2.5'
|
||||
'@codemirror/state': '^6.7.1'
|
||||
'@codemirror/view': '^6.43.9'
|
||||
'@commitlint/cli': '^21.2.2'
|
||||
'@commitlint/config-conventional': '^21.2.2'
|
||||
'@dnd-kit/core': '^6.3.1'
|
||||
'@dnd-kit/modifiers': '^9.0.0'
|
||||
'@dnd-kit/sortable': '^10.0.0'
|
||||
'@dnd-kit/utilities': '^3.2.2'
|
||||
'@grafana/data': '^13.2.0'
|
||||
'@hanzo/insights': '1.358.1'
|
||||
'@hanzo/ui': '8.27.2'
|
||||
'@jest/globals': '^30.5.0'
|
||||
'@jest/types': '^30.5.0'
|
||||
'@monaco-editor/react': '^4.7.0'
|
||||
'@radix-ui/react-avatar': '^1.2.6'
|
||||
'@radix-ui/react-checkbox': '^1.3.11'
|
||||
'@radix-ui/react-dialog': '^1.1.23'
|
||||
'@radix-ui/react-dropdown-menu': '^2.1.24'
|
||||
'@radix-ui/react-popover': '^1.1.23'
|
||||
'@radix-ui/react-progress': '^1.1.16'
|
||||
'@radix-ui/react-radio-group': '^1.4.7'
|
||||
'@radix-ui/react-select': '^2.3.7'
|
||||
'@radix-ui/react-slider': '^1.4.7'
|
||||
'@radix-ui/react-slot': '^1.3.3'
|
||||
'@radix-ui/react-switch': '^1.3.7'
|
||||
'@radix-ui/react-tabs': '^1.1.21'
|
||||
'@radix-ui/react-toggle-group': '^1.1.19'
|
||||
'@radix-ui/react-tooltip': '^1.2.16'
|
||||
'@sentry/react': '^10.72.0'
|
||||
'@sentry/vite-plugin': '^5.4.0'
|
||||
'@tanstack/react-table': '^9.2.4'
|
||||
'@tanstack/react-virtual': '^3.14.10'
|
||||
'@testing-library/jest-dom': '^7.0.1'
|
||||
'@testing-library/react': '^16.3.3'
|
||||
'@testing-library/user-event': '^14.6.6'
|
||||
'@types/color': '^4.2.1'
|
||||
'@types/crypto-js': '^4.2.2'
|
||||
'@types/d3-hierarchy': '^3.1.7'
|
||||
'@types/event-source-polyfill': '^1.0.5'
|
||||
'@types/history': '^5.0.0'
|
||||
'@types/jest': '^30.0.0'
|
||||
'@types/lodash-es': '^4.17.12'
|
||||
'@types/node': '26.4.0'
|
||||
'@types/papaparse': '^5.5.2'
|
||||
'@types/react': '19.2.18'
|
||||
'@types/react-addons-update': '^0.14.24'
|
||||
'@types/react-dom': '19.2.5'
|
||||
'@types/react-grid-layout': '^2.1.0'
|
||||
'@types/react-resizable': '^4.0.0'
|
||||
'@types/react-router-dom': '^5.3.3'
|
||||
'@types/react-syntax-highlighter': '^15.5.13'
|
||||
'@types/redux-mock-store': '^1.5.0'
|
||||
'@types/styled-components': '^5.1.36'
|
||||
'@types/testing-library__jest-dom': '^6.0.0'
|
||||
'@types/uuid': '^11.0.0'
|
||||
'@typescript/native-preview': '^7.0.0-dev.20260707.2'
|
||||
'@uiw/codemirror-theme-copilot': '^4.25.11'
|
||||
'@uiw/codemirror-theme-github': '^4.25.11'
|
||||
'@uiw/react-codemirror': '^4.25.11'
|
||||
'@visx/group': '^4.0.0'
|
||||
'@visx/hierarchy': '^4.0.0'
|
||||
'@visx/shape': '^4.0.0'
|
||||
'@visx/tooltip': '^4.0.0'
|
||||
'@visx/vendor': '^4.0.0'
|
||||
'@vitejs/plugin-react': '^6.0.2'
|
||||
'ansi-to-html': '^0.7.2'
|
||||
'antd': '^6.6.2'
|
||||
'antd-table-saveas-excel': '^2.2.1'
|
||||
'antlr4': '^4.13.2'
|
||||
'axios': '^1.20.0'
|
||||
'babel-jest': '^30.5.0'
|
||||
'chart.js': '^4.5.1'
|
||||
'chartjs-adapter-date-fns': '^3.0.0'
|
||||
'chartjs-plugin-annotation': '^3.1.0'
|
||||
'class-variance-authority': '^0.7.1'
|
||||
'classnames': '^2.5.1'
|
||||
'clsx': '^2.1.1'
|
||||
'cmdk': '^1.1.1'
|
||||
'color': '^5.0.3'
|
||||
'crypto-js': '^4.2.0'
|
||||
'd3-hierarchy': '^3.1.2'
|
||||
'dayjs': '^1.11.23'
|
||||
'dompurify': '^3.4.14'
|
||||
'eslint-plugin-sonarjs': '^4.2.0'
|
||||
'event-source-polyfill': '^1.0.31'
|
||||
'eventemitter3': '^5.0.4'
|
||||
'geist': '^1.7.2'
|
||||
'glob': '^13.0.6'
|
||||
'history': '^5.3.0'
|
||||
'http-proxy-middleware': '^4.2.0'
|
||||
'http-status-codes': '^2.3.0'
|
||||
'husky': '^9.1.7'
|
||||
'i18next': '^26.4.0'
|
||||
'i18next-browser-languagedetector': '^8.2.1'
|
||||
'i18next-http-backend': '^4.0.1'
|
||||
'immer': '^11.1.18'
|
||||
'is-ci': '^4.1.0'
|
||||
'jest': '^30.5.0'
|
||||
'jest-environment-jsdom': '^30.5.0'
|
||||
'jest-styled-components': '^7.4.0'
|
||||
'js-base64': '^3.9.3'
|
||||
'json-schema-to-typescript': '^16.0.0'
|
||||
'lint-staged': '^17.4.1'
|
||||
'lodash-es': '^4.18.1'
|
||||
'lucide-react': '^1.33.0'
|
||||
'monaco-editor': '^0.56.0'
|
||||
'motion': '^13.1.1'
|
||||
'msw': '^2.15.0'
|
||||
'nuqs': '^2.10.1'
|
||||
'orval': '^8.27.0'
|
||||
'overlayscrollbars': '^2.16.0'
|
||||
'overlayscrollbars-react': '^0.5.6'
|
||||
'oxfmt': '^0.65.0'
|
||||
'oxlint': '^1.80.0'
|
||||
'oxlint-tsgolint': '^7.0.2001'
|
||||
'papaparse': '^5.7.0'
|
||||
'postcss': '^8.5.26'
|
||||
'postcss-scss': '^4.0.9'
|
||||
'rc-tween-one': '^3.0.6'
|
||||
'react': '19.2.8'
|
||||
'react-addons-update': '^15.6.3'
|
||||
'react-day-picker': '^10.0.1'
|
||||
'react-dnd': '^16.0.1'
|
||||
'react-dnd-html5-backend': '^16.0.1'
|
||||
'react-dom': '19.2.8'
|
||||
'react-drag-listview': '^2.0.0'
|
||||
'react-force-graph-2d': '^1.29.1'
|
||||
'react-full-screen': '^1.1.1'
|
||||
'react-grid-layout': '^2.2.4'
|
||||
'react-helmet-async': '^3.0.0'
|
||||
'react-hook-form': '^7.86.0'
|
||||
'react-i18next': '^17.0.12'
|
||||
'react-json-tree': '^0.20.0'
|
||||
'react-markdown': '^10.1.0'
|
||||
'react-query': '^3.39.3'
|
||||
'react-redux': '^9.3.0'
|
||||
'react-resizable': '^4.0.2'
|
||||
'react-resizable-panels': '^2.1.9'
|
||||
'react-rnd': '^10.5.3'
|
||||
'react-router-dom': '^7.18.3'
|
||||
'react-router-dom-v5-compat': '^6.30.6'
|
||||
'react-syntax-highlighter': '^16.1.1'
|
||||
'react-use': '^17.6.1'
|
||||
'react-virtuoso': '^4.18.12'
|
||||
'redux': '^5.0.1'
|
||||
'redux-mock-store': '^1.5.5'
|
||||
'redux-thunk': '^3.1.0'
|
||||
'rehype-raw': '^7.0.0'
|
||||
'remark-gfm': '^4.0.1'
|
||||
'rollup-plugin-visualizer': '^7.1.1'
|
||||
'rrule': '^2.8.1'
|
||||
'sass': '^1.103.1'
|
||||
'sharp': '^0.35.4'
|
||||
'sonner': '^2.0.8'
|
||||
'styled-components': '^6.5.3'
|
||||
'stylelint': '^17.14.1'
|
||||
'svgo': '^4.1.0'
|
||||
'tailwind-merge': '^3.6.0'
|
||||
'timestamp-nano': '^1.0.1'
|
||||
'ts-jest': '^29.4.12'
|
||||
'typescript': '7.0.2'
|
||||
'typescript-plugin-css-modules': '^5.2.0'
|
||||
'uplot': '^1.6.32'
|
||||
'use-sync-external-store': '^1.6.0'
|
||||
'uuid': '^14.0.2'
|
||||
'vaul': '^1.1.2'
|
||||
'vite-plugin-checker': '^0.14.5'
|
||||
'vite-plugin-compression': '^0.5.1'
|
||||
'vite-plugin-html': '^3.2.2'
|
||||
'vite-plugin-image-optimizer': '^2.0.3'
|
||||
'vite-tsconfig-paths': '^6.1.1'
|
||||
'zod': '^4.5.2'
|
||||
'zustand': '^5.0.15'
|
||||
|
||||
@@ -4,12 +4,14 @@ import { QueryKey } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import localStorageGet from 'api/browser/localstorage/get';
|
||||
import localStorageSet from 'api/browser/localstorage/set';
|
||||
import ErrorInPlace from 'components/ErrorInPlace/ErrorInPlace';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { SKIP_ONBOARDING } from 'constants/onboarding';
|
||||
import useGetTopLevelOperations from 'hooks/useGetTopLevelOperations';
|
||||
import useResourceAttribute from 'hooks/useResourceAttribute';
|
||||
import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils';
|
||||
import { AppState } from 'store/reducers';
|
||||
import APIError from 'types/api/error';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { Tags } from 'types/reducer/trace';
|
||||
|
||||
@@ -34,7 +36,7 @@ function ServicesUsingMetrics(): JSX.Element {
|
||||
selectedTags,
|
||||
globalSelectedInterval,
|
||||
];
|
||||
const { data, isLoading, isError } = useGetTopLevelOperations(queryKey, {
|
||||
const { data, error, isLoading, isError } = useGetTopLevelOperations(queryKey, {
|
||||
start: minTime,
|
||||
end: maxTime,
|
||||
});
|
||||
@@ -50,14 +52,26 @@ function ServicesUsingMetrics(): JSX.Element {
|
||||
|
||||
const topLevelOperations = Object.entries(data || {});
|
||||
|
||||
if (isLoading === false && !skipOnboarding && isError === true) {
|
||||
return <SkipOnBoardingModal onContinueClick={onContinueClick} />;
|
||||
// A FAILED READ IS NOT AN EMPTY ONE — and this branch was worse than its
|
||||
// sibling in ServiceTraces: it never looked at the data at all. `isError ===
|
||||
// true` was the WHOLE condition, so the "instrument your application" modal
|
||||
// was shown if and only if the request FAILED, and a genuinely empty
|
||||
// deployment — the one case onboarding exists for — never saw it.
|
||||
//
|
||||
// Now: a failure shows the failure, a successful empty read offers
|
||||
// onboarding, and neither is mistaken for the other.
|
||||
if (isError) {
|
||||
return <ErrorInPlace error={error as APIError} />;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return <Spinner tip="Loading..." />;
|
||||
}
|
||||
|
||||
if (topLevelOperations.length === 0 && !skipOnboarding) {
|
||||
return <SkipOnBoardingModal onContinueClick={onContinueClick} />;
|
||||
}
|
||||
|
||||
return <ServiceMetricsApplication topLevelOperations={topLevelOperations} />;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useSelector } from 'react-redux';
|
||||
import localStorageGet from 'api/browser/localstorage/get';
|
||||
import localStorageSet from 'api/browser/localstorage/set';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ErrorInPlace from 'components/ErrorInPlace/ErrorInPlace';
|
||||
import { SKIP_ONBOARDING } from 'constants/onboarding';
|
||||
import useErrorNotification from 'hooks/useErrorNotification';
|
||||
import { useQueryService } from 'hooks/useQueryService';
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
} from 'hooks/useResourceAttribute/utils';
|
||||
import { isUndefined } from 'lodash-es';
|
||||
import { AppState } from 'store/reducers';
|
||||
import APIError from 'types/api/error';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { Tags } from 'types/reducer/trace';
|
||||
|
||||
@@ -78,12 +80,23 @@ function ServiceTraces(): JSX.Element {
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [data]);
|
||||
|
||||
if (
|
||||
services.length === 0 &&
|
||||
isLoading === false &&
|
||||
!skipOnboarding &&
|
||||
isError === true
|
||||
) {
|
||||
// A FAILED READ IS NOT AN EMPTY ONE.
|
||||
//
|
||||
// This branch used to require `isError === true` and then render the
|
||||
// "instrument your application" onboarding modal — so the ONLY way to reach
|
||||
// that modal was for the request to FAIL. When HIP-0132 dropped the database
|
||||
// this list reads, every customer with a fully instrumented fleet was told
|
||||
// their fleet was not instrumented, and the actual reason
|
||||
// (`Code: 81 UNKNOWN_DATABASE`) appeared nowhere on the page.
|
||||
//
|
||||
// The two states are separate now and each says what is true: a failed read
|
||||
// shows the failure, and only a SUCCESSFUL read that returned nothing offers
|
||||
// onboarding.
|
||||
if (isError) {
|
||||
return <ErrorInPlace error={error as unknown as APIError} />;
|
||||
}
|
||||
|
||||
if (services.length === 0 && isLoading === false && !skipOnboarding) {
|
||||
return <SkipOnBoardingModal onContinueClick={onContinueClick} />;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,28 @@ import (
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/http/handler"
|
||||
"github.com/hanzoai/o11y/pkg/http/routing"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
"github.com/hanzoai/o11y/pkg/types"
|
||||
qbtypes "github.com/hanzoai/o11y/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
)
|
||||
|
||||
// The Datastore-SQL request examples below are the ONLY documentation a customer
|
||||
// has for writing raw SQL against the plane, and they are copied verbatim into
|
||||
// real queries. They named o11y_traces and o11y_logs — databases HIP-0132 dropped
|
||||
// — so every customer who followed the docs wrote a query that could only answer
|
||||
// UNKNOWN_DATABASE. An example that teaches a dead name is worse than no example.
|
||||
//
|
||||
// They are composed from the same constants the readers use, so an example
|
||||
// cannot drift from the plane again.
|
||||
const (
|
||||
exSpan = telemetryplane.DBName + "." + telemetrytraces.SpanTableName
|
||||
exSpanResource = telemetryplane.DBName + "." + telemetrytraces.SpanResourceTableName
|
||||
exLog = telemetryplane.DBName + "." + telemetrylogs.LogTableName
|
||||
exLogResource = telemetryplane.DBName + "." + telemetrylogs.LogResourceTableName
|
||||
)
|
||||
|
||||
// DUAL DISPATCH. These registrations stay: the standalone server reaches them
|
||||
// directly, and the composed binary reaches the SAME handlers through the typed
|
||||
// query-engine ops in the repo root's querycore.go (querierQueryRange,
|
||||
@@ -374,10 +392,10 @@ func (provider *provider) addQuerierRoutes(router routing.Router) {
|
||||
"spec": map[string]any{
|
||||
"name": "span_rate",
|
||||
"query": "WITH __resource_filter AS (" +
|
||||
" SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource" +
|
||||
" SELECT fingerprint FROM " + exSpanResource +
|
||||
" WHERE seen_at_ts_bucket_start >= $start_timestamp - 1800 AND seen_at_ts_bucket_start <= $end_timestamp" +
|
||||
" ) SELECT toStartOfInterval(timestamp, INTERVAL 60 SECOND) AS ts, count() AS value" +
|
||||
" FROM o11y_traces.distributed_o11y_index_v3" +
|
||||
" FROM " + exSpan +
|
||||
" WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter)" +
|
||||
" AND timestamp >= $start_datetime AND timestamp <= $end_datetime" +
|
||||
" AND ts_bucket_start >= $start_timestamp - 1800 AND ts_bucket_start <= $end_timestamp" +
|
||||
@@ -403,10 +421,10 @@ func (provider *provider) addQuerierRoutes(router routing.Router) {
|
||||
"spec": map[string]any{
|
||||
"name": "recent_errors",
|
||||
"query": "WITH __resource_filter AS (" +
|
||||
" SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource" +
|
||||
" SELECT fingerprint FROM " + exLogResource +
|
||||
" WHERE seen_at_ts_bucket_start >= $start_timestamp - 1800 AND seen_at_ts_bucket_start <= $end_timestamp" +
|
||||
" ) SELECT timestamp, body" +
|
||||
" FROM o11y_logs.distributed_logs_v2" +
|
||||
" FROM " + exLog +
|
||||
" WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter)" +
|
||||
" AND timestamp >= $start_timestamp_nano AND timestamp <= $end_timestamp_nano" +
|
||||
" AND ts_bucket_start >= $start_timestamp - 1800 AND ts_bucket_start <= $end_timestamp" +
|
||||
@@ -433,10 +451,10 @@ func (provider *provider) addQuerierRoutes(router routing.Router) {
|
||||
"spec": map[string]any{
|
||||
"name": "total_spans",
|
||||
"query": "WITH __resource_filter AS (" +
|
||||
" SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource" +
|
||||
" SELECT fingerprint FROM " + exSpanResource +
|
||||
" WHERE seen_at_ts_bucket_start >= $start_timestamp - 1800 AND seen_at_ts_bucket_start <= $end_timestamp" +
|
||||
" ) SELECT count() AS value" +
|
||||
" FROM o11y_traces.distributed_o11y_index_v3" +
|
||||
" FROM " + exSpan +
|
||||
" WHERE resource_fingerprint GLOBAL IN (SELECT fingerprint FROM __resource_filter)" +
|
||||
" AND timestamp >= $start_datetime AND timestamp <= $end_datetime" +
|
||||
" AND ts_bucket_start >= $start_timestamp - 1800 AND ts_bucket_start <= $end_timestamp",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
//
|
||||
// WHY THIS EXISTS. Before it, the log lane's only wired path was the embedded
|
||||
// otelcol pipeline in hanzoai/cloud (datastorelogsexporter), which writes the
|
||||
// OTLP-fork family (o11y_logs.distributed_logs_v2 + its four side tables) that
|
||||
// OTLP-fork family (the retired o11y_logs.distributed_logs_v2 + its four side tables) that
|
||||
// the event-plane readers do not read. This driver is the one log write path
|
||||
// onto the envelope those readers query.
|
||||
//
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// WHY THIS EXISTS. Before it, the span lane had NO event-plane writer: the only
|
||||
// wired path was the embedded otelcol pipeline in hanzoai/cloud
|
||||
// (datastoretracesexporter), which writes the OTLP-fork family
|
||||
// (o11y_traces.o11y_index_v3) that the event-plane readers do not read. This
|
||||
// (the retired o11y_traces.o11y_index_v3) that the event-plane readers do not read. This
|
||||
// driver is the one span write path onto the envelope those readers query.
|
||||
//
|
||||
// IDEMPOTENT RE-INGEST. event.span is ReplacingMergeTree(ingested_at) with
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// OccurrenceSink is the OPTIONAL bridge that would also persist each occurrence to
|
||||
// the shared telemetry store (o11y_logs as an ERROR-severity record) for OTel-native
|
||||
// the shared telemetry store (event.log as an ERROR-severity record) for OTel-native
|
||||
// drill-down. It is deliberately a seam, and the default is NoopSink:
|
||||
//
|
||||
// - Authoritative storage is o11y_issues — the grouped issue plus the latest
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/datastoresql"
|
||||
|
||||
"github.com/hanzo-ds/sqlbuilder"
|
||||
"github.com/hanzoai/o11y/pkg/errors"
|
||||
"github.com/hanzoai/o11y/pkg/flagger"
|
||||
"github.com/hanzoai/o11y/pkg/querybuilder"
|
||||
@@ -17,7 +18,6 @@ import (
|
||||
qbtypes "github.com/hanzoai/o11y/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/hanzoai/o11y/pkg/types/telemetrytypes"
|
||||
"github.com/hanzoai/o11y/pkg/valuer"
|
||||
"github.com/hanzo-ds/sqlbuilder"
|
||||
)
|
||||
|
||||
// quoteIdentifier wraps s in backticks for use as a Datastore identifier,
|
||||
@@ -469,7 +469,7 @@ func (m *module) getEarliestMetricTime(ctx context.Context, metricNames []string
|
||||
}
|
||||
|
||||
// getMetricsExistence returns, for each requested metric name, whether it has ever
|
||||
// been reported (present in o11y_metrics.distributed_metadata). No time window.
|
||||
// been reported (present in the metric-metadata table). No time window.
|
||||
func (m *module) getMetricsExistence(ctx context.Context, metricNames []string) (map[string]bool, error) {
|
||||
present := make(map[string]bool, len(metricNames))
|
||||
for _, n := range metricNames {
|
||||
|
||||
@@ -9,17 +9,22 @@ import (
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/datastoresql"
|
||||
|
||||
sqlbuilder "github.com/hanzo-ds/sqlbuilder"
|
||||
"github.com/hanzoai/o11y/pkg/querybuilder"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrystore"
|
||||
qbtypes "github.com/hanzoai/o11y/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/hanzoai/o11y/pkg/types/rulestatehistorytypes"
|
||||
"github.com/hanzoai/o11y/pkg/types/ruletypes"
|
||||
"github.com/hanzoai/o11y/pkg/types/telemetrytypes"
|
||||
sqlbuilder "github.com/hanzo-ds/sqlbuilder"
|
||||
)
|
||||
|
||||
// o11y_analytics is NOT the event plane and must not be repointed at it:
|
||||
// AddRuleStateHistory in this same file WRITES it, so the rows are there. It was
|
||||
// spelled here AND in datastorereader, which is two places for one name; it is
|
||||
// spelled once now, in pkg/telemetryplane, beside the plane it is not part of.
|
||||
const (
|
||||
o11yHistoryDBName = "o11y_analytics"
|
||||
o11yHistoryDBName = telemetryplane.AnalyticsDBName
|
||||
ruleStateHistoryTableName = "distributed_rule_state_history_v0"
|
||||
)
|
||||
|
||||
|
||||
@@ -3,8 +3,18 @@ package tracefunnel
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
// spanTable is the one table every funnel query reads. All six templates below
|
||||
// spelled `o11y_traces.distributed_o11y_index_v3` — a database HIP-0132 dropped
|
||||
// and a table whose successor is event.span — so every funnel answered
|
||||
// `Code: 81 ... UNKNOWN_DATABASE`. Six copies of a name is six chances to miss
|
||||
// one; it is spelled here and interpolated.
|
||||
var spanTable = telemetryplane.DBName + "." + telemetrytraces.SpanTableName
|
||||
|
||||
// BuildFunnelValidationQuery builds a validation query for n-step funnels.
|
||||
func BuildFunnelValidationQuery(
|
||||
steps []struct {
|
||||
@@ -57,7 +67,7 @@ SELECT
|
||||
FROM (
|
||||
SELECT
|
||||
%s
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM ` + spanTable + `
|
||||
WHERE
|
||||
%s
|
||||
GROUP BY trace_id
|
||||
@@ -182,7 +192,7 @@ WITH
|
||||
, funnel AS (
|
||||
SELECT
|
||||
%s
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM ` + spanTable + `
|
||||
WHERE
|
||||
%s
|
||||
GROUP BY trace_id
|
||||
@@ -297,7 +307,7 @@ SELECT
|
||||
FROM (
|
||||
SELECT
|
||||
%s
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM ` + spanTable + `
|
||||
WHERE
|
||||
%s
|
||||
GROUP BY trace_id
|
||||
@@ -431,7 +441,7 @@ FROM (
|
||||
FROM (
|
||||
SELECT
|
||||
%s
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM ` + spanTable + `
|
||||
WHERE
|
||||
%s
|
||||
GROUP BY trace_id
|
||||
@@ -506,7 +516,7 @@ FROM (
|
||||
%[11]s AS t1_time,
|
||||
%[12]s AS t2_time,
|
||||
count() AS span_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM ` + spanTable + `
|
||||
WHERE
|
||||
timestamp BETWEEN start_ts AND end_ts
|
||||
AND (
|
||||
@@ -584,7 +594,7 @@ FROM (
|
||||
toUInt8(anyIf(has_error, resource_string_service$$name = step1.1 AND name = step1.2)) AS t1_error,
|
||||
toUInt8(anyIf(has_error, resource_string_service$$name = step2.1 AND name = step2.2)) AS t2_error,
|
||||
count() AS span_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM ` + spanTable + `
|
||||
WHERE
|
||||
timestamp BETWEEN start_ts AND end_ts
|
||||
AND (
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package tracefunnel
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
// All six funnel queries named `o11y_traces.distributed_o11y_index_v3` — a
|
||||
// database HIP-0132 dropped — and the tests in this package stayed green through
|
||||
// all of it, because every one of them asserts on the WITH clause and the step
|
||||
// predicates and none of them ever looked at the FROM.
|
||||
//
|
||||
// A test that checks everything except the one thing that breaks is not
|
||||
// coverage. This checks the FROM.
|
||||
func TestEveryFunnelQueryReadsThePlane(t *testing.T) {
|
||||
type step2 = struct {
|
||||
ServiceName string
|
||||
SpanName string
|
||||
ContainsError int
|
||||
Clause string
|
||||
}
|
||||
type stepLatency = struct {
|
||||
ServiceName string
|
||||
SpanName string
|
||||
ContainsError int
|
||||
LatencyPointer string
|
||||
Clause string
|
||||
}
|
||||
type stepLatencyTyped = struct {
|
||||
ServiceName string
|
||||
SpanName string
|
||||
ContainsError int
|
||||
LatencyPointer string
|
||||
LatencyType string
|
||||
Clause string
|
||||
}
|
||||
|
||||
plain := []step2{
|
||||
{ServiceName: "a", SpanName: "s1", ContainsError: 0, Clause: ""},
|
||||
{ServiceName: "b", SpanName: "s2", ContainsError: 0, Clause: ""},
|
||||
}
|
||||
latency := []stepLatency{
|
||||
{ServiceName: "a", SpanName: "s1", ContainsError: 0, LatencyPointer: "start", Clause: ""},
|
||||
{ServiceName: "b", SpanName: "s2", ContainsError: 0, LatencyPointer: "start", Clause: ""},
|
||||
}
|
||||
latencyTyped := []stepLatencyTyped{
|
||||
{ServiceName: "a", SpanName: "s1", ContainsError: 0, LatencyPointer: "start", LatencyType: "p99", Clause: ""},
|
||||
{ServiceName: "b", SpanName: "s2", ContainsError: 0, LatencyPointer: "start", LatencyType: "p99", Clause: ""},
|
||||
}
|
||||
|
||||
const start, end = int64(1700000000000000000), int64(1700003600000000000)
|
||||
|
||||
queries := map[string]string{
|
||||
"validation": BuildFunnelValidationQuery(plain, start, end),
|
||||
"overview": BuildFunnelOverviewQuery(latency, start, end),
|
||||
"count": BuildFunnelCountQuery(plain, start, end),
|
||||
"stepOverview": BuildFunnelStepOverviewQuery(latencyTyped, start, end, 1, 2),
|
||||
"topSlowTraces": BuildFunnelTopSlowTracesQuery(0, 0, start, end, "a", "s1", "b", "s2", "", "", "start", "start"),
|
||||
"topSlowErrTraces": BuildFunnelTopSlowErrorTracesQuery(0, 1, start, end, "a", "s1", "b", "s2", "", "", "start", "start"),
|
||||
}
|
||||
|
||||
wantTable := telemetryplane.DBName + "." + telemetrytraces.SpanTableName
|
||||
|
||||
for name, sql := range queries {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require.NotEmpty(t, sql)
|
||||
assert.Containsf(t, sql, wantTable,
|
||||
"funnel query must read the event plane's span table, got:\n%s", sql)
|
||||
for _, gone := range []string{"o11y_traces", "o11y_logs", "o11y_metrics"} {
|
||||
assert.NotContainsf(t, sql, gone,
|
||||
"funnel query names %s, a database HIP-0132 dropped", gone)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -149,7 +149,7 @@ func NewModules(
|
||||
ruleStore := sqlrulestore.NewRuleStore(sqlstore, queryParser, providerSettings)
|
||||
authDomainModule := implauthdomain.NewModule(implauthdomain.NewStore(sqlstore), authNs, authz)
|
||||
|
||||
// Error tracking (o11y_issues lifecycle) and trace detail (o11y_traces waterfall)
|
||||
// Error tracking (issue lifecycle) and trace detail (the event.span waterfall)
|
||||
// are pulled into locals so the Sentry product face can COMPOSE them rather than
|
||||
// reconstruct them — one issue lifecycle, one trace read, two product faces.
|
||||
errorTrackingModule := implerrortracking.NewModule(
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
package datastoreprometheus
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetrics"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
)
|
||||
|
||||
// The names the PromQL adapter reads by. o11y_metrics was dropped by HIP-0132,
|
||||
// so every PromQL panel — the whole alerting evaluation path included — answered
|
||||
// `Code: 81 ... UNKNOWN_DATABASE`. Aliases of pkg/telemetrymetrics/tables.go:
|
||||
// time_series_v4 IS event.series and samples_v4 IS event.metric.
|
||||
const (
|
||||
databaseName string = "o11y_metrics"
|
||||
distributedTimeSeriesV4 string = "distributed_time_series_v4"
|
||||
distributedTimeSeriesV46hrs string = "distributed_time_series_v4_6hrs"
|
||||
distributedTimeSeriesV41day string = "distributed_time_series_v4_1day"
|
||||
distributedSamplesV4 string = "distributed_samples_v4"
|
||||
databaseName string = telemetryplane.DBName
|
||||
distributedTimeSeriesV4 string = telemetrymetrics.SeriesTableName
|
||||
distributedTimeSeriesV46hrs string = telemetrymetrics.Series6hTableName
|
||||
distributedTimeSeriesV41day string = telemetrymetrics.Series1dTableName
|
||||
distributedSamplesV4 string = telemetrymetrics.MetricTableName
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
+33
-3
@@ -20,7 +20,11 @@ import (
|
||||
"github.com/hanzoai/o11y/pkg/prometheus"
|
||||
"github.com/hanzoai/o11y/pkg/query-service/utils"
|
||||
"github.com/hanzoai/o11y/pkg/querybuilder"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetrics"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrystore"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
"github.com/hanzoai/o11y/pkg/types/ctxtypes"
|
||||
"github.com/hanzoai/o11y/pkg/types/instrumentationtypes"
|
||||
"github.com/hanzoai/o11y/pkg/types/metrictypes"
|
||||
@@ -296,14 +300,40 @@ func (q *querier) populateQBEvent(event *qbtypes.QBEvent, queries []qbtypes.Quer
|
||||
case qbtypes.QueryTypeDatastoreSQL:
|
||||
sql := query.GetQuery()
|
||||
if strings.TrimSpace(sql) != "" {
|
||||
event.MetricsUsed = strings.Contains(sql, "o11y_metrics")
|
||||
event.LogsUsed = strings.Contains(sql, "o11y_logs")
|
||||
event.TracesUsed = strings.Contains(sql, "o11y_traces")
|
||||
m, l, t := SignalsInSQL(sql)
|
||||
event.MetricsUsed, event.LogsUsed, event.TracesUsed = m, l, t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SignalsInSQL reports which signals a raw Datastore-SQL query reads.
|
||||
//
|
||||
// EXPORTED because query-service/app/query_info.go asked the same question with
|
||||
// its own copy of the answer, and two copies of a discriminator is how one of
|
||||
// them gets fixed. One function, two callers.
|
||||
//
|
||||
// IT USED TO ASK WHICH DATABASE THE SQL NAMED — o11y_metrics, o11y_logs,
|
||||
// o11y_traces. HIP-0132 unified all three into `event`, so all three tests went
|
||||
// permanently false and every raw-SQL query was recorded as touching NO signal.
|
||||
// That is a silent defect: nothing errors, the usage analytics just quietly stop
|
||||
// counting, and the number they feed is a number nobody can tell is wrong.
|
||||
//
|
||||
// With one database the discriminator is the TABLE, which is what it should have
|
||||
// been all along — a database is where rows live, a table is what they are. The
|
||||
// prefixes are deliberate: event.log also matches log_attribute and log_resource,
|
||||
// event.span matches span_attribute and span_resource, event.metric matches
|
||||
// metric_5m and event.series matches series_6h — all of which are that signal's
|
||||
// support tables and SHOULD count as that signal.
|
||||
func SignalsInSQL(sql string) (metrics, logs, traces bool) {
|
||||
const qualify = telemetryplane.DBName + "."
|
||||
metrics = strings.Contains(sql, qualify+telemetrymetrics.MetricTableName) ||
|
||||
strings.Contains(sql, qualify+telemetrymetrics.SeriesTableName)
|
||||
logs = strings.Contains(sql, qualify+telemetrylogs.LogTableName)
|
||||
traces = strings.Contains(sql, qualify+telemetrytraces.SpanTableName)
|
||||
return metrics, logs, traces
|
||||
}
|
||||
|
||||
// resolveMetricMetadata fetches metadata for every metric referenced by builder
|
||||
// metric-aggregation queries, patches each query's aggregations in place with
|
||||
// the resolved values, and classifies any metric that could not be resolved.
|
||||
|
||||
@@ -30,7 +30,7 @@ type mockMetricStmtBuilder struct{}
|
||||
|
||||
func (m *mockMetricStmtBuilder) Build(_ context.Context, _, _ uint64, _ qbtypes.RequestType, _ qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation], _ map[string]qbtypes.VariableItem) (*qbtypes.Statement, error) {
|
||||
return &qbtypes.Statement{
|
||||
Query: "SELECT ts, value FROM o11y_metrics",
|
||||
Query: "SELECT ts, value FROM event.metric",
|
||||
Args: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -139,14 +139,14 @@ func (r *DatastoreReader) getValuesForLogAttributes(
|
||||
select * from (
|
||||
(
|
||||
select tag_key, string_value, number_value
|
||||
from o11y_logs.distributed_tag_attributes_v2
|
||||
from event.log_attribute
|
||||
where tag_key = $1 and (
|
||||
string_value != '' or number_value is not null
|
||||
)
|
||||
limit 2
|
||||
) UNION DISTINCT (
|
||||
select tag_key, string_value, number_value
|
||||
from o11y_logs.distributed_tag_attributes_v2
|
||||
from event.log_attribute
|
||||
where tag_key = $2 and (
|
||||
string_value != '' or number_value is not null
|
||||
)
|
||||
@@ -154,7 +154,7 @@ func (r *DatastoreReader) getValuesForLogAttributes(
|
||||
)
|
||||
) settings max_threads=2
|
||||
```
|
||||
Since tag_attributes table uses ReplacingMergeTree, the values would be distinct and no order by
|
||||
Since log_attribute uses ReplacingMergeTree, the values would be distinct and no order by
|
||||
is being used to ensure the `limit` clause minimizes the amount of data scanned.
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,6 +4,11 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hanzo-ds/go"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetadata"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
type Encoding string
|
||||
@@ -15,42 +20,74 @@ const (
|
||||
EncodingProto Encoding = "protobuf"
|
||||
)
|
||||
|
||||
// The defaults this reader is constructed with.
|
||||
//
|
||||
// EVERY NAME IS AN ALIAS. Both databases this file used to spell — o11y_traces
|
||||
// and o11y_logs — were dropped by HIP-0132 and unified into the event plane, so
|
||||
// every default here named something that no longer existed. The spellings live
|
||||
// in pkg/telemetryplane and the table names in pkg/telemetry{traces,logs}/
|
||||
// tables.go, which is the canonical statement of the plane's shape; this file
|
||||
// now only says WHICH of them each role takes.
|
||||
//
|
||||
// THE V2-ERA NAMES ARE NOT ALIASED, and the second block below is where they
|
||||
// stay. operations, index_v2, error_index_v2, durationSort, usage_explorer,
|
||||
// o11y_spans and dependency_graph_minutes_v2 were dropped WITH o11y_traces and
|
||||
// the plane has no successor with their columns. Pointing one at an event-plane
|
||||
// table would swap `UNKNOWN_TABLE`, which names the retired table and is true,
|
||||
// for `THERE_IS_NO_COLUMN`, which names a live table and reads like the plane is
|
||||
// broken. The engine's error is the honest reason and it names the exact table;
|
||||
// this comment is what an operator finds when they grep for it.
|
||||
const (
|
||||
defaultTraceDB string = "o11y_traces"
|
||||
defaultOperationsTable string = "distributed_o11y_operations"
|
||||
defaultIndexTable string = "distributed_o11y_index_v2"
|
||||
defaultLocalIndexTable string = "o11y_index_v2"
|
||||
defaultErrorTable string = "distributed_o11y_error_index_v2"
|
||||
defaultDurationTable string = "distributed_durationSort"
|
||||
defaultUsageExplorerTable string = "distributed_usage_explorer"
|
||||
defaultSpansTable string = "distributed_o11y_spans"
|
||||
defaultDependencyGraphTable string = "distributed_dependency_graph_minutes_v2"
|
||||
defaultTopLevelOperationsTable string = "distributed_top_level_operations"
|
||||
defaultSpanAttributeTableV2 string = "distributed_tag_attributes_v2"
|
||||
defaultSpanAttributeKeysTable string = "distributed_span_attributes_keys"
|
||||
defaultLogsDB string = "o11y_logs"
|
||||
defaultLogsTable string = "distributed_logs"
|
||||
defaultLogsLocalTable string = "logs"
|
||||
defaultLogAttributeKeysTable string = "distributed_logs_attribute_keys"
|
||||
defaultLogResourceKeysTable string = "distributed_logs_resource_keys"
|
||||
defaultLogTagAttributeTableV2 string = "distributed_tag_attributes_v2"
|
||||
defaultTraceDB string = telemetryplane.DBName
|
||||
defaultTopLevelOperationsTable string = telemetrytraces.OperationTableName
|
||||
defaultSpanAttributeTableV2 string = telemetrytraces.SpanAttributeTableName
|
||||
defaultSpanAttributeKeysTable string = telemetrytraces.SpanKeyTableName
|
||||
defaultLogsDB string = telemetryplane.DBName
|
||||
defaultLogsTable string = telemetrylogs.LogTableName
|
||||
defaultLogsLocalTable string = telemetrylogs.LogLocalTableName
|
||||
defaultLogAttributeKeysTable string = telemetrylogs.LogKeyTableName
|
||||
defaultLogResourceKeysTable string = telemetrylogs.LogResourceKeyTableName
|
||||
defaultLogTagAttributeTableV2 string = telemetrylogs.LogAttributeTableName
|
||||
defaultLiveTailRefreshSeconds int = 5
|
||||
defaultWriteBatchDelay time.Duration = 5 * time.Second
|
||||
defaultWriteBatchSize int = 10000
|
||||
defaultEncoding Encoding = EncodingJSON
|
||||
|
||||
defaultLogsLocalTableV2 string = "logs_v2"
|
||||
defaultLogsTableV2 string = "distributed_logs_v2"
|
||||
defaultLogsResourceLocalTableV2 string = "logs_v2_resource"
|
||||
defaultLogsResourceTableV2 string = "distributed_logs_v2_resource"
|
||||
defaultLogsLocalTableV2 string = telemetrylogs.LogLocalTableName
|
||||
defaultLogsTableV2 string = telemetrylogs.LogTableName
|
||||
defaultLogsResourceLocalTableV2 string = telemetrylogs.LogResourceTableName
|
||||
defaultLogsResourceTableV2 string = telemetrylogs.LogResourceTableName
|
||||
|
||||
defaultTraceIndexTableV3 string = "distributed_o11y_index_v3"
|
||||
defaultTraceLocalTableName string = "o11y_index_v3"
|
||||
defaultTraceResourceTableV3 string = "distributed_traces_v3_resource"
|
||||
defaultTraceSummaryTable string = "distributed_trace_summary"
|
||||
defaultTraceIndexTableV3 string = telemetrytraces.SpanTableName
|
||||
defaultTraceLocalTableName string = telemetrytraces.SpanLocalTableName
|
||||
defaultTraceResourceTableV3 string = telemetrytraces.SpanResourceTableName
|
||||
defaultTraceSummaryTable string = telemetrytraces.TraceTableName
|
||||
|
||||
defaultMetadataDB string = "o11y_metadata"
|
||||
defaultMetadataTable string = "distributed_attributes_metadata"
|
||||
defaultMetadataDB string = telemetrymetadata.DBName
|
||||
defaultMetadataTable string = telemetrymetadata.AttributesMetadataTableName
|
||||
)
|
||||
|
||||
// RETIRED — the v2-era tables of the old trace schema. Every one of them was
|
||||
// dropped with o11y_traces and NONE of them has an event-plane successor that
|
||||
// carries its columns: the exceptions pages read errorID/groupID/exceptionType,
|
||||
// the service map reads a precomputed edge table, and the usage explorer reads a
|
||||
// per-hour count. The event plane stores the SPANS those were derived from and
|
||||
// nothing else.
|
||||
//
|
||||
// They are kept as literals, in one block, so that the read that reaches one
|
||||
// fails with `Code: 60 UNKNOWN_TABLE: event.distributed_o11y_error_index_v2` —
|
||||
// a message that names the retired table, which is the true reason. The
|
||||
// alternative is a false empty, and a customer told "no errors" by a page that
|
||||
// cannot see the table burns a day before opening a ticket.
|
||||
const (
|
||||
defaultOperationsTable string = "distributed_o11y_operations"
|
||||
defaultIndexTable string = "distributed_o11y_index_v2"
|
||||
defaultLocalIndexTable string = "o11y_index_v2"
|
||||
defaultErrorTable string = "distributed_o11y_error_index_v2"
|
||||
defaultDurationTable string = "distributed_durationSort"
|
||||
defaultUsageExplorerTable string = "distributed_usage_explorer"
|
||||
defaultSpansTable string = "distributed_o11y_spans"
|
||||
defaultDependencyGraphTable string = "distributed_dependency_graph_minutes_v2"
|
||||
)
|
||||
|
||||
// NamespaceConfig is Datastore's internal configuration data
|
||||
|
||||
@@ -41,6 +41,10 @@ import (
|
||||
"github.com/hanzo-ds/go/lib/driver"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/cache"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetadata"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymeter"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetrics"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
|
||||
"log/slog"
|
||||
|
||||
@@ -58,51 +62,79 @@ import (
|
||||
"github.com/hanzoai/o11y/pkg/query-service/utils"
|
||||
)
|
||||
|
||||
// The names this reader reads by.
|
||||
//
|
||||
// EVERY DATABASE NAME HERE IS AN ALIAS, NOT A SPELLING. This file used to spell
|
||||
// five of them — o11y_traces, o11y_metrics, o11y_metadata, o11y_meter,
|
||||
// o11y_analytics — three of which had been dropped by HIP-0132, which is why
|
||||
// every read through this reader answered `Code: 81 ... UNKNOWN_DATABASE`.
|
||||
// A name that is spelled in two files drifts; a name that is spelled once cannot.
|
||||
// pkg/telemetryplane holds the spellings and plane_test.go enforces it.
|
||||
//
|
||||
// THE TABLE NAMES MOVED TOO, and they are aliases for the same reason. The event
|
||||
// plane names a table for WHAT IT IS — span, log, metric, series — and drops the
|
||||
// `distributed_` prefix (there are no Distributed wrappers on this deployment)
|
||||
// and the `_v2`/`_v3`/`_v4` suffix (a version in a name is a second table waiting
|
||||
// to happen). The mapping below is one-to-one and comes from
|
||||
// pkg/telemetry{traces,logs,metrics}/tables.go, which is the canonical statement
|
||||
// of the plane's shape.
|
||||
//
|
||||
// THE V2-ERA TABLES ARE GONE AND ARE NOT ALIASED. durationSort, usage_explorer,
|
||||
// o11y_spans, o11y_error_index_v2, o11y_index_v2 and dependency_graph_minutes_v2
|
||||
// were dropped WITH o11y_traces and the event plane has no successor for them.
|
||||
// Their constants are DELETED rather than repointed: an alias to `event` would
|
||||
// name a table that has never existed there, and the read would fail as if the
|
||||
// plane were broken. Where they were enumerated for TTL they are removed from the
|
||||
// list — one dead name in an ALTER list fails the TTL run for every live table
|
||||
// beside it.
|
||||
const (
|
||||
primaryNamespace = "datastore"
|
||||
archiveNamespace = "datastore-archive"
|
||||
o11yTraceDBName = "o11y_traces"
|
||||
o11yHistoryDBName = "o11y_analytics"
|
||||
primaryNamespace = "datastore"
|
||||
archiveNamespace = "datastore-archive"
|
||||
|
||||
// The one plane. Traces, logs and metrics all resolve here.
|
||||
o11yTraceDBName = telemetryplane.DBName
|
||||
o11yMetricDBName = telemetryplane.DBName
|
||||
|
||||
// Not the plane; each has a live writer. See pkg/telemetryplane.
|
||||
o11yHistoryDBName = telemetryplane.AnalyticsDBName
|
||||
o11yMetadataDbName = telemetrymetadata.DBName
|
||||
o11yMeterDBName = telemetryplane.MeterDBName
|
||||
|
||||
ruleStateHistoryTableName = "distributed_rule_state_history_v0"
|
||||
o11yDurationMVTable = "distributed_durationSort"
|
||||
o11yUsageExplorerTable = "distributed_usage_explorer"
|
||||
o11ySpansTable = "distributed_o11y_spans"
|
||||
o11yErrorIndexTable = "distributed_o11y_error_index_v2"
|
||||
o11yTraceTableName = "distributed_o11y_index_v2"
|
||||
o11yTraceLocalTableName = "o11y_index_v2"
|
||||
o11yMetricDBName = "o11y_metrics"
|
||||
o11yMetadataDbName = "o11y_metadata"
|
||||
o11yMeterDBName = "o11y_meter"
|
||||
o11yMeterSamplesName = "samples_agg_1d"
|
||||
|
||||
o11ySampleLocalTableName = "samples_v4"
|
||||
o11ySampleTableName = "distributed_samples_v4"
|
||||
o11yMeterSamplesName = telemetrymeter.SamplesAgg1dLocalTableName
|
||||
|
||||
o11ySamplesAgg5mLocalTableName = "samples_v4_agg_5m"
|
||||
o11ySamplesAgg5mTableName = "distributed_samples_v4_agg_5m"
|
||||
// samples_v4 -> metric: a row is one sample of one metric.
|
||||
o11ySampleLocalTableName = telemetrymetrics.MetricLocalTableName
|
||||
o11ySampleTableName = telemetrymetrics.MetricTableName
|
||||
|
||||
o11ySamplesAgg30mLocalTableName = "samples_v4_agg_30m"
|
||||
o11ySamplesAgg30mTableName = "distributed_samples_v4_agg_30m"
|
||||
o11ySamplesAgg5mLocalTableName = telemetrymetrics.Metric5mLocalTableName
|
||||
o11ySamplesAgg5mTableName = telemetrymetrics.Metric5mTableName
|
||||
|
||||
o11yExpHistLocalTableName = "exp_hist"
|
||||
o11yExpHistTableName = "distributed_exp_hist"
|
||||
o11ySamplesAgg30mLocalTableName = telemetrymetrics.Metric30mLocalTableName
|
||||
o11ySamplesAgg30mTableName = telemetrymetrics.Metric30mTableName
|
||||
|
||||
o11yTSLocalTableNameV4 = "time_series_v4"
|
||||
o11yTSTableNameV4 = "distributed_time_series_v4"
|
||||
o11yExpHistLocalTableName = telemetrymetrics.HistogramLocalTableName
|
||||
o11yExpHistTableName = telemetrymetrics.HistogramTableName
|
||||
|
||||
o11yTSLocalTableNameV46Hrs = "time_series_v4_6hrs"
|
||||
o11yTSTableNameV46Hrs = "distributed_time_series_v4_6hrs"
|
||||
// time_series_v4 -> series: a row is one series.
|
||||
o11yTSLocalTableNameV4 = telemetrymetrics.SeriesLocalTableName
|
||||
o11yTSTableNameV4 = telemetrymetrics.SeriesTableName
|
||||
|
||||
o11yTSLocalTableNameV41Day = "time_series_v4_1day"
|
||||
o11yTSTableNameV41Day = "distributed_time_series_v4_1day"
|
||||
o11yTSLocalTableNameV46Hrs = telemetrymetrics.Series6hLocalTableName
|
||||
o11yTSTableNameV46Hrs = telemetrymetrics.Series6hTableName
|
||||
|
||||
o11yTSLocalTableNameV41Week = "time_series_v4_1week"
|
||||
o11yTSTableNameV41Week = "distributed_time_series_v4_1week"
|
||||
o11yTSLocalTableNameV41Day = telemetrymetrics.Series1dLocalTableName
|
||||
o11yTSTableNameV41Day = telemetrymetrics.Series1dTableName
|
||||
|
||||
o11yTSTableNameV4Reduced = "distributed_time_series_v4_reduced"
|
||||
o11yTSLocalTableNameV41Week = telemetrymetrics.Series1wLocalTableName
|
||||
o11yTSTableNameV41Week = telemetrymetrics.Series1wTableName
|
||||
|
||||
o11yTableAttributesMetadata = "distributed_attributes_metadata"
|
||||
o11yLocalTableAttributesMetadata = "attributes_metadata"
|
||||
o11yTSTableNameV4Reduced = telemetrymetrics.SeriesReducedTableName
|
||||
|
||||
// The metadata pair stays in o11y_metadata with it.
|
||||
o11yTableAttributesMetadata = telemetrymetadata.AttributesMetadataTableName
|
||||
o11yLocalTableAttributesMetadata = telemetrymetadata.AttributesMetadataLocalTableName
|
||||
|
||||
o11yUpdatedMetricsMetadataLocalTable = "updated_metadata"
|
||||
o11yUpdatedMetricsMetadataTable = "distributed_updated_metadata"
|
||||
@@ -1103,12 +1135,14 @@ func (r *DatastoreReader) setTTLTraces(ctx context.Context, orgID string, params
|
||||
// uuid is used as transaction id
|
||||
uuidWithHyphen := uuid.New()
|
||||
uuid := strings.Replace(uuidWithHyphen.String(), "-", "", -1)
|
||||
// The trace plane's tables, and only the ones that exist. The three v2-era
|
||||
// names that used to sit here — error_index_v2, usage_explorer and
|
||||
// dependency_graph_minutes_v2 — went with o11y_traces. ALTER TABLE names one
|
||||
// table per statement, so one dead name did not degrade this run, it FAILED
|
||||
// it: setting retention on traces stopped working for every live table too.
|
||||
tableNames := []string{
|
||||
r.TraceDB + "." + r.traceTableName,
|
||||
r.TraceDB + "." + r.traceResourceTableV3,
|
||||
r.TraceDB + "." + o11yErrorIndexTable,
|
||||
r.TraceDB + "." + o11yUsageExplorerTable,
|
||||
r.TraceDB + "." + defaultDependencyGraphTable,
|
||||
r.TraceDB + "." + r.traceSummaryTable,
|
||||
r.TraceDB + "." + r.spanAttributesKeysTable,
|
||||
}
|
||||
@@ -2135,12 +2169,11 @@ func (r *DatastoreReader) GetTTL(ctx context.Context, orgID string, ttlParams *r
|
||||
|
||||
switch ttlParams.Type {
|
||||
case retentiontypes.TraceTTL:
|
||||
// Same list as setTTLTraces, and it has to stay the same list: this one
|
||||
// READS the status of what that one WROTE.
|
||||
tableNameArray := []string{
|
||||
r.TraceDB + "." + r.traceTableName,
|
||||
r.TraceDB + "." + r.traceResourceTableV3,
|
||||
r.TraceDB + "." + o11yErrorIndexTable,
|
||||
r.TraceDB + "." + o11yUsageExplorerTable,
|
||||
r.TraceDB + "." + defaultDependencyGraphTable,
|
||||
r.TraceDB + "." + r.traceSummaryTable,
|
||||
}
|
||||
tableNameArray = getLocalTableNameArray(tableNameArray)
|
||||
|
||||
@@ -121,7 +121,7 @@ func TestPrepareQuery(t *testing.T) {
|
||||
{
|
||||
name: "query text produces template exec error",
|
||||
postData: &model.DashboardVars{
|
||||
Query: "SELECT durationNano from o11y_traces.o11y_index_v2 WHERE id = {{if .X}}1{{else}}2{{else}}3{{end}}",
|
||||
Query: "SELECT durationNano from event.span WHERE id = {{if .X}}1{{else}}2{{else}}3{{end}}",
|
||||
},
|
||||
expectedErr: true,
|
||||
errMsg: "expected end; found {{else}}",
|
||||
|
||||
@@ -2,8 +2,18 @@ package kafka
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
// spanTable is the one table these thirteen templates read. Every one of them
|
||||
// spelled “ + spanTable + “ — a database HIP-0132 dropped
|
||||
// and a table whose successor is event.span — so the Kafka/messaging views
|
||||
// answered `Code: 81 ... UNKNOWN_DATABASE` on every panel. Thirteen copies of a
|
||||
// name is thirteen chances to miss one; it is spelled here and interpolated.
|
||||
var spanTable = telemetryplane.DBName + "." + telemetrytraces.SpanTableName
|
||||
|
||||
func generateConsumerSQL(start, end int64, topic, partition, consumerGroup, queueType string) string {
|
||||
timeRange := (end - start) / 1000000000
|
||||
tsBucketStart := (start / 1000000000) - 1800
|
||||
@@ -16,7 +26,7 @@ WITH consumer_query AS (
|
||||
COUNT(*) AS total_requests,
|
||||
sumIf(1, status_code = 2) AS error_count,
|
||||
avg(CASE WHEN has(attributes_number, 'messaging.message.body.size') THEN attributes_number['messaging.message.body.size'] ELSE NULL END) AS avg_msg_size
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -56,7 +66,7 @@ WITH partition_query AS (
|
||||
count(*) AS total_requests,
|
||||
attributes_string['messaging.destination.name'] AS topic,
|
||||
attributes_string['messaging.destination.partition.id'] AS partition
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -93,7 +103,7 @@ WITH consumer_pl AS (
|
||||
quantile(0.99)(durationNano) / 1000000 AS p99,
|
||||
COUNT(*) AS total_requests,
|
||||
sumIf(1, status_code = 2) AS error_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -133,7 +143,7 @@ WITH producer_latency AS (
|
||||
attributes_string['messaging.destination.name'] AS topic,
|
||||
COUNT(*) AS total_requests,
|
||||
sumIf(1, status_code = 2) AS error_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -168,7 +178,7 @@ WITH consumer_latency AS (
|
||||
attributes_string['messaging.destination.partition.id'] AS partition,
|
||||
COUNT(*) AS total_requests,
|
||||
sumIf(1, status_code = 2) AS error_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -206,7 +216,7 @@ WITH consumer_latency AS (
|
||||
COUNT(*) AS total_requests,
|
||||
sumIf(1, status_code = 2) AS error_count,
|
||||
SUM(attributes_number['messaging.message.body.size']) AS total_bytes
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -244,7 +254,7 @@ WITH consumer_latency AS (
|
||||
attributes_string['messaging.destination.partition.id'] AS partition,
|
||||
COUNT(*) AS total_requests,
|
||||
sumIf(1, status_code = 2) AS error_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -281,9 +291,9 @@ WITH trace_data AS (
|
||||
p.durationNano AS durationNano,
|
||||
(toUnixTimestamp64Nano(c.timestamp) - toUnixTimestamp64Nano(p.timestamp)) + p.durationNano AS time_difference
|
||||
FROM
|
||||
o11y_traces.distributed_o11y_index_v3 p
|
||||
`+spanTable+` p
|
||||
GLOBAL INNER JOIN
|
||||
o11y_traces.distributed_o11y_index_v3 c
|
||||
`+spanTable+` c
|
||||
ON p.trace_id = c.trace_id
|
||||
AND c.parent_span_id = p.span_id
|
||||
WHERE
|
||||
@@ -329,7 +339,7 @@ WITH producer_query AS (
|
||||
quantile(0.99)(durationNano) / 1000000 AS p99,
|
||||
count(*) AS total_count,
|
||||
sumIf(1, status_code = 2) AS error_count
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -365,7 +375,7 @@ SELECT
|
||||
resources_string['service.instance.id'] AS service_instance_id,
|
||||
resource_string_service$$name AS service_name,
|
||||
count(*) / %d AS throughput
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -392,7 +402,7 @@ SELECT
|
||||
COUNT(IF(has(attributes_string, 'messaging.destination.name'), 1, NULL)) = 0 AS destination,
|
||||
COUNT(IF(has(attributes_string, 'messaging.destination.partition.id'), 1, NULL)) = 0 AS partition
|
||||
FROM
|
||||
o11y_traces.distributed_o11y_index_v3
|
||||
`+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
@@ -416,7 +426,7 @@ SELECT
|
||||
COUNT(IF(has(attributes_number, 'messaging.message.body.size'), 1, NULL)) = 0 AS bodysize,
|
||||
COUNT(IF(has(attributes_string, 'messaging.client_id'), 1, NULL)) = 0 AS clientid,
|
||||
COUNT(IF(has(resources_string, 'service.instance.id'), 1, NULL)) = 0 AS instanceid
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
timestamp >= '%d'
|
||||
AND timestamp <= '%d'
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package kafka
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
// This package had NO test at all, and thirteen SQL templates in it named
|
||||
// `o11y_traces` — a database HIP-0132 dropped. Every messaging/Kafka panel
|
||||
// answered `Code: 81 UNKNOWN_DATABASE` and nothing in the tree noticed, because
|
||||
// nothing in the tree ever looked at the SQL these functions produce.
|
||||
//
|
||||
// This is that look. It does not pin the whole query — a golden that pins 40
|
||||
// lines of SQL fails on every unrelated edit and gets regenerated without being
|
||||
// read. It pins the ONE thing that was wrong and is invisible until production:
|
||||
// which database and table the read names.
|
||||
func TestEveryGeneratedQueryNamesThePlane(t *testing.T) {
|
||||
const start, end = int64(1700000000000000000), int64(1700003600000000000)
|
||||
|
||||
queries := map[string]string{
|
||||
"consumer": generateConsumerSQL(start, end, "topic", "0", "group", "kafka"),
|
||||
"partitionLatency": generatePartitionLatencySQL(start, end, "kafka"),
|
||||
"consumerPartitionLatency": generateConsumerPartitionLatencySQL(start, end, "topic", "0", "kafka"),
|
||||
"producerPartitionThroughput": generateProducerPartitionThroughputSQL(start, end, "kafka"),
|
||||
"producerTopicLatency": generateProducerTopicLatencySQL(start, end, "topic", "svc", "kafka"),
|
||||
"consumerLatency": generateConsumerLatencySQL(start, end, "kafka"),
|
||||
"consumerServiceLatency": generateConsumerServiceLatencySQL(start, end, "topic", "svc", "kafka"),
|
||||
"producerConsumerEval": generateProducerConsumerEvalSQL(start, end, "kafka", 100),
|
||||
"producer": generateProducerSQL(start, end, "topic", "0", "kafka"),
|
||||
"networkLatencyThroughput": generateNetworkLatencyThroughputSQL(start, end, "group", "0", "kafka"),
|
||||
}
|
||||
|
||||
wantTable := telemetryplane.DBName + "." + telemetrytraces.SpanTableName
|
||||
|
||||
for name, sql := range queries {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
require.NotEmpty(t, sql)
|
||||
assert.Containsf(t, sql, wantTable,
|
||||
"query must read the event plane's span table, got:\n%s", sql)
|
||||
for _, gone := range []string{"o11y_traces", "o11y_logs", "o11y_metrics"} {
|
||||
assert.NotContainsf(t, sql, gone,
|
||||
"query names %s, a database HIP-0132 dropped", gone)
|
||||
}
|
||||
// A qualifier with no database is the other way to reach the wrong
|
||||
// plane: it resolves against the connection's default database.
|
||||
assert.Falsef(t, strings.Contains(sql, " FROM "+telemetrytraces.SpanTableName+" "),
|
||||
"query reads an UNQUALIFIED table; it must name the plane explicitly")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,14 @@ import (
|
||||
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
format "github.com/hanzoai/o11y/pkg/query-service/utils"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
// spanTable — see the kafka sibling. o11y_traces was dropped by HIP-0132;
|
||||
// distributed_o11y_index_v3 IS event.span.
|
||||
var spanTable = telemetryplane.DBName + "." + telemetrytraces.SpanTableName
|
||||
|
||||
// generateOverviewSQL builds the Datastore SQL query with optional filters.
|
||||
// If a filter slice is empty, the query does not constrain on that field.
|
||||
func generateOverviewSQL(start, end int64, item []v3.FilterItem) string {
|
||||
@@ -65,7 +71,7 @@ WITH
|
||||
) AS destination,
|
||||
durationNano,
|
||||
status_code
|
||||
FROM o11y_traces.distributed_o11y_index_v3
|
||||
FROM `+spanTable+`
|
||||
WHERE
|
||||
ts_bucket_start >= toDateTime64(%f, 9)
|
||||
AND ts_bucket_start <= toDateTime64(%f, 9)
|
||||
|
||||
@@ -7,8 +7,15 @@ import (
|
||||
"github.com/hanzoai/o11y/pkg/query-service/constants"
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
"github.com/hanzoai/o11y/pkg/query-service/utils"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
)
|
||||
|
||||
// The v3 logs builder read o11y_logs.distributed_logs — a database HIP-0132
|
||||
// dropped and a table whose successor is event.log. Spelled once, here, and
|
||||
// resolved from pkg/telemetryplane like every other reader.
|
||||
const logsFrom = telemetryplane.DBName + "." + telemetrylogs.LogTableName
|
||||
|
||||
var AggregateOperatorToPercentile = map[v3.AggregateOperator]float64{
|
||||
v3.AggregateOperatorP05: 0.05,
|
||||
v3.AggregateOperatorP10: 0.10,
|
||||
@@ -284,7 +291,7 @@ func buildLogsQuery(panelType v3.PanelType, start, end, step int64, mq *v3.Build
|
||||
queryTmpl =
|
||||
queryTmpl + selectLabels +
|
||||
" %s as value " +
|
||||
"from o11y_logs.distributed_logs " +
|
||||
"from " + logsFrom + " " +
|
||||
"where " + timeFilter + "%s" +
|
||||
"%s%s" +
|
||||
"%s"
|
||||
@@ -356,7 +363,7 @@ func buildLogsQuery(panelType v3.PanelType, start, end, step int64, mq *v3.Build
|
||||
query := fmt.Sprintf(queryTmpl, op, filterSubQuery, groupBy, having, orderBy)
|
||||
return query, nil
|
||||
case v3.AggregateOperatorNoOp:
|
||||
queryTmpl := constants.LogsSQLSelect + "from o11y_logs.distributed_logs where %s%s order by %s"
|
||||
queryTmpl := constants.LogsSQLSelect + "from " + logsFrom + " where %s%s order by %s"
|
||||
query := fmt.Sprintf(queryTmpl, timeFilter, filterSubQuery, orderBy)
|
||||
return query, nil
|
||||
default:
|
||||
@@ -372,7 +379,7 @@ func buildLogsLiveTailQuery(mq *v3.BuilderQuery) (string, error) {
|
||||
|
||||
switch mq.AggregateOperator {
|
||||
case v3.AggregateOperatorNoOp:
|
||||
query := constants.LogsSQLSelect + "from o11y_logs.distributed_logs where "
|
||||
query := constants.LogsSQLSelect + "from " + logsFrom + " where "
|
||||
if len(filterSubQuery) > 0 {
|
||||
query = query + filterSubQuery + " AND "
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ var testBuildLogsQueryData = []struct {
|
||||
Expression: "A",
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) group by ts order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) group by ts order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate count on a attribute",
|
||||
@@ -380,7 +380,7 @@ var testBuildLogsQueryData = []struct {
|
||||
Expression: "A",
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'user_name') group by ts order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'user_name') group by ts order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate count on a with filter",
|
||||
@@ -398,7 +398,7 @@ var testBuildLogsQueryData = []struct {
|
||||
Expression: "A",
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND attributes_float64_value[indexOf(attributes_float64_key, 'bytes')] > 100.000000 AND has(attributes_string_key, 'user_name') group by ts order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND attributes_float64_value[indexOf(attributes_float64_key, 'bytes')] > 100.000000 AND has(attributes_string_key, 'user_name') group by ts order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate count distinct and order by value",
|
||||
@@ -414,7 +414,7 @@ var testBuildLogsQueryData = []struct {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "#O11Y_VALUE", Order: "ASC"}},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(`attribute_string_name`))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND `attribute_string_name_exists`=true group by ts order by value ASC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(`attribute_string_name`))) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND `attribute_string_name_exists`=true group by ts order by value ASC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate count distinct on non selected field",
|
||||
@@ -429,7 +429,7 @@ var testBuildLogsQueryData = []struct {
|
||||
Expression: "A",
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by ts order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by ts order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate count distinct on non selected field containing dot",
|
||||
@@ -447,7 +447,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'host.name')] as `host.name`, " +
|
||||
"toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'method.name')]))) as value from o11y_logs.distributed_logs " +
|
||||
"toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'method.name')]))) as value from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'host.name') AND has(attributes_string_key, 'method.name') " +
|
||||
"group by `host.name`,ts order by `host.name` ASC",
|
||||
},
|
||||
@@ -468,7 +468,7 @@ var testBuildLogsQueryData = []struct {
|
||||
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, `attribute_string_host$$name` as `host.name`, toFloat64(count(distinct(`attribute_string_method$$name`))) as value" +
|
||||
" from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
" from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND `attribute_string_host$$name_exists`=true AND `attribute_string_method$$name_exists`=true " +
|
||||
"group by `host.name`,ts " +
|
||||
"order by `host.name` ASC",
|
||||
@@ -495,7 +495,7 @@ var testBuildLogsQueryData = []struct {
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"toFloat64(count(distinct(`attribute_string_name`))) as value from o11y_logs.distributed_logs " +
|
||||
"toFloat64(count(distinct(`attribute_string_name`))) as value from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND resources_string_value[indexOf(resources_string_key, 'x')] != 'abc' " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
@@ -526,7 +526,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"resources_string_value[indexOf(resources_string_key, 'x')] as `x`, " +
|
||||
"toFloat64(count(distinct(`attribute_string_name`))) as value from o11y_logs.distributed_logs " +
|
||||
"toFloat64(count(distinct(`attribute_string_name`))) as value from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND resources_string_value[indexOf(resources_string_key, 'x')] != 'abc' " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
@@ -557,7 +557,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"avg(attributes_float64_value[indexOf(attributes_float64_key, 'bytes')]) as value " +
|
||||
"from o11y_logs.distributed_logs " +
|
||||
"from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
@@ -587,7 +587,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"sum(`attribute_float64_bytes`) as value " +
|
||||
"from o11y_logs.distributed_logs " +
|
||||
"from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
@@ -617,7 +617,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"min(`attribute_float64_bytes`) as value " +
|
||||
"from o11y_logs.distributed_logs " +
|
||||
"from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
@@ -647,7 +647,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"max(`attribute_float64_bytes`) as value " +
|
||||
"from o11y_logs.distributed_logs " +
|
||||
"from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
@@ -674,7 +674,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts," +
|
||||
" attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"quantile(0.05)(`attribute_float64_bytes`) as value " +
|
||||
"from o11y_logs.distributed_logs " +
|
||||
"from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
"AND `attribute_float64_bytes_exists`=true " +
|
||||
@@ -698,7 +698,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`" +
|
||||
", sum(`attribute_float64_bytes`)/60.000000 as value from o11y_logs.distributed_logs " +
|
||||
", sum(`attribute_float64_bytes`)/60.000000 as value from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
"AND `attribute_float64_bytes_exists`=true " +
|
||||
@@ -722,7 +722,7 @@ var testBuildLogsQueryData = []struct {
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`" +
|
||||
", count(attributes_float64_value[indexOf(attributes_float64_key, 'bytes')])/60.000000 as value " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
"AND has(attributes_float64_key, 'bytes') " +
|
||||
"group by `method`,ts " +
|
||||
@@ -747,7 +747,7 @@ var testBuildLogsQueryData = []struct {
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, " +
|
||||
"attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, " +
|
||||
"sum(attributes_float64_value[indexOf(attributes_float64_key, 'bytes')])/60.000000 as value " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) " +
|
||||
"AND has(attributes_string_key, 'method') " +
|
||||
"AND has(attributes_float64_key, 'bytes') " +
|
||||
"group by `method`,ts " +
|
||||
@@ -771,7 +771,7 @@ var testBuildLogsQueryData = []struct {
|
||||
"CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool," +
|
||||
"CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string," +
|
||||
"CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) order by timestamp DESC",
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) order by timestamp DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test Noop order by custom",
|
||||
@@ -791,7 +791,7 @@ var testBuildLogsQueryData = []struct {
|
||||
"CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool," +
|
||||
"CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string," +
|
||||
"CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) order by `attribute_string_method` ASC",
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) order by `attribute_string_method` ASC",
|
||||
},
|
||||
{
|
||||
Name: "Test Noop with filter",
|
||||
@@ -812,7 +812,7 @@ var testBuildLogsQueryData = []struct {
|
||||
"CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool," +
|
||||
"CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string," +
|
||||
"CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND severity_number != 0 order by timestamp DESC",
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND severity_number != 0 order by timestamp DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate with having clause",
|
||||
@@ -834,7 +834,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test aggregate with having clause and filters",
|
||||
@@ -860,7 +860,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test top level key",
|
||||
@@ -886,7 +886,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND lower(body) LIKE lower('%test%') AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND lower(body) LIKE lower('%test%') AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "Test attribute with same name as top level key",
|
||||
@@ -912,7 +912,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'body')] ILIKE '%test%' AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'body')] ILIKE '%test%' AND has(attributes_string_key, 'name') group by ts having value > 10 order by value DESC",
|
||||
},
|
||||
|
||||
// Tests for table panel type
|
||||
@@ -928,7 +928,7 @@ var testBuildLogsQueryData = []struct {
|
||||
Expression: "A",
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) order by value DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "TABLE: Test count with groupBy",
|
||||
@@ -945,7 +945,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by `name` order by value DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by `name` order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "TABLE: Test rate with groupBy",
|
||||
@@ -962,7 +962,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, count()/97.000000 as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by `name` order by value DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, count()/97.000000 as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by `name` order by value DESC",
|
||||
},
|
||||
{
|
||||
Name: "TABLE: Test count with groupBy, orderBy",
|
||||
@@ -982,7 +982,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by `name` order by `name` DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND has(attributes_string_key, 'name') group by `name` order by `name` DESC",
|
||||
},
|
||||
{
|
||||
Name: "TABLE: Test count with JSON Filter, groupBy, orderBy",
|
||||
@@ -1016,7 +1016,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND lower(body) like lower('%message%') AND JSON_EXISTS(body, '$.\"message\"') AND JSON_VALUE(body, '$.\"message\"') ILIKE '%a%' AND has(attributes_string_key, 'name') group by `name` order by `name` DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND lower(body) like lower('%message%') AND JSON_EXISTS(body, '$.\"message\"') AND JSON_VALUE(body, '$.\"message\"') ILIKE '%a%' AND has(attributes_string_key, 'name') group by `name` order by `name` DESC",
|
||||
},
|
||||
{
|
||||
Name: "TABLE: Test count with JSON Filter Array, groupBy, orderBy",
|
||||
@@ -1050,7 +1050,7 @@ var testBuildLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND lower(body) like lower('%requestor_list%') AND lower(body) like lower('%index_service%') AND has(JSONExtract(JSON_QUERY(body, '$.\"requestor_list\"[*]'), 'Array(String)'), 'index_service') AND has(attributes_string_key, 'name') group by `name` order by `name` DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND lower(body) like lower('%requestor_list%') AND lower(body) like lower('%index_service%') AND has(JSONExtract(JSON_QUERY(body, '$.\"requestor_list\"[*]'), 'Array(String)'), 'index_service') AND has(attributes_string_key, 'name') group by `name` order by `name` DESC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1233,7 +1233,7 @@ var testPrepLogsQueryData = []struct {
|
||||
GroupBy: []v3.AttributeKey{{Key: "method", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag}},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT `method` from (SELECT attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') group by `method` order by value DESC) LIMIT 10",
|
||||
ExpectedQuery: "SELECT `method` from (SELECT attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') group by `method` order by value DESC) LIMIT 10",
|
||||
Options: v3.QBOptions{GraphLimitQtype: constants.FirstQueryGraphLimit},
|
||||
},
|
||||
{
|
||||
@@ -1256,7 +1256,7 @@ var testPrepLogsQueryData = []struct {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: constants.O11yOrderByValue, Order: "ASC"}},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT `method` from (SELECT attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') group by `method` order by value ASC) LIMIT 10",
|
||||
ExpectedQuery: "SELECT `method` from (SELECT attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') group by `method` order by value ASC) LIMIT 10",
|
||||
Options: v3.QBOptions{GraphLimitQtype: constants.FirstQueryGraphLimit},
|
||||
},
|
||||
{
|
||||
@@ -1279,7 +1279,7 @@ var testPrepLogsQueryData = []struct {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "method", Order: "ASC"}},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT `method` from (SELECT attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') group by `method` order by `method` ASC) LIMIT 10",
|
||||
ExpectedQuery: "SELECT `method` from (SELECT attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') group by `method` order by `method` ASC) LIMIT 10",
|
||||
Options: v3.QBOptions{GraphLimitQtype: constants.FirstQueryGraphLimit},
|
||||
},
|
||||
{
|
||||
@@ -1301,7 +1301,7 @@ var testPrepLogsQueryData = []struct {
|
||||
Limit: 2,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') AND (`method`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `method`,ts order by value DESC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') AND (`method`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `method`,ts order by value DESC",
|
||||
Options: v3.QBOptions{GraphLimitQtype: constants.SecondQueryGraphLimit},
|
||||
},
|
||||
{
|
||||
@@ -1324,7 +1324,7 @@ var testPrepLogsQueryData = []struct {
|
||||
Limit: 2,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') AND (`method`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `method`,ts order by `method` ASC",
|
||||
ExpectedQuery: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string_value[indexOf(attributes_string_key, 'method')] as `method`, toFloat64(count(distinct(attributes_string_value[indexOf(attributes_string_key, 'name')]))) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND has(attributes_string_key, 'method') AND has(attributes_string_key, 'name') AND (`method`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `method`,ts order by `method` ASC",
|
||||
Options: v3.QBOptions{GraphLimitQtype: constants.SecondQueryGraphLimit},
|
||||
},
|
||||
// Live tail
|
||||
@@ -1344,7 +1344,7 @@ var testPrepLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND ",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' AND ",
|
||||
Options: v3.QBOptions{IsLivetailQuery: true},
|
||||
},
|
||||
{
|
||||
@@ -1363,7 +1363,7 @@ var testPrepLogsQueryData = []struct {
|
||||
},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where attributes_string_value[indexOf(attributes_string_key, 'method')] ILIKE '%GET%' AND ",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where attributes_string_value[indexOf(attributes_string_key, 'method')] ILIKE '%GET%' AND ",
|
||||
Options: v3.QBOptions{IsLivetailQuery: true},
|
||||
},
|
||||
{
|
||||
@@ -1379,7 +1379,7 @@ var testPrepLogsQueryData = []struct {
|
||||
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where ",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where ",
|
||||
Options: v3.QBOptions{IsLivetailQuery: true},
|
||||
},
|
||||
{
|
||||
@@ -1395,7 +1395,7 @@ var testPrepLogsQueryData = []struct {
|
||||
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by value DESC",
|
||||
ExpectedQuery: "SELECT now() as ts, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by value DESC",
|
||||
Options: v3.QBOptions{},
|
||||
},
|
||||
{
|
||||
@@ -1412,7 +1412,7 @@ var testPrepLogsQueryData = []struct {
|
||||
Limit: 10,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT now() as ts, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by value DESC LIMIT 10",
|
||||
ExpectedQuery: "SELECT now() as ts, toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by value DESC LIMIT 10",
|
||||
Options: v3.QBOptions{},
|
||||
},
|
||||
{
|
||||
@@ -1443,7 +1443,7 @@ var testPrepLogsQueryData = []struct {
|
||||
"attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as " +
|
||||
"attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string," +
|
||||
"CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND id < 'logid' order by " +
|
||||
"from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND id < 'logid' order by " +
|
||||
"timestamp DESC LIMIT 100",
|
||||
},
|
||||
{
|
||||
@@ -1474,7 +1474,7 @@ var testPrepLogsQueryData = []struct {
|
||||
"attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as " +
|
||||
"attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string," +
|
||||
"CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope " +
|
||||
"from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' order by " +
|
||||
"from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND attributes_string_value[indexOf(attributes_string_key, 'method')] = 'GET' order by " +
|
||||
"resources_string_value[indexOf(resources_string_key, 'mycolumn')] DESC LIMIT 100 OFFSET 100",
|
||||
},
|
||||
}
|
||||
@@ -1520,7 +1520,7 @@ var testPrepLogsQueryLimitOffsetData = []struct {
|
||||
PageSize: 5,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by timestamp desc LIMIT 1",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by timestamp desc LIMIT 1",
|
||||
},
|
||||
{
|
||||
Name: "Test limit greater than pageSize - order by ts",
|
||||
@@ -1541,7 +1541,7 @@ var testPrepLogsQueryLimitOffsetData = []struct {
|
||||
PageSize: 10,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by timestamp desc LIMIT 10",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by timestamp desc LIMIT 10",
|
||||
},
|
||||
{
|
||||
Name: "Test limit less than pageSize - order by custom",
|
||||
@@ -1560,7 +1560,7 @@ var testPrepLogsQueryLimitOffsetData = []struct {
|
||||
PageSize: 5,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by attributes_string_value[indexOf(attributes_string_key, 'method')] desc LIMIT 1 OFFSET 0",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) order by attributes_string_value[indexOf(attributes_string_key, 'method')] desc LIMIT 1 OFFSET 0",
|
||||
},
|
||||
{
|
||||
Name: "Test limit greater than pageSize - order by custom",
|
||||
@@ -1581,7 +1581,7 @@ var testPrepLogsQueryLimitOffsetData = []struct {
|
||||
PageSize: 50,
|
||||
},
|
||||
TableName: "logs",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from o11y_logs.distributed_logs where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by attributes_string_value[indexOf(attributes_string_key, 'method')] desc LIMIT 50 OFFSET 50",
|
||||
ExpectedQuery: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body,CAST((attributes_string_key, attributes_string_value), 'Map(String, String)') as attributes_string,CAST((attributes_int64_key, attributes_int64_value), 'Map(String, Int64)') as attributes_int64,CAST((attributes_float64_key, attributes_float64_value), 'Map(String, Float64)') as attributes_float64,CAST((attributes_bool_key, attributes_bool_value), 'Map(String, Bool)') as attributes_bool,CAST((resources_string_key, resources_string_value), 'Map(String, String)') as resources_string,CAST((scope_string_key, scope_string_value), 'Map(String, String)') as scope from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by attributes_string_value[indexOf(attributes_string_key, 'method')] desc LIMIT 50 OFFSET 50",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/hanzoai/o11y/pkg/query-service/constants"
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
"github.com/hanzoai/o11y/pkg/query-service/utils"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
)
|
||||
|
||||
var logOperators = map[v3.FilterOperator]string{
|
||||
@@ -42,11 +44,16 @@ var skipExistsFilter = map[v3.FilterOperator]struct{}{
|
||||
}
|
||||
|
||||
const (
|
||||
BODY = "body"
|
||||
DISTRIBUTED_LOGS_V2 = "distributed_logs_v2"
|
||||
DISTRIBUTED_LOGS_V2_RESOURCE = "distributed_logs_v2_resource"
|
||||
DB_NAME = "o11y_logs"
|
||||
NANOSECOND = 1000000000
|
||||
BODY = "body"
|
||||
|
||||
// distributed_logs_v2 IS event.log and distributed_logs_v2_resource IS
|
||||
// event.log_resource; o11y_logs was dropped by HIP-0132. Aliases, not
|
||||
// spellings — see pkg/telemetryplane.
|
||||
DISTRIBUTED_LOGS_V2 = telemetrylogs.LogTableName
|
||||
DISTRIBUTED_LOGS_V2_RESOURCE = telemetrylogs.LogResourceTableName
|
||||
DB_NAME = telemetryplane.DBName
|
||||
|
||||
NANOSECOND = 1000000000
|
||||
)
|
||||
|
||||
func getDatastoreLogsColumnDataType(columnDataType v3.AttributeKeyDataType) string {
|
||||
@@ -308,7 +315,7 @@ func generateAggregateClause(panelType v3.PanelType, start, end int64, aggOp v3.
|
||||
having string,
|
||||
orderBy string,
|
||||
) (string, error) {
|
||||
queryTmpl := " %s as value from o11y_logs." + DISTRIBUTED_LOGS_V2 +
|
||||
queryTmpl := " %s as value from " + DB_NAME + "." + DISTRIBUTED_LOGS_V2 +
|
||||
" where " + timeFilter + "%s" +
|
||||
"%s%s" +
|
||||
"%s"
|
||||
@@ -405,7 +412,7 @@ func buildLogsQuery(panelType v3.PanelType, start, end, step int64, mq *v3.Build
|
||||
if mq.AggregateOperator == v3.AggregateOperatorNoOp {
|
||||
// with noop any filter or different order by other than ts will use new table
|
||||
sqlSelect := constants.LogsSQLSelectV2
|
||||
queryTmpl := sqlSelect + "from o11y_logs.%s where %s%s order by %s"
|
||||
queryTmpl := sqlSelect + "from " + DB_NAME + ".%s where %s%s order by %s"
|
||||
query := fmt.Sprintf(queryTmpl, DISTRIBUTED_LOGS_V2, timeFilter, filterSubQuery, orderBy)
|
||||
return query, nil
|
||||
// ---- NOOP ends here ----
|
||||
@@ -488,7 +495,7 @@ func buildLogsLiveTailQuery(mq *v3.BuilderQuery) (string, error) {
|
||||
// the reader will add the timestamp and id filters
|
||||
switch mq.AggregateOperator {
|
||||
case v3.AggregateOperatorNoOp:
|
||||
query := constants.LogsSQLSelectV2 + "from o11y_logs." + DISTRIBUTED_LOGS_V2 + " where "
|
||||
query := constants.LogsSQLSelectV2 + "from " + DB_NAME + "." + DISTRIBUTED_LOGS_V2 + " where "
|
||||
if len(filterSubQuery) > 0 {
|
||||
query = query + filterSubQuery + " AND "
|
||||
}
|
||||
|
||||
@@ -692,7 +692,7 @@ func Test_generateAggregateClause(t *testing.T) {
|
||||
having: "",
|
||||
orderBy: " order by `user_name` desc",
|
||||
},
|
||||
want: " count(test)/60.000000 as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
||||
want: " count(test)/60.000000 as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
||||
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['service.name'] = 'test' " +
|
||||
"group by `user_name` order by `user_name` desc",
|
||||
},
|
||||
@@ -709,7 +709,7 @@ func Test_generateAggregateClause(t *testing.T) {
|
||||
having: " having value > 10",
|
||||
orderBy: " order by `user_name` desc",
|
||||
},
|
||||
want: " count(test)/60.000000 as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
||||
want: " count(test)/60.000000 as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
||||
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['service.name'] = 'test' group by `user_name` having value > 10 order by " +
|
||||
"`user_name` desc",
|
||||
},
|
||||
@@ -728,7 +728,7 @@ func Test_generateAggregateClause(t *testing.T) {
|
||||
having: "",
|
||||
orderBy: " order by `user_name` desc",
|
||||
},
|
||||
want: " count(test)/3600.000000 as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
||||
want: " count(test)/3600.000000 as value from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND " +
|
||||
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['service.name'] = 'test' " +
|
||||
"group by `user_name` order by `user_name` desc",
|
||||
},
|
||||
@@ -799,7 +799,7 @@ func Test_buildLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "SELECT attributes_string['user_name'] as `user_name`, toFloat64(count(*)) as value from o11y_logs.distributed_logs_v2 " +
|
||||
want: "SELECT attributes_string['user_name'] as `user_name`, toFloat64(count(*)) as value from event.log " +
|
||||
"where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') AND mapContains(attributes_string, 'user_name') " +
|
||||
"group by `user_name` order by `user_name` desc",
|
||||
@@ -835,7 +835,7 @@ func Test_buildLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string " +
|
||||
"from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_string['service.name'] = 'test' AND mapContains(attributes_string, 'service.name') order by timestamp desc",
|
||||
},
|
||||
{
|
||||
@@ -890,9 +890,9 @@ func Test_buildLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, resources_string['host'] as `host`, avg(attributes_number['duration']) as value " +
|
||||
"from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"from event.log where (timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_number['duration'] > 1000.000000 AND mapContains(attributes_number, 'duration') AND mapContains(attributes_number, 'duration') AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.log_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) " +
|
||||
"AND simpleJSONExtractString(labels, 'service.name') = 'test' AND labels like '%service.name\":\"test%' AND ( (simpleJSONHas(labels, 'host') AND labels like '%host%') ))) " +
|
||||
"group by `host`,ts order by `host` desc",
|
||||
},
|
||||
@@ -960,10 +960,10 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "SELECT attributes_string['name'] as `name`, resources_string['host'] as `host`, toFloat64(count(*)) as value from o11y_logs.distributed_logs_v2 where " +
|
||||
want: "SELECT attributes_string['name'] as `name`, resources_string['host'] as `host`, toFloat64(count(*)) as value from event.log where " +
|
||||
"(timestamp >= 1680066360726210000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND lower(body) like lower('%requestor_list%') " +
|
||||
"AND lower(body) like lower('%index_service%') AND has(JSONExtract(JSON_QUERY(body, '$.\"requestor_list\"[*]'), 'Array(String)'), 'index_service') AND mapContains(attributes_string, 'name') AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.log_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
||||
"( (simpleJSONHas(labels, 'host') AND labels like '%host%') ))) group by `name`,`host` order by `name` DESC",
|
||||
},
|
||||
{
|
||||
@@ -989,10 +989,10 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
},
|
||||
options: v3.QBOptions{GraphLimitQtype: constants.FirstQueryGraphLimit},
|
||||
},
|
||||
want: "SELECT `user` from (SELECT attributes_string['user'] as `user`, toFloat64(count(distinct(attributes_string['name']))) as value from o11y_logs.distributed_logs_v2 " +
|
||||
want: "SELECT `user` from (SELECT attributes_string['user'] as `user`, toFloat64(count(distinct(attributes_string['name']))) as value from event.log " +
|
||||
"where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['method'] = 'GET' " +
|
||||
"AND mapContains(attributes_string, 'method') AND mapContains(attributes_string, 'user') AND mapContains(attributes_string, 'name') AND (resource_fingerprint GLOBAL IN " +
|
||||
"(SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'app' " +
|
||||
"(SELECT fingerprint FROM event.log_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'app' " +
|
||||
"AND labels like '%service.name\":\"app%')) group by `user` order by value DESC) LIMIT 10",
|
||||
},
|
||||
{
|
||||
@@ -1019,9 +1019,9 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
options: v3.QBOptions{GraphLimitQtype: constants.SecondQueryGraphLimit},
|
||||
},
|
||||
want: "SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_string['user'] as `user`, toFloat64(count(distinct(attributes_string['name']))) as value " +
|
||||
"from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND " +
|
||||
"from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND " +
|
||||
"attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND mapContains(attributes_string, 'user') AND mapContains(attributes_string, 'name') AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.log_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
||||
"simpleJSONExtractString(labels, 'service.name') = 'app' AND labels like '%service.name\":\"app%')) AND (`user`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `user`,ts order by value DESC",
|
||||
},
|
||||
{
|
||||
@@ -1044,7 +1044,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
options: v3.QBOptions{IsLivetailQuery: true},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string " +
|
||||
"from o11y_logs.distributed_logs_v2 where attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND ",
|
||||
"from event.log where attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND ",
|
||||
},
|
||||
{
|
||||
name: "Live Tail Query with resource attribute",
|
||||
@@ -1067,8 +1067,8 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
options: v3.QBOptions{IsLivetailQuery: true},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string from " +
|
||||
"o11y_logs.distributed_logs_v2 where attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE simpleJSONExtractString(lower(labels), 'service.name') LIKE '%app%' AND lower(labels) like '%service.name%app%' AND ",
|
||||
"event.log where attributes_string['method'] = 'GET' AND mapContains(attributes_string, 'method') AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.log_resource WHERE simpleJSONExtractString(lower(labels), 'service.name') LIKE '%app%' AND lower(labels) like '%service.name%app%' AND ",
|
||||
},
|
||||
{
|
||||
name: "Live Tail Query W/O filter",
|
||||
@@ -1087,7 +1087,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
options: v3.QBOptions{IsLivetailQuery: true},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string " +
|
||||
"from o11y_logs.distributed_logs_v2 where ",
|
||||
"from event.log where ",
|
||||
},
|
||||
{
|
||||
name: "Table query with limit",
|
||||
@@ -1105,7 +1105,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
Limit: 10,
|
||||
},
|
||||
},
|
||||
want: "SELECT toFloat64(count(*)) as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) order by value DESC LIMIT 10",
|
||||
want: "SELECT toFloat64(count(*)) as value from event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) order by value DESC LIMIT 10",
|
||||
},
|
||||
{
|
||||
name: "Test limit less than pageSize - order by ts",
|
||||
@@ -1127,7 +1127,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string from " +
|
||||
"o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"order by timestamp desc LIMIT 1 OFFSET 0",
|
||||
},
|
||||
{
|
||||
@@ -1152,7 +1152,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string from " +
|
||||
"o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by timestamp desc LIMIT 10 OFFSET 10",
|
||||
},
|
||||
{
|
||||
@@ -1175,7 +1175,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string from " +
|
||||
"o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"order by attributes_string['method'] desc LIMIT 1 OFFSET 0",
|
||||
},
|
||||
{
|
||||
@@ -1200,7 +1200,7 @@ func TestPrepareLogsQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp, id, trace_id, span_id, trace_flags, severity_text, severity_number, scope_name, scope_version, body, attributes_string, attributes_number, attributes_bool, resources_string, scope_string from " +
|
||||
"o11y_logs.distributed_logs_v2 where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND " +
|
||||
"event.log where (timestamp >= 1680066360726000000 AND timestamp <= 1680066458000000000) AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND " +
|
||||
"id < '2TNh4vp2TpiWyLt3SzuadLJF2s4' order by attributes_string['method'] desc LIMIT 50 OFFSET 50",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestPanelTableForCumulative(t *testing.T) {
|
||||
},
|
||||
Expression: "A",
|
||||
},
|
||||
expected: "SELECT toStartOfHour(now()) as ts, sum(rate_value)/29 as value FROM (SELECT ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch']) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(rate_value) = 0 GROUP BY ts ORDER BY ts",
|
||||
expected: "SELECT toStartOfHour(now()) as ts, sum(rate_value)/29 as value FROM (SELECT ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch']) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(rate_value) = 0 GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
{
|
||||
name: "latency p50",
|
||||
@@ -66,7 +66,7 @@ func TestPanelTableForCumulative(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "SELECT toStartOfHour(now()) as ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.500) as value FROM (SELECT le, toStartOfHour(now()) as ts, sum(rate_value)/29 as value FROM (SELECT le, ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') = 'frontend') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY fingerprint, le,ts ORDER BY fingerprint, le ASC, ts) WINDOW rate_window as (PARTITION BY fingerprint, le ORDER BY fingerprint, le ASC, ts)) WHERE isNaN(rate_value) = 0 GROUP BY le,ts ORDER BY le ASC, ts) GROUP BY ts ORDER BY ts",
|
||||
expected: "SELECT toStartOfHour(now()) as ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.500) as value FROM (SELECT le, toStartOfHour(now()) as ts, sum(rate_value)/29 as value FROM (SELECT le, ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM event.series WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') = 'frontend') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY fingerprint, le,ts ORDER BY fingerprint, le ASC, ts) WINDOW rate_window as (PARTITION BY fingerprint, le ORDER BY fingerprint, le ASC, ts)) WHERE isNaN(rate_value) = 0 GROUP BY le,ts ORDER BY le ASC, ts) GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
{
|
||||
name: "latency p99 with group by",
|
||||
@@ -88,7 +88,7 @@ func TestPanelTableForCumulative(t *testing.T) {
|
||||
},
|
||||
Expression: "A",
|
||||
},
|
||||
expected: "SELECT service_name, toStartOfHour(now()) as ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name,le, toStartOfHour(now()) as ts, sum(rate_value)/29 as value FROM (SELECT service_name,le, ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, service_name,le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY fingerprint, service_name,le,ts ORDER BY fingerprint, service_name ASC,le ASC, ts) WINDOW rate_window as (PARTITION BY fingerprint, service_name,le ORDER BY fingerprint, service_name ASC,le ASC, ts)) WHERE isNaN(rate_value) = 0 GROUP BY service_name,le,ts ORDER BY service_name ASC,le ASC, ts) GROUP BY service_name,ts ORDER BY service_name ASC, ts",
|
||||
expected: "SELECT service_name, toStartOfHour(now()) as ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name,le, toStartOfHour(now()) as ts, sum(rate_value)/29 as value FROM (SELECT service_name,le, ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, service_name,le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM event.series WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY fingerprint, service_name,le,ts ORDER BY fingerprint, service_name ASC,le ASC, ts) WINDOW rate_window as (PARTITION BY fingerprint, service_name,le ORDER BY fingerprint, service_name ASC,le ASC, ts)) WHERE isNaN(rate_value) = 0 GROUP BY service_name,le,ts ORDER BY service_name ASC,le ASC, ts) GROUP BY service_name,ts ORDER BY service_name ASC, ts",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestPanelTableForDelta(t *testing.T) {
|
||||
},
|
||||
Expression: "A",
|
||||
},
|
||||
expected: "SELECT toStartOfHour(now()) as ts, sum(value)/1800 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch']) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY ts ORDER BY ts",
|
||||
expected: "SELECT toStartOfHour(now()) as ts, sum(value)/1800 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch']) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
{
|
||||
name: "latency p50",
|
||||
@@ -61,7 +61,7 @@ func TestPanelTableForDelta(t *testing.T) {
|
||||
},
|
||||
Expression: "A",
|
||||
},
|
||||
expected: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.500) as value FROM (SELECT le, toStartOfHour(now()) as ts, sum(value)/1800 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') = 'frontend') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY le,ts ORDER BY le ASC, ts) GROUP BY ts ORDER BY ts",
|
||||
expected: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.500) as value FROM (SELECT le, toStartOfHour(now()) as ts, sum(value)/1800 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000 AND JSONExtractString(labels, 'service_name') = 'frontend') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY le,ts ORDER BY le ASC, ts) GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
{
|
||||
name: "latency p99 with group by",
|
||||
@@ -80,7 +80,7 @@ func TestPanelTableForDelta(t *testing.T) {
|
||||
},
|
||||
Expression: "A",
|
||||
},
|
||||
expected: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name,le, toStartOfHour(now()) as ts, sum(value)/1800 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY service_name,le,ts ORDER BY service_name ASC,le ASC, ts) GROUP BY service_name,ts ORDER BY service_name ASC, ts",
|
||||
expected: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name,le, toStartOfHour(now()) as ts, sum(value)/1800 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1689253200000 AND unix_milli < 1689257640000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1689255866000 AND unix_milli <= 1689257640000 GROUP BY service_name,le,ts ORDER BY service_name ASC,le ASC, ts) GROUP BY service_name,ts ORDER BY service_name ASC, ts",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ func TestBuildQueryWithMultipleQueries(t *testing.T) {
|
||||
func TestBuildQueryXRate(t *testing.T) {
|
||||
t.Run("TestBuildQueryXRate", func(t *testing.T) {
|
||||
|
||||
tmpl := `SELECT ts, %s(rate_value) as value FROM (SELECT ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['name'] AND temporality = '' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['name'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts) ) WHERE isNaN(rate_value) = 0 GROUP BY ts ORDER BY ts`
|
||||
tmpl := `SELECT ts, %s(rate_value) as value FROM (SELECT ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as rate_value FROM(SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['name'] AND temporality = '' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['name'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts) ) WHERE isNaN(rate_value) = 0 GROUP BY ts ORDER BY ts`
|
||||
|
||||
cases := []struct {
|
||||
aggregateOperator v3.AggregateOperator
|
||||
@@ -403,7 +403,7 @@ func TestBuildQueryWithDotInMetricAndAttributes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "SELECT *, now() AS ts FROM (SELECT avgIf(value, toUnixTimestamp(ts) != 0) as value, anyIf(ts, toUnixTimestamp(ts) != 0) AS timestamp FROM (SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.memory.usage'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000 AND JSONExtractString(labels, 'os.type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735036080000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` asc, ts) )",
|
||||
expected: "SELECT *, now() AS ts FROM (SELECT avgIf(value, toUnixTimestamp(ts) != 0) as value, anyIf(ts, toUnixTimestamp(ts) != 0) AS timestamp FROM (SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM event.series_1d WHERE metric_name IN ['system.memory.usage'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000 AND JSONExtractString(labels, 'os.type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735036080000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` asc, ts) )",
|
||||
},
|
||||
{
|
||||
name: "TestBuildQueryWithDotInMetricAndAttributes with dot in metric and attributes with rate_avg aggregation",
|
||||
@@ -474,7 +474,7 @@ func TestBuildQueryWithDotInMetricAndAttributes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: "SELECT *, now() AS ts FROM (SELECT avgIf(value, toUnixTimestamp(ts) != 0) as value, anyIf(ts, toUnixTimestamp(ts) != 0) AS timestamp FROM (SELECT `os.type`, ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as value FROM(SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.memory.usage'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000 AND JSONExtractString(labels, 'os.type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735036020000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` asc, ts) WINDOW rate_window as (PARTITION BY `os.type` ORDER BY `os.type`, ts) ) )",
|
||||
expected: "SELECT *, now() AS ts FROM (SELECT avgIf(value, toUnixTimestamp(ts) != 0) as value, anyIf(ts, toUnixTimestamp(ts) != 0) AS timestamp FROM (SELECT `os.type`, ts, If((value - lagInFrame(value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (value - lagInFrame(value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as value FROM(SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM event.series_1d WHERE metric_name IN ['system.memory.usage'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000 AND JSONExtractString(labels, 'os.type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735036020000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` asc, ts) WINDOW rate_window as (PARTITION BY `os.type` ORDER BY `os.type`, ts) ) )",
|
||||
},
|
||||
}
|
||||
for _, testCase := range cases {
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestPrepareTableQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = cumulative",
|
||||
@@ -93,7 +93,7 @@ func TestPrepareTableQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = avg, space aggregation = avg, temporality = unspecified, testing metrics and attribute name with dot",
|
||||
@@ -148,7 +148,7 @@ func TestPrepareTableQuery(t *testing.T) {
|
||||
},
|
||||
start: 1735295140000,
|
||||
end: 1735554340000,
|
||||
expectedQueryContains: "SELECT state, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(sum) / sum(count) as per_series_value FROM o11y_metrics.distributed_samples_v4_agg_5m INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.memory.usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1735257600000 AND unix_milli < 1735554340000 AND JSONExtractString(labels, 'host.name') = 'o11y-host') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735295140000 AND unix_milli < 1735554340000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, ts ORDER BY state desc, ts ASC",
|
||||
expectedQueryContains: "SELECT state, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(sum) / sum(count) as per_series_value FROM event.metric_5m INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, fingerprint FROM event.series_1d WHERE metric_name IN ['system.memory.usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1735257600000 AND unix_milli < 1735554340000 AND JSONExtractString(labels, 'host.name') = 'o11y-host') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735295140000 AND unix_milli < 1735554340000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, ts ORDER BY state desc, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ func TestPrepareTimeAggregationSubQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'service_name') != 'payment_service' AND JSONExtractString(labels, 'endpoint') IN ['/paycallback','/payme','/paypal']) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts",
|
||||
expectedQueryContains: "SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'service_name') != 'payment_service' AND JSONExtractString(labels, 'endpoint') IN ['/paycallback','/payme','/paypal']) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, temporality = cumulative",
|
||||
@@ -107,7 +107,7 @@ func TestPrepareTimeAggregationSubQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)",
|
||||
expectedQueryContains: "SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = cumulative",
|
||||
@@ -210,7 +210,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = avg, space aggregation = avg, temporality = unspecified, testing metrics and attribute name with dot",
|
||||
@@ -265,7 +265,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1735295140000,
|
||||
end: 1735554340000,
|
||||
expectedQueryContains: "SELECT state, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(sum) / sum(count) as per_series_value FROM o11y_metrics.distributed_samples_v4_agg_5m INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.memory.usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1735257600000 AND unix_milli < 1735554340000 AND JSONExtractString(labels, 'host.name') = 'o11y-host') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735295140000 AND unix_milli < 1735554340000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, ts ORDER BY state desc, ts ASC",
|
||||
expectedQueryContains: "SELECT state, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(sum) / sum(count) as per_series_value FROM event.metric_5m INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, fingerprint FROM event.series_1d WHERE metric_name IN ['system.memory.usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1735257600000 AND unix_milli < 1735554340000 AND JSONExtractString(labels, 'host.name') = 'o11y-host') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735295140000 AND unix_milli < 1735554340000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, ts ORDER BY state desc, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestPrepareTableQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = delta",
|
||||
@@ -95,7 +95,7 @@ func TestPrepareTableQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = avg, temporality = delta, testing metrics and attribute name with dot",
|
||||
@@ -143,7 +143,7 @@ func TestPrepareTableQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT ts, avg(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y.latency.sum'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'host.name') = '4f6ec470feea') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y.latency.sum'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, avg(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['o11y.latency.sum'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'host.name') = '4f6ec470feea') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y.latency.sum'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ func TestPrepareTimeAggregationSubQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'service_name') != 'payment_service' AND JSONExtractString(labels, 'endpoint') IN ['/paycallback','/payme','/paypal']) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts",
|
||||
expectedQueryContains: "SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'service_name') != 'payment_service' AND JSONExtractString(labels, 'endpoint') IN ['/paycallback','/payme','/paypal']) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, temporality = delta",
|
||||
@@ -107,7 +107,7 @@ func TestPrepareTimeAggregationSubQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts",
|
||||
expectedQueryContains: "SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND JSONExtractString(labels, 'state') != 'idle') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = delta",
|
||||
@@ -210,7 +210,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000 AND like(JSONExtractString(labels, 'service_name'), '%payment_service%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['http_requests'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation percentile99, type = ExponentialHistogram",
|
||||
@@ -244,7 +244,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1701794980000,
|
||||
end: 1701796780000,
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, quantilesDDMerge(0.01, 0.990000)(sketch)[1] as value FROM o11y_metrics.distributed_exp_hist INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['o11y_latency'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, quantilesDDMerge(0.01, 0.990000)(sketch)[1] as value FROM event.histogram INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['o11y_latency'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1701792000000 AND unix_milli < 1701796780000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency'] AND unix_milli >= 1701794980000 AND unix_milli < 1701796780000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = max, temporality = delta, testing metrics and attribute name with dot",
|
||||
@@ -299,7 +299,7 @@ func TestPrepareTimeseriesQuery(t *testing.T) {
|
||||
},
|
||||
start: 1735036101000,
|
||||
end: 1735637901000,
|
||||
expectedQueryContains: "SELECT `host.name`, ts, max(per_series_value) as value FROM (SELECT fingerprint, any(`host.name`) as `host.name`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(sum)/60 as per_series_value FROM o11y_metrics.distributed_samples_v4_agg_5m INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'host.name') as `host.name`, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y.latency.sum'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637901000 AND JSONExtractString(labels, 'host_name') = '4f6ec470feea') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y.latency.sum'] AND unix_milli >= 1735036101000 AND unix_milli < 1735637901000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY `host.name`, ts ORDER BY `host.name` ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT `host.name`, ts, max(per_series_value) as value FROM (SELECT fingerprint, any(`host.name`) as `host.name`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(sum)/60 as per_series_value FROM event.metric_5m INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'host.name') as `host.name`, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y.latency.sum'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637901000 AND JSONExtractString(labels, 'host_name') = '4f6ec470feea') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y.latency.sum'] AND unix_milli >= 1735036101000 AND unix_milli < 1735637901000 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY `host.name`, ts ORDER BY `host.name` ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestPrepareMetricQueryCumulativeRatePreAgg(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = cumulative, multiple group by",
|
||||
@@ -81,7 +81,7 @@ func TestPrepareMetricQueryCumulativeRatePreAgg(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, endpoint, ts, sum(per_series_value) as value FROM (SELECT service_name, endpoint, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(endpoint) as endpoint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'endpoint') as endpoint, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, endpoint, ts ORDER BY service_name ASC, endpoint ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, endpoint, ts, sum(per_series_value) as value FROM (SELECT service_name, endpoint, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(endpoint) as endpoint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'endpoint') as endpoint, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, endpoint, ts ORDER BY service_name ASC, endpoint ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func TestPrepareMetricQueryDeltaRatePreAgg(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = delta, group by service_name",
|
||||
@@ -147,7 +147,7 @@ func TestPrepareMetricQueryDeltaRatePreAgg(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ func TestPrepreMetricQueryCumulativeQuantilePreAgg(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, ts, sum(per_series_value) as value FROM (SELECT service_name, le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, ts, sum(per_series_value) as value FROM (SELECT service_name, le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test temporality = cumulative, quantile = 0.99 without group by",
|
||||
@@ -231,7 +231,7 @@ func TestPrepreMetricQueryCumulativeQuantilePreAgg(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, ts, sum(per_series_value) as value FROM (SELECT le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, ts, sum(per_series_value) as value FROM (SELECT le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ func TestPrepreMetricQueryDeltaQuantilePreAgg(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test temporality = delta, quantile = 0.99 no group by",
|
||||
@@ -315,7 +315,7 @@ func TestPrepreMetricQueryDeltaQuantilePreAgg(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ func TestPrepareMetricQueryGaugePreAgg(t *testing.T) {
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
Disabled: false,
|
||||
},
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test gauge query with group by host_name",
|
||||
@@ -381,7 +381,7 @@ func TestPrepareMetricQueryGaugePreAgg(t *testing.T) {
|
||||
Expression: "A",
|
||||
Disabled: false,
|
||||
},
|
||||
expectedQueryContains: "SELECT host_name, ts, sum(per_series_value) as value FROM (SELECT fingerprint, any(host_name) as host_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'host_name') as host_name, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY host_name, ts ORDER BY host_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT host_name, ts, sum(per_series_value) as value FROM (SELECT fingerprint, any(host_name) as host_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'host_name') as host_name, fingerprint FROM event.series_1d WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY host_name, ts ORDER BY host_name ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ func TestPrepareTimeseriesFilterQuery(t *testing.T) {
|
||||
Disabled: false,
|
||||
// remaining struct fields are not needed here
|
||||
},
|
||||
expectedQueryContains: "SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000",
|
||||
expectedQueryContains: "SELECT DISTINCT fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000",
|
||||
},
|
||||
{
|
||||
name: "test prepare time series with no filters and group by",
|
||||
@@ -58,7 +58,7 @@ func TestPrepareTimeseriesFilterQuery(t *testing.T) {
|
||||
Disabled: false,
|
||||
// remaining struct fields are not needed here
|
||||
},
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000",
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000",
|
||||
},
|
||||
{
|
||||
name: "test prepare time series with no filters and multiple group by",
|
||||
@@ -90,7 +90,7 @@ func TestPrepareTimeseriesFilterQuery(t *testing.T) {
|
||||
Disabled: false,
|
||||
// remaining struct fields are not needed here
|
||||
},
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'endpoint') as endpoint, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000",
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'endpoint') as endpoint, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000",
|
||||
},
|
||||
{
|
||||
name: "test prepare time series with filters and multiple group by",
|
||||
@@ -138,7 +138,7 @@ func TestPrepareTimeseriesFilterQuery(t *testing.T) {
|
||||
Disabled: false,
|
||||
// remaining struct fields are not needed here
|
||||
},
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000 AND JSONExtractString(labels, 'service_name') != 'payment_service' AND JSONExtractString(labels, 'endpoint') IN ['/paycallback','/payme','/paypal']",
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000 AND JSONExtractString(labels, 'service_name') != 'payment_service' AND JSONExtractString(labels, 'endpoint') IN ['/paycallback','/payme','/paypal']",
|
||||
},
|
||||
{
|
||||
name: "test prepare time series with filters and multiple group by",
|
||||
@@ -186,7 +186,7 @@ func TestPrepareTimeseriesFilterQuery(t *testing.T) {
|
||||
Disabled: false,
|
||||
// remaining struct fields are not needed here
|
||||
},
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000 AND ilike(JSONExtractString(labels, 'service_name'), 'payment_service') AND notILike(JSONExtractString(labels, 'endpoint'), 'payment_service')",
|
||||
expectedQueryContains: "SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series WHERE metric_name IN ['http_requests'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1706428800000 AND unix_milli < 1706434026000 AND ilike(JSONExtractString(labels, 'service_name'), 'payment_service') AND notILike(JSONExtractString(labels, 'endpoint'), 'payment_service')",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ func TestPrepareMetricQueryCumulativeRate(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, sum(per_series_value) as value FROM (SELECT service_name, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = cumulative, multiple group by",
|
||||
@@ -274,7 +274,7 @@ func TestPrepareMetricQueryCumulativeRate(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, endpoint, ts, sum(per_series_value) as value FROM (SELECT service_name, endpoint, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(endpoint) as endpoint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'endpoint') as endpoint, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, endpoint, ts ORDER BY service_name ASC, endpoint ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, endpoint, ts, sum(per_series_value) as value FROM (SELECT service_name, endpoint, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(endpoint) as endpoint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'endpoint') as endpoint, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, endpoint, ts ORDER BY service_name ASC, endpoint ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ func TestPrepareMetricQueryDeltaRate(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test time aggregation = rate, space aggregation = sum, temporality = delta, group by service_name",
|
||||
@@ -340,7 +340,7 @@ func TestPrepareMetricQueryDeltaRate(t *testing.T) {
|
||||
TimeAggregation: v3.TimeAggregationRate,
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_calls_total'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_calls_total'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ func TestPrepreMetricQueryCumulativeQuantile(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, ts, sum(per_series_value) as value FROM (SELECT service_name, le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, ts, sum(per_series_value) as value FROM (SELECT service_name, le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(service_name) as service_name, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test temporality = cumulative, quantile = 0.99 without group by",
|
||||
@@ -424,7 +424,7 @@ func TestPrepreMetricQueryCumulativeQuantile(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, ts, sum(per_series_value) as value FROM (SELECT le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, ts, sum(per_series_value) as value FROM (SELECT le, ts, If((per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) < 0, nan, If((ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window) >= 86400, nan, (per_series_value - lagInFrame(per_series_value, 1, 0) OVER rate_window) / (ts - lagInFrame(ts, 1, toDate('1970-01-01')) OVER rate_window))) as per_series_value FROM (SELECT fingerprint, any(le) as le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WINDOW rate_window as (PARTITION BY fingerprint ORDER BY fingerprint, ts)) WHERE isNaN(per_series_value) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ func TestPrepreMetricQueryDeltaQuantile(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT service_name, le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY service_name, le, ts ORDER BY service_name ASC, le ASC, ts ASC) GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test temporality = delta, quantile = 0.99 no group by",
|
||||
@@ -508,7 +508,7 @@ func TestPrepreMetricQueryDeltaQuantile(t *testing.T) {
|
||||
Disabled: false,
|
||||
SpaceAggregation: v3.SpaceAggregationPercentile99,
|
||||
},
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.990) as value FROM (SELECT le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY le, ts ORDER BY le ASC, ts ASC) GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -548,7 +548,7 @@ func TestPrepareMetricQueryGauge(t *testing.T) {
|
||||
SpaceAggregation: v3.SpaceAggregationSum,
|
||||
Disabled: false,
|
||||
},
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
expectedQueryContains: "SELECT ts, sum(per_series_value) as value FROM (SELECT fingerprint, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY ts ORDER BY ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test value filter with string value",
|
||||
@@ -605,7 +605,7 @@ func TestPrepareMetricQueryGauge(t *testing.T) {
|
||||
Expression: "A",
|
||||
Disabled: false,
|
||||
},
|
||||
expectedQueryContains: "SELECT host_name, ts, sum(per_series_value) as value FROM (SELECT fingerprint, any(host_name) as host_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'host_name') as host_name, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY host_name, ts ORDER BY host_name ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT host_name, ts, sum(per_series_value) as value FROM (SELECT fingerprint, any(host_name) as host_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'host_name') as host_name, fingerprint FROM event.series_1d WHERE metric_name IN ['system_cpu_usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system_cpu_usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY host_name, ts ORDER BY host_name ASC, ts ASC",
|
||||
},
|
||||
{
|
||||
name: "test gauge query with multiple group by with metric and attribute name containing dot",
|
||||
@@ -674,7 +674,7 @@ func TestPrepareMetricQueryGauge(t *testing.T) {
|
||||
ReduceTo: v3.ReduceToOperatorAvg,
|
||||
Having: []v3.Having{},
|
||||
},
|
||||
expectedQueryContains: "SELECT `os.type`, state, `host.name`, ts, max(per_series_value) as value FROM (SELECT fingerprint, any(`os.type`) as `os.type`, any(state) as state, any(`host.name`) as `host.name`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, JSONExtractString(labels, 'state') as state, JSONExtractString(labels, 'host.name') as `host.name`, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.memory.usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'host.name') = 'o11y-host') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY `os.type`, state, `host.name`, ts ORDER BY `os.type` desc, state asc, `host.name` ASC, ts ASC",
|
||||
expectedQueryContains: "SELECT `os.type`, state, `host.name`, ts, max(per_series_value) as value FROM (SELECT fingerprint, any(`os.type`) as `os.type`, any(state) as state, any(`host.name`) as `host.name`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, max(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, JSONExtractString(labels, 'state') as state, JSONExtractString(labels, 'host.name') as `host.name`, fingerprint FROM event.series_1d WHERE metric_name IN ['system.memory.usage'] AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'host.name') = 'o11y-host') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY `os.type`, state, `host.name`, ts ORDER BY `os.type` desc, state asc, `host.name` ASC, ts ASC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -753,7 +753,7 @@ func TestPrepareMetricQueryValueTypePanelWithGroupBY(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedQueryContains: "SELECT max(value) as aggregated_value, ts FROM (SELECT state, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, anyLast(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1735891200000 AND unix_milli < 1735894800000 AND JSONExtractString(labels, 'os_type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1735891800000 AND unix_milli < 1735894800000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, ts ORDER BY state desc, ts ASC) GROUP BY ts ORDER BY ts",
|
||||
expectedQueryContains: "SELECT max(value) as aggregated_value, ts FROM (SELECT state, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, anyLast(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, fingerprint FROM event.series WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1735891200000 AND unix_milli < 1735894800000 AND JSONExtractString(labels, 'os_type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1735891800000 AND unix_milli < 1735894800000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, ts ORDER BY state desc, ts ASC) GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
{
|
||||
name: "test temporality = cumulative, panel = value, series agg = max group by state, host_name",
|
||||
@@ -819,7 +819,7 @@ func TestPrepareMetricQueryValueTypePanelWithGroupBY(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedQueryContains: "SELECT max(value) as aggregated_value, ts FROM (SELECT state, host_name, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, any(host_name) as host_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, anyLast(value) as per_series_value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, JSONExtractString(labels, 'host_name') as host_name, fingerprint FROM o11y_metrics.time_series_v4 WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1735891200000 AND unix_milli < 1735894800000 AND JSONExtractString(labels, 'os_type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1735891800000 AND unix_milli < 1735894800000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, host_name, ts ORDER BY state desc, host_name ASC, ts ASC) GROUP BY ts ORDER BY ts",
|
||||
expectedQueryContains: "SELECT max(value) as aggregated_value, ts FROM (SELECT state, host_name, ts, avg(per_series_value) as value FROM (SELECT fingerprint, any(state) as state, any(host_name) as host_name, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, anyLast(value) as per_series_value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'state') as state, JSONExtractString(labels, 'host_name') as host_name, fingerprint FROM event.series WHERE metric_name IN ['system_memory_usage'] AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1735891200000 AND unix_milli < 1735894800000 AND JSONExtractString(labels, 'os_type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system_memory_usage'] AND unix_milli >= 1735891800000 AND unix_milli < 1735894800000 AND bitAnd(flags, 1) = 0 GROUP BY fingerprint, ts ORDER BY fingerprint, ts) WHERE isNaN(per_series_value) = 0 GROUP BY state, host_name, ts ORDER BY state desc, host_name ASC, ts ASC) GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ func TestBuildQueryWithThreeOrMoreQueriesRefAndFormula(t *testing.T) {
|
||||
qb := NewQueryBuilder(qbOptions)
|
||||
|
||||
queries, err := qb.PrepareQueries(q)
|
||||
require.Contains(t, queries["F1"], "SELECT A.`os.type` as `os.type`, A.`ts` as `ts`, A.value + B.value as value FROM (SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.memory.usage'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000 AND JSONExtractString(labels, 'os.type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735036080000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` ASC, ts) as A INNER JOIN (SELECT * FROM (SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value) as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['system.network.io'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system.network.io'] AND unix_milli >= 1735036020000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` ASC, ts) HAVING value > 4) as B ON A.`os.type` = B.`os.type` AND A.`ts` = B.`ts`")
|
||||
require.Contains(t, queries["F1"], "SELECT A.`os.type` as `os.type`, A.`ts` as `ts`, A.value + B.value as value FROM (SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, avg(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM event.series_1d WHERE metric_name IN ['system.memory.usage'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000 AND JSONExtractString(labels, 'os.type') = 'linux') as filtered_time_series USING fingerprint WHERE metric_name IN ['system.memory.usage'] AND unix_milli >= 1735036080000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` ASC, ts) as A INNER JOIN (SELECT * FROM (SELECT `os.type`, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value) as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'os.type') as `os.type`, fingerprint FROM event.series_1d WHERE metric_name IN ['system.network.io'] AND temporality = '' AND __normalized = false AND unix_milli >= 1734998400000 AND unix_milli < 1735637880000) as filtered_time_series USING fingerprint WHERE metric_name IN ['system.network.io'] AND unix_milli >= 1735036020000 AND unix_milli < 1735637880000 GROUP BY `os.type`, ts ORDER BY `os.type` ASC, ts) HAVING value > 4) as B ON A.`os.type` = B.`os.type` AND A.`ts` = B.`ts`")
|
||||
require.NoError(t, err)
|
||||
|
||||
})
|
||||
@@ -386,7 +386,7 @@ func TestDeltaQueryBuilder(t *testing.T) {
|
||||
},
|
||||
},
|
||||
queryToTest: "A",
|
||||
expected: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch'] AND JSONExtractString(labels, '__temporality__') = 'Delta') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY ts ORDER BY ts",
|
||||
expected: "SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch'] AND JSONExtractString(labels, '__temporality__') = 'Delta') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY ts ORDER BY ts",
|
||||
},
|
||||
{
|
||||
name: "TestQueryWithExpression - Error rate",
|
||||
@@ -456,7 +456,7 @@ func TestDeltaQueryBuilder(t *testing.T) {
|
||||
},
|
||||
},
|
||||
queryToTest: "C",
|
||||
expected: "SELECT A.`ts` as `ts`, A.value * 100 / B.value as value FROM (SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch'] AND JSONExtractString(labels, 'status_code') IN ['STATUS_CODE_ERROR'] AND JSONExtractString(labels, '__temporality__') = 'Delta') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY ts ORDER BY ts) as A INNER JOIN (SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch'] AND JSONExtractString(labels, '__temporality__') = 'Delta') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY ts ORDER BY ts) as B ON A.`ts` = B.`ts`",
|
||||
expected: "SELECT A.`ts` as `ts`, A.value * 100 / B.value as value FROM (SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch'] AND JSONExtractString(labels, 'status_code') IN ['STATUS_CODE_ERROR'] AND JSONExtractString(labels, '__temporality__') = 'Delta') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY ts ORDER BY ts) as A INNER JOIN (SELECT toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_count'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'service_name') IN ['frontend'] AND JSONExtractString(labels, 'operation') IN ['HTTP GET /dispatch'] AND JSONExtractString(labels, '__temporality__') = 'Delta') as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_count'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY ts ORDER BY ts) as B ON A.`ts` = B.`ts`",
|
||||
},
|
||||
{
|
||||
name: "TestQuery - Quantile",
|
||||
@@ -484,7 +484,7 @@ func TestDeltaQueryBuilder(t *testing.T) {
|
||||
},
|
||||
},
|
||||
queryToTest: "A",
|
||||
expected: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.950) as value FROM (SELECT service_name,le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM o11y_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM o11y_metrics.time_series_v4_1day WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY service_name,le,ts ORDER BY service_name ASC,le ASC, ts) GROUP BY service_name,ts ORDER BY service_name ASC, ts",
|
||||
expected: "SELECT service_name, ts, histogramQuantile(arrayMap(x -> toFloat64(x), groupArray(le)), groupArray(value), 0.950) as value FROM (SELECT service_name,le, toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) as ts, sum(value)/60 as value FROM event.metric INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, JSONExtractString(labels, 'le') as le, fingerprint FROM event.series_1d WHERE metric_name IN ['o11y_latency_bucket'] AND temporality = 'Delta' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name IN ['o11y_latency_bucket'] AND unix_milli >= 1650991980000 AND unix_milli <= 1651078380000 GROUP BY service_name,le,ts ORDER BY service_name ASC,le ASC, ts) GROUP BY service_name,ts ORDER BY service_name ASC, ts",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -563,9 +563,9 @@ var testLogsWithFormula = []struct {
|
||||
},
|
||||
ExpectedQuery: "SELECT A.`key_1` as `key_1`, A.`ts` as `ts`, A.value + B.value as value FROM " +
|
||||
"(SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_bool_value[indexOf(attributes_bool_key, 'key_1')] as `key_1`, toFloat64(count(*)) as value from " +
|
||||
"o11y_logs.distributed_logs where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key_1')] = true AND " +
|
||||
"event.log where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key_1')] = true AND " +
|
||||
"has(attributes_bool_key, 'key_1') group by `key_1`,ts order by value DESC) as A INNER JOIN (SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, " +
|
||||
"attributes_bool_value[indexOf(attributes_bool_key, 'key_1')] as `key_1`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) " +
|
||||
"attributes_bool_value[indexOf(attributes_bool_key, 'key_1')] as `key_1`, toFloat64(count(*)) as value from event.log where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) " +
|
||||
"AND attributes_bool_value[indexOf(attributes_bool_key, 'key_2')] = true AND has(attributes_bool_key, 'key_1') group by `key_1`,ts order by value DESC) as B ON A.`key_1` = B.`key_1` AND A.`ts` = B.`ts`",
|
||||
},
|
||||
{
|
||||
@@ -623,9 +623,9 @@ var testLogsWithFormula = []struct {
|
||||
},
|
||||
},
|
||||
ExpectedQuery: "SELECT A.`key1.1` as `key1.1`, A.value + B.value as value FROM (SELECT now() as ts, attributes_bool_value[indexOf(attributes_bool_key, 'key1.1')] as `key1.1`, " +
|
||||
"toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key1.1')] = true AND " +
|
||||
"toFloat64(count(*)) as value from event.log where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key1.1')] = true AND " +
|
||||
"has(attributes_bool_key, 'key1.1') group by `key1.1` order by value DESC) as A INNER JOIN (SELECT now() as ts, attributes_bool_value[indexOf(attributes_bool_key, 'key1.1')] as `key1.1`, " +
|
||||
"toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key1.2')] = true AND " +
|
||||
"toFloat64(count(*)) as value from event.log where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key1.2')] = true AND " +
|
||||
"has(attributes_bool_key, 'key1.1') group by `key1.1` order by value DESC) as B ON A.`key1.1` = B.`key1.1`",
|
||||
},
|
||||
{
|
||||
@@ -683,9 +683,9 @@ var testLogsWithFormula = []struct {
|
||||
},
|
||||
},
|
||||
ExpectedQuery: "SELECT A.`key1.1` as `key1.1`, A.`ts` as `ts`, A.value - B.value as value FROM (SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, " +
|
||||
"`attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1702980884000000000 AND timestamp <= 1702984484000000000) AND " +
|
||||
"`attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from event.log where (timestamp >= 1702980884000000000 AND timestamp <= 1702984484000000000) AND " +
|
||||
"`attribute_bool_key_2` = true AND `attribute_bool_key1$$1_exists`=true group by `key1.1`,ts order by value DESC) as A INNER JOIN (SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), " +
|
||||
"INTERVAL 60 SECOND) AS ts, `attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from o11y_logs.distributed_logs where (timestamp >= 1702980884000000000 AND " +
|
||||
"INTERVAL 60 SECOND) AS ts, `attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from event.log where (timestamp >= 1702980884000000000 AND " +
|
||||
"timestamp <= 1702984484000000000) AND attributes_bool_value[indexOf(attributes_bool_key, 'key_1')] = true AND `attribute_bool_key1$$1_exists`=true group by `key1.1`,ts order by value DESC) as B " +
|
||||
"ON A.`key1.1` = B.`key1.1` AND A.`ts` = B.`ts`",
|
||||
},
|
||||
@@ -770,10 +770,10 @@ var testLogsWithFormulaV2 = []struct {
|
||||
},
|
||||
ExpectedQuery: "SELECT A.`key_1` as `key_1`, A.`ts` as `ts`, A.value + B.value as value FROM " +
|
||||
"(SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_bool['key_1'] as `key_1`, toFloat64(count(*)) as value from " +
|
||||
"o11y_logs.distributed_logs_v2 where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) AND (ts_bucket_start >= 1702977475 AND ts_bucket_start <= 1702981075) " +
|
||||
"event.log where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) AND (ts_bucket_start >= 1702977475 AND ts_bucket_start <= 1702981075) " +
|
||||
"AND attributes_bool['key_1'] = true AND mapContains(attributes_bool, 'key_1') AND mapContains(attributes_bool, 'key_1') group by `key_1`,ts order by value DESC) as A INNER JOIN (SELECT " +
|
||||
"toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, attributes_bool['key_1'] as `key_1`, toFloat64(count(*)) as value " +
|
||||
"from o11y_logs.distributed_logs_v2 where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) AND (ts_bucket_start >= 1702977475 AND ts_bucket_start <= 1702981075) " +
|
||||
"from event.log where (timestamp >= 1702979275000000000 AND timestamp <= 1702981075000000000) AND (ts_bucket_start >= 1702977475 AND ts_bucket_start <= 1702981075) " +
|
||||
"AND attributes_bool['key_2'] = true AND mapContains(attributes_bool, 'key_2') AND mapContains(attributes_bool, 'key_1') group by `key_1`,ts order by value DESC) as B ON A.`key_1` = B.`key_1` AND A.`ts` = B.`ts`",
|
||||
},
|
||||
{
|
||||
@@ -831,9 +831,9 @@ var testLogsWithFormulaV2 = []struct {
|
||||
},
|
||||
},
|
||||
ExpectedQuery: "SELECT A.`key1.1` as `key1.1`, A.value + B.value as value FROM (SELECT attributes_bool['key1.1'] as `key1.1`, " +
|
||||
"toFloat64(count(*)) as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) AND (ts_bucket_start >= 1702977256 AND ts_bucket_start <= 1702982656) " +
|
||||
"toFloat64(count(*)) as value from event.log where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) AND (ts_bucket_start >= 1702977256 AND ts_bucket_start <= 1702982656) " +
|
||||
"AND attributes_bool['key1.1'] = true AND mapContains(attributes_bool, 'key1.1') AND mapContains(attributes_bool, 'key1.1') group by `key1.1` order by value DESC) as A INNER JOIN (SELECT " +
|
||||
"attributes_bool['key1.1'] as `key1.1`, toFloat64(count(*)) as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) " +
|
||||
"attributes_bool['key1.1'] as `key1.1`, toFloat64(count(*)) as value from event.log where (timestamp >= 1702979056000000000 AND timestamp <= 1702982656000000000) " +
|
||||
"AND (ts_bucket_start >= 1702977256 AND ts_bucket_start <= 1702982656) AND attributes_bool['key1.2'] = true AND mapContains(attributes_bool, 'key1.2') AND " +
|
||||
"mapContains(attributes_bool, 'key1.1') group by `key1.1` order by value DESC) as B ON A.`key1.1` = B.`key1.1`",
|
||||
},
|
||||
@@ -892,10 +892,10 @@ var testLogsWithFormulaV2 = []struct {
|
||||
},
|
||||
},
|
||||
ExpectedQuery: "SELECT A.`key1.1` as `key1.1`, A.`ts` as `ts`, A.value - B.value as value FROM (SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, " +
|
||||
"`attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from o11y_logs.distributed_logs_v2 where (timestamp >= 1702980884000000000 AND timestamp <= 1702984484000000000) AND " +
|
||||
"`attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from event.log where (timestamp >= 1702980884000000000 AND timestamp <= 1702984484000000000) AND " +
|
||||
"(ts_bucket_start >= 1702979084 AND ts_bucket_start <= 1702984484) AND `attribute_bool_key_2` = true AND `attribute_bool_key1$$1_exists`=true group by `key1.1`,ts order by value DESC) as " +
|
||||
"A INNER JOIN (SELECT toStartOfInterval(fromUnixTimestamp64Nano(timestamp), INTERVAL 60 SECOND) AS ts, `attribute_bool_key1$$1` as `key1.1`, toFloat64(count(*)) as value from " +
|
||||
"o11y_logs.distributed_logs_v2 where (timestamp >= 1702980884000000000 AND timestamp <= 1702984484000000000) AND (ts_bucket_start >= 1702979084 AND ts_bucket_start <= 1702984484) AND " +
|
||||
"event.log where (timestamp >= 1702980884000000000 AND timestamp <= 1702984484000000000) AND (ts_bucket_start >= 1702979084 AND ts_bucket_start <= 1702984484) AND " +
|
||||
"attributes_bool['key_1'] = true AND mapContains(attributes_bool, 'key_1') AND `attribute_bool_key1$$1_exists`=true group by `key1.1`,ts order by value DESC) as B " +
|
||||
"ON A.`key1.1` = B.`key1.1` AND A.`ts` = B.`ts`",
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/querier"
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
)
|
||||
|
||||
@@ -67,16 +68,19 @@ func NewQueryInfoResult(postData *v3.QueryRangeParamsV3, version string) QueryIn
|
||||
}
|
||||
}
|
||||
} else if postData.CompositeQuery.QueryType == v3.QueryTypeDatastoreSQL {
|
||||
// This block asked which DATABASE the SQL named — o11y_metrics,
|
||||
// o11y_logs, o11y_traces. HIP-0132 unified all three into `event`, so
|
||||
// all three tests went permanently false and raw-SQL queries were
|
||||
// recorded as touching no signal at all. querier.SignalsInSQL is the one
|
||||
// answer to that question; there is no second copy of it here.
|
||||
for _, query := range postData.CompositeQuery.DatastoreQueries {
|
||||
if strings.Contains(query.Query, "o11y_metrics") && len(query.Query) > 0 {
|
||||
queryInfoResult.MetricsUsed = true
|
||||
}
|
||||
if strings.Contains(query.Query, "o11y_logs") && len(query.Query) > 0 {
|
||||
queryInfoResult.LogsUsed = true
|
||||
}
|
||||
if strings.Contains(query.Query, "o11y_traces") && len(query.Query) > 0 {
|
||||
queryInfoResult.TracesUsed = true
|
||||
if len(query.Query) == 0 {
|
||||
continue
|
||||
}
|
||||
m, l, t := querier.SignalsInSQL(query.Query)
|
||||
queryInfoResult.MetricsUsed = queryInfoResult.MetricsUsed || m
|
||||
queryInfoResult.LogsUsed = queryInfoResult.LogsUsed || l
|
||||
queryInfoResult.TracesUsed = queryInfoResult.TracesUsed || t
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
)
|
||||
|
||||
func Test_buildResourceFilter(t *testing.T) {
|
||||
@@ -530,7 +532,7 @@ func Test_buildResourceSubQuery(t *testing.T) {
|
||||
Type: v3.AttributeKeyTypeResource,
|
||||
},
|
||||
},
|
||||
want: "(SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE " +
|
||||
want: "(SELECT fingerprint FROM event.log_resource WHERE " +
|
||||
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND " +
|
||||
"simpleJSONExtractString(labels, 'service.name') = 'test' AND labels like '%service.name\":\"test%' " +
|
||||
"AND simpleJSONExtractString(lower(labels), 'namespace') LIKE '%test1%' AND lower(labels) like '%namespace%test1%' " +
|
||||
@@ -541,7 +543,7 @@ func Test_buildResourceSubQuery(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := BuildResourceSubQuery("o11y_logs", "distributed_logs_v2_resource", tt.args.bucketStart, tt.args.bucketEnd, tt.args.fs, tt.args.groupBy, tt.args.aggregateAttribute, false)
|
||||
got, err := BuildResourceSubQuery(telemetryplane.DBName, telemetrylogs.LogResourceTableName, tt.args.bucketStart, tt.args.bucketEnd, tt.args.fs, tt.args.groupBy, tt.args.aggregateAttribute, false)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("buildResourceSubQuery() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/hanzoai/o11y/pkg/query-service/constants"
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
"github.com/hanzoai/o11y/pkg/query-service/utils"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
const NANOSECOND = 1000000000
|
||||
@@ -282,7 +283,9 @@ func buildTracesQuery(start, end, step int64, mq *v3.BuilderQuery, panelType v3.
|
||||
filterSubQuery = filterSubQuery + " AND " + emptyValuesInGroupByFilter
|
||||
}
|
||||
|
||||
resourceSubQuery, err := resource.BuildResourceSubQuery("o11y_traces", "distributed_traces_v3_resource", bucketStart, bucketEnd, mq.Filters, mq.GroupBy, mq.AggregateAttribute, false)
|
||||
// The one place this builder still spelled a database. o11y_traces was
|
||||
// dropped by HIP-0132 and distributed_traces_v3_resource IS event.span_resource.
|
||||
resourceSubQuery, err := resource.BuildResourceSubQuery(constants.O11Y_TRACE_DBNAME, telemetrytraces.SpanResourceTableName, bucketStart, bucketEnd, mq.Filters, mq.GroupBy, mq.AggregateAttribute, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -516,7 +516,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
{ColumnName: "http.method", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT attributes_string['http.method'] as `http.method`, toFloat64(count()) as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT attributes_string['http.method'] as `http.method`, toFloat64(count()) as value from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['http.method'] = '100' AND mapContains(attributes_string, 'http.method') " +
|
||||
"group by `http.method` order by `http.method` ASC",
|
||||
},
|
||||
@@ -544,7 +544,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
{ColumnName: "http.method", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT attributes_string['http.method'] as `http.method`, toFloat64(count()) as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT attributes_string['http.method'] as `http.method`, toFloat64(count()) as value from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['http.method'] = '100' AND mapContains(attributes_string, 'http.method') AND mapContains(attributes_string, 'name') " +
|
||||
"group by `http.method` order by `http.method` ASC",
|
||||
},
|
||||
@@ -572,7 +572,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
{ColumnName: "http.method", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT attributes_string['http.method'] as `http.method`, toFloat64(count()) as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT attributes_string['http.method'] as `http.method`, toFloat64(count()) as value from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['http.method'] = '100' AND mapContains(attributes_string, 'http.method') AND name != '' " +
|
||||
"group by `http.method` order by `http.method` ASC",
|
||||
},
|
||||
@@ -596,9 +596,9 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
{ColumnName: "host", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT resources_number['host'] as `host`, toFloat64(count()) as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT resources_number['host'] as `host`, toFloat64(count()) as value from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_number['bytes'] > 100 AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND " +
|
||||
"(resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.span_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND " +
|
||||
"(seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name\":\"myService%' AND " +
|
||||
"( (simpleJSONHas(labels, 'host') AND labels like '%host%') ))) " +
|
||||
"group by `host` order by `host` ASC",
|
||||
@@ -616,7 +616,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "timestamp", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) order by timestamp ASC",
|
||||
},
|
||||
{
|
||||
@@ -632,8 +632,8 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "timestamp", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND ((name, `resource_string_service$$name`) GLOBAL IN ( SELECT DISTINCT name, serviceName from o11y_traces.distributed_top_level_operations )) AND parent_span_id != '' order by timestamp ASC",
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND ((name, `resource_string_service$$name`) GLOBAL IN ( SELECT DISTINCT name, serviceName from event.operation )) AND parent_span_id != '' order by timestamp ASC",
|
||||
},
|
||||
{
|
||||
name: "test noop list view with root_spans",
|
||||
@@ -648,7 +648,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "timestamp", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND parent_span_id = '' order by timestamp ASC",
|
||||
},
|
||||
{
|
||||
@@ -664,7 +664,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "timestamp", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND parent_span_id = '' order by timestamp ASC",
|
||||
},
|
||||
{
|
||||
@@ -680,8 +680,8 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
OrderBy: []v3.OrderBy{{ColumnName: "timestamp", Order: "ASC"}},
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'cartservice' AND labels like '%service.name\":\"cartservice%')) AND parent_span_id = '' order by timestamp ASC",
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.span_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'cartservice' AND labels like '%service.name\":\"cartservice%')) AND parent_span_id = '' order by timestamp ASC",
|
||||
},
|
||||
{
|
||||
name: "test noop list view-without ts",
|
||||
@@ -695,7 +695,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
SelectColumns: []v3.AttributeKey{{Key: "name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag, IsColumn: true}},
|
||||
},
|
||||
},
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
want: "SELECT timestamp as timestamp_datetime, span_id as spanID, trace_id as traceID, name as `name` from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') " +
|
||||
"AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) order by timestamp DESC",
|
||||
},
|
||||
{
|
||||
@@ -715,10 +715,10 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT subQuery.serviceName as `subQuery.serviceName`, subQuery.name as `subQuery.name`, count() AS span_count, subQuery.durationNano as `subQuery.durationNano`, subQuery.traceID FROM " +
|
||||
"(SELECT traceID AS dist_traceID, timestamp, ts_bucket_start FROM o11y_traces.distributed_o11y_index_v3 WHERE (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['method'] = 'GET' " +
|
||||
"AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name\":\"myService%'))) as dist_table " +
|
||||
"(SELECT traceID AS dist_traceID, timestamp, ts_bucket_start FROM event.span WHERE (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_string['method'] = 'GET' " +
|
||||
"AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.span_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name\":\"myService%'))) as dist_table " +
|
||||
"INNER JOIN " +
|
||||
"( SELECT * FROM (SELECT traceID, durationNano, serviceName, name FROM o11y_traces.o11y_index_v3 WHERE parentSpanID = '' AND (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"( SELECT * FROM (SELECT traceID, durationNano, serviceName, name FROM event.span WHERE parentSpanID = '' AND (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"ORDER BY durationNano DESC LIMIT 1 BY traceID) AS inner_subquery ) AS subQuery ON dist_table.dist_traceID = subQuery.traceID " +
|
||||
"GROUP BY subQuery.traceID, subQuery.durationNano, subQuery.name, subQuery.serviceName ORDER BY " +
|
||||
"subQuery.durationNano desc LIMIT 1 BY subQuery.traceID LIMIT 100 settings distributed_product_mode='allow', max_memory_usage=10000000000",
|
||||
@@ -740,11 +740,11 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "SELECT serviceName, name, subQuery.span_count as span_count, durationNano, trace_id as traceID from o11y_traces.distributed_o11y_index_v3 GLOBAL INNER JOIN " +
|
||||
"( SELECT * FROM (SELECT trace_id, count() as span_count FROM o11y_traces.o11y_index_v3 WHERE (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_string['method'] = 'GET' AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE " +
|
||||
want: "SELECT serviceName, name, subQuery.span_count as span_count, durationNano, trace_id as traceID from event.span GLOBAL INNER JOIN " +
|
||||
"( SELECT * FROM (SELECT trace_id, count() as span_count FROM event.span WHERE (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_string['method'] = 'GET' AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.span_resource WHERE " +
|
||||
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'service.name') = 'myService' AND labels like '%service.name\":\"myService%')) " +
|
||||
"GROUP BY trace_id ORDER BY span_count DESC LIMIT 1 BY trace_id LIMIT 100) AS inner_subquery ) AS subQuery ON o11y_traces.distributed_o11y_index_v3.trace_id = subQuery.trace_id " +
|
||||
"GROUP BY trace_id ORDER BY span_count DESC LIMIT 1 BY trace_id LIMIT 100) AS inner_subquery ) AS subQuery ON event.span.trace_id = subQuery.trace_id " +
|
||||
"WHERE parent_span_id = '' AND (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"ORDER BY subQuery.span_count DESC LIMIT 100 settings distributed_product_mode='allow', max_memory_usage=10000000000",
|
||||
},
|
||||
@@ -768,7 +768,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
want: "SELECT toFloat64(count(distinct(name))) as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND " +
|
||||
want: "SELECT toFloat64(count(distinct(name))) as value from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND " +
|
||||
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) having value > 10 order by value ASC",
|
||||
},
|
||||
{
|
||||
@@ -783,7 +783,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
AggregateAttribute: v3.AttributeKey{Key: "timestamp", IsColumn: false, Type: v3.AttributeKeyTypeTag},
|
||||
},
|
||||
},
|
||||
want: "SELECT max(toUnixTimestamp64Nano(timestamp)) as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND " +
|
||||
want: "SELECT max(toUnixTimestamp64Nano(timestamp)) as value from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND " +
|
||||
"(ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) order by value DESC",
|
||||
},
|
||||
{
|
||||
@@ -799,7 +799,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
Filters: &v3.FilterSet{},
|
||||
},
|
||||
},
|
||||
want: "SELECT toStartOfInterval(timestamp, INTERVAL 60 SECOND) AS ts, count()/60.000000 as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1745315470000000000' AND " +
|
||||
want: "SELECT toStartOfInterval(timestamp, INTERVAL 60 SECOND) AS ts, count()/60.000000 as value from event.span where (timestamp >= '1745315470000000000' AND " +
|
||||
"timestamp <= '1745319070000000000') AND (ts_bucket_start >= 1745313670 AND ts_bucket_start <= 1745319070) group by ts order by value DESC",
|
||||
},
|
||||
{
|
||||
@@ -815,7 +815,7 @@ func Test_buildTracesQuery(t *testing.T) {
|
||||
Filters: &v3.FilterSet{},
|
||||
},
|
||||
},
|
||||
want: "SELECT count()/3600.000000 as value from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1745315470000000000' AND " +
|
||||
want: "SELECT count()/3600.000000 as value from event.span where (timestamp >= '1745315470000000000' AND " +
|
||||
"timestamp <= '1745319070000000000') AND (ts_bucket_start >= 1745313670 AND ts_bucket_start <= 1745319070) order by value DESC",
|
||||
},
|
||||
}
|
||||
@@ -866,7 +866,7 @@ func TestPrepareTracesQuery(t *testing.T) {
|
||||
GraphLimitQtype: constants.FirstQueryGraphLimit,
|
||||
},
|
||||
},
|
||||
want: "SELECT `function` from (SELECT attributes_string['function'] as `function`, toFloat64(count(distinct(name))) as value from o11y_traces.distributed_o11y_index_v3 " +
|
||||
want: "SELECT `function` from (SELECT attributes_string['function'] as `function`, toFloat64(count(distinct(name))) as value from event.span " +
|
||||
"where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND mapContains(attributes_string, 'function') group by `function` order by value DESC) LIMIT 10",
|
||||
},
|
||||
{
|
||||
@@ -888,7 +888,7 @@ func TestPrepareTracesQuery(t *testing.T) {
|
||||
GraphLimitQtype: constants.SecondQueryGraphLimit,
|
||||
},
|
||||
},
|
||||
want: "SELECT attributes_string['function'] as `function`, toFloat64(count(distinct(name))) as value from o11y_traces.distributed_o11y_index_v3 where " +
|
||||
want: "SELECT attributes_string['function'] as `function`, toFloat64(count(distinct(name))) as value from event.span where " +
|
||||
"(timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND mapContains(attributes_string, 'function') AND (`function`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `function` order by value DESC",
|
||||
},
|
||||
{
|
||||
@@ -928,8 +928,8 @@ func TestPrepareTracesQuery(t *testing.T) {
|
||||
},
|
||||
},
|
||||
want: "SELECT `function`,`service.name` from (SELECT `attribute_string_function` as `function`, `resource_string_service$$name` as `service.name`, toFloat64(count(distinct(name))) as value " +
|
||||
"from o11y_traces.distributed_o11y_index_v3 where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_number['line'] = 100 AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE " +
|
||||
"from event.span where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) " +
|
||||
"AND attributes_number['line'] = 100 AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.span_resource WHERE " +
|
||||
"(seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) AND simpleJSONExtractString(labels, 'hostname') = 'server1' AND labels like '%hostname\":\"server1%' AND " +
|
||||
"( (simpleJSONHas(labels, 'service.name') AND labels like '%service.name%') ))) group by `function`,`service.name` order by value DESC) LIMIT 10",
|
||||
},
|
||||
@@ -969,9 +969,9 @@ func TestPrepareTracesQuery(t *testing.T) {
|
||||
GraphLimitQtype: constants.SecondQueryGraphLimit,
|
||||
},
|
||||
},
|
||||
want: "SELECT `attribute_string_function` as `function`, resource_string_service$$name as `serviceName`, toFloat64(count(distinct(name))) as value from o11y_traces.distributed_o11y_index_v3 " +
|
||||
want: "SELECT `attribute_string_function` as `function`, resource_string_service$$name as `serviceName`, toFloat64(count(distinct(name))) as value from event.span " +
|
||||
"where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000') AND (ts_bucket_start >= 1680064560 AND ts_bucket_start <= 1680066458) AND attributes_number['line'] = 100 " +
|
||||
"AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) " +
|
||||
"AND (resource_fingerprint GLOBAL IN (SELECT fingerprint FROM event.span_resource WHERE (seen_at_ts_bucket_start >= 1680064560) AND (seen_at_ts_bucket_start <= 1680066458) " +
|
||||
"AND simpleJSONExtractString(labels, 'hostname') = 'server1' AND labels like '%hostname\":\"server1%')) AND (`function`,`serviceName`) GLOBAL IN (#LIMIT_PLACEHOLDER) group by `function`,`serviceName` order by value DESC",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@ import (
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/query-service/model"
|
||||
v3 "github.com/hanzoai/o11y/pkg/query-service/model/v3"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetadata"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetrics"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
"github.com/hanzoai/o11y/pkg/valuer"
|
||||
)
|
||||
|
||||
@@ -92,35 +96,61 @@ var GroupByColMap = map[string]struct{}{
|
||||
ResponseStatusCode: {},
|
||||
}
|
||||
|
||||
// The names the v3/v4 query builders read by — twenty-seven call sites across
|
||||
// metrics v3, metrics v4, inframetrics and traces v4 reach the plane through
|
||||
// exactly these constants.
|
||||
//
|
||||
// BOTH DATABASE NAMES WERE DEAD. o11y_metrics and o11y_traces were dropped by
|
||||
// HIP-0132 and unified into the event plane, so every one of those call sites
|
||||
// answered `Code: 81 ... UNKNOWN_DATABASE`. They are ALIASES now — the plane is
|
||||
// spelled once, in pkg/telemetryplane, and plane_test.go enforces that.
|
||||
//
|
||||
// The table names are aliases of pkg/telemetry{traces,metrics}/tables.go for the
|
||||
// same reason: samples_v4 IS event.metric, time_series_v4 IS event.series,
|
||||
// o11y_index_v3 IS event.span. A name that says `_v4` in one file and `metric`
|
||||
// in another is one table with two names, which is how a migration leaves half
|
||||
// a plane behind.
|
||||
const (
|
||||
O11Y_METRIC_DBNAME = "o11y_metrics"
|
||||
O11Y_SAMPLES_V4_LOCAL_TABLENAME = "samples_v4"
|
||||
O11Y_SAMPLES_V4_TABLENAME = "distributed_samples_v4"
|
||||
O11Y_SAMPLES_V4_AGG_5M_TABLENAME = "distributed_samples_v4_agg_5m"
|
||||
O11Y_SAMPLES_V4_AGG_30M_TABLENAME = "distributed_samples_v4_agg_30m"
|
||||
O11Y_EXP_HISTOGRAM_TABLENAME = "distributed_exp_hist"
|
||||
O11Y_EXP_HISTOGRAM_LOCAL_TABLENAME = "exp_hist"
|
||||
O11Y_TRACE_DBNAME = "o11y_traces"
|
||||
O11Y_SPAN_INDEX_TABLENAME = "distributed_o11y_index_v2"
|
||||
O11Y_SPAN_INDEX_V3 = "distributed_o11y_index_v3"
|
||||
O11Y_SPAN_INDEX_LOCAL_TABLENAME = "o11y_index_v2"
|
||||
O11Y_SPAN_INDEX_V3_LOCAL_TABLENAME = "o11y_index_v3"
|
||||
O11Y_TIMESERIES_v4_LOCAL_TABLENAME = "time_series_v4"
|
||||
O11Y_TIMESERIES_V4_TABLENAME = "distributed_time_series_v4"
|
||||
O11Y_TIMESERIES_v4_6HRS_LOCAL_TABLENAME = "time_series_v4_6hrs"
|
||||
O11Y_TIMESERIES_v4_1DAY_LOCAL_TABLENAME = "time_series_v4_1day"
|
||||
O11Y_TIMESERIES_v4_1WEEK_LOCAL_TABLENAME = "time_series_v4_1week"
|
||||
O11Y_TIMESERIES_v4_1DAY_TABLENAME = "distributed_time_series_v4_1day"
|
||||
O11Y_TOP_LEVEL_OPERATIONS_TABLENAME = "distributed_top_level_operations"
|
||||
O11Y_TIMESERIES_v4_TABLENAME = "distributed_time_series_v4"
|
||||
O11Y_TIMESERIES_v4_1WEEK_TABLENAME = "distributed_time_series_v4_1week"
|
||||
O11Y_TIMESERIES_v4_6HRS_TABLENAME = "distributed_time_series_v4_6hrs"
|
||||
O11Y_ATTRIBUTES_METADATA_TABLENAME = "distributed_attributes_metadata"
|
||||
O11Y_ATTRIBUTES_METADATA_LOCAL_TABLENAME = "attributes_metadata"
|
||||
O11Y_METRIC_DBNAME = telemetryplane.DBName
|
||||
O11Y_SAMPLES_V4_LOCAL_TABLENAME = telemetrymetrics.MetricLocalTableName
|
||||
O11Y_SAMPLES_V4_TABLENAME = telemetrymetrics.MetricTableName
|
||||
O11Y_SAMPLES_V4_AGG_5M_TABLENAME = telemetrymetrics.Metric5mTableName
|
||||
O11Y_SAMPLES_V4_AGG_30M_TABLENAME = telemetrymetrics.Metric30mTableName
|
||||
O11Y_EXP_HISTOGRAM_TABLENAME = telemetrymetrics.HistogramTableName
|
||||
O11Y_EXP_HISTOGRAM_LOCAL_TABLENAME = telemetrymetrics.HistogramLocalTableName
|
||||
|
||||
O11Y_TRACE_DBNAME = telemetryplane.DBName
|
||||
O11Y_SPAN_INDEX_V3 = telemetrytraces.SpanTableName
|
||||
O11Y_SPAN_INDEX_V3_LOCAL_TABLENAME = telemetrytraces.SpanLocalTableName
|
||||
|
||||
O11Y_TIMESERIES_v4_LOCAL_TABLENAME = telemetrymetrics.SeriesLocalTableName
|
||||
O11Y_TIMESERIES_V4_TABLENAME = telemetrymetrics.SeriesTableName
|
||||
O11Y_TIMESERIES_v4_TABLENAME = telemetrymetrics.SeriesTableName
|
||||
O11Y_TIMESERIES_v4_6HRS_LOCAL_TABLENAME = telemetrymetrics.Series6hLocalTableName
|
||||
O11Y_TIMESERIES_v4_6HRS_TABLENAME = telemetrymetrics.Series6hTableName
|
||||
O11Y_TIMESERIES_v4_1DAY_LOCAL_TABLENAME = telemetrymetrics.Series1dLocalTableName
|
||||
O11Y_TIMESERIES_v4_1DAY_TABLENAME = telemetrymetrics.Series1dTableName
|
||||
O11Y_TIMESERIES_v4_1WEEK_LOCAL_TABLENAME = telemetrymetrics.Series1wLocalTableName
|
||||
O11Y_TIMESERIES_v4_1WEEK_TABLENAME = telemetrymetrics.Series1wTableName
|
||||
|
||||
// top_level_operations IS event.operation — one (service, operation) pair.
|
||||
O11Y_TOP_LEVEL_OPERATIONS_TABLENAME = telemetrytraces.OperationTableName
|
||||
|
||||
// The metadata pair is NOT the plane: o11y_metadata still has a live writer.
|
||||
O11Y_ATTRIBUTES_METADATA_TABLENAME = telemetrymetadata.AttributesMetadataTableName
|
||||
O11Y_ATTRIBUTES_METADATA_LOCAL_TABLENAME = telemetrymetadata.AttributesMetadataLocalTableName
|
||||
O11Y_METADATA_TABLENAME = "distributed_metadata"
|
||||
O11Y_METADATA_LOCAL_TABLENAME = "metadata"
|
||||
)
|
||||
|
||||
// RETIRED — the v2 span index. It was dropped with o11y_traces and the event
|
||||
// plane has no table with its columns. Kept as a literal so a read that reaches
|
||||
// it fails naming the retired table, which is the true reason.
|
||||
const (
|
||||
O11Y_SPAN_INDEX_TABLENAME = "distributed_o11y_index_v2"
|
||||
O11Y_SPAN_INDEX_LOCAL_TABLENAME = "o11y_index_v2"
|
||||
)
|
||||
|
||||
// alert related constants
|
||||
const (
|
||||
// AlertHelpPage is used in case default alert repo url is not set
|
||||
|
||||
@@ -40,7 +40,7 @@ func GenerateMetricQueryCHArgs(
|
||||
|
||||
// Adjust start time to nearest hour
|
||||
oneHourInMilliseconds := uint64(time.Hour.Milliseconds())
|
||||
// start time for filtering o11y_metrics.time_series_v4 with start time
|
||||
// start time for filtering event.series with start time
|
||||
timeSeriesCTEStartTime := start - (start % oneHourInMilliseconds)
|
||||
|
||||
queryArgs := []interface{}{
|
||||
@@ -61,7 +61,7 @@ func GenerateMetricQueryCHArgs(
|
||||
queryArgs = append(queryArgs, false)
|
||||
|
||||
// Step2: Add temporal aggregation args
|
||||
// build args for filtering o11y_metrics.distributed_samples_v4 table
|
||||
// build args for filtering the event.metric table
|
||||
temporalAggArgs := []interface{}{
|
||||
metricName,
|
||||
start,
|
||||
|
||||
@@ -135,7 +135,7 @@ func TestDatastoreFilterExtractor_GroupByColumns(t *testing.T) {
|
||||
JSONExtractString(labels, 'http.method') AS http_method,
|
||||
metric_name as metricName,
|
||||
rand() as value
|
||||
FROM o11y_metrics.time_series_v4
|
||||
FROM event.series
|
||||
WHERE (metric_name IN ('test_metric_cardinality'))
|
||||
GROUP BY
|
||||
ts,
|
||||
@@ -163,7 +163,7 @@ func TestDatastoreFilterExtractor_GroupByColumns(t *testing.T) {
|
||||
JSONExtractString(labels, 'http.method'),
|
||||
metric_name as metricName,
|
||||
rand() as value
|
||||
FROM o11y_metrics.time_series_v4
|
||||
FROM event.series
|
||||
WHERE (metric_name IN ('test_metric_cardinality'))
|
||||
GROUP BY
|
||||
ts,
|
||||
@@ -845,13 +845,13 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
service,
|
||||
op,
|
||||
sum(value) / 60 AS value
|
||||
FROM o11y_metrics.distributed_samples_v4 AS points
|
||||
FROM event.metric AS points
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
fingerprint,
|
||||
JSONExtractString(labels, 'service.name') AS service,
|
||||
JSONExtractString(labels, 'operation') AS op
|
||||
FROM o11y_metrics.time_series_v4
|
||||
FROM event.series
|
||||
WHERE (metric_name IN ('app_requests_total')) AND (unix_milli >= 1731340800000) AND (unix_milli <= 1731344400000) AND (LOWER(temporality) LIKE LOWER('delta')) AND (__normalized = false)
|
||||
GROUP BY
|
||||
fingerprint,
|
||||
@@ -882,10 +882,10 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
fingerprint,
|
||||
toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), toIntervalSecond(60)) AS ts,
|
||||
avg(value) AS per_series_value
|
||||
FROM o11y_metrics.distributed_samples_v4 AS points
|
||||
FROM event.metric AS points
|
||||
INNER JOIN (
|
||||
SELECT fingerprint
|
||||
FROM o11y_metrics.time_series_v4
|
||||
FROM event.series
|
||||
WHERE (metric_name IN ('node.cpu.usage')) AND (unix_milli >= 1731427200000) AND (unix_milli <= 1731430800000) AND (LOWER(temporality) LIKE LOWER('cumulative')) AND (__normalized = false)
|
||||
GROUP BY fingerprint
|
||||
) AS filtered_time_series
|
||||
@@ -922,13 +922,13 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
svc,
|
||||
le,
|
||||
sum(value)/60 AS value
|
||||
FROM o11y_metrics.distributed_samples_v4 AS points
|
||||
FROM event.metric AS points
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
fingerprint,
|
||||
JSONExtractString(labels, 'service.name') AS svc,
|
||||
JSONExtractString(labels, 'le') AS le
|
||||
FROM o11y_metrics.time_series_v4
|
||||
FROM event.series
|
||||
WHERE
|
||||
metric_name IN ('http_request_duration.bucket')
|
||||
AND unix_milli >= 1731513600000
|
||||
@@ -1001,12 +1001,12 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
any(le) AS le,
|
||||
toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) AS ts,
|
||||
max(value) AS per_series_value
|
||||
FROM o11y_metrics.distributed_samples_v4
|
||||
FROM event.metric
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT
|
||||
JSONExtractString(labels, 'le') AS le,
|
||||
fingerprint
|
||||
FROM o11y_metrics.time_series_v4_1day
|
||||
FROM event.series_1d
|
||||
WHERE
|
||||
metric_name IN ['o11y_latency_bucket']
|
||||
AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')
|
||||
@@ -1056,8 +1056,8 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
maxIf(s.value, s.metric_name='k8s.job.failed_pods') AS failed,
|
||||
maxIf(s.value, s.metric_name='k8s.job.successful_pods') AS success,
|
||||
maxIf(s.value, s.metric_name='k8s.job.desired_successful_pods') AS desired
|
||||
FROM o11y_metrics.distributed_samples_v4 AS s
|
||||
JOIN o11y_metrics.time_series_v4_1day AS tsv
|
||||
FROM event.metric AS s
|
||||
JOIN event.series_1d AS tsv
|
||||
ON s.fingerprint = tsv.fingerprint
|
||||
WHERE s.metric_name IN (
|
||||
'k8s.job.failed_pods',
|
||||
@@ -1127,14 +1127,14 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
any(` + "`host_name`" + `) AS ` + "`host_name`" + `,
|
||||
toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) AS ts,
|
||||
max(value) AS per_series_value
|
||||
FROM o11y_metrics.distributed_samples_v4
|
||||
FROM event.metric
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT
|
||||
JSONExtractString(labels, 'os.type') AS ` + "`os.type`" + `,
|
||||
JSONExtractString(labels, 'state') AS state,
|
||||
JSONExtractString(labels, 'host_name') AS ` + "`host_name`" + `,
|
||||
fingerprint
|
||||
FROM o11y_metrics.time_series_v4_1day
|
||||
FROM event.series_1d
|
||||
WHERE
|
||||
metric_name IN ['system.memory.usage']
|
||||
AND temporality = 'Unspecified' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND JSONExtractString(labels, 'host.name') = 'o11y-host' ) AS filtered_time_series
|
||||
@@ -1178,8 +1178,8 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
JSONExtractString(tsv.labels, 'k8s.job.name') AS job,
|
||||
maxIf(s.value, s.metric_name = 'k8s.job.successful_pods') AS max_success,
|
||||
maxIf(s.value, s.metric_name = 'k8s.job.desired_successful_pods') AS max_desired
|
||||
FROM o11y_metrics.distributed_samples_v4 AS s
|
||||
JOIN o11y_metrics.time_series_v4_1day AS tsv
|
||||
FROM event.metric AS s
|
||||
JOIN event.series_1d AS tsv
|
||||
ON s.fingerprint = tsv.fingerprint
|
||||
WHERE s.metric_name IN ('k8s.job.successful_pods', 'k8s.job.desired_successful_pods')
|
||||
AND s.unix_milli >= start_ms AND s.unix_milli < end_ms
|
||||
@@ -1243,12 +1243,12 @@ func TestDatastoreFilterExtractor_NestedComplexCTEGroupByQueries(t *testing.T) {
|
||||
any(le) AS le,
|
||||
toStartOfInterval(toDateTime(intDiv(unix_milli, 1000)), INTERVAL 60 SECOND) AS ts,
|
||||
max(value) AS per_series_value
|
||||
FROM o11y_metrics.distributed_samples_v4
|
||||
FROM event.metric
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT
|
||||
JSONExtractString(labels, 'le') AS le,
|
||||
fingerprint
|
||||
FROM o11y_metrics.time_series_v4_1day
|
||||
FROM event.series_1d
|
||||
WHERE
|
||||
metric_name IN ['o11y_latency_bucket']
|
||||
AND temporality = 'Cumulative' AND __normalized = false AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000 AND like(JSONExtractString(labels, 'service_name'), '%frontend%')
|
||||
|
||||
@@ -12,10 +12,29 @@ import (
|
||||
"github.com/hanzoai/o11y/pkg/errors"
|
||||
"github.com/hanzoai/o11y/pkg/factory"
|
||||
"github.com/hanzoai/o11y/pkg/sqlstore"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrystore"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
"github.com/hanzoai/o11y/pkg/transition"
|
||||
)
|
||||
|
||||
// The three key tables both v5 migrations read. All three were qualified by
|
||||
// databases HIP-0132 dropped — o11y_logs and o11y_traces — so each migration
|
||||
// logged a warning and returned NO duplicate keys, which is indistinguishable
|
||||
// from "there are none". A migration that silently decides nothing needs
|
||||
// migrating is the false empty in its worst form: invisible in any UI, visible
|
||||
// six weeks later as a rule querying the wrong column.
|
||||
//
|
||||
// distributed_logs_attribute_keys IS event.log_key,
|
||||
// distributed_logs_resource_keys IS event.log_resource_key and
|
||||
// distributed_span_attributes_keys IS event.span_key.
|
||||
var (
|
||||
logKeyTable = telemetryplane.DBName + "." + telemetrylogs.LogKeyTableName
|
||||
logResourceKeyTable = telemetryplane.DBName + "." + telemetrylogs.LogResourceKeyTableName
|
||||
spanKeyTable = telemetryplane.DBName + "." + telemetrytraces.SpanKeyTableName
|
||||
)
|
||||
|
||||
type queryBuilderV5Migration struct {
|
||||
store sqlstore.SQLStore
|
||||
telemetryStore telemetrystore.TelemetryStore
|
||||
@@ -52,7 +71,7 @@ func (migration *queryBuilderV5Migration) Register(migrations *migrate.Migration
|
||||
func (migration *queryBuilderV5Migration) getTraceDuplicateKeys(ctx context.Context) ([]string, error) {
|
||||
query := `
|
||||
SELECT tagKey
|
||||
FROM o11y_traces.distributed_span_attributes_keys
|
||||
FROM ` + spanKeyTable + `
|
||||
WHERE tagType IN ('tag', 'resource')
|
||||
GROUP BY tagKey
|
||||
HAVING COUNT(DISTINCT tagType) > 1
|
||||
@@ -83,9 +102,9 @@ func (migration *queryBuilderV5Migration) getLogDuplicateKeys(ctx context.Contex
|
||||
query := `
|
||||
SELECT name
|
||||
FROM (
|
||||
SELECT DISTINCT name FROM o11y_logs.distributed_logs_attribute_keys
|
||||
SELECT DISTINCT name FROM ` + logKeyTable + `
|
||||
INTERSECT
|
||||
SELECT DISTINCT name FROM o11y_logs.distributed_logs_resource_keys
|
||||
SELECT DISTINCT name FROM ` + logResourceKeyTable + `
|
||||
)
|
||||
ORDER BY name
|
||||
`
|
||||
|
||||
@@ -48,9 +48,9 @@ func (migration *migrateRulesV4ToV5) getLogDuplicateKeys(ctx context.Context) ([
|
||||
query := `
|
||||
SELECT name
|
||||
FROM (
|
||||
SELECT DISTINCT name FROM o11y_logs.distributed_logs_attribute_keys
|
||||
SELECT DISTINCT name FROM ` + logKeyTable + `
|
||||
INTERSECT
|
||||
SELECT DISTINCT name FROM o11y_logs.distributed_logs_resource_keys
|
||||
SELECT DISTINCT name FROM ` + logResourceKeyTable + `
|
||||
)
|
||||
ORDER BY name
|
||||
`
|
||||
@@ -78,7 +78,7 @@ func (migration *migrateRulesV4ToV5) getLogDuplicateKeys(ctx context.Context) ([
|
||||
func (migration *migrateRulesV4ToV5) getTraceDuplicateKeys(ctx context.Context) ([]string, error) {
|
||||
query := `
|
||||
SELECT tagKey
|
||||
FROM o11y_traces.distributed_span_attributes_keys
|
||||
FROM ` + spanKeyTable + `
|
||||
WHERE tagType IN ('tag', 'resource')
|
||||
GROUP BY tagKey
|
||||
HAVING COUNT(DISTINCT tagType) > 1
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// addErrorTracking creates the one net-new table backing error/crash tracking:
|
||||
// o11y_issues (grouped-error lifecycle). Occurrences stay in the telemetry store
|
||||
// (o11y_traces / o11y_logs); only non-derivable lifecycle state lives here. The
|
||||
// (event.span / event.log); only non-derivable lifecycle state lives here. The
|
||||
// unique index on (org_id, fingerprint) is the grouping key the ingest upsert
|
||||
// conflicts on; (org_id, last_seen) serves the default list ordering.
|
||||
type addErrorTracking struct {
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
package telemetryaudit
|
||||
|
||||
import "github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
|
||||
// DBName is NOT the event plane. o11y_audit holds the audit trail, which has a
|
||||
// different retention and a different access gate from telemetry and was not in
|
||||
// HIP-0132's scope. The name is spelled in pkg/telemetryplane with the plane and
|
||||
// the other survivors.
|
||||
const (
|
||||
DBName = "o11y_audit"
|
||||
DBName = telemetryplane.AuditDBName
|
||||
AuditLogsTableName = "distributed_logs"
|
||||
AuditLogsLocalTableName = "logs"
|
||||
TagAttributesTableName = "distributed_tag_attributes"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package telemetrylogs
|
||||
|
||||
import "github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
|
||||
// Logs live in the ONE event database beside the other signals, as event.log:
|
||||
// singular, because a row is one log line. It carries the same 15-column envelope as
|
||||
// event.event / event.error / event.span, and is sorted (org, service, time) — the
|
||||
@@ -9,7 +11,7 @@ package telemetrylogs
|
||||
// name of a table are the same string. The pair is kept because the query builders
|
||||
// distinguish the two roles.
|
||||
const (
|
||||
DBName = "event"
|
||||
DBName = telemetryplane.DBName
|
||||
|
||||
LogTableName = "log"
|
||||
LogLocalTableName = "log"
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
package telemetrymetadata
|
||||
|
||||
import "github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
|
||||
// DBName is NOT the event plane, and that is deliberate.
|
||||
//
|
||||
// HIP-0132 unified the three SIGNAL databases — o11y_logs, o11y_traces,
|
||||
// o11y_metrics — into `event`, and dropped them. It did not touch o11y_metadata,
|
||||
// which the otel-collector metadata exporter still WRITES on every flush. A
|
||||
// reader repointed at `event` would stop reading a table that is being fed,
|
||||
// which is the same defect as reading a database that was dropped, pointed the
|
||||
// other way.
|
||||
//
|
||||
// The name is spelled in pkg/telemetryplane with the plane and the other three
|
||||
// survivors, so "which databases does this binary name?" has one answer.
|
||||
const (
|
||||
DBName = "o11y_metadata"
|
||||
DBName = telemetryplane.MetadataDBName
|
||||
AttributesMetadataTableName = "distributed_attributes_metadata"
|
||||
AttributesMetadataLocalTableName = "attributes_metadata"
|
||||
ColumnEvolutionMetadataTableName = "distributed_column_evolution_metadata"
|
||||
|
||||
@@ -4,11 +4,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/errors"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/types/metrictypes"
|
||||
)
|
||||
|
||||
// DBName is NOT the event plane. o11y_meter holds METERING — the billing-grade
|
||||
// usage counters — which HIP-0132 did not unify and no writer has left. The name
|
||||
// is spelled in pkg/telemetryplane beside the plane it is not part of, so
|
||||
// "which databases does this binary name?" has one answer.
|
||||
const (
|
||||
DBName = "o11y_meter"
|
||||
DBName = telemetryplane.MeterDBName
|
||||
SamplesTableName = "distributed_samples"
|
||||
SamplesLocalTableName = "samples"
|
||||
SamplesAgg1dTableName = "distributed_samples_agg_1d"
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/errors"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/types/metrictypes"
|
||||
)
|
||||
|
||||
@@ -20,7 +21,7 @@ import (
|
||||
// distinguish the two roles, and a sharded deployment would reintroduce the split in
|
||||
// exactly one place: here.
|
||||
const (
|
||||
DBName = "event"
|
||||
DBName = telemetryplane.DBName
|
||||
|
||||
DescriptorTableName = "descriptor"
|
||||
DescriptorLocalTableName = "descriptor"
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Package telemetryplane is the single answer to "which databases does this
|
||||
// binary name?".
|
||||
//
|
||||
// WHY IT EXISTS. HIP-0132 unified the three SIGNAL databases — o11y_logs,
|
||||
// o11y_traces, o11y_metrics — into one `event` database and dropped them. The
|
||||
// commit that restored the reads (5be9208c4e, "o11y: read the event plane")
|
||||
// pointed THREE files at `event` and said so in its own message:
|
||||
//
|
||||
// NOTE, deliberately left as-is: DBName is still a compile-time constant. It
|
||||
// is now a CORRECT hardcode rather than a wrong one, but one name in three
|
||||
// files is still three places to change.
|
||||
//
|
||||
// It was thirty files, not three. The other twenty-seven kept naming databases
|
||||
// that had been dropped, so every read through them answered
|
||||
// `Code: 81 ... UNKNOWN_DATABASE` — and the views on top of them rendered an
|
||||
// error boundary, or worse a FALSE EMPTY that told the customer to instrument an
|
||||
// already-instrumented application.
|
||||
//
|
||||
// This is that cut. A database name is a VALUE, so it has ONE address, and every
|
||||
// layer can reach it because this package imports nothing. The signal packages,
|
||||
// the legacy v3/v4 query builders, the Prometheus adapter and the query-service
|
||||
// constants sit at four different depths and some of them are imported BY
|
||||
// telemetrystore, so the constants cannot live there without a cycle.
|
||||
//
|
||||
// plane_test.go asserts that no OTHER file in the tree spells a database name.
|
||||
// That assertion is the point of the package: a new hardcode fails the build
|
||||
// instead of failing a customer's dashboard six weeks later.
|
||||
package telemetryplane
|
||||
|
||||
// DBName is the telemetry plane: ONE database holding every signal —
|
||||
// event.log, event.span, event.error and the metric tables. Every table in
|
||||
// every signal is qualified by this and nothing else.
|
||||
//
|
||||
// It is a constant, not config: a deployment that pointed half its readers at a
|
||||
// second database would be two planes wearing one name, and the failure mode is
|
||||
// the silent one — half the rows.
|
||||
const DBName = "event"
|
||||
|
||||
// THE DATABASES THAT ARE NOT THE PLANE.
|
||||
//
|
||||
// Listing them here is not an invitation to add more. It is what makes the
|
||||
// question answerable: "the plane, and these four" is checkable, while a name
|
||||
// spelled in whichever file happened to need it is not. Each has a live WRITER,
|
||||
// which is the whole reason it was out of HIP-0132's scope — repointing a reader
|
||||
// at `event` when the rows are still landing somewhere else is the same defect as
|
||||
// reading a dropped database, pointed the other way.
|
||||
//
|
||||
// Each name is aliased by exactly one package, which owns its table names too:
|
||||
//
|
||||
// MetadataDBName -> telemetrymetadata (otel-collector metadata exporter writes it)
|
||||
// MeterDBName -> telemetrymeter (metering/usage counters)
|
||||
// AuditDBName -> telemetryaudit (audit trail; separate retention and gate)
|
||||
// AnalyticsDBName -> implrulestatehistory (AddRuleStateHistory writes it)
|
||||
//
|
||||
// A name leaves this block by being MIGRATED — a writer moves, the rows move,
|
||||
// the alias becomes DBName — never by being deleted.
|
||||
const (
|
||||
MetadataDBName = "o11y_metadata"
|
||||
MeterDBName = "o11y_meter"
|
||||
AuditDBName = "o11y_audit"
|
||||
AnalyticsDBName = "o11y_analytics"
|
||||
)
|
||||
@@ -0,0 +1,268 @@
|
||||
package telemetryplane_test
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/telemetryaudit"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrylogs"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetadata"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymeter"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrymetrics"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
"github.com/hanzoai/o11y/pkg/telemetrytraces"
|
||||
)
|
||||
|
||||
// TestPlaneIsOneName pins the value. Everything below only checks that nothing
|
||||
// else spells it; this checks it is right.
|
||||
func TestPlaneIsOneName(t *testing.T) {
|
||||
assert.Equal(t, "event", telemetryplane.DBName)
|
||||
}
|
||||
|
||||
// TestEverySignalResolvesToThePlane is the assertion HIP-0132 needed and did not
|
||||
// have. The three signal packages each declared their own DBName; two of the
|
||||
// three were wrong for six weeks and nothing failed.
|
||||
func TestEverySignalResolvesToThePlane(t *testing.T) {
|
||||
for name, got := range map[string]string{
|
||||
"telemetrylogs": telemetrylogs.DBName,
|
||||
"telemetrytraces": telemetrytraces.DBName,
|
||||
"telemetrymetrics": telemetrymetrics.DBName,
|
||||
} {
|
||||
assert.Equalf(t, telemetryplane.DBName, got,
|
||||
"%s.DBName must BE the plane, not a copy of its current value", name)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSurvivorsAreAliasedNotRespelled — the four databases HIP-0132 did not
|
||||
// unify still exist and still have writers, so their names are real. What is not
|
||||
// allowed is spelling one twice: that is exactly how o11y_metadata ended up in
|
||||
// three files and o11y_analytics in two.
|
||||
func TestSurvivorsAreAliasedNotRespelled(t *testing.T) {
|
||||
assert.Equal(t, telemetryplane.MetadataDBName, telemetrymetadata.DBName)
|
||||
assert.Equal(t, telemetryplane.MeterDBName, telemetrymeter.DBName)
|
||||
assert.Equal(t, telemetryplane.AuditDBName, telemetryaudit.DBName)
|
||||
|
||||
// And none of the survivors is the plane — an alias that collapsed onto
|
||||
// `event` would silently read a database nothing writes.
|
||||
for _, survivor := range []string{
|
||||
telemetryplane.MetadataDBName,
|
||||
telemetryplane.MeterDBName,
|
||||
telemetryplane.AuditDBName,
|
||||
telemetryplane.AnalyticsDBName,
|
||||
} {
|
||||
assert.NotEqual(t, telemetryplane.DBName, survivor)
|
||||
}
|
||||
}
|
||||
|
||||
// dropped matches a database HIP-0132 DELETED, in either form a Go string
|
||||
// literal can carry it: bare (`"o11y_logs"`, how five constants held it) or as a
|
||||
// SQL qualifier (`"… FROM o11y_traces.distributed_o11y_index_v3"`, how nineteen
|
||||
// templates held it). Both forms shipped; both must be unreachable.
|
||||
//
|
||||
// It enumerates three names rather than matching `o11y_*` because
|
||||
// `o11y_calls_total` and `o11y_latency_bucket` are Prometheus metrics this fork
|
||||
// emits about ITSELF, not databases.
|
||||
var dropped = regexp.MustCompile(`o11y_(logs|traces|metrics)\b`)
|
||||
|
||||
// survivor matches the four databases HIP-0132 did NOT unify. They are real, so
|
||||
// naming one is not by itself a defect — spelling it in a second place is.
|
||||
var survivor = regexp.MustCompile(`^o11y_(metadata|meter|audit|analytics)$`)
|
||||
|
||||
// TestNoDroppedDatabaseIsNamedAnywhere is the point of the package.
|
||||
//
|
||||
// THE DEFECT THIS CATCHES IS THE ONE THAT HAPPENED. HIP-0132 dropped o11y_logs,
|
||||
// o11y_traces and o11y_metrics. A commit repointed THREE files at `event` and
|
||||
// left thirty spelling the dropped names, and the tree stayed GREEN — because a
|
||||
// string literal naming a database that no longer exists compiles perfectly, and
|
||||
// because the golden tests asserted the same dead SQL the readers emitted. Two
|
||||
// copies of a wrong answer agree with each other. The failure surfaced only in
|
||||
// production: 316 `Code: 81 UNKNOWN_DATABASE` in thirty minutes, five views
|
||||
// showing an error boundary or a false empty.
|
||||
//
|
||||
// That is why this walks TEST files too. A golden that encodes the broken SQL is
|
||||
// not a test, it is a second vote for the bug.
|
||||
//
|
||||
// It parses rather than greps, so a dropped name inside a COMMENT — of which
|
||||
// there are many, deliberately, recording what moved where — is not a finding.
|
||||
// Only a string literal in code is.
|
||||
func TestNoDroppedDatabaseIsNamedAnywhere(t *testing.T) {
|
||||
root := repoRoot(t)
|
||||
|
||||
type finding struct{ file, lit string }
|
||||
var findings []finding
|
||||
|
||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
switch info.Name() {
|
||||
case ".git", "node_modules", "frontend", "vendor", "attic":
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !strings.HasSuffix(path, ".go") {
|
||||
return nil
|
||||
}
|
||||
rel, relErr := filepath.Rel(root, path)
|
||||
if relErr != nil {
|
||||
return relErr
|
||||
}
|
||||
// This package is the one address. Its own test is where the names are
|
||||
// enumerated, so both are exempt.
|
||||
if strings.HasPrefix(rel, filepath.Join("pkg", "telemetryplane")) {
|
||||
return nil
|
||||
}
|
||||
// The datastore cutover migrations are a RECORD of the rename. They have
|
||||
// to say the old names; that is what a migration is.
|
||||
if strings.HasPrefix(rel, filepath.Join("deploy", "datastore")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
f, parseErr := parser.ParseFile(fset, path, nil, 0) // 0 => comments dropped
|
||||
if parseErr != nil {
|
||||
return nil // not our business to police unparseable files
|
||||
}
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
lit, ok := n.(*ast.BasicLit)
|
||||
if !ok || lit.Kind != token.STRING {
|
||||
return true
|
||||
}
|
||||
v, uqErr := strconv.Unquote(lit.Value)
|
||||
if uqErr != nil {
|
||||
return true
|
||||
}
|
||||
if m := dropped.FindString(v); m != "" {
|
||||
findings = append(findings, finding{
|
||||
file: rel + ":" + strconv.Itoa(fset.Position(lit.Pos()).Line),
|
||||
lit: m,
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
sort.Slice(findings, func(i, j int) bool { return findings[i].file < findings[j].file })
|
||||
if len(findings) > 0 {
|
||||
var b strings.Builder
|
||||
b.WriteString("a database HIP-0132 DROPPED is still named in code:\n")
|
||||
for _, f := range findings {
|
||||
b.WriteString(" " + f.file + " " + strconv.Quote(f.lit) + "\n")
|
||||
}
|
||||
b.WriteString("\nEvery read through one of these answers Code: 81 UNKNOWN_DATABASE.\n")
|
||||
b.WriteString("Use telemetryplane.DBName, and the table constants in\n")
|
||||
b.WriteString("pkg/telemetry{logs,traces,metrics}/tables.go for the tables.\n")
|
||||
t.Fatal(b.String())
|
||||
}
|
||||
}
|
||||
|
||||
// repoRoot walks up from this test file to the directory holding go.mod. The
|
||||
// walk above has to start from the repository, not from this package.
|
||||
func repoRoot(t *testing.T) string {
|
||||
t.Helper()
|
||||
dir, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
for {
|
||||
if _, statErr := os.Stat(filepath.Join(dir, "go.mod")); statErr == nil {
|
||||
return dir
|
||||
}
|
||||
parent := filepath.Dir(dir)
|
||||
require.NotEqual(t, dir, parent, "walked to / without finding go.mod")
|
||||
dir = parent
|
||||
}
|
||||
}
|
||||
|
||||
// TestSurvivorsAreSpelledOnce covers the other half. o11y_metadata, o11y_meter,
|
||||
// o11y_audit and o11y_analytics still exist and still have writers, so naming one
|
||||
// is correct — naming one TWICE is the defect, and it had already happened:
|
||||
// o11y_metadata was spelled in three files and o11y_analytics in two, which is
|
||||
// how a rename lands in one of them and not the others.
|
||||
//
|
||||
// Golden SQL fixtures are exempt: a fixture asserting
|
||||
// `FROM o11y_audit.distributed_logs` is asserting the SQL a live reader emits,
|
||||
// and it goes red on its own the moment that reader moves. What is checked here
|
||||
// is the BARE literal — a constant declaration — which is the form that drifts
|
||||
// silently.
|
||||
func TestSurvivorsAreSpelledOnce(t *testing.T) {
|
||||
root := repoRoot(t)
|
||||
|
||||
type finding struct{ file, lit string }
|
||||
var findings []finding
|
||||
|
||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
switch info.Name() {
|
||||
case ".git", "node_modules", "frontend", "vendor", "attic":
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if !strings.HasSuffix(path, ".go") {
|
||||
return nil
|
||||
}
|
||||
rel, relErr := filepath.Rel(root, path)
|
||||
if relErr != nil {
|
||||
return relErr
|
||||
}
|
||||
if strings.HasPrefix(rel, filepath.Join("pkg", "telemetryplane")) {
|
||||
return nil
|
||||
}
|
||||
if strings.HasPrefix(rel, filepath.Join("deploy", "datastore")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
f, parseErr := parser.ParseFile(fset, path, nil, 0)
|
||||
if parseErr != nil {
|
||||
return nil
|
||||
}
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
lit, ok := n.(*ast.BasicLit)
|
||||
if !ok || lit.Kind != token.STRING {
|
||||
return true
|
||||
}
|
||||
v, uqErr := strconv.Unquote(lit.Value)
|
||||
if uqErr != nil {
|
||||
return true
|
||||
}
|
||||
if survivor.MatchString(v) {
|
||||
findings = append(findings, finding{
|
||||
file: rel + ":" + strconv.Itoa(fset.Position(lit.Pos()).Line),
|
||||
lit: v,
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
sort.Slice(findings, func(i, j int) bool { return findings[i].file < findings[j].file })
|
||||
if len(findings) > 0 {
|
||||
var b strings.Builder
|
||||
b.WriteString("a database name is spelled outside pkg/telemetryplane:\n")
|
||||
for _, f := range findings {
|
||||
b.WriteString(" " + f.file + " " + strconv.Quote(f.lit) + "\n")
|
||||
}
|
||||
b.WriteString("\nUse the telemetryplane.<X>DBName alias. One value, one address.\n")
|
||||
t.Fatal(b.String())
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/hanzoai/o11y/pkg/flagger/flaggertest"
|
||||
"github.com/hanzoai/o11y/pkg/instrumentation/instrumentationtest"
|
||||
"github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
qbtypes "github.com/hanzoai/o11y/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/hanzoai/o11y/pkg/types/telemetrytypes"
|
||||
"github.com/hanzoai/o11y/pkg/types/telemetrytypes/telemetrytypestest"
|
||||
@@ -119,7 +120,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis-manual", "%service.name%", "%service.name\":\"redis-manual%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -134,7 +135,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE ((simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND (simpleJSONExtractString(labels, 'k8s.namespace.name') = ? AND labels LIKE ? AND labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE ((simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND (simpleJSONExtractString(labels, 'k8s.namespace.name') = ? AND labels LIKE ? AND labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis-manual", "%service.name%", "%service.name\":\"redis-manual%", "production", "%k8s.namespace.name%", "%k8s.namespace.name\":\"production%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -183,7 +184,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONExtractString(labels, 'service.name') ILIKE ? AND labels LIKE ? AND labels ILIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONExtractString(labels, 'service.name') ILIKE ? AND labels LIKE ? AND labels ILIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis%", "%service.name%", "%service.name%redis%%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -198,7 +199,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONHas(labels, 'service.name') = ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONHas(labels, 'service.name') = ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{true, "%service.name%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -213,7 +214,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONHas(labels, 'service.name') <> ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONHas(labels, 'service.name') <> ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{true, expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -228,7 +229,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE ((simpleJSONExtractString(labels, 'service.name') = ? OR simpleJSONExtractString(labels, 'service.name') = ?) AND labels LIKE ? AND (labels LIKE ? OR labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE ((simpleJSONExtractString(labels, 'service.name') = ? OR simpleJSONExtractString(labels, 'service.name') = ?) AND labels LIKE ? AND (labels LIKE ? OR labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis", "postgres", "%service.name%", "%service.name\":\"redis%", "%service.name\":\"postgres%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -243,7 +244,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE ((simpleJSONExtractString(labels, 'service.name') <> ? AND simpleJSONExtractString(labels, 'service.name') <> ?) AND (labels NOT LIKE ? AND labels NOT LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE ((simpleJSONExtractString(labels, 'service.name') <> ? AND simpleJSONExtractString(labels, 'service.name') <> ?) AND (labels NOT LIKE ? AND labels NOT LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis", "postgres", "%service.name\":\"redis%", "%service.name\":\"postgres%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -258,7 +259,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONExtractString(labels, 'service.name') ILIKE ? AND labels LIKE ? AND labels ILIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONExtractString(labels, 'service.name') ILIKE ? AND labels LIKE ? AND labels ILIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"%redis%", "%service.name%", "%service.name%redis%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -273,7 +274,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (match(simpleJSONExtractString(labels, 'service.name'), ?) AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (match(simpleJSONExtractString(labels, 'service.name'), ?) AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis.*", "%service.name%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -288,7 +289,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONExtractString(labels, 'service.name') <> ? AND labels NOT LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONExtractString(labels, 'service.name') <> ? AND labels NOT LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis", "%service.name\":\"redis%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -315,7 +316,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: 0,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis", "%service.name%", "%service.name\":\"redis%", expectedBucketStart},
|
||||
},
|
||||
},
|
||||
@@ -330,7 +331,7 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE NOT (((simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?))) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE NOT (((simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?))) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis", "%service.name%", "%service.name\":\"redis%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -355,8 +356,8 @@ func TestResourceFilterStatementBuilder_Traces(t *testing.T) {
|
||||
|
||||
builder := New[qbtypes.TraceAggregation](
|
||||
instrumentationtest.New().ToProviderSettings(),
|
||||
"o11y_traces",
|
||||
"distributed_traces_v3_resource",
|
||||
telemetryplane.DBName,
|
||||
"span_resource",
|
||||
telemetrytypes.SignalTraces,
|
||||
telemetrytypes.SourceUnspecified,
|
||||
mockMetadataStore,
|
||||
@@ -406,7 +407,7 @@ func TestResourceFilterStatementBuilder_Logs(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.log_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis-manual", "%service.name%", "%service.name\":\"redis-manual%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -443,7 +444,7 @@ func TestResourceFilterStatementBuilder_Logs(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE ((simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND (simpleJSONExtractString(labels, 'k8s.namespace.name') = ? AND labels LIKE ? AND labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.log_resource WHERE ((simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND (simpleJSONExtractString(labels, 'k8s.namespace.name') = ? AND labels LIKE ? AND labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis", "%service.name%", "%service.name\":\"redis%", "default", "%k8s.namespace.name%", "%k8s.namespace.name\":\"default%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -461,7 +462,7 @@ func TestResourceFilterStatementBuilder_Logs(t *testing.T) {
|
||||
start: uint64(1769976178000000000), // These will give bucket start 1769974378 and end 1770062578
|
||||
end: uint64(1770062578000000000),
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_logs.distributed_logs_v2_resource WHERE ((simpleJSONExtractString(labels, 'env') = ? AND labels LIKE ? AND labels LIKE ?) AND (simpleJSONExtractString(labels, 'k8s.deployment.name') = ? AND labels LIKE ? AND labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.log_resource WHERE ((simpleJSONExtractString(labels, 'env') = ? AND labels LIKE ? AND labels LIKE ?) AND (simpleJSONExtractString(labels, 'k8s.deployment.name') = ? AND labels LIKE ? AND labels LIKE ?)) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"prod", "%env%", "%env\":\"prod%", "prod-deployment", "%k8s.deployment.name%", "%k8s.deployment.name\":\"prod-deployment%", uint64(1769974378), uint64(1770062578)},
|
||||
},
|
||||
},
|
||||
@@ -549,8 +550,8 @@ func TestResourceFilterStatementBuilder_Logs(t *testing.T) {
|
||||
|
||||
builder := New[qbtypes.LogAggregation](
|
||||
instrumentationtest.New().ToProviderSettings(),
|
||||
"o11y_logs",
|
||||
"distributed_logs_v2_resource",
|
||||
telemetryplane.DBName,
|
||||
"log_resource",
|
||||
telemetrytypes.SignalLogs,
|
||||
telemetrytypes.SourceUnspecified,
|
||||
mockMetadataStore,
|
||||
@@ -606,7 +607,7 @@ func TestResourceFilterStatementBuilder_Variables(t *testing.T) {
|
||||
start: testStartNs,
|
||||
end: testEndNs,
|
||||
expected: &qbtypes.Statement{
|
||||
Query: "SELECT fingerprint FROM o11y_traces.distributed_traces_v3_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Query: "SELECT fingerprint FROM event.span_resource WHERE (simpleJSONExtractString(labels, 'service.name') = ? AND labels LIKE ? AND labels LIKE ?) AND seen_at_ts_bucket_start >= ? AND seen_at_ts_bucket_start <= ? GROUP BY fingerprint",
|
||||
Args: []any{"redis-manual", "%service.name%", "%service.name\":\"redis-manual%", expectedBucketStart, expectedBucketEnd},
|
||||
},
|
||||
},
|
||||
@@ -617,8 +618,8 @@ func TestResourceFilterStatementBuilder_Variables(t *testing.T) {
|
||||
|
||||
builder := New[qbtypes.TraceAggregation](
|
||||
instrumentationtest.New().ToProviderSettings(),
|
||||
"o11y_traces",
|
||||
"distributed_traces_v3_resource",
|
||||
telemetryplane.DBName,
|
||||
"span_resource",
|
||||
telemetrytypes.SignalTraces,
|
||||
telemetrytypes.SourceUnspecified,
|
||||
mockMetadataStore,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package telemetrytraces
|
||||
|
||||
import "github.com/hanzoai/o11y/pkg/telemetryplane"
|
||||
|
||||
// Spans live in the ONE event database beside the other signals, as event.span:
|
||||
// singular, because a row is one span. It carries the same 15-column envelope as
|
||||
// event.event / event.error / event.log, so correlating a span with an error is a
|
||||
@@ -10,7 +12,7 @@ package telemetrytraces
|
||||
// name of a table are the same string. The pair is kept because the query builders
|
||||
// distinguish the two roles.
|
||||
const (
|
||||
DBName = "event"
|
||||
DBName = telemetryplane.DBName
|
||||
|
||||
SpanTableName = "span"
|
||||
SpanLocalTableName = "span"
|
||||
|
||||
@@ -139,7 +139,7 @@ func TestTraceTimeRangeFinderQuery(t *testing.T) {
|
||||
SELECT
|
||||
toUnixTimestamp64Nano(min(timestamp)) as start_time,
|
||||
toUnixTimestamp64Nano(max(timestamp)) as end_time
|
||||
FROM o11y_traces.distributed_o11y_spans
|
||||
FROM event.span
|
||||
WHERE traceID = ?
|
||||
AND timestamp >= now() - INTERVAL 30 DAY
|
||||
`
|
||||
@@ -150,7 +150,7 @@ func TestTraceTimeRangeFinderQuery(t *testing.T) {
|
||||
SELECT
|
||||
toUnixTimestamp64Nano(min(timestamp)) as start_time,
|
||||
toUnixTimestamp64Nano(max(timestamp)) as end_time
|
||||
FROM o11y_traces.distributed_o11y_spans
|
||||
FROM event.span
|
||||
WHERE traceID = ?
|
||||
AND timestamp >= now() - INTERVAL 30 DAY
|
||||
`
|
||||
|
||||
@@ -39,8 +39,8 @@ func (s IssueStatus) Valid() bool {
|
||||
const DefaultLevel = "error"
|
||||
|
||||
// Issue is the grouped error — a fingerprint bucket. It is the ONE net-new table
|
||||
// backing error tracking. Occurrences live in the telemetry store (o11y_traces /
|
||||
// o11y_logs); only the lifecycle state that CANNOT be derived from telemetry —
|
||||
// backing error tracking. Occurrences live in the telemetry store (event.span /
|
||||
// event.log); only the lifecycle state that CANNOT be derived from telemetry —
|
||||
// status, assignee, first/last-seen, running count, regression — lives here.
|
||||
// Grouping is done at INGEST (the shim computes the fingerprint), so the Issues
|
||||
// list is a plain org-scoped SELECT, never an unscoped scan over an org-less
|
||||
|
||||
@@ -5,7 +5,7 @@ import "time"
|
||||
// Occurrence is a single normalized error event (one exception instance). It is
|
||||
// derived from a Sentry event (envelope / legacy store item) or, later, from an
|
||||
// OTel exception span-event. It is the OTel-shaped occurrence the shim persists
|
||||
// to o11y_logs (the reused occurrence store) and the "latest event" sample kept
|
||||
// to event.log (the reused occurrence store) and the "latest event" sample kept
|
||||
// on the issue for the detail view. Purely a value — no store, no tags of its own.
|
||||
type Occurrence struct {
|
||||
EventID string `json:"eventId"`
|
||||
|
||||
@@ -53,7 +53,7 @@ type EventStore interface {
|
||||
ListForFingerprint(ctx context.Context, orgID, projectID valuer.UUID, fingerprint string, limit int) ([]*Event, error)
|
||||
|
||||
// ListForTrace returns the (org, project)-scoped error events referencing a trace
|
||||
// id — the tenant-safe "errors in this trace" detail (the o11y_traces span plane is
|
||||
// id — the tenant-safe "errors in this trace" detail (the event.span plane is
|
||||
// NOT read: it has no general org column and cannot be tenant-scoped).
|
||||
ListForTrace(ctx context.Context, orgID, projectID valuer.UUID, traceID string, limit int) ([]*Event, error)
|
||||
|
||||
|
||||
@@ -15,12 +15,12 @@ func TestTransform(t *testing.T) {
|
||||
{
|
||||
name: "Example 1: Only service_name is __all__",
|
||||
sql: `SELECT trace_id, name, kind, status
|
||||
FROM o11y_traces.o11y_index_v3
|
||||
FROM event.span
|
||||
WHERE service_name = $service_name
|
||||
AND operation_name IN ($operation_names)
|
||||
AND duration >= $min_duration
|
||||
AND attributes['http.method'] = $http_method
|
||||
AND op IN (SELECT op FROM o11y_traces.operations WHERE service_name = $service_name AND kind = 'server')
|
||||
AND op IN (SELECT op FROM event.operation WHERE service_name = $service_name AND kind = 'server')
|
||||
AND timestamp BETWEEN $start_time AND $end_time`,
|
||||
|
||||
// Define our variables and their values/metadata
|
||||
@@ -62,17 +62,17 @@ WHERE service_name = $service_name
|
||||
FieldType: "scalar",
|
||||
},
|
||||
},
|
||||
expected: `SELECT trace_id, name, kind, status FROM o11y_traces.o11y_index_v3 WHERE operation_name IN ($operation_names) AND duration >= $min_duration AND attributes['http.method'] = $http_method AND op IN (SELECT op FROM o11y_traces.operations WHERE kind = 'server') AND timestamp BETWEEN $start_time AND $end_time;`,
|
||||
expected: `SELECT trace_id, name, kind, status FROM event.span WHERE operation_name IN ($operation_names) AND duration >= $min_duration AND attributes['http.method'] = $http_method AND op IN (SELECT op FROM event.operation WHERE kind = 'server') AND timestamp BETWEEN $start_time AND $end_time;`,
|
||||
},
|
||||
{
|
||||
name: "Example 2: Multiple __all__ selections and map lookups",
|
||||
sql: `SELECT trace_id, name, kind, status
|
||||
FROM o11y_traces.o11y_index_v3
|
||||
FROM event.span
|
||||
WHERE service_name = $service_name
|
||||
AND operation_name IN ($operation_names)
|
||||
AND duration >= $min_duration
|
||||
AND attributes['http.method'] = $http_method
|
||||
AND op IN (SELECT op FROM o11y_traces.operations WHERE service_name = $service_name AND kind = 'server')
|
||||
AND op IN (SELECT op FROM event.operation WHERE service_name = $service_name AND kind = 'server')
|
||||
AND timestamp BETWEEN $start_time AND $end_time`,
|
||||
|
||||
variables: []VariableValue{
|
||||
@@ -113,17 +113,17 @@ WHERE service_name = $service_name
|
||||
FieldType: "scalar",
|
||||
},
|
||||
},
|
||||
expected: `SELECT trace_id, name, kind, status FROM o11y_traces.o11y_index_v3 WHERE attributes['http.method'] = $http_method AND op IN (SELECT op FROM o11y_traces.operations WHERE kind = 'server') AND timestamp BETWEEN $start_time AND $end_time;`,
|
||||
expected: `SELECT trace_id, name, kind, status FROM event.span WHERE attributes['http.method'] = $http_method AND op IN (SELECT op FROM event.operation WHERE kind = 'server') AND timestamp BETWEEN $start_time AND $end_time;`,
|
||||
},
|
||||
{
|
||||
name: "Example 3: Multiple __all__ selections and map lookups",
|
||||
sql: `SELECT trace_id, name, kind, status
|
||||
FROM o11y_traces.o11y_index_v3
|
||||
FROM event.span
|
||||
WHERE service_name = $service_name
|
||||
AND operation_name IN ($operation_names)
|
||||
AND duration >= $min_duration
|
||||
AND attributes['http.method'] = $http_method
|
||||
AND op IN (SELECT op FROM o11y_traces.operations WHERE service_name = $service_name AND kind = 'server')
|
||||
AND op IN (SELECT op FROM event.operation WHERE service_name = $service_name AND kind = 'server')
|
||||
AND timestamp BETWEEN $start_time AND $end_time`,
|
||||
|
||||
variables: []VariableValue{
|
||||
@@ -152,17 +152,17 @@ WHERE service_name = $service_name
|
||||
FieldType: "map",
|
||||
},
|
||||
},
|
||||
expected: `SELECT trace_id, name, kind, status FROM o11y_traces.o11y_index_v3 WHERE op IN (SELECT op FROM o11y_traces.operations WHERE kind = 'server') AND timestamp BETWEEN $start_time AND $end_time;`,
|
||||
expected: `SELECT trace_id, name, kind, status FROM event.span WHERE op IN (SELECT op FROM event.operation WHERE kind = 'server') AND timestamp BETWEEN $start_time AND $end_time;`,
|
||||
},
|
||||
{
|
||||
name: "Example 3: Multiple __all__ selections and map lookups",
|
||||
sql: `SELECT trace_id, name, kind, status
|
||||
FROM o11y_traces.o11y_index_v3
|
||||
FROM event.span
|
||||
WHERE service_name = {{service_name}}
|
||||
AND operation_name IN {{.operation_names}}
|
||||
AND duration >= {{min_duration}}
|
||||
AND attributes['http.method'] = $http_method
|
||||
AND op IN (SELECT op FROM o11y_traces.operations WHERE service_name = {{service_name}} AND kind = 'server')`,
|
||||
AND op IN (SELECT op FROM event.operation WHERE service_name = {{service_name}} AND kind = 'server')`,
|
||||
|
||||
variables: []VariableValue{
|
||||
{
|
||||
@@ -190,7 +190,7 @@ WHERE service_name = {{service_name}}
|
||||
FieldType: "map",
|
||||
},
|
||||
},
|
||||
expected: `SELECT trace_id, name, kind, status FROM o11y_traces.o11y_index_v3 WHERE op IN (SELECT op FROM o11y_traces.operations WHERE kind = 'server');`,
|
||||
expected: `SELECT trace_id, name, kind, status FROM event.span WHERE op IN (SELECT op FROM event.operation WHERE kind = 'server');`,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@
|
||||
"@zap-proto/zap": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"typescript": "^5.6.0"
|
||||
"@types/node": "26.4.0",
|
||||
"typescript": "7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.12.0"
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.57.0-alpha-2025-10-09",
|
||||
"@types/node": "^20.0.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint-plugin-playwright": "^2.10.2",
|
||||
"oxfmt": "^0.41.0",
|
||||
"oxlint": "^1.59.0",
|
||||
"oxlint-tsgolint": "^0.20.0",
|
||||
"typescript": "^5.0.0"
|
||||
"@playwright/test": "^1.62.1",
|
||||
"@types/node": "26.4.0",
|
||||
"dotenv": "^17.4.2",
|
||||
"eslint-plugin-playwright": "^2.11.0",
|
||||
"oxfmt": "^0.65.0",
|
||||
"oxlint": "^1.80.0",
|
||||
"oxlint-tsgolint": "^7.0.2001",
|
||||
"typescript": "7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
|
||||
Reference in New Issue
Block a user