Merge pull request #4917 from SigNoz/release/v0.44

Release/v0.44
This commit is contained in:
Prashant Shahi 2024-04-25 19:26:25 +05:30 committed by GitHub
commit ee421af95c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 580 additions and 312 deletions

View File

@ -0,0 +1,31 @@
name: Jest Coverage - changed files
on:
pull_request:
branches: develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: "refs/heads/develop"
token: ${{ secrets.GITHUB_TOKEN }} # Provide the GitHub token for authentication
- name: Fetch branch
run: git fetch origin ${{ github.event.pull_request.head.ref }}
- run: |
git checkout ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: cd frontend && npm install -g yarn && yarn
- name: npm run test:changedsince
run: cd frontend && npm run i18n:generate-hash && npm run test:changedsince

View File

@ -22,7 +22,7 @@ x-clickhouse-defaults: &clickhouse-defaults
"wget", "wget",
"--spider", "--spider",
"-q", "-q",
"localhost:8123/ping" "0.0.0.0:8123/ping"
] ]
interval: 30s interval: 30s
timeout: 5s timeout: 5s
@ -146,7 +146,7 @@ services:
condition: on-failure condition: on-failure
query-service: query-service:
image: signoz/query-service:0.43.0 image: signoz/query-service:0.44.0
command: command:
[ [
"-config=/root/config/prometheus.yml", "-config=/root/config/prometheus.yml",
@ -186,7 +186,7 @@ services:
<<: *db-depend <<: *db-depend
frontend: frontend:
image: signoz/frontend:0.43.0 image: signoz/frontend:0.44.0
deploy: deploy:
restart_policy: restart_policy:
condition: on-failure condition: on-failure
@ -199,7 +199,7 @@ services:
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
otel-collector: otel-collector:
image: signoz/signoz-otel-collector:0.88.20 image: signoz/signoz-otel-collector:0.88.21
command: command:
[ [
"--config=/etc/otel-collector-config.yaml", "--config=/etc/otel-collector-config.yaml",
@ -237,7 +237,7 @@ services:
- query-service - query-service
otel-collector-migrator: otel-collector-migrator:
image: signoz/signoz-schema-migrator:0.88.20 image: signoz/signoz-schema-migrator:0.88.21
deploy: deploy:
restart_policy: restart_policy:
condition: on-failure condition: on-failure

View File

@ -111,18 +111,18 @@ processors:
exporters: exporters:
clickhousetraces: clickhousetraces:
datasource: tcp://clickhouse:9000/?database=signoz_traces datasource: tcp://clickhouse:9000/signoz_traces
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING} low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING}
clickhousemetricswrite: clickhousemetricswrite:
endpoint: tcp://clickhouse:9000/?database=signoz_metrics endpoint: tcp://clickhouse:9000/signoz_metrics
resource_to_telemetry_conversion: resource_to_telemetry_conversion:
enabled: true enabled: true
clickhousemetricswrite/prometheus: clickhousemetricswrite/prometheus:
endpoint: tcp://clickhouse:9000/?database=signoz_metrics endpoint: tcp://clickhouse:9000/signoz_metrics
# logging: {} # logging: {}
clickhouselogsexporter: clickhouselogsexporter:
dsn: tcp://clickhouse:9000/ dsn: tcp://clickhouse:9000/signoz_logs
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
timeout: 10s timeout: 10s
extensions: extensions:

View File

@ -22,4 +22,4 @@ rule_files:
scrape_configs: [] scrape_configs: []
remote_read: remote_read:
- url: tcp://clickhouse:9000/?database=signoz_metrics - url: tcp://clickhouse:9000/signoz_metrics

View File

@ -46,7 +46,7 @@ services:
"wget", "wget",
"--spider", "--spider",
"-q", "-q",
"localhost:8123/ping" "0.0.0.0:8123/ping"
] ]
interval: 30s interval: 30s
timeout: 5s timeout: 5s
@ -66,7 +66,7 @@ services:
- --storage.path=/data - --storage.path=/data
otel-collector-migrator: otel-collector-migrator:
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.20} image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.21}
container_name: otel-migrator container_name: otel-migrator
command: command:
- "--dsn=tcp://clickhouse:9000" - "--dsn=tcp://clickhouse:9000"
@ -81,7 +81,7 @@ services:
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
otel-collector: otel-collector:
container_name: signoz-otel-collector container_name: signoz-otel-collector
image: signoz/signoz-otel-collector:0.88.20 image: signoz/signoz-otel-collector:0.88.21
command: command:
[ [
"--config=/etc/otel-collector-config.yaml", "--config=/etc/otel-collector-config.yaml",

View File

@ -21,7 +21,7 @@ x-clickhouse-defaults: &clickhouse-defaults
"wget", "wget",
"--spider", "--spider",
"-q", "-q",
"localhost:8123/ping" "0.0.0.0:8123/ping"
] ]
interval: 30s interval: 30s
timeout: 5s timeout: 5s
@ -164,7 +164,7 @@ services:
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md` # Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
query-service: query-service:
image: signoz/query-service:${DOCKER_TAG:-0.43.0} image: signoz/query-service:${DOCKER_TAG:-0.44.0}
container_name: signoz-query-service container_name: signoz-query-service
command: command:
[ [
@ -203,7 +203,7 @@ services:
<<: *db-depend <<: *db-depend
frontend: frontend:
image: signoz/frontend:${DOCKER_TAG:-0.43.0} image: signoz/frontend:${DOCKER_TAG:-0.44.0}
container_name: signoz-frontend container_name: signoz-frontend
restart: on-failure restart: on-failure
depends_on: depends_on:
@ -215,7 +215,7 @@ services:
- ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf - ../common/nginx-config.conf:/etc/nginx/conf.d/default.conf
otel-collector-migrator: otel-collector-migrator:
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.20} image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.21}
container_name: otel-migrator container_name: otel-migrator
command: command:
- "--dsn=tcp://clickhouse:9000" - "--dsn=tcp://clickhouse:9000"
@ -229,7 +229,7 @@ services:
otel-collector: otel-collector:
image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.20} image: signoz/signoz-otel-collector:${OTELCOL_TAG:-0.88.21}
container_name: signoz-otel-collector container_name: signoz-otel-collector
command: command:
[ [

View File

@ -122,21 +122,20 @@ extensions:
exporters: exporters:
clickhousetraces: clickhousetraces:
datasource: tcp://clickhouse:9000/?database=signoz_traces datasource: tcp://clickhouse:9000/signoz_traces
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING} low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING}
clickhousemetricswrite: clickhousemetricswrite:
endpoint: tcp://clickhouse:9000/?database=signoz_metrics endpoint: tcp://clickhouse:9000/signoz_metrics
resource_to_telemetry_conversion: resource_to_telemetry_conversion:
enabled: true enabled: true
clickhousemetricswrite/prometheus: clickhousemetricswrite/prometheus:
endpoint: tcp://clickhouse:9000/?database=signoz_metrics endpoint: tcp://clickhouse:9000/signoz_metrics
# logging: {}
clickhouselogsexporter: clickhouselogsexporter:
dsn: tcp://clickhouse:9000/ dsn: tcp://clickhouse:9000/signoz_logs
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
timeout: 10s timeout: 10s
# logging: {}
service: service:
telemetry: telemetry:

View File

@ -22,4 +22,4 @@ rule_files:
scrape_configs: [] scrape_configs: []
remote_read: remote_read:
- url: tcp://clickhouse:9000/?database=signoz_metrics - url: tcp://clickhouse:9000/signoz_metrics

View File

@ -35,6 +35,14 @@ const config: Config.InitialOptions = {
browsers: ['chromium', 'firefox', 'webkit'], browsers: ['chromium', 'firefox', 'webkit'],
}, },
}, },
coverageThreshold: {
global: {
statements: 80,
branches: 65,
functions: 80,
lines: 80,
},
},
}; };
export default config; export default config;

View File

@ -21,7 +21,9 @@
"playwright:codegen:local": "playwright codegen http://localhost:3301", "playwright:codegen:local": "playwright codegen http://localhost:3301",
"playwright:codegen:local:auth": "yarn playwright:codegen:local --load-storage=tests/auth.json", "playwright:codegen:local:auth": "yarn playwright:codegen:local --load-storage=tests/auth.json",
"husky:configure": "cd .. && husky install frontend/.husky && cd frontend && chmod ug+x .husky/*", "husky:configure": "cd .. && husky install frontend/.husky && cd frontend && chmod ug+x .husky/*",
"commitlint": "commitlint --edit $1" "commitlint": "commitlint --edit $1",
"test": "jest --coverage",
"test:changedsince": "jest --changedSince=develop --coverage --silent"
}, },
"engines": { "engines": {
"node": ">=16.15.0" "node": ">=16.15.0"

View File

@ -1,8 +1,9 @@
/* eslint-disable react/jsx-props-no-spreading */ /* eslint-disable react/jsx-props-no-spreading */
import './DynamicColumnTable.syles.scss'; import './DynamicColumnTable.syles.scss';
import { Button, Dropdown, MenuProps, Switch } from 'antd'; import { Button, Dropdown, Flex, MenuProps, Switch } from 'antd';
import { ColumnsType } from 'antd/lib/table'; import { ColumnsType } from 'antd/lib/table';
import FacingIssueBtn from 'components/facingIssueBtn/FacingIssueBtn';
import { SlidersHorizontal } from 'lucide-react'; import { SlidersHorizontal } from 'lucide-react';
import { memo, useEffect, useState } from 'react'; import { memo, useEffect, useState } from 'react';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
@ -20,6 +21,7 @@ function DynamicColumnTable({
columns, columns,
dynamicColumns, dynamicColumns,
onDragColumn, onDragColumn,
facingIssueBtn,
...restProps ...restProps
}: DynamicColumnTableProps): JSX.Element { }: DynamicColumnTableProps): JSX.Element {
const [columnsData, setColumnsData] = useState<ColumnsType | undefined>( const [columnsData, setColumnsData] = useState<ColumnsType | undefined>(
@ -83,19 +85,22 @@ function DynamicColumnTable({
return ( return (
<div className="DynamicColumnTable"> <div className="DynamicColumnTable">
{dynamicColumns && ( <Flex justify="flex-end" align="center" gap={8}>
<Dropdown {facingIssueBtn && <FacingIssueBtn {...facingIssueBtn} />}
getPopupContainer={popupContainer} {dynamicColumns && (
menu={{ items }} <Dropdown
trigger={['click']} getPopupContainer={popupContainer}
> menu={{ items }}
<Button trigger={['click']}
className="dynamicColumnTable-button filter-btn" >
size="middle" <Button
icon={<SlidersHorizontal size={14} />} className="dynamicColumnTable-button filter-btn"
/> size="middle"
</Dropdown> icon={<SlidersHorizontal size={14} />}
)} />
</Dropdown>
)}
</Flex>
<ResizeTable <ResizeTable
columns={columnsData} columns={columnsData}

View File

@ -2,6 +2,7 @@
import { TableProps } from 'antd'; import { TableProps } from 'antd';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
import { ColumnGroupType, ColumnType } from 'antd/lib/table'; import { ColumnGroupType, ColumnType } from 'antd/lib/table';
import { FacingIssueBtnProps } from 'components/facingIssueBtn/FacingIssueBtn';
import { TableDataSource } from './contants'; import { TableDataSource } from './contants';
@ -12,6 +13,7 @@ export interface DynamicColumnTableProps extends TableProps<any> {
tablesource: typeof TableDataSource[keyof typeof TableDataSource]; tablesource: typeof TableDataSource[keyof typeof TableDataSource];
dynamicColumns: TableProps<any>['columns']; dynamicColumns: TableProps<any>['columns'];
onDragColumn?: (fromIndex: number, toIndex: number) => void; onDragColumn?: (fromIndex: number, toIndex: number) => void;
facingIssueBtn?: FacingIssueBtnProps;
} }
export type GetVisibleColumnsFunction = ( export type GetVisibleColumnsFunction = (

View File

@ -0,0 +1,9 @@
.facing-issue-button {
color: var(--bg-amber-500);
border-color: var(--bg-amber-500);
.ant-btn:hover {
color: var(--bg-amber-400) !important;
border-color: var(--bg-amber-300) !important;
}
}

View File

@ -0,0 +1,57 @@
import './FacingIssueBtn.style.scss';
import { Button } from 'antd';
import logEvent from 'api/common/logEvent';
import cx from 'classnames';
import { FeatureKeys } from 'constants/features';
import useFeatureFlags from 'hooks/useFeatureFlag';
import { defaultTo } from 'lodash-es';
import { HelpCircle } from 'lucide-react';
import { isCloudUser } from 'utils/app';
export interface FacingIssueBtnProps {
eventName: string;
attributes: Record<string, unknown>;
message?: string;
buttonText?: string;
className?: string;
}
function FacingIssueBtn({
attributes,
eventName,
message = '',
buttonText = '',
className = '',
}: FacingIssueBtnProps): JSX.Element | null {
const handleFacingIssuesClick = (): void => {
logEvent(eventName, attributes);
if (window.Intercom) {
window.Intercom('showNewMessage', defaultTo(message, ''));
}
};
const isChatSupportEnabled = useFeatureFlags(FeatureKeys.CHAT_SUPPORT)?.active;
const isCloudUserVal = isCloudUser();
return isCloudUserVal && isChatSupportEnabled ? ( // Note: we would need to move this condition to license based in future
<div className="facing-issue-button">
<Button
className={cx('periscope-btn', 'facing-issue-button', className)}
onClick={handleFacingIssuesClick}
icon={<HelpCircle size={14} />}
>
{buttonText || 'Facing issues?'}
</Button>
</div>
) : null;
}
FacingIssueBtn.defaultProps = {
message: '',
buttonText: '',
className: '',
};
export default FacingIssueBtn;

View File

@ -1,4 +1,5 @@
.billing-container { .billing-container {
margin-bottom: 40px;
padding-top: 36px; padding-top: 36px;
width: 65%; width: 65%;

View File

@ -2,6 +2,7 @@ import { Form, Row } from 'antd';
import { ENTITY_VERSION_V4 } from 'constants/app'; import { ENTITY_VERSION_V4 } from 'constants/app';
import FormAlertRules from 'container/FormAlertRules'; import FormAlertRules from 'container/FormAlertRules';
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam'; import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
import { isEqual } from 'lodash-es';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { AlertTypes } from 'types/api/alerts/alertTypes'; import { AlertTypes } from 'types/api/alerts/alertTypes';
@ -18,9 +19,7 @@ import SelectAlertType from './SelectAlertType';
function CreateRules(): JSX.Element { function CreateRules(): JSX.Element {
const [initValues, setInitValues] = useState<AlertDef | null>(null); const [initValues, setInitValues] = useState<AlertDef | null>(null);
const [alertType, setAlertType] = useState<AlertTypes>( const [alertType, setAlertType] = useState<AlertTypes>();
AlertTypes.METRICS_BASED_ALERT,
);
const location = useLocation(); const location = useLocation();
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
@ -56,10 +55,10 @@ function CreateRules(): JSX.Element {
} }
const dataSource = compositeQuery?.builder?.queryData[0]?.dataSource; const dataSource = compositeQuery?.builder?.queryData[0]?.dataSource;
const alertType = ALERT_TYPE_VS_SOURCE_MAPPING[dataSource]; const alertTypeFromQuery = ALERT_TYPE_VS_SOURCE_MAPPING[dataSource];
if (alertType) { if (alertTypeFromQuery && !isEqual(alertType, alertTypeFromQuery)) {
onSelectType(alertType); onSelectType(alertTypeFromQuery);
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [compositeQuery]); }, [compositeQuery]);

View File

@ -1,45 +1,50 @@
.create-alert-modal { .create-alert-modal {
.ant-modal-content { .ant-modal-content {
background-color: var(--bg-ink-300); background-color: var(--bg-ink-300);
.ant-modal-confirm-title { .ant-modal-confirm-title {
color: var(--bg-vanilla-100); color: var(--bg-vanilla-100);
} }
.ant-modal-confirm-content { .ant-modal-confirm-content {
.ant-typography { .ant-typography {
color: var(--bg-vanilla-100); color: var(--bg-vanilla-100);
} }
} }
.ant-modal-confirm-btns { .ant-modal-confirm-btns {
button:nth-of-type(1) { button:nth-of-type(1) {
background-color: var(--bg-slate-400); background-color: var(--bg-slate-400);
border: none; border: none;
color: var(--bg-vanilla-100); color: var(--bg-vanilla-100);
} }
} }
} }
} }
.lightMode { .lightMode {
.ant-modal-content { .ant-modal-content {
background-color: var(--bg-vanilla-100); background-color: var(--bg-vanilla-100);
.ant-modal-confirm-title { .ant-modal-confirm-title {
color: var(--bg-ink-500); color: var(--bg-ink-500);
} }
.ant-modal-confirm-content { .ant-modal-confirm-content {
.ant-typography { .ant-typography {
color: var(--bg-ink-500); color: var(--bg-ink-500);
} }
} }
.ant-modal-confirm-btns { .ant-modal-confirm-btns {
button:nth-of-type(1) { button:nth-of-type(1) {
background-color: var(--bg-vanilla-300); background-color: var(--bg-vanilla-300);
border: none; border: none;
color: var(--bg-ink-500); color: var(--bg-ink-500);
} }
} }
} }
}
.facing-issue-btn {
margin-top: 20px;
width: 100%;
} }

View File

@ -11,6 +11,7 @@ import {
} from 'antd'; } from 'antd';
import saveAlertApi from 'api/alerts/save'; import saveAlertApi from 'api/alerts/save';
import testAlertApi from 'api/alerts/testAlert'; import testAlertApi from 'api/alerts/testAlert';
import FacingIssueBtn from 'components/facingIssueBtn/FacingIssueBtn';
import { FeatureKeys } from 'constants/features'; import { FeatureKeys } from 'constants/features';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder'; import { PANEL_TYPES } from 'constants/queryBuilder';
@ -138,15 +139,21 @@ function FormAlertRules({
useEffect(() => { useEffect(() => {
// Set selectedQueryName based on the length of queryOptions // Set selectedQueryName based on the length of queryOptions
setAlertDef((def) => ({ const selectedQueryName = alertDef?.condition?.selectedQueryName;
...def, if (
condition: { !selectedQueryName ||
...def.condition, !queryOptions.some((option) => option.value === selectedQueryName)
selectedQueryName: ) {
queryOptions.length > 0 ? String(queryOptions[0].value) : undefined, setAlertDef((def) => ({
}, ...def,
})); condition: {
}, [currentQuery?.queryType, queryOptions]); ...def.condition,
selectedQueryName:
queryOptions.length > 0 ? String(queryOptions[0].value) : undefined,
},
}));
}
}, [alertDef, currentQuery?.queryType, queryOptions]);
const onCancelHandler = useCallback(() => { const onCancelHandler = useCallback(() => {
history.replace(ROUTES.LIST_ALL_ALERT); history.replace(ROUTES.LIST_ALL_ALERT);
@ -482,6 +489,8 @@ function FormAlertRules({
alertDef?.broadcastToAll || alertDef?.broadcastToAll ||
(alertDef.preferredChannels && alertDef.preferredChannels.length > 0); (alertDef.preferredChannels && alertDef.preferredChannels.length > 0);
const isRuleCreated = !ruleId || ruleId === 0;
return ( return (
<> <>
{Element} {Element}
@ -563,6 +572,30 @@ function FormAlertRules({
</StyledLeftContainer> </StyledLeftContainer>
<Col flex="1 1 300px"> <Col flex="1 1 300px">
<UserGuide queryType={currentQuery.queryType} /> <UserGuide queryType={currentQuery.queryType} />
<FacingIssueBtn
attributes={{
alert: alertDef?.alert,
alertType: alertDef?.alertType,
id: ruleId,
ruleType: alertDef?.ruleType,
state: (alertDef as any)?.state,
panelType,
screen: isRuleCreated ? 'Edit Alert' : 'New Alert',
}}
className="facing-issue-btn"
eventName="Alert: Facing Issues in alert"
buttonText="Facing Issues in alert"
message={`Hi Team,
I am facing issues configuring alerts in SigNoz. Here are my alert rule details
Name: ${alertDef?.alert || ''}
Alert Type: ${alertDef?.alertType || ''}
State: ${(alertDef as any)?.state || ''}
Alert Id: ${ruleId}
Thanks`}
/>
</Col> </Col>
</PanelContainer> </PanelContainer>
</> </>

View File

@ -1,7 +1,8 @@
import './GridCardLayout.styles.scss'; import './GridCardLayout.styles.scss';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import { Tooltip } from 'antd'; import { Flex, Tooltip } from 'antd';
import FacingIssueBtn from 'components/facingIssueBtn/FacingIssueBtn';
import { SOMETHING_WENT_WRONG } from 'constants/api'; import { SOMETHING_WENT_WRONG } from 'constants/api';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder'; import { PANEL_TYPES } from 'constants/queryBuilder';
@ -169,28 +170,47 @@ function GraphLayout({ onAddPanelHandler }: GraphLayoutProps): JSX.Element {
return ( return (
<> <>
<ButtonContainer> <Flex justify="flex-end" gap={8} align="center">
<Tooltip title="Open in Full Screen"> <FacingIssueBtn
<Button attributes={{
className="periscope-btn" uuid: selectedDashboard?.uuid,
loading={updateDashboardMutation.isLoading} title: data?.title,
onClick={handle.enter} screen: 'Dashboard Details',
icon={<FullscreenIcon size={16} />} }}
disabled={updateDashboardMutation.isLoading} eventName="Dashboard: Facing Issues in dashboard"
/> buttonText="Facing Issues in dashboard"
</Tooltip> message={`Hi Team,
{!isDashboardLocked && addPanelPermission && ( I am facing issues configuring dashboard in SigNoz. Here are my dashboard details
<Button
className="periscope-btn" Name: ${data?.title || ''}
onClick={onAddPanelHandler} Dashboard Id: ${selectedDashboard?.uuid || ''}
icon={<PlusOutlined />}
data-testid="add-panel" Thanks`}
> />
{t('dashboard:add_panel')} <ButtonContainer>
</Button> <Tooltip title="Open in Full Screen">
)} <Button
</ButtonContainer> className="periscope-btn"
loading={updateDashboardMutation.isLoading}
onClick={handle.enter}
icon={<FullscreenIcon size={16} />}
disabled={updateDashboardMutation.isLoading}
/>
</Tooltip>
{!isDashboardLocked && addPanelPermission && (
<Button
className="periscope-btn"
onClick={onAddPanelHandler}
icon={<PlusOutlined />}
data-testid="add-panel"
>
{t('dashboard:add_panel')}
</Button>
)}
</ButtonContainer>
</Flex>
<FullScreen handle={handle} className="fullscreen-grid-container"> <FullScreen handle={handle} className="fullscreen-grid-container">
<ReactGridLayout <ReactGridLayout

View File

@ -358,6 +358,18 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
pagination={{ pagination={{
defaultCurrent: Number(paginationParam) || 1, defaultCurrent: Number(paginationParam) || 1,
}} }}
facingIssueBtn={{
attributes: {
screen: 'Alert list page',
},
eventName: 'Alert: Facing Issues in alert',
buttonText: 'Facing Issues in alert',
message: `Hi Team,
I am facing issues with alerts.
Thanks`,
}}
/> />
</> </>
); );

View File

@ -385,6 +385,18 @@ function DashboardsList(): JSX.Element {
dataSource={data} dataSource={data}
onChange={handleChange} onChange={handleChange}
showSorterTooltip showSorterTooltip
facingIssueBtn={{
attributes: {
screen: 'Dashboard list page',
},
eventName: 'Dashboard: Facing Issues in dashboard',
buttonText: 'Facing Issues in dashboard',
message: `Hi Team,
I am facing issues with dashboards.
Thanks`,
}}
/> />
</TableContainer> </TableContainer>
</Card> </Card>

View File

@ -1,146 +1,59 @@
import { SOMETHING_WENT_WRONG } from 'constants/api';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder'; import { PANEL_TYPES } from 'constants/queryBuilder';
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
import { useNotifications } from 'hooks/useNotifications';
import createQueryParams from 'lib/createQueryParams'; import createQueryParams from 'lib/createQueryParams';
import history from 'lib/history'; import history from 'lib/history';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { LogsAggregatorOperator } from 'types/common/queryBuilder'; import { LogsAggregatorOperator } from 'types/common/queryBuilder';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { import { PANEL_TYPES_INITIAL_QUERY } from './constants';
listViewInitialLogQuery,
listViewInitialTraceQuery,
PANEL_TYPES_INITIAL_QUERY,
} from './constants';
import menuItems from './menuItems'; import menuItems from './menuItems';
import { Card, Container, Text } from './styles'; import { Card, Container, Text } from './styles';
function DashboardGraphSlider(): JSX.Element { function DashboardGraphSlider(): JSX.Element {
const { const { handleToggleDashboardSlider } = useDashboard();
handleToggleDashboardSlider,
layouts,
selectedDashboard,
} = useDashboard();
const { data } = selectedDashboard || {};
const { notifications } = useNotifications();
const updateDashboardMutation = useUpdateDashboard();
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
const onClickHandler = (name: PANEL_TYPES) => (): void => { const onClickHandler = (name: PANEL_TYPES) => (): void => {
const id = uuid(); const id = uuid();
handleToggleDashboardSlider(false);
updateDashboardMutation.mutateAsync( const queryParamsLog = {
{ graphType: name,
uuid: selectedDashboard?.uuid || '', widgetId: id,
data: { [QueryParams.compositeQuery]: JSON.stringify({
title: data?.title || '', ...PANEL_TYPES_INITIAL_QUERY[name],
variables: data?.variables || {}, builder: {
description: data?.description || '', ...PANEL_TYPES_INITIAL_QUERY[name].builder,
name: data?.name || '', queryData: [
tags: data?.tags || [],
version: data?.version || 'v3',
layout: [
{ {
i: id, ...PANEL_TYPES_INITIAL_QUERY[name].builder.queryData[0],
w: 6, aggregateOperator: LogsAggregatorOperator.NOOP,
x: 0, orderBy: [{ columnName: 'timestamp', order: 'desc' }],
h: 3, offset: 0,
y: 0, pageSize: 100,
},
...(layouts.filter((layout) => layout.i !== PANEL_TYPES.EMPTY_WIDGET) ||
[]),
],
widgets: [
...(data?.widgets || []),
{
id,
title: '',
description: '',
isStacked: false,
nullZeroValues: '',
opacity: '',
panelTypes: name,
query:
name === PANEL_TYPES.LIST
? listViewInitialLogQuery
: PANEL_TYPES_INITIAL_QUERY[name],
timePreferance: 'GLOBAL_TIME',
softMax: null,
softMin: null,
selectedLogFields: [
{
dataType: 'string',
type: '',
name: 'body',
},
{
dataType: 'string',
type: '',
name: 'timestamp',
},
],
selectedTracesFields: [
...listViewInitialTraceQuery.builder.queryData[0].selectColumns,
],
}, },
], ],
}, },
}, }),
{ };
onSuccess: (data) => {
if (data.payload) {
handleToggleDashboardSlider(false);
const queryParamsLog = {
graphType: name,
widgetId: id,
[QueryParams.compositeQuery]: JSON.stringify({
...PANEL_TYPES_INITIAL_QUERY[name],
builder: {
...PANEL_TYPES_INITIAL_QUERY[name].builder,
queryData: [
{
...PANEL_TYPES_INITIAL_QUERY[name].builder.queryData[0],
aggregateOperator: LogsAggregatorOperator.NOOP,
orderBy: [{ columnName: 'timestamp', order: 'desc' }],
offset: 0,
pageSize: 100,
},
],
},
}),
};
const queryParams = { const queryParams = {
graphType: name, graphType: name,
widgetId: id, widgetId: id,
[QueryParams.compositeQuery]: JSON.stringify( [QueryParams.compositeQuery]: JSON.stringify(
PANEL_TYPES_INITIAL_QUERY[name], PANEL_TYPES_INITIAL_QUERY[name],
), ),
}; };
if (name === PANEL_TYPES.LIST) { if (name === PANEL_TYPES.LIST) {
history.push( history.push(
`${history.location.pathname}/new?${createQueryParams(queryParamsLog)}`, `${history.location.pathname}/new?${createQueryParams(queryParamsLog)}`,
); );
} else { } else {
history.push( history.push(
`${history.location.pathname}/new?${createQueryParams(queryParams)}`, `${history.location.pathname}/new?${createQueryParams(queryParams)}`,
); );
} }
}
},
onError: () => {
notifications.success({
message: SOMETHING_WENT_WRONG,
});
},
},
);
}; };
return ( return (

View File

@ -72,6 +72,7 @@ function DashboardVariableSelection(): JSX.Element | null {
id: string, id: string,
value: IDashboardVariable['selectedValue'], value: IDashboardVariable['selectedValue'],
allSelected: boolean, allSelected: boolean,
// eslint-disable-next-line sonarjs/cognitive-complexity
): void => { ): void => {
if (id) { if (id) {
updateLocalStorageDashboardVariables(name, value, allSelected); updateLocalStorageDashboardVariables(name, value, allSelected);
@ -79,17 +80,29 @@ function DashboardVariableSelection(): JSX.Element | null {
if (selectedDashboard) { if (selectedDashboard) {
setSelectedDashboard((prev) => { setSelectedDashboard((prev) => {
if (prev) { if (prev) {
const oldVariables = prev?.data.variables;
// this is added to handle case where we have two different
// schemas for variable response
if (oldVariables[id]) {
oldVariables[id] = {
...oldVariables[id],
selectedValue: value,
allSelected,
};
}
if (oldVariables[name]) {
oldVariables[name] = {
...oldVariables[name],
selectedValue: value,
allSelected,
};
}
return { return {
...prev, ...prev,
data: { data: {
...prev?.data, ...prev?.data,
variables: { variables: {
...prev?.data.variables, ...oldVariables,
[id]: {
...prev.data.variables[id],
selectedValue: value,
allSelected,
},
}, },
}, },
}; };

View File

@ -4,6 +4,7 @@ import { Button, Tabs, Tooltip, Typography } from 'antd';
import TextToolTip from 'components/TextToolTip'; import TextToolTip from 'components/TextToolTip';
import { PANEL_TYPES } from 'constants/queryBuilder'; import { PANEL_TYPES } from 'constants/queryBuilder';
import { QBShortcuts } from 'constants/shortcuts/QBShortcuts'; import { QBShortcuts } from 'constants/shortcuts/QBShortcuts';
import { getDefaultWidgetData } from 'container/NewWidget/utils';
import { QueryBuilder } from 'container/QueryBuilder'; import { QueryBuilder } from 'container/QueryBuilder';
import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces'; import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interfaces';
import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys'; import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys';
@ -11,6 +12,7 @@ import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl'; import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval'; import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { defaultTo } from 'lodash-es';
import { Atom, Play, Terminal } from 'lucide-react'; import { Atom, Play, Terminal } from 'lucide-react';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { import {
@ -55,8 +57,11 @@ function QuerySection({
const getWidget = useCallback(() => { const getWidget = useCallback(() => {
const widgetId = urlQuery.get('widgetId'); const widgetId = urlQuery.get('widgetId');
return widgets?.find((e) => e.id === widgetId); return defaultTo(
}, [widgets, urlQuery]); widgets?.find((e) => e.id === widgetId),
getDefaultWidgetData(widgetId || '', selectedGraph),
);
}, [urlQuery, widgets, selectedGraph]);
const selectedWidget = getWidget() as Widgets; const selectedWidget = getWidget() as Widgets;

View File

@ -1,6 +1,7 @@
/* eslint-disable sonarjs/cognitive-complexity */ /* eslint-disable sonarjs/cognitive-complexity */
import { LockFilled, WarningOutlined } from '@ant-design/icons'; import { LockFilled, WarningOutlined } from '@ant-design/icons';
import { Button, Modal, Space, Tooltip, Typography } from 'antd'; import { Button, Flex, Modal, Space, Tooltip, Typography } from 'antd';
import FacingIssueBtn from 'components/facingIssueBtn/FacingIssueBtn';
import { SOMETHING_WENT_WRONG } from 'constants/api'; import { SOMETHING_WENT_WRONG } from 'constants/api';
import { FeatureKeys } from 'constants/features'; import { FeatureKeys } from 'constants/features';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
@ -14,6 +15,7 @@ import { MESSAGE, useIsFeatureDisabled } from 'hooks/useFeatureFlag';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history'; import history from 'lib/history';
import { defaultTo, isUndefined } from 'lodash-es';
import { DashboardWidgetPageParams } from 'pages/DashboardWidget'; import { DashboardWidgetPageParams } from 'pages/DashboardWidget';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { import {
@ -45,7 +47,11 @@ import {
RightContainerWrapper, RightContainerWrapper,
} from './styles'; } from './styles';
import { NewWidgetProps } from './types'; import { NewWidgetProps } from './types';
import { getIsQueryModified, handleQueryChange } from './utils'; import {
getDefaultWidgetData,
getIsQueryModified,
handleQueryChange,
} from './utils';
function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element { function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
const { const {
@ -80,10 +86,26 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
const { dashboardId } = useParams<DashboardWidgetPageParams>(); const { dashboardId } = useParams<DashboardWidgetPageParams>();
const [isNewDashboard, setIsNewDashboard] = useState<boolean>(false);
useEffect(() => {
const widgetId = query.get('widgetId');
const selectedWidget = widgets?.find((e) => e.id === widgetId);
const isWidgetNotPresent = isUndefined(selectedWidget);
if (isWidgetNotPresent) {
setIsNewDashboard(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const getWidget = useCallback(() => { const getWidget = useCallback(() => {
const widgetId = query.get('widgetId'); const widgetId = query.get('widgetId');
return widgets?.find((e) => e.id === widgetId); const selectedWidget = widgets?.find((e) => e.id === widgetId);
}, [query, widgets]); return defaultTo(
selectedWidget,
getDefaultWidgetData(widgetId || '', selectedGraph),
);
}, [query, selectedGraph, widgets]);
const [selectedWidget, setSelectedWidget] = useState(getWidget()); const [selectedWidget, setSelectedWidget] = useState(getWidget());
@ -227,6 +249,20 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
return; return;
} }
const widgetId = query.get('widgetId');
let updatedLayout = selectedDashboard.data.layout || [];
if (isNewDashboard) {
updatedLayout = [
{
i: widgetId || '',
w: 6,
x: 0,
h: 3,
y: 0,
},
...updatedLayout,
];
}
const dashboard: Dashboard = { const dashboard: Dashboard = {
...selectedDashboard, ...selectedDashboard,
uuid: selectedDashboard.uuid, uuid: selectedDashboard.uuid,
@ -254,6 +290,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
}, },
...afterWidgets, ...afterWidgets,
], ],
layout: [...updatedLayout],
}, },
}; };
@ -274,6 +311,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
}); });
}, [ }, [
selectedDashboard, selectedDashboard,
query,
isNewDashboard,
preWidgets, preWidgets,
selectedWidget, selectedWidget,
selectedTime.enum, selectedTime.enum,
@ -363,33 +402,55 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
return ( return (
<Container> <Container>
<ButtonContainer> <Flex justify="space-between" align="center">
{isSaveDisabled && ( <FacingIssueBtn
<Tooltip title={MESSAGE.PANEL}> attributes={{
uuid: selectedDashboard?.uuid,
title: selectedDashboard?.data.title,
panelType: graphType,
widgetId: query.get('widgetId'),
queryType: currentQuery.queryType,
}}
eventName="Dashboard: Facing Issues in dashboard"
buttonText="Facing Issues in dashboard"
message={`Hi Team,
I am facing issues configuring dashboard in SigNoz. Here are my dashboard details
Name: ${selectedDashboard?.data.title || ''}
Panel type: ${graphType}
Dashboard Id: ${selectedDashboard?.uuid || ''}
Thanks`}
/>
<ButtonContainer>
{isSaveDisabled && (
<Tooltip title={MESSAGE.PANEL}>
<Button
icon={<LockFilled />}
type="primary"
disabled={isSaveDisabled}
onClick={onSaveDashboard}
>
Save Changes
</Button>
</Tooltip>
)}
{!isSaveDisabled && (
<Button <Button
icon={<LockFilled />}
type="primary" type="primary"
data-testid="new-widget-save"
loading={updateDashboardMutation.isLoading}
disabled={isSaveDisabled} disabled={isSaveDisabled}
onClick={onSaveDashboard} onClick={onSaveDashboard}
> >
Save Changes Save Changes
</Button> </Button>
</Tooltip> )}
)} <Button onClick={onClickDiscardHandler}>Discard Changes</Button>
</ButtonContainer>
{!isSaveDisabled && ( </Flex>
<Button
type="primary"
data-testid="new-widget-save"
loading={updateDashboardMutation.isLoading}
disabled={isSaveDisabled}
onClick={onSaveDashboard}
>
Save Changes
</Button>
)}
<Button onClick={onClickDiscardHandler}>Discard Changes</Button>
</ButtonContainer>
<PanelContainer> <PanelContainer>
<LeftContainerWrapper flex={5}> <LeftContainerWrapper flex={5}>

View File

@ -3,7 +3,13 @@ import {
initialQueryBuilderFormValuesMap, initialQueryBuilderFormValuesMap,
PANEL_TYPES, PANEL_TYPES,
} from 'constants/queryBuilder'; } from 'constants/queryBuilder';
import {
listViewInitialLogQuery,
listViewInitialTraceQuery,
PANEL_TYPES_INITIAL_QUERY,
} from 'container/NewDashboard/ComponentsSlider/constants';
import { isEqual, set, unset } from 'lodash-es'; import { isEqual, set, unset } from 'lodash-es';
import { Widgets } from 'types/api/dashboard/getAll';
import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData'; import { IBuilderQuery, Query } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
@ -302,3 +308,38 @@ export function handleQueryChange(
}, },
}; };
} }
export const getDefaultWidgetData = (
id: string,
name: PANEL_TYPES,
): Widgets => ({
id,
title: '',
description: '',
isStacked: false,
nullZeroValues: '',
opacity: '',
panelTypes: name,
query:
name === PANEL_TYPES.LIST
? listViewInitialLogQuery
: PANEL_TYPES_INITIAL_QUERY[name],
timePreferance: 'GLOBAL_TIME',
softMax: null,
softMin: null,
selectedLogFields: [
{
dataType: 'string',
type: '',
name: 'body',
},
{
dataType: 'string',
type: '',
name: 'timestamp',
},
],
selectedTracesFields: [
...listViewInitialTraceQuery.builder.queryData[0].selectColumns,
],
});

View File

@ -10,6 +10,7 @@ import {
LeftCircleOutlined, LeftCircleOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { Button, Space, Steps, Typography } from 'antd'; import { Button, Space, Steps, Typography } from 'antd';
import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { stepsMap } from 'container/OnboardingContainer/constants/stepsConfig'; import { stepsMap } from 'container/OnboardingContainer/constants/stepsConfig';
import { DataSourceType } from 'container/OnboardingContainer/Steps/DataSource/DataSource'; import { DataSourceType } from 'container/OnboardingContainer/Steps/DataSource/DataSource';
@ -381,11 +382,12 @@ export default function ModuleStepsContainer({
}; };
const handleFacingIssuesClick = (): void => { const handleFacingIssuesClick = (): void => {
trackEvent('Onboarding V2: Facing Issues Sending Data to SigNoz', { logEvent('Onboarding V2: Facing Issues Sending Data to SigNoz', {
dataSource: selectedDataSource?.id, dataSource: selectedDataSource?.id,
framework: selectedFramework, framework: selectedFramework,
environment: selectedEnvironment, environment: selectedEnvironment,
module: activeStep?.module?.id, module: activeStep?.module?.id,
step: activeStep?.step?.id,
}); });
const message = `Hi Team, const message = `Hi Team,

View File

@ -105,8 +105,8 @@ export default function QBEntityOptions({
onQueryFunctionsUpdates && ( onQueryFunctionsUpdates && (
<QueryFunctions <QueryFunctions
query={query} query={query}
queryFunctions={query.functions} queryFunctions={query.functions || []}
key={query.functions.toString()} key={query.functions?.toString()}
onChange={onQueryFunctionsUpdates} onChange={onQueryFunctionsUpdates}
maxFunctions={isLogsDataSource ? 1 : 3} maxFunctions={isLogsDataSource ? 1 : 3}
/> />

View File

@ -24,7 +24,14 @@ export const getTraceLink = (record: RowData): string =>
export const getListColumns = ( export const getListColumns = (
selectedColumns: BaseAutocompleteData[], selectedColumns: BaseAutocompleteData[],
): ColumnsType<RowData> => { ): ColumnsType<RowData> => {
const initialColumns: ColumnsType<RowData> = []; const initialColumns: ColumnsType<RowData> = [
{
dataIndex: 'date',
key: 'date',
title: 'Timestamp',
width: 145,
},
];
const columns: ColumnsType<RowData> = const columns: ColumnsType<RowData> =
selectedColumns.map(({ dataType, key, type }) => ({ selectedColumns.map(({ dataType, key, type }) => ({

View File

@ -49,15 +49,11 @@ function DashboardWidget(): JSX.Element | null {
); );
} }
if (selectedWidget === undefined) {
return null;
}
return ( return (
<NewWidget <NewWidget
yAxisUnit={selectedWidget.yAxisUnit} yAxisUnit={selectedWidget?.yAxisUnit}
selectedGraph={selectedGraph} selectedGraph={selectedGraph}
fillSpans={selectedWidget.fillSpans} fillSpans={selectedWidget?.fillSpans}
/> />
); );
} }

View File

@ -176,8 +176,6 @@ export function DashboardProvider({
return data; return data;
}; };
console.log(variablesToGetUpdated);
const dashboardResponse = useQuery( const dashboardResponse = useQuery(
[REACT_QUERY_KEY.DASHBOARD_BY_ID, isDashboardPage?.params], [REACT_QUERY_KEY.DASHBOARD_BY_ID, isDashboardPage?.params],
{ {

11
go.mod
View File

@ -6,7 +6,7 @@ require (
github.com/ClickHouse/clickhouse-go/v2 v2.20.0 github.com/ClickHouse/clickhouse-go/v2 v2.20.0
github.com/DATA-DOG/go-sqlmock v1.5.2 github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd
github.com/SigNoz/signoz-otel-collector v0.88.20 github.com/SigNoz/signoz-otel-collector v0.88.21
github.com/SigNoz/zap_otlp/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974 github.com/SigNoz/zap_otlp/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974
github.com/SigNoz/zap_otlp/zap_otlp_sync v0.0.0-20230822164844-1b861a431974 github.com/SigNoz/zap_otlp/zap_otlp_sync v0.0.0-20230822164844-1b861a431974
github.com/antonmedv/expr v1.15.3 github.com/antonmedv/expr v1.15.3
@ -46,7 +46,6 @@ require (
github.com/russellhaering/goxmldsig v1.2.0 github.com/russellhaering/goxmldsig v1.2.0
github.com/samber/lo v1.38.1 github.com/samber/lo v1.38.1
github.com/sethvargo/go-password v0.2.0 github.com/sethvargo/go-password v0.2.0
github.com/smartystreets/assertions v1.13.1
github.com/smartystreets/goconvey v1.8.1 github.com/smartystreets/goconvey v1.8.1
github.com/soheilhy/cmux v0.1.5 github.com/soheilhy/cmux v0.1.5
github.com/srikanthccv/ClickHouse-go-mock v0.7.0 github.com/srikanthccv/ClickHouse-go-mock v0.7.0
@ -66,9 +65,9 @@ require (
go.opentelemetry.io/otel/sdk v1.23.1 go.opentelemetry.io/otel/sdk v1.23.1
go.uber.org/multierr v1.11.0 go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0 go.uber.org/zap v1.27.0
golang.org/x/crypto v0.19.0 golang.org/x/crypto v0.21.0
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
golang.org/x/net v0.21.0 golang.org/x/net v0.23.0
golang.org/x/oauth2 v0.16.0 golang.org/x/oauth2 v0.16.0
google.golang.org/grpc v1.62.0 google.golang.org/grpc v1.62.0
google.golang.org/protobuf v1.33.0 google.golang.org/protobuf v1.33.0
@ -190,7 +189,7 @@ require (
go.uber.org/atomic v1.11.0 // indirect go.uber.org/atomic v1.11.0 // indirect
go.uber.org/goleak v1.3.0 // indirect go.uber.org/goleak v1.3.0 // indirect
golang.org/x/sync v0.6.0 // indirect golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.17.0 // indirect golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
gonum.org/v1/gonum v0.14.0 // indirect gonum.org/v1/gonum v0.14.0 // indirect
@ -203,4 +202,4 @@ require (
k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect
) )
replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.10.1 replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.11.0

26
go.sum
View File

@ -96,10 +96,10 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd h1:Bk43AsDYe0fhkbj57eGXx8H3ZJ4zhmQXBnrW523ktj8= github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd h1:Bk43AsDYe0fhkbj57eGXx8H3ZJ4zhmQXBnrW523ktj8=
github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd/go.mod h1:nxRcH/OEdM8QxzH37xkGzomr1O0JpYBRS6pwjsWW6Pc= github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd/go.mod h1:nxRcH/OEdM8QxzH37xkGzomr1O0JpYBRS6pwjsWW6Pc=
github.com/SigNoz/prometheus v1.10.1 h1:2LKRtPDMgSJpgDRDy0GUQiXi+yhDNqcbptuEon4Wpls= github.com/SigNoz/prometheus v1.11.0 h1:toX7fU2wqY1TnzvPzDglIYx6OxpqrZ0NNlM/H5S5+u8=
github.com/SigNoz/prometheus v1.10.1/go.mod h1:MffmFu2qFILQrOHehx3D0XjYtaZMVfI+Ppeiv98x4Ww= github.com/SigNoz/prometheus v1.11.0/go.mod h1:MffmFu2qFILQrOHehx3D0XjYtaZMVfI+Ppeiv98x4Ww=
github.com/SigNoz/signoz-otel-collector v0.88.20 h1:saC1unOxkpw4VCKyPsIIUq37vKkQ5fK/eDlnuHMm0UE= github.com/SigNoz/signoz-otel-collector v0.88.21 h1:9K1FLUncUZh7cPfOLDPuT8itU8LyCufk4QwGp18hK88=
github.com/SigNoz/signoz-otel-collector v0.88.20/go.mod h1:PThU+A6SgzEotT3ngKN4WVGWW0+eS7F1a2Rnq11aZZA= github.com/SigNoz/signoz-otel-collector v0.88.21/go.mod h1:sT1EM9PFDaOJLbAz5npWpgXK6OhpWJ9PpSwyhHWs9rU=
github.com/SigNoz/zap_otlp v0.1.0 h1:T7rRcFN87GavY8lDGZj0Z3Xv6OhJA6Pj3I9dNPmqvRc= github.com/SigNoz/zap_otlp v0.1.0 h1:T7rRcFN87GavY8lDGZj0Z3Xv6OhJA6Pj3I9dNPmqvRc=
github.com/SigNoz/zap_otlp v0.1.0/go.mod h1:lcHvbDbRgvDnPxo9lDlaL1JK2PyOyouP/C3ynnYIvyo= github.com/SigNoz/zap_otlp v0.1.0/go.mod h1:lcHvbDbRgvDnPxo9lDlaL1JK2PyOyouP/C3ynnYIvyo=
github.com/SigNoz/zap_otlp/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974 h1:PKVgdf83Yw+lZJbFtNGBgqXiXNf3+kOXW2qZ7Ms7OaY= github.com/SigNoz/zap_otlp/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974 h1:PKVgdf83Yw+lZJbFtNGBgqXiXNf3+kOXW2qZ7Ms7OaY=
@ -777,8 +777,6 @@ github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGB
github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/assertions v1.13.1 h1:Ef7KhSmjZcK6AVf9YbJdvPYG9avaF0ZxudX+ThRdWfU=
github.com/smartystreets/assertions v1.13.1/go.mod h1:cXr/IwVfSo/RbCSPhoAPv73p3hlSdrBH/b3SdnW/LMY=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY=
@ -946,8 +944,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -1044,8 +1042,8 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1179,13 +1177,13 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

View File

@ -252,6 +252,8 @@ func buildLogsQuery(panelType v3.PanelType, start, end, step int64, mq *v3.Build
} else if panelType == v3.PanelTypeTable { } else if panelType == v3.PanelTypeTable {
queryTmpl = queryTmpl =
"SELECT now() as ts," "SELECT now() as ts,"
// step or aggregate interval is whole time period in case of table panel
step = (utils.GetEpochNanoSecs(end) - utils.GetEpochNanoSecs(start)) / 1000000000
} else if panelType == v3.PanelTypeGraph || panelType == v3.PanelTypeValue { } else if panelType == v3.PanelTypeGraph || panelType == v3.PanelTypeValue {
// Select the aggregate value for interval // Select the aggregate value for interval
queryTmpl = queryTmpl =

View File

@ -906,6 +906,23 @@ var testBuildLogsQueryData = []struct {
TableName: "logs", TableName: "logs",
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, toFloat64(count(*)) as value from signoz_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 signoz_logs.distributed_logs 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",
PanelType: v3.PanelTypeTable,
Start: 1680066360726210000,
End: 1680066458000000000,
BuilderQuery: &v3.BuilderQuery{
QueryName: "A",
StepInterval: 60,
AggregateOperator: v3.AggregateOperatorRate,
Expression: "A",
GroupBy: []v3.AttributeKey{
{Key: "name", DataType: v3.AttributeKeyDataTypeString, Type: v3.AttributeKeyTypeTag},
},
},
TableName: "logs",
ExpectedQuery: "SELECT now() as ts, attributes_string_value[indexOf(attributes_string_key, 'name')] as `name`, count()/97.000000 as value from signoz_logs.distributed_logs 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", Name: "TABLE: Test count with groupBy, orderBy",
PanelType: v3.PanelTypeTable, PanelType: v3.PanelTypeTable,

View File

@ -52,10 +52,10 @@ extensions:
zpages: {} zpages: {}
exporters: exporters:
clickhousetraces: clickhousetraces:
datasource: tcp://localhost:9000/?database=signoz_traces datasource: tcp://localhost:9000/signoz_traces
migrations: exporter/clickhousetracesexporter/migrations migrations: exporter/clickhousetracesexporter/migrations
clickhousemetricswrite: clickhousemetricswrite:
endpoint: tcp://localhost:9000/?database=signoz_metrics endpoint: tcp://localhost:9000/signoz_metrics
resource_to_telemetry_conversion: resource_to_telemetry_conversion:
enabled: true enabled: true
prometheus: prometheus:

View File

@ -262,6 +262,8 @@ func buildTracesQuery(start, end, step int64, mq *v3.BuilderQuery, tableName str
} else if panelType == v3.PanelTypeTable { } else if panelType == v3.PanelTypeTable {
queryTmpl = queryTmpl =
"SELECT now() as ts," "SELECT now() as ts,"
// step or aggregate interval is whole time period in case of table panel
step = (end*getZerosForEpochNano(end) - start*getZerosForEpochNano(start))/1000000000
} else if panelType == v3.PanelTypeGraph || panelType == v3.PanelTypeValue { } else if panelType == v3.PanelTypeGraph || panelType == v3.PanelTypeValue {
// Select the aggregate value for interval // Select the aggregate value for interval
queryTmpl = queryTmpl =

View File

@ -1017,7 +1017,7 @@ var testBuildTracesQueryData = []struct {
PanelType: v3.PanelTypeValue, PanelType: v3.PanelTypeValue,
}, },
{ {
Name: "Test aggregate PXX", Name: "Test aggregate PXX with groupby",
Start: 1680066360726210000, Start: 1680066360726210000,
End: 1680066458000000000, End: 1680066458000000000,
BuilderQuery: &v3.BuilderQuery{ BuilderQuery: &v3.BuilderQuery{
@ -1059,6 +1059,26 @@ var testBuildTracesQueryData = []struct {
"where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000')", "where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000')",
PanelType: v3.PanelTypeTable, PanelType: v3.PanelTypeTable,
}, },
{
Name: "Test aggregate rate table panel",
Start: 1680066360726210000,
End: 1680066458000000000,
BuilderQuery: &v3.BuilderQuery{
QueryName: "A",
StepInterval: 60,
AggregateAttribute: v3.AttributeKey{Key: "durationNano", IsColumn: true, DataType: v3.AttributeKeyDataTypeFloat64, Type: v3.AttributeKeyTypeTag},
AggregateOperator: v3.AggregateOperatorRate,
Expression: "A",
Filters: &v3.FilterSet{Operator: "AND", Items: []v3.FilterItem{}},
GroupBy: []v3.AttributeKey{},
OrderBy: []v3.OrderBy{},
},
TableName: "signoz_traces.distributed_signoz_index_v2",
ExpectedQuery: "SELECT now() as ts, count(durationNano)/97.000000 as value " +
"from signoz_traces.distributed_signoz_index_v2 " +
"where (timestamp >= '1680066360726210000' AND timestamp <= '1680066458000000000')",
PanelType: v3.PanelTypeTable,
},
{ {
Name: "Test Noop list view", Name: "Test Noop list view",
Start: 1680066360726210000, Start: 1680066360726210000,

View File

@ -22,4 +22,4 @@ rule_files:
scrape_configs: [] scrape_configs: []
remote_read: remote_read:
- url: tcp://localhost:9000/?database=signoz_metrics - url: tcp://localhost:9000/signoz_metrics

View File

@ -20,7 +20,7 @@ x-clickhouse-defaults: &clickhouse-defaults
"wget", "wget",
"--spider", "--spider",
"-q", "-q",
"localhost:8123/ping" "0.0.0.0:8123/ping"
] ]
interval: 30s interval: 30s
timeout: 5s timeout: 5s
@ -192,7 +192,7 @@ services:
<<: *db-depend <<: *db-depend
otel-collector-migrator: otel-collector-migrator:
image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.20} image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.21}
container_name: otel-migrator container_name: otel-migrator
command: command:
- "--dsn=tcp://clickhouse:9000" - "--dsn=tcp://clickhouse:9000"
@ -205,7 +205,7 @@ services:
# condition: service_healthy # condition: service_healthy
otel-collector: otel-collector:
image: signoz/signoz-otel-collector:0.88.20 image: signoz/signoz-otel-collector:0.88.21
container_name: signoz-otel-collector container_name: signoz-otel-collector
command: command:
[ [

View File

@ -101,21 +101,20 @@ extensions:
exporters: exporters:
clickhousetraces: clickhousetraces:
datasource: tcp://clickhouse:9000/?database=signoz_traces datasource: tcp://clickhouse:9000/signoz_traces
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING} low_cardinal_exception_grouping: ${LOW_CARDINAL_EXCEPTION_GROUPING}
clickhousemetricswrite: clickhousemetricswrite:
endpoint: tcp://clickhouse:9000/?database=signoz_metrics endpoint: tcp://clickhouse:9000/signoz_metrics
resource_to_telemetry_conversion: resource_to_telemetry_conversion:
enabled: true enabled: true
prometheus: prometheus:
endpoint: 0.0.0.0:8889 endpoint: 0.0.0.0:8889
# logging: {}
clickhouselogsexporter: clickhouselogsexporter:
dsn: tcp://clickhouse:9000/ dsn: tcp://clickhouse:9000/signoz_logs
docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER} docker_multi_node_cluster: ${DOCKER_MULTI_NODE_CLUSTER}
timeout: 10s timeout: 10s
# logging: {}
service: service:
telemetry: telemetry:

View File

@ -22,4 +22,4 @@ rule_files:
scrape_configs: [] scrape_configs: []
remote_read: remote_read:
- url: tcp://clickhouse:9000/?database=signoz_metrics - url: tcp://clickhouse:9000/signoz_metrics