@@ -399,17 +431,29 @@ export default function BillingContainer(): JSX.Element {
) : null}
-
+
+ }
+ >
+ Download CSV
+
+
+
{licensesData?.payload?.onTrial &&
diff --git a/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx b/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx
index 0aecc5d102..3afee8d0d6 100644
--- a/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx
+++ b/frontend/src/container/BillingContainer/BillingUsageGraph/BillingUsageGraph.tsx
@@ -166,6 +166,7 @@ export function BillingUsageGraph(props: BillingUsageGraphProps): JSX.Element {
),
yAxisUnit: '',
isBillingUsageGraphs: true,
+ isDarkMode,
}),
],
}),
diff --git a/frontend/src/container/BillingContainer/BillingUsageGraph/generateCsvData.ts b/frontend/src/container/BillingContainer/BillingUsageGraph/generateCsvData.ts
new file mode 100644
index 0000000000..b70526aaa8
--- /dev/null
+++ b/frontend/src/container/BillingContainer/BillingUsageGraph/generateCsvData.ts
@@ -0,0 +1,129 @@
+import dayjs from 'dayjs';
+
+export interface QuantityData {
+ metric: string;
+ values: [number, number][];
+ queryName: string;
+ legend: string;
+ quantity: number[];
+ unit: string;
+}
+
+interface DataPoint {
+ date: string;
+ metric: {
+ total: number;
+ cost: number;
+ };
+ trace: {
+ total: number;
+ cost: number;
+ };
+ log: {
+ total: number;
+ cost: number;
+ };
+}
+
+interface CsvData {
+ Date: string;
+ 'Metrics Vol (Mn samples)': number;
+ 'Metrics Cost ($)': number;
+ 'Traces Vol (GBs)': number;
+ 'Traces Cost ($)': number;
+ 'Logs Vol (GBs)': number;
+ 'Logs Cost ($)': number;
+}
+
+const formatDate = (timestamp: number): string =>
+ dayjs.unix(timestamp).format('MM/DD/YYYY');
+
+const getQuantityData = (
+ data: QuantityData[],
+ metricName: string,
+): QuantityData => {
+ const defaultData: QuantityData = {
+ metric: metricName,
+ values: [],
+ queryName: metricName,
+ legend: metricName,
+ quantity: [],
+ unit: '',
+ };
+ return data.find((d) => d.metric === metricName) || defaultData;
+};
+
+const generateCsvData = (quantityData: QuantityData[]): any[] => {
+ const convertData = (data: QuantityData[]): DataPoint[] => {
+ const metricsData = getQuantityData(data, 'Metrics');
+ const tracesData = getQuantityData(data, 'Traces');
+ const logsData = getQuantityData(data, 'Logs');
+
+ const timestamps = metricsData.values.map((value) => value[0]);
+
+ return timestamps.map((timestamp, index) => {
+ const date = formatDate(timestamp);
+
+ return {
+ date,
+ metric: {
+ total: metricsData.quantity[index] ?? 0,
+ cost: metricsData.values[index]?.[1] ?? 0,
+ },
+ trace: {
+ total: tracesData.quantity[index] ?? 0,
+ cost: tracesData.values[index]?.[1] ?? 0,
+ },
+ log: {
+ total: logsData.quantity[index] ?? 0,
+ cost: logsData.values[index]?.[1] ?? 0,
+ },
+ };
+ });
+ };
+
+ const formattedData = convertData(quantityData);
+
+ // Calculate totals
+ const totals = formattedData.reduce(
+ (acc, dataPoint) => {
+ acc.metric.total += dataPoint.metric.total;
+ acc.metric.cost += dataPoint.metric.cost;
+ acc.trace.total += dataPoint.trace.total;
+ acc.trace.cost += dataPoint.trace.cost;
+ acc.log.total += dataPoint.log.total;
+ acc.log.cost += dataPoint.log.cost;
+ return acc;
+ },
+ {
+ metric: { total: 0, cost: 0 },
+ trace: { total: 0, cost: 0 },
+ log: { total: 0, cost: 0 },
+ },
+ );
+
+ const csvData: CsvData[] = formattedData.map((dataPoint) => ({
+ Date: dataPoint.date,
+ 'Metrics Vol (Mn samples)': parseFloat(dataPoint.metric.total.toFixed(2)),
+ 'Metrics Cost ($)': parseFloat(dataPoint.metric.cost.toFixed(2)),
+ 'Traces Vol (GBs)': parseFloat(dataPoint.trace.total.toFixed(2)),
+ 'Traces Cost ($)': parseFloat(dataPoint.trace.cost.toFixed(2)),
+ 'Logs Vol (GBs)': parseFloat(dataPoint.log.total.toFixed(2)),
+ 'Logs Cost ($)': parseFloat(dataPoint.log.cost.toFixed(2)),
+ }));
+
+ // Add totals row
+ csvData.push({
+ Date: 'Total',
+ 'Metrics Vol (Mn samples)': parseFloat(totals.metric.total.toFixed(2)),
+ 'Metrics Cost ($)': parseFloat(totals.metric.cost.toFixed(2)),
+ 'Traces Vol (GBs)': parseFloat(totals.trace.total.toFixed(2)),
+ 'Traces Cost ($)': parseFloat(totals.trace.cost.toFixed(2)),
+ 'Logs Vol (GBs)': parseFloat(totals.log.total.toFixed(2)),
+ 'Logs Cost ($)': parseFloat(totals.log.cost.toFixed(2)),
+ });
+
+ return csvData;
+};
+
+export default generateCsvData;
diff --git a/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts b/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts
index d40c8a6097..5123d59329 100644
--- a/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts
+++ b/frontend/src/container/BillingContainer/BillingUsageGraph/utils.ts
@@ -1,6 +1,12 @@
+import { UsageResponsePayloadProps } from 'api/billing/getUsage';
+import dayjs from 'dayjs';
+import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
import { isEmpty, isNull } from 'lodash-es';
+import { unparse } from 'papaparse';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
+import generateCsvData, { QuantityData } from './generateCsvData';
+
export const convertDataToMetricRangePayload = (
data: any,
): MetricRangePayloadProps => {
@@ -58,10 +64,7 @@ export const convertDataToMetricRangePayload = (
};
};
-export function fillMissingValuesForQuantities(
- data: any,
- timestampArray: number[],
-): MetricRangePayloadProps {
+export function quantityDataArr(data: any, timestampArray: number[]): any[] {
const { result } = data.data;
const transformedResultArr: any[] = [];
@@ -76,6 +79,14 @@ export function fillMissingValuesForQuantities(
);
transformedResultArr.push({ ...item, quantity: quantityArray });
});
+ return transformedResultArr;
+}
+
+export function fillMissingValuesForQuantities(
+ data: any,
+ timestampArray: number[],
+): MetricRangePayloadProps {
+ const transformedResultArr = quantityDataArr(data, timestampArray);
return {
data: {
@@ -85,3 +96,36 @@ export function fillMissingValuesForQuantities(
},
};
}
+
+const formatDate = (timestamp: number): string =>
+ dayjs.unix(timestamp).format('MM/DD/YYYY');
+
+export function csvFileName(csvData: QuantityData[]): string {
+ if (!csvData.length) {
+ return `billing-usage.csv`;
+ }
+
+ const { values } = csvData[0];
+
+ const timestamps = values.map((item) => item[0]);
+ const startDate = formatDate(Math.min(...timestamps));
+ const endDate = formatDate(Math.max(...timestamps));
+
+ return `billing_usage_(${startDate}-${endDate}).csv`;
+}
+
+export function prepareCsvData(
+ data: Partial
,
+): {
+ csvData: string;
+ fileName: string;
+} {
+ const graphCompatibleData = convertDataToMetricRangePayload(data);
+ const chartData = getUPlotChartData(graphCompatibleData);
+ const quantityMapArr = quantityDataArr(graphCompatibleData, chartData[0]);
+
+ return {
+ csvData: unparse(generateCsvData(quantityMapArr)),
+ fileName: csvFileName(quantityMapArr),
+ };
+}
diff --git a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx
index 60bf658e5d..cd837b666b 100644
--- a/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx
+++ b/frontend/src/container/CreateAlertRule/SelectAlertType/index.tsx
@@ -12,6 +12,30 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
const optionList = getOptionList(t);
+ function handleRedirection(option: AlertTypes): void {
+ let url = '';
+ switch (option) {
+ case AlertTypes.METRICS_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples';
+ break;
+ case AlertTypes.LOGS_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples';
+ break;
+ case AlertTypes.TRACES_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples';
+ break;
+ case AlertTypes.EXCEPTIONS_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-source-selection-page#examples';
+ break;
+ default:
+ break;
+ }
+ window.open(url, '_blank');
+ }
const renderOptions = useMemo(
() => (
<>
@@ -23,7 +47,16 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
onSelect(option.selection);
}}
>
- {option.description}
+ {option.description}{' '}
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ handleRedirection(option.selection);
+ }}
+ >
+ Click here to see how to create a sample alert.
+ {' '}
))}
>
diff --git a/frontend/src/container/CreateAlertRule/defaults.ts b/frontend/src/container/CreateAlertRule/defaults.ts
index 677f4accc4..20cd020158 100644
--- a/frontend/src/container/CreateAlertRule/defaults.ts
+++ b/frontend/src/container/CreateAlertRule/defaults.ts
@@ -130,7 +130,7 @@ export const exceptionAlertDefaults: AlertDef = {
disabled: false,
},
},
- queryType: EQueryType.QUERY_BUILDER,
+ queryType: EQueryType.CLICKHOUSE,
panelType: PANEL_TYPES.TIME_SERIES,
unit: undefined,
},
diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss b/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss
index 8af1e4ad0a..2076b858f9 100644
--- a/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss
+++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.styles.scss
@@ -1,18 +1,27 @@
+.explorer-options-container {
+ position: fixed;
+ bottom: 24px;
+ left: calc(50% + 240px);
+ transform: translate(calc(-50% - 120px), 0);
+ transition: left 0.2s linear;
+
+ display: flex;
+ gap: 16px;
+ background-color: transparent;
+}
+
.hide-update {
left: calc(50% - 72px) !important;
}
+
.explorer-update {
- position: fixed;
- bottom: 24px;
- left: calc(50% - 352px);
- display: flex;
+ display: inline-flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
border-radius: 50px;
border: 1px solid var(--bg-slate-400);
background: rgba(22, 24, 29, 0.6);
- box-shadow: 4px 4px 16px 4px rgba(0, 0, 0, 0.25);
backdrop-filter: blur(20px);
.action-icon {
@@ -38,16 +47,10 @@
}
.explorer-options {
- position: fixed;
- bottom: 24px;
- left: calc(50% + 240px);
padding: 10px 12px;
- transform: translate(calc(-50% - 120px), 0);
- transition: left 0.2s linear;
border: 1px solid var(--bg-slate-400);
border-radius: 50px;
background: rgba(22, 24, 29, 0.6);
- box-shadow: 4px 4px 16px 4px rgba(0, 0, 0, 0.25);
backdrop-filter: blur(20px);
cursor: default;
@@ -124,7 +127,7 @@
.app-content {
&.collapsed {
- .explorer-options {
+ .explorer-options-container {
left: calc(50% + 72px);
}
}
diff --git a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx
index 7253b45b94..1aaf22f796 100644
--- a/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx
+++ b/frontend/src/container/ExplorerOptions/ExplorerOptions.tsx
@@ -289,7 +289,7 @@ function ExplorerOptions({
const isEditDeleteSupported = allowedRoles.includes(role as string);
return (
- <>
+
{isQueryUpdated && !isExplorerOptionHidden && (
- >
+
);
}
diff --git a/frontend/src/container/FormAlertRules/BasicInfo.tsx b/frontend/src/container/FormAlertRules/BasicInfo.tsx
index 54877f5e0b..5fae4a713d 100644
--- a/frontend/src/container/FormAlertRules/BasicInfo.tsx
+++ b/frontend/src/container/FormAlertRules/BasicInfo.tsx
@@ -1,7 +1,17 @@
-import { Form, Select, Switch } from 'antd';
-import { useEffect, useState } from 'react';
+import './FormAlertRules.styles.scss';
+
+import { PlusOutlined } from '@ant-design/icons';
+import { Button, Form, Select, Switch, Tooltip } from 'antd';
+import getChannels from 'api/channels/getAll';
+import ROUTES from 'constants/routes';
+import useComponentPermission from 'hooks/useComponentPermission';
+import useFetch from 'hooks/useFetch';
+import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { useSelector } from 'react-redux';
+import { AppState } from 'store/reducers';
import { AlertDef, Labels } from 'types/api/alerts/def';
+import AppReducer from 'types/reducer/app';
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
import { popupContainer } from 'utils/selectPopupContainer';
@@ -31,6 +41,13 @@ function BasicInfo({
}: BasicInfoProps): JSX.Element {
const { t } = useTranslation('alerts');
+ const channels = useFetch(getChannels);
+ const { role } = useSelector((state) => state.app);
+ const [addNewChannelPermission] = useComponentPermission(
+ ['add_new_channel'],
+ role,
+ );
+
const [
shouldBroadCastToAllChannels,
setShouldBroadCastToAllChannels,
@@ -54,6 +71,11 @@ function BasicInfo({
});
};
+ const noChannels = channels.payload?.length === 0;
+ const handleCreateNewChannels = useCallback(() => {
+ window.open(ROUTES.CHANNELS_NEW, '_blank');
+ }, []);
+
return (
<>
{t('alert_form_step3')}
@@ -137,32 +159,74 @@ function BasicInfo({
name="alert_all_configured_channels"
label="Alert all the configured channels"
>
-
+
+
+
{!shouldBroadCastToAllChannels && (
-
- {
- setAlertDef({
- ...alertDef,
- preferredChannels,
- });
- }}
- />
-
+
+ {
+ setAlertDef({
+ ...alertDef,
+ preferredChannels,
+ });
+ }}
+ />
+
+
+ )}
+
+ {noChannels && (
+
+ }
+ className="create-notification-btn"
+ disabled={!addNewChannelPermission}
+ >
+ Create a notification channel
+
+
)}
>
diff --git a/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx b/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx
index 15f391c7cf..ad1b9fb327 100644
--- a/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx
+++ b/frontend/src/container/FormAlertRules/ChannelSelect/index.tsx
@@ -1,9 +1,9 @@
import { Select } from 'antd';
-import getChannels from 'api/channels/getAll';
-import useFetch from 'hooks/useFetch';
+import { State } from 'hooks/useFetch';
import { useNotifications } from 'hooks/useNotifications';
import { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';
+import { PayloadProps } from 'types/api/channels/getAll';
import { StyledSelect } from './styles';
@@ -11,38 +11,42 @@ export interface ChannelSelectProps {
disabled?: boolean;
currentValue?: string[];
onSelectChannels: (s: string[]) => void;
+ channels: State;
}
function ChannelSelect({
disabled,
currentValue,
onSelectChannels,
+ channels,
}: ChannelSelectProps): JSX.Element | null {
// init namespace for translations
const { t } = useTranslation('alerts');
- const { loading, payload, error, errorMessage } = useFetch(getChannels);
-
const { notifications } = useNotifications();
const handleChange = (value: string[]): void => {
onSelectChannels(value);
};
- if (error && errorMessage !== '') {
+ if (channels.error && channels.errorMessage !== '') {
notifications.error({
message: 'Error',
- description: errorMessage,
+ description: channels.errorMessage,
});
}
const renderOptions = (): ReactNode[] => {
const children: ReactNode[] = [];
- if (loading || payload === undefined || payload.length === 0) {
+ if (
+ channels.loading ||
+ channels.payload === undefined ||
+ channels.payload.length === 0
+ ) {
return children;
}
- payload.forEach((o) => {
+ channels.payload.forEach((o) => {
children.push(
{o.name}
@@ -55,7 +59,7 @@ function ChannelSelect({
return (
((state) => state.globalTime);
const urlQuery = useUrlQuery();
- const panelType = urlQuery.get(QueryParams.panelTypes) as PANEL_TYPES | null;
+ // In case of alert the panel types should always be "Graph" only
+ const panelType = PANEL_TYPES.TIME_SERIES;
const {
currentQuery,
@@ -102,6 +104,13 @@ function FormAlertRules({
const [alertDef, setAlertDef] = useState(initialValue);
const [yAxisUnit, setYAxisUnit] = useState(currentQuery.unit || '');
+ useEffect(() => {
+ if (!isEqual(currentQuery.unit, yAxisUnit)) {
+ setYAxisUnit(currentQuery.unit || '');
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [currentQuery.unit]);
+
// initQuery contains initial query when component was mounted
const initQuery = useMemo(() => initialValue.condition.compositeQuery, [
initialValue,
@@ -183,7 +192,9 @@ function FormAlertRules({
}
const query: Query = { ...currentQuery, queryType: val };
- redirectWithQueryBuilderData(updateStepInterval(query, maxTime, minTime));
+ // update step interval is removed from here as if the user enters
+ // any value we will use that rather than auto update
+ redirectWithQueryBuilderData(query);
};
const { notifications } = useNotifications();
@@ -245,7 +256,7 @@ function FormAlertRules({
if (
!currentQuery.builder.queryData ||
- currentQuery.builder.queryData.length === 0
+ currentQuery.builder.queryData?.length === 0
) {
notifications.error({
message: 'Error',
@@ -502,6 +513,31 @@ function FormAlertRules({
const isRuleCreated = !ruleId || ruleId === 0;
+ function handleRedirection(option: AlertTypes): void {
+ let url = '';
+ switch (option) {
+ case AlertTypes.METRICS_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples';
+ break;
+ case AlertTypes.LOGS_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples';
+ break;
+ case AlertTypes.TRACES_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples';
+ break;
+ case AlertTypes.EXCEPTIONS_BASED_ALERT:
+ url =
+ 'https://signoz.io/docs/alerts-management/exceptions-based-alerts/?utm_source=product&utm_medium=alert-creation-page#examples';
+ break;
+ default:
+ break;
+ }
+ window.open(url, '_blank');
+ }
+
return (
<>
{Element}
@@ -532,7 +568,7 @@ function FormAlertRules({
queryCategory={currentQuery.queryType}
setQueryCategory={onQueryCategoryChange}
alertType={alertType || AlertTypes.METRICS_BASED_ALERT}
- runQuery={handleRunQuery}
+ runQuery={(): void => handleRunQuery(true)}
alertDef={alertDef}
panelType={panelType || PANEL_TYPES.TIME_SERIES}
key={currentQuery.queryType}
@@ -585,22 +621,33 @@ function FormAlertRules({
-
+
+
+
+
>
diff --git a/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx b/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx
index 184c34e77b..02d71ed9bb 100644
--- a/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx
+++ b/frontend/src/container/GridCardLayout/GridCard/FullView/index.tsx
@@ -15,7 +15,6 @@ import {
} from 'container/NewWidget/RightContainer/timeItems';
import PanelWrapper from 'container/PanelWrapper/PanelWrapper';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
-import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
import { useChartMutable } from 'hooks/useChartMutable';
import useUrlQuery from 'hooks/useUrlQuery';
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
@@ -71,7 +70,7 @@ function FullView({
enum: widget?.timePreferance || 'GLOBAL_TIME',
});
- const updatedQuery = useStepInterval(widget?.query);
+ const updatedQuery = widget?.query;
const [requestData, setRequestData] = useState(() => {
if (widget.panelTypes !== PANEL_TYPES.LIST) {
@@ -204,7 +203,7 @@ function FullView({
l.i === widget.id,
+ );
+
+ // added the cloned panel on the top as it is given most priority when arranging
+ // in the layout. React_grid_layout assigns priority from top, hence no random position for cloned panel
const layout = [
- ...(selectedDashboard.data.layout || []),
{
i: uuid,
- w: 6,
+ w: originalPanelLayout?.w || 6,
x: 0,
- h: 6,
+ h: originalPanelLayout?.h || 6,
y: 0,
},
+ ...(selectedDashboard.data.layout || []),
];
updateDashboardMutation.mutateAsync(
diff --git a/frontend/src/container/GridCardLayout/GridCard/index.tsx b/frontend/src/container/GridCardLayout/GridCard/index.tsx
index a553fe7241..28c67ae92e 100644
--- a/frontend/src/container/GridCardLayout/GridCard/index.tsx
+++ b/frontend/src/container/GridCardLayout/GridCard/index.tsx
@@ -3,7 +3,6 @@ import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder';
import { CustomTimeType } from 'container/TopNav/DateTimeSelectionV2/config';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
-import { useStepInterval } from 'hooks/queryBuilder/useStepInterval';
import { useIntersectionObserver } from 'hooks/useIntersectionObserver';
import { getDashboardVariables } from 'lib/dashbaordVariables/getDashboardVariables';
import { GetQueryResultsProps } from 'lib/dashboard/getQueryResults';
@@ -90,7 +89,7 @@ function GridCardGraph({
}
}, [toScrollWidgetId, setToScrollWidgetId, widget.id]);
- const updatedQuery = useStepInterval(widget?.query);
+ const updatedQuery = widget?.query;
const isEmptyWidget =
widget?.id === PANEL_TYPES.EMPTY_WIDGET || isEmpty(widget);
@@ -109,6 +108,7 @@ function GridCardGraph({
query: updatedQuery,
globalSelectedInterval,
variables: getDashboardVariables(variables),
+ fillGaps: widget.fillSpans,
};
}
updatedQuery.builder.queryData[0].pageSize = 10;
@@ -123,6 +123,7 @@ function GridCardGraph({
limit: updatedQuery.builder.queryData[0].limit || 0,
},
},
+ fillGaps: widget.fillSpans,
};
});
@@ -153,6 +154,7 @@ function GridCardGraph({
widget?.query,
widget?.panelTypes,
widget.timePreferance,
+ widget.fillSpans,
requestData,
],
retry(failureCount, error): boolean {
diff --git a/frontend/src/container/GridTableComponent/index.tsx b/frontend/src/container/GridTableComponent/index.tsx
index 26bdda1a49..171f09da07 100644
--- a/frontend/src/container/GridTableComponent/index.tsx
+++ b/frontend/src/container/GridTableComponent/index.tsx
@@ -62,10 +62,11 @@ function GridTableComponent({
mutateDataSource = mutateDataSource.map(
(val): RowData => {
- const newValue = val;
+ const newValue = { ...val };
Object.keys(val).forEach((k) => {
if (columnUnits[k]) {
newValue[k] = getYAxisFormattedValue(String(val[k]), columnUnits[k]);
+ newValue[`${k}_without_unit`] = val[k];
}
});
return newValue;
@@ -81,7 +82,6 @@ function GridTableComponent({
applyColumnUnits,
originalDataSource,
]);
-
useEffect(() => {
if (tableProcessedDataRef) {
// eslint-disable-next-line no-param-reassign
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx
new file mode 100644
index 0000000000..76403a1884
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertInfoCard.tsx
@@ -0,0 +1,37 @@
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+import { ArrowRightOutlined } from '@ant-design/icons';
+import { Typography } from 'antd';
+
+interface AlertInfoCardProps {
+ header: string;
+ subheader: string;
+ link: string;
+}
+
+function AlertInfoCard({
+ header,
+ subheader,
+ link,
+}: AlertInfoCardProps): JSX.Element {
+ return (
+
{
+ window.open(link, '_blank');
+ }}
+ >
+
+
+ {header}
+
+
+ {subheader}
+
+
+
+
+ );
+}
+
+export default AlertInfoCard;
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss
new file mode 100644
index 0000000000..c852b5833b
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.styles.scss
@@ -0,0 +1,251 @@
+.alert-list-container {
+ margin-top: 104px;
+ margin-bottom: 30px;
+ display: flex;
+ justify-content: center;
+ width: 100%;
+
+ .alert-list-view-content {
+ width: calc(100% - 30px);
+ max-width: 836px;
+
+ .alert-list-title-container {
+ .title {
+ color: var(--bg-vanilla-100);
+ font-size: var(--font-size-lg);
+ font-style: normal;
+ font-weight: var(--font-weight-normal);
+ line-height: 28px; /* 155.556% */
+ letter-spacing: -0.09px;
+ }
+
+ .subtitle {
+ color: var(--bg-vanilla-400);
+ font-size: var(--font-size-sm);
+ font-style: normal;
+ font-weight: var(--font-weight-normal);
+ line-height: 20px; /* 142.857% */
+ letter-spacing: -0.07px;
+ }
+ }
+
+ .empty-alert-info-container {
+ display: flex;
+ padding: 71px 193.5px;
+ justify-content: center;
+ align-items: center;
+ border-radius: 6px;
+ border: 1px dashed var(--bg-slate-500);
+ margin-top: 16px;
+
+ .alert-content {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 12px;
+
+ .heading {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+
+ .icons {
+ color: white;
+ }
+
+ .empty-alert-action {
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 24px; /* 171.429% */
+ letter-spacing: -0.07px;
+ }
+
+ .empty-info {
+ color: var(--bg-vanilla-100);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px;
+ letter-spacing: -0.07px;
+ }
+ }
+
+ .action-container {
+ display: flex;
+ gap: 24px;
+ align-items: center;
+ padding-top: 24px;
+ padding-bottom: 24px;
+ width: 100%;
+ }
+ }
+ }
+
+ .get-started-text {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 16px;
+ margin-top: 24px;
+ margin-bottom: 24px;
+ width: 100%;
+
+ .ant-divider::before,
+ .ant-divider::after {
+ border-bottom: 2px dotted var(--bg-slate-300);
+ border-top: 2px dotted var(--bg-slate-300);
+ height: 8px;
+ }
+
+ .ant-typography {
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 166.667% */
+ letter-spacing: 0.48px;
+ text-transform: uppercase;
+ padding-top: 8px;
+ }
+ }
+
+ .alert-info-card {
+ display: flex;
+ padding: 16px;
+ justify-content: space-between;
+ align-items: center;
+
+ border-radius: 6px;
+ border: 1px solid var(--bg-slate-500);
+ background: var(--bg-ink-400);
+ margin-bottom: 16px;
+
+ &:hover {
+ cursor: pointer;
+ }
+
+ .alert-card-text {
+ display: flex;
+ gap: 2px;
+ flex-direction: column;
+
+ .alert-card-text-header {
+ color: var(--bg-vanilla-100);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 20px; /* 142.857% */
+ letter-spacing: -0.07px;
+ }
+
+ .alert-card-text-subheader {
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 18px; /* 150% */
+ }
+ }
+ }
+ }
+}
+
+.info-text {
+ color: var(--bg-robin-400) !important;
+ font-family: Inter;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 16px; /* 133.333% */
+ letter-spacing: -0.06px;
+}
+
+.info-link-container {
+ .anticon {
+ color: var(--bg-robin-400);
+ }
+
+ :hover {
+ cursor: pointer;
+ }
+}
+
+.lightMode {
+ .alert-list-container {
+ .alert-list-view-content {
+ .alert-list-title-container {
+ .title {
+ color: var(--bg-slate-400);
+ }
+
+ .subtitle {
+ color: var(--bg-slate-100);
+ }
+ }
+
+ .empty-alert-info-container {
+ border: 1px dashed var(--bg-vanilla-400);
+
+ .alert-content {
+ .heading {
+ .icons {
+ color: white;
+ }
+
+ .empty-alert-action {
+ color: var(--bg-slate-100);
+ }
+
+ .empty-info {
+ color: var(--bg-slate-400);
+ }
+ }
+ }
+ }
+
+ .get-started-text {
+ .ant-divider::before,
+ .ant-divider::after {
+ border-bottom: 2px dotted var(--bg-vanilla-400);
+ border-top: 2px dotted var(--bg-vanilla-400);
+ }
+
+ .ant-typography {
+ color: var(--bg-slate-100);
+ }
+ }
+
+ .alert-info-card {
+ border: 1px solid var(--bg-vanilla-200);
+ background: var(--bg-vanilla-100);
+
+ .alert-card-text {
+ .alert-card-text-header {
+ color: var(--bg-slate-400);
+ }
+
+ .alert-card-text-subheader {
+ color: var(--bg-slate-100);
+ }
+ }
+ }
+ }
+ }
+
+ .info-text {
+ color: var(--bg-robin-600) !important;
+ }
+
+ .info-link-container {
+ .anticon {
+ color: var(--bg-robin-400);
+ }
+ }
+}
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx
new file mode 100644
index 0000000000..0f388053c0
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/AlertsEmptyState.tsx
@@ -0,0 +1,127 @@
+import './AlertsEmptyState.styles.scss';
+
+import { PlusOutlined } from '@ant-design/icons';
+import { Button, Divider, Typography } from 'antd';
+import ROUTES from 'constants/routes';
+import useComponentPermission from 'hooks/useComponentPermission';
+import { useNotifications } from 'hooks/useNotifications';
+import history from 'lib/history';
+import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useSelector } from 'react-redux';
+import { AppState } from 'store/reducers';
+import AppReducer from 'types/reducer/app';
+
+import AlertInfoCard from './AlertInfoCard';
+import { ALERT_CARDS, ALERT_INFO_LINKS } from './alertLinks';
+import InfoLinkText from './InfoLinkText';
+
+export function AlertsEmptyState(): JSX.Element {
+ const { t } = useTranslation('common');
+ const { role, featureResponse } = useSelector
(
+ (state) => state.app,
+ );
+ const [addNewAlert] = useComponentPermission(
+ ['add_new_alert', 'action'],
+ role,
+ );
+
+ const { notifications: notificationsApi } = useNotifications();
+
+ const handleError = useCallback((): void => {
+ notificationsApi.error({
+ message: t('something_went_wrong'),
+ });
+ }, [notificationsApi, t]);
+
+ const [loading, setLoading] = useState(false);
+
+ const onClickNewAlertHandler = useCallback(() => {
+ setLoading(true);
+ featureResponse
+ .refetch()
+ .then(() => {
+ setLoading(false);
+ history.push(ROUTES.ALERTS_NEW);
+ })
+ .catch(handleError)
+ .finally(() => setLoading(false));
+ }, [featureResponse, handleError]);
+
+ return (
+
+
+
+ Alert Rules
+
+ Create and manage alert rules for your resources.
+
+
+
+
+
+
+
+
+ No Alert rules yet.{' '}
+
+
+ Create an Alert Rule to get started
+
+
+
+
+ }
+ disabled={!addNewAlert}
+ loading={loading}
+ type="primary"
+ data-testid="add-alert"
+ >
+ New Alert Rule
+
+
+
+
+ {ALERT_INFO_LINKS.map((info) => (
+
+ ))}
+
+
+
+
+
+ Or get started with these sample alerts
+
+
+
+
+ {ALERT_CARDS.map((card) => (
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx b/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx
new file mode 100644
index 0000000000..1f17cd3969
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/InfoLinkText.tsx
@@ -0,0 +1,31 @@
+import { ArrowRightOutlined, PlayCircleFilled } from '@ant-design/icons';
+import { Flex, Typography } from 'antd';
+
+interface InfoLinkTextProps {
+ infoText: string;
+ link: string;
+ leftIconVisible: boolean;
+ rightIconVisible: boolean;
+}
+
+function InfoLinkText({
+ infoText,
+ link,
+ leftIconVisible,
+ rightIconVisible,
+}: InfoLinkTextProps): JSX.Element {
+ return (
+ {
+ window.open(link, '_blank');
+ }}
+ className="info-link-container"
+ >
+ {leftIconVisible && }
+ {infoText}
+ {rightIconVisible && }
+
+ );
+}
+
+export default InfoLinkText;
diff --git a/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts b/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts
new file mode 100644
index 0000000000..fac0ad6b12
--- /dev/null
+++ b/frontend/src/container/ListAlertRules/AlertsEmptyState/alertLinks.ts
@@ -0,0 +1,50 @@
+export const ALERT_INFO_LINKS = [
+ {
+ infoText: 'How to create Metrics-based alerts',
+ link:
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page',
+ leftIconVisible: false,
+ rightIconVisible: true,
+ },
+ {
+ infoText: 'How to create Log-based alerts',
+ link:
+ 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-empty-page',
+ leftIconVisible: false,
+ rightIconVisible: true,
+ },
+ {
+ infoText: 'How to create Trace-based alerts',
+ link:
+ 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-empty-page',
+ leftIconVisible: false,
+ rightIconVisible: true,
+ },
+];
+
+export const ALERT_CARDS = [
+ {
+ header: 'Alert on high memory usage',
+ subheader: "Monitor your host's memory usage",
+ link:
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-memory-usage-for-host-goes-above-400-mb-or-any-fixed-memory',
+ },
+ {
+ header: 'Alert on slow external API calls',
+ subheader: 'Monitor your external API calls',
+ link:
+ 'https://signoz.io/docs/alerts-management/trace-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-external-api-latency-p90-is-over-1-second-for-last-5-mins',
+ },
+ {
+ header: 'Alert on high percentage of timeout errors in logs',
+ subheader: 'Monitor your logs for errors',
+ link:
+ 'https://signoz.io/docs/alerts-management/log-based-alerts/?utm_source=product&utm_medium=alert-empty-page#1-alert-when-percentage-of-redis-timeout-error-logs-greater-than-7-in-last-5-mins',
+ },
+ {
+ header: 'Alert on high error percentage of an endpoint',
+ subheader: 'Monitor your API endpoint',
+ link:
+ 'https://signoz.io/docs/alerts-management/metrics-based-alerts/?utm_source=product&utm_medium=alert-empty-page#3-alert-when-the-error-percentage-for-an-endpoint-exceeds-5',
+ },
+];
diff --git a/frontend/src/container/ListAlertRules/ListAlert.tsx b/frontend/src/container/ListAlertRules/ListAlert.tsx
index 37a56ba921..91e0786e05 100644
--- a/frontend/src/container/ListAlertRules/ListAlert.tsx
+++ b/frontend/src/container/ListAlertRules/ListAlert.tsx
@@ -55,6 +55,9 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
role,
);
+ const [editLoader, setEditLoader] = useState(false);
+ const [cloneLoader, setCloneLoader] = useState(false);
+
const params = useUrlQuery();
const orderColumnParam = params.get('columnKey');
const orderQueryParam = params.get('order');
@@ -113,6 +116,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
}, [featureResponse, handleError]);
const onEditHandler = (record: GettableAlert) => (): void => {
+ setEditLoader(true);
featureResponse
.refetch()
.then(() => {
@@ -129,9 +133,11 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
params.set(QueryParams.ruleId, record.id.toString());
+ setEditLoader(false);
history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`);
})
- .catch(handleError);
+ .catch(handleError)
+ .finally(() => setEditLoader(false));
};
const onCloneHandler = (
@@ -143,33 +149,41 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
};
const apiReq = { data: copyAlert };
- const response = await saveAlertApi(apiReq);
+ try {
+ setCloneLoader(true);
+ const response = await saveAlertApi(apiReq);
- if (response.statusCode === 200) {
- notificationsApi.success({
- message: 'Success',
- description: 'Alert cloned successfully',
- });
+ if (response.statusCode === 200) {
+ notificationsApi.success({
+ message: 'Success',
+ description: 'Alert cloned successfully',
+ });
- const { data: refetchData, status } = await refetch();
- if (status === 'success' && refetchData.payload) {
- setData(refetchData.payload || []);
- setTimeout(() => {
- const clonedAlert = refetchData.payload[refetchData.payload.length - 1];
- params.set(QueryParams.ruleId, String(clonedAlert.id));
- history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`);
- }, 2000);
- }
- if (status === 'error') {
+ const { data: refetchData, status } = await refetch();
+ if (status === 'success' && refetchData.payload) {
+ setData(refetchData.payload || []);
+ setTimeout(() => {
+ const clonedAlert = refetchData.payload[refetchData.payload.length - 1];
+ params.set(QueryParams.ruleId, String(clonedAlert.id));
+ history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`);
+ }, 2000);
+ }
+ if (status === 'error') {
+ notificationsApi.error({
+ message: t('something_went_wrong'),
+ });
+ }
+ } else {
notificationsApi.error({
- message: t('something_went_wrong'),
+ message: 'Error',
+ description: response.error || t('something_went_wrong'),
});
}
- } else {
- notificationsApi.error({
- message: 'Error',
- description: response.error || t('something_went_wrong'),
- });
+ } catch (error) {
+ handleError();
+ console.error(error);
+ } finally {
+ setCloneLoader(false);
}
};
@@ -314,10 +328,20 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
setData={setData}
id={id}
/>,
-
+
Edit
,
-
+
Clone
,
;
+ }
+
// in case of loading
if (isLoading || !data?.payload) {
return ;
diff --git a/frontend/src/container/ListAlertRules/styles.ts b/frontend/src/container/ListAlertRules/styles.ts
index c0deac35de..6d89b88c53 100644
--- a/frontend/src/container/ListAlertRules/styles.ts
+++ b/frontend/src/container/ListAlertRules/styles.ts
@@ -27,5 +27,8 @@ export const ColumnButton = styled(ButtonComponent)`
padding-left: 0;
padding-right: 0;
margin-right: 1.5em;
+ width: 100%;
+ display: flex;
+ align-items: center;
}
`;
diff --git a/frontend/src/container/ListOfDashboard/DashboardsList.tsx b/frontend/src/container/ListOfDashboard/DashboardsList.tsx
index f44b71e2bd..1c8e96b6f7 100644
--- a/frontend/src/container/ListOfDashboard/DashboardsList.tsx
+++ b/frontend/src/container/ListOfDashboard/DashboardsList.tsx
@@ -53,6 +53,7 @@ import {
Search,
} from 'lucide-react';
import { handleContactSupport } from 'pages/Integrations/utils';
+import { useDashboard } from 'providers/Dashboard/Dashboard';
import {
ChangeEvent,
Key,
@@ -91,6 +92,11 @@ function DashboardsList(): JSX.Element {
const { role } = useSelector((state) => state.app);
+ const {
+ listSortOrder: sortOrder,
+ setListSortOrder: setSortOrder,
+ } = useDashboard();
+
const [action, createNewDashboard] = useComponentPermission(
['action', 'create_new_dashboards'],
role,
@@ -116,18 +122,9 @@ function DashboardsList(): JSX.Element {
);
const params = useUrlQuery();
- const orderColumnParam = params.get('columnKey');
- const orderQueryParam = params.get('order');
- const paginationParam = params.get('page');
const searchParams = params.get('search');
const [searchString, setSearchString] = useState(searchParams || '');
- const [sortOrder, setSortOrder] = useState({
- columnKey: orderColumnParam,
- order: orderQueryParam,
- pagination: paginationParam,
- });
-
const getLocalStorageDynamicColumns = (): DashboardDynamicColumns => {
const dashboardDynamicColumnsString = localStorage.getItem('dashboard');
let dashboardDynamicColumns: DashboardDynamicColumns = {
@@ -198,7 +195,6 @@ function DashboardsList(): JSX.Element {
}, [sortOrder]);
const sortHandle = (key: string): void => {
- console.log(dashboards);
if (!dashboards) return;
if (key === 'createdAt') {
sortDashboardsByCreatedAt(dashboards);
@@ -225,13 +221,29 @@ function DashboardsList(): JSX.Element {
}
useEffect(() => {
- sortDashboardsByCreatedAt(dashboardListResponse);
const filteredDashboards = filterDashboard(
searchString,
dashboardListResponse,
);
- setDashboards(filteredDashboards || []);
- }, [dashboardListResponse, searchString]);
+ if (sortOrder.columnKey === 'updatedAt') {
+ sortDashboardsByUpdatedAt(filteredDashboards || []);
+ } else if (sortOrder.columnKey === 'createdAt') {
+ sortDashboardsByCreatedAt(filteredDashboards || []);
+ } else if (sortOrder.columnKey === 'null') {
+ setSortOrder({
+ columnKey: 'updatedAt',
+ order: 'descend',
+ pagination: sortOrder.pagination || '1',
+ });
+ sortDashboardsByUpdatedAt(filteredDashboards || []);
+ }
+ }, [
+ dashboardListResponse,
+ searchString,
+ setSortOrder,
+ sortOrder.columnKey,
+ sortOrder.pagination,
+ ]);
const [newDashboardState, setNewDashboardState] = useState({
loading: false,
@@ -687,7 +699,16 @@ function DashboardsList(): JSX.Element {
New Dashboard
-
diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx
index 4007c152ef..9651e16d3a 100644
--- a/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx
+++ b/frontend/src/container/MetricsApplication/Tabs/Overview/ServiceOverview.tsx
@@ -21,7 +21,11 @@ import { v4 as uuid } from 'uuid';
import { Button } from '../styles';
import { IServiceName } from '../types';
-import { handleNonInQueryRange, onViewTracePopupClick } from '../util';
+import {
+ handleNonInQueryRange,
+ onViewTracePopupClick,
+ useGetAPMToTracesQueries,
+} from '../util';
function ServiceOverview({
onDragSelect,
@@ -69,6 +73,8 @@ function ServiceOverview({
const isQueryEnabled =
!topLevelOperationsIsLoading && topLevelOperationsRoute.length > 0;
+ const apmToTraceQuery = useGetAPMToTracesQueries({ servicename });
+
return (
<>
View Traces
diff --git a/frontend/src/container/MetricsApplication/Tabs/Overview/TableRenderer/ColumnWithLink.tsx b/frontend/src/container/MetricsApplication/Tabs/Overview/TableRenderer/ColumnWithLink.tsx
index 99230f3a75..02dc0f9cf4 100644
--- a/frontend/src/container/MetricsApplication/Tabs/Overview/TableRenderer/ColumnWithLink.tsx
+++ b/frontend/src/container/MetricsApplication/Tabs/Overview/TableRenderer/ColumnWithLink.tsx
@@ -1,6 +1,10 @@
import { Tooltip, Typography } from 'antd';
import { navigateToTrace } from 'container/MetricsApplication/utils';
import { RowData } from 'lib/query/createTableColumnsFromQuery';
+import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
+import { v4 as uuid } from 'uuid';
+
+import { useGetAPMToTracesQueries } from '../../util';
function ColumnWithLink({
servicename,
@@ -11,6 +15,25 @@ function ColumnWithLink({
}: LinkColumnProps): JSX.Element {
const text = record.toString();
+ const apmToTraceQuery = useGetAPMToTracesQueries({
+ servicename,
+ filters: [
+ {
+ id: uuid().slice(0, 8),
+ key: {
+ key: 'name',
+ dataType: DataTypes.String,
+ type: 'tag',
+ isColumn: true,
+ isJSON: false,
+ id: 'name--string--tag--true',
+ },
+ op: 'in',
+ value: [text],
+ },
+ ],
+ });
+
const handleOnClick = (operation: string) => (): void => {
navigateToTrace({
servicename,
@@ -18,6 +41,7 @@ function ColumnWithLink({
minTime,
maxTime,
selectedTraceTags,
+ apmToTraceQuery,
});
};
diff --git a/frontend/src/container/MetricsApplication/Tabs/util.ts b/frontend/src/container/MetricsApplication/Tabs/util.ts
index c44e7462f4..6832fe9d02 100644
--- a/frontend/src/container/MetricsApplication/Tabs/util.ts
+++ b/frontend/src/container/MetricsApplication/Tabs/util.ts
@@ -1,11 +1,20 @@
import { QueryParams } from 'constants/query';
+import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import { routeConfig } from 'container/SideNav/config';
import { getQueryString } from 'container/SideNav/helper';
+import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import history from 'lib/history';
-import { Dispatch, SetStateAction } from 'react';
-import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
+import { traceFilterKeys } from 'pages/TracesExplorer/Filter/filterUtils';
+import { Dispatch, SetStateAction, useMemo } from 'react';
+import {
+ BaseAutocompleteData,
+ DataTypes,
+} from 'types/api/queryBuilder/queryAutocompleteResponse';
+import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
+import { DataSource } from 'types/common/queryBuilder';
import { Tags } from 'types/reducer/trace';
+import { v4 as uuid } from 'uuid';
export const dbSystemTags: Tags[] = [
{
@@ -21,13 +30,13 @@ interface OnViewTracePopupClickProps {
servicename: string | undefined;
selectedTraceTags: string;
timestamp: number;
- isExternalCall?: boolean;
+ apmToTraceQuery: Query;
}
export function onViewTracePopupClick({
selectedTraceTags,
servicename,
timestamp,
- isExternalCall,
+ apmToTraceQuery,
}: OnViewTracePopupClickProps): VoidFunction {
return (): void => {
const currentTime = timestamp;
@@ -40,13 +49,17 @@ export function onViewTracePopupClick({
const avialableParams = routeConfig[ROUTES.TRACE];
const queryString = getQueryString(avialableParams, urlParams);
- history.replace(
- `${
- ROUTES.TRACE
- }?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"]}&spanAggregateCurrentPage=1${
- isExternalCall ? '&spanKind=3' : ''
- }&${queryString.join('&')}`,
+ const JSONCompositeQuery = encodeURIComponent(
+ JSON.stringify(apmToTraceQuery),
);
+
+ const newTraceExplorerPath = `${
+ ROUTES.TRACES_EXPLORER
+ }?${urlParams.toString()}&selected={"serviceName":["${servicename}"]}&filterToFetchData=["duration","status","serviceName"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${
+ QueryParams.compositeQuery
+ }=${JSONCompositeQuery}&${queryString.join('&')}`;
+
+ history.push(newTraceExplorerPath);
};
}
@@ -87,3 +100,104 @@ export const handleNonInQueryRange = (tags: TagFilterItem[]): TagFilterItem[] =>
}
return tag;
});
+
+export function handleQueryChange(
+ query: Query,
+ attributeKeys: BaseAutocompleteData,
+ serviceAttribute: string,
+ filters?: TagFilterItem[],
+): Query {
+ const filterItem: TagFilterItem[] = [
+ {
+ id: uuid().slice(0, 8),
+ key: attributeKeys,
+ op: 'in',
+ value: serviceAttribute,
+ },
+ ];
+ return {
+ ...query,
+ builder: {
+ ...query.builder,
+ queryData: query.builder.queryData?.map((item) => ({
+ ...item,
+ filters: {
+ ...item.filters,
+ items: [...item.filters.items, ...filterItem, ...(filters || [])],
+ },
+ })),
+ },
+ };
+}
+
+export function useGetAPMToTracesQueries({
+ servicename,
+ isExternalCall,
+ isDBCall,
+ filters,
+}: {
+ servicename: string;
+ isExternalCall?: boolean;
+ isDBCall?: boolean;
+ filters?: TagFilterItem[];
+}): Query {
+ const { updateAllQueriesOperators } = useQueryBuilder();
+
+ const finalFilters: TagFilterItem[] = [];
+ let spanKindFilter: TagFilterItem;
+ let dbCallFilter: TagFilterItem;
+
+ if (isExternalCall) {
+ spanKindFilter = {
+ id: uuid().slice(0, 8),
+ key: {
+ key: 'spanKind',
+ dataType: DataTypes.String,
+ type: 'tag',
+ isColumn: true,
+ isJSON: false,
+ id: 'spanKind--string--tag--true',
+ },
+ op: '=',
+ value: 'Client',
+ };
+ finalFilters.push(spanKindFilter);
+ }
+
+ if (isDBCall) {
+ dbCallFilter = {
+ id: uuid().slice(0, 8),
+ key: {
+ key: 'dbSystem',
+ dataType: DataTypes.String,
+ type: 'tag',
+ isColumn: true,
+ isJSON: false,
+ id: 'dbSystem--string--tag--true',
+ },
+ op: 'exists',
+ value: '',
+ };
+ finalFilters.push(dbCallFilter);
+ }
+
+ if (filters?.length) {
+ finalFilters.push(...filters);
+ }
+
+ return useMemo(() => {
+ const updatedQuery = updateAllQueriesOperators(
+ initialQueriesMap.traces,
+ PANEL_TYPES.TRACE,
+ DataSource.TRACES,
+ );
+
+ return handleQueryChange(
+ updatedQuery,
+ traceFilterKeys.serviceName,
+ servicename,
+ finalFilters,
+ );
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [servicename, updateAllQueriesOperators]);
+}
diff --git a/frontend/src/container/MetricsApplication/TopOperationsTable.tsx b/frontend/src/container/MetricsApplication/TopOperationsTable.tsx
index 3042db8958..bd518d629d 100644
--- a/frontend/src/container/MetricsApplication/TopOperationsTable.tsx
+++ b/frontend/src/container/MetricsApplication/TopOperationsTable.tsx
@@ -12,9 +12,13 @@ import { useRef } from 'react';
import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';
import { AppState } from 'store/reducers';
+import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
+import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { GlobalReducer } from 'types/reducer/globalTime';
+import { v4 as uuid } from 'uuid';
import { IServiceName } from './Tabs/types';
+import { useGetAPMToTracesQueries } from './Tabs/util';
import {
convertedTracesToDownloadData,
getErrorRate,
@@ -38,18 +42,49 @@ function TopOperationsTable({
convertRawQueriesToTraceSelectedTags(queries) || [],
);
+ const apmToTraceQuery = useGetAPMToTracesQueries({ servicename });
+
const params = useParams<{ servicename: string }>();
const handleOnClick = (operation: string): void => {
const { servicename: encodedServiceName } = params;
const servicename = decodeURIComponent(encodedServiceName);
+ const opFilter: TagFilterItem = {
+ id: uuid().slice(0, 8),
+ key: {
+ key: 'name',
+ dataType: DataTypes.String,
+ type: 'tag',
+ isColumn: true,
+ isJSON: false,
+ id: 'name--string--tag--true',
+ },
+ op: 'in',
+ value: [operation],
+ };
+
+ const preparedQuery: Query = {
+ ...apmToTraceQuery,
+ builder: {
+ ...apmToTraceQuery.builder,
+ queryData: apmToTraceQuery.builder.queryData?.map((item) => ({
+ ...item,
+ filters: {
+ ...item.filters,
+ items: [...item.filters.items, opFilter],
+ },
+ })),
+ },
+ };
+
navigateToTrace({
servicename,
operation,
minTime,
maxTime,
selectedTraceTags,
+ apmToTraceQuery: preparedQuery,
});
};
diff --git a/frontend/src/container/MetricsApplication/types.ts b/frontend/src/container/MetricsApplication/types.ts
index d8464d1248..4b4cc2f4f1 100644
--- a/frontend/src/container/MetricsApplication/types.ts
+++ b/frontend/src/container/MetricsApplication/types.ts
@@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { Widgets } from 'types/api/dashboard/getAll';
-import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
+import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { IServiceName } from './Tabs/types';
@@ -19,6 +19,7 @@ export interface NavigateToTraceProps {
minTime: number;
maxTime: number;
selectedTraceTags: string;
+ apmToTraceQuery: Query;
}
export interface DatabaseCallsRPSProps extends DatabaseCallProps {
diff --git a/frontend/src/container/MetricsApplication/utils.ts b/frontend/src/container/MetricsApplication/utils.ts
index 290b9a6179..303632b06f 100644
--- a/frontend/src/container/MetricsApplication/utils.ts
+++ b/frontend/src/container/MetricsApplication/utils.ts
@@ -18,15 +18,21 @@ export const navigateToTrace = ({
minTime,
maxTime,
selectedTraceTags,
+ apmToTraceQuery,
}: NavigateToTraceProps): void => {
const urlParams = new URLSearchParams();
urlParams.set(QueryParams.startTime, (minTime / 1000000).toString());
urlParams.set(QueryParams.endTime, (maxTime / 1000000).toString());
- history.push(
- `${
- ROUTES.TRACE
- }?${urlParams.toString()}&selected={"serviceName":["${servicename}"],"operation":["${operation}"]}&filterToFetchData=["duration","status","serviceName","operation"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&&isFilterExclude={"serviceName":false,"operation":false}&userSelectedFilter={"status":["error","ok"],"serviceName":["${servicename}"],"operation":["${operation}"]}&spanAggregateCurrentPage=1`,
- );
+
+ const JSONCompositeQuery = encodeURIComponent(JSON.stringify(apmToTraceQuery));
+
+ const newTraceExplorerPath = `${
+ ROUTES.TRACES_EXPLORER
+ }?${urlParams.toString()}&selected={"serviceName":["${servicename}"],"operation":["${operation}"]}&filterToFetchData=["duration","status","serviceName","operation"]&spanAggregateCurrentPage=1&selectedTags=${selectedTraceTags}&${
+ QueryParams.compositeQuery
+ }=${JSONCompositeQuery}`;
+
+ history.push(newTraceExplorerPath);
};
export const getNearestHighestBucketValue = (
diff --git a/frontend/src/container/NewDashboard/DashboardDescription/Description.styles.scss b/frontend/src/container/NewDashboard/DashboardDescription/Description.styles.scss
index 78c5c05a4e..39802eaba9 100644
--- a/frontend/src/container/NewDashboard/DashboardDescription/Description.styles.scss
+++ b/frontend/src/container/NewDashboard/DashboardDescription/Description.styles.scss
@@ -53,53 +53,59 @@
padding: 0px;
}
- .dashboard-breadcrumbs {
- height: 48px;
- padding: 16px;
+ .dashboard-header {
border-bottom: 1px solid var(--bg-slate-400);
display: flex;
- gap: 6px;
+ justify-content: space-between;
align-items: center;
- .dashboard-btn {
+ .dashboard-breadcrumbs {
+ height: 48px;
+ padding: 16px;
display: flex;
+ gap: 6px;
align-items: center;
- color: var(--bg-vanilla-400);
- font-family: Inter;
- font-size: 14px;
- font-style: normal;
- font-weight: 400;
- line-height: 20px; /* 142.857% */
- letter-spacing: -0.07px;
- padding: 0px;
- height: 20px;
- }
- .dashboard-btn:hover {
- background-color: unset;
- }
-
- .id-btn {
- display: flex;
- align-items: center;
- padding: 0px 2px;
- border-radius: 2px;
- background: rgba(113, 144, 249, 0.1);
- color: var(--bg-robin-400);
- font-family: Inter;
- font-size: 14px;
- font-style: normal;
- font-weight: 400;
- line-height: 20px; /* 142.857% */
- height: 20px;
-
- .ant-btn-icon {
- margin-inline-end: 4px;
+ .dashboard-btn {
+ display: flex;
+ align-items: center;
+ color: var(--bg-vanilla-400);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px; /* 142.857% */
+ letter-spacing: -0.07px;
+ padding: 0px;
+ height: 20px;
+ }
+
+ .dashboard-btn:hover {
+ background-color: unset;
+ }
+
+ .id-btn {
+ display: flex;
+ align-items: center;
+ padding: 0px 2px;
+ border-radius: 2px;
+ background: rgba(113, 144, 249, 0.1);
+ color: var(--bg-robin-400);
+ font-family: Inter;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 20px; /* 142.857% */
+ height: 20px;
+
+ .ant-btn-icon {
+ margin-inline-end: 4px;
+ }
+ }
+ .id-btn:hover {
+ background: rgba(113, 144, 249, 0.1);
+ color: var(--bg-robin-300);
}
- }
- .id-btn:hover {
- background: rgba(113, 144, 249, 0.1);
- color: var(--bg-robin-300);
}
}
@@ -562,11 +568,12 @@
.dashboard-description-container {
color: var(--bg-ink-400);
- .dashboard-breadcrumbs {
+ .dashboard-header {
border-bottom: 1px solid var(--bg-vanilla-300);
-
- .dashboard-btn {
- color: var(--bg-ink-400);
+ .dashboard-breadcrumbs {
+ .dashboard-btn {
+ color: var(--bg-ink-400);
+ }
}
}
diff --git a/frontend/src/container/NewDashboard/DashboardDescription/index.tsx b/frontend/src/container/NewDashboard/DashboardDescription/index.tsx
index 0af57abdc7..f1288493bd 100644
--- a/frontend/src/container/NewDashboard/DashboardDescription/index.tsx
+++ b/frontend/src/container/NewDashboard/DashboardDescription/index.tsx
@@ -1,19 +1,11 @@
import './Description.styles.scss';
import { PlusOutlined } from '@ant-design/icons';
-import {
- Button,
- Card,
- Flex,
- Input,
- Modal,
- Popover,
- Tag,
- Typography,
-} from 'antd';
+import { Button, Card, Input, Modal, Popover, Tag, Typography } from 'antd';
import FacingIssueBtn from 'components/facingIssueBtn/FacingIssueBtn';
import { dashboardHelpMessage } from 'components/facingIssueBtn/util';
import { SOMETHING_WENT_WRONG } from 'constants/api';
+import { QueryParams } from 'constants/query';
import { PANEL_GROUP_TYPES, PANEL_TYPES } from 'constants/queryBuilder';
import ROUTES from 'constants/routes';
import { DeleteButton } from 'container/ListOfDashboard/TableComponents/DeleteButton';
@@ -21,6 +13,7 @@ import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
import useComponentPermission from 'hooks/useComponentPermission';
import { useNotifications } from 'hooks/useNotifications';
+import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import { isEmpty } from 'lodash-es';
import {
@@ -70,6 +63,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
layouts,
setLayouts,
isDashboardLocked,
+ listSortOrder,
setSelectedDashboard,
handleToggleDashboardSlider,
handleDashboardLockToggle,
@@ -91,6 +85,8 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
const updateDashboardMutation = useUpdateDashboard();
+ const urlQuery = useUrlQuery();
+
const { featureResponse, user, role } = useSelector(
(state) => state.app,
);
@@ -259,15 +255,25 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
});
}
+ function goToListPage(): void {
+ urlQuery.set('columnKey', listSortOrder.columnKey as string);
+ urlQuery.set('order', listSortOrder.order as string);
+ urlQuery.set('page', listSortOrder.pagination as string);
+ urlQuery.delete(QueryParams.relativeTime);
+
+ const generatedUrl = `${ROUTES.ALL_DASHBOARD}?${urlQuery.toString()}`;
+ history.replace(generatedUrl);
+ }
+
return (
-
+
}
className="dashboard-btn"
- onClick={(): void => history.push(ROUTES.ALL_DASHBOARD)}
+ onClick={(): void => goToListPage()}
>
Dashboard /
@@ -297,7 +303,7 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
buttonText="Facing issues with dashboards?"
onHoverText="Click here to get help with dashboard details"
/>
-
+
![]()
{
let numberOfUnsavedChanges = 0;
- if (!isEqual(updatedTitle, selectedData?.title)) {
- numberOfUnsavedChanges += 1;
- }
- if (!isEqual(updatedDescription, selectedData?.description)) {
- numberOfUnsavedChanges += 1;
- }
- if (!isEqual(updatedTags, selectedData?.tags)) {
- numberOfUnsavedChanges += 1;
- }
- if (!isEqual(updatedImage, selectedData?.image)) {
- numberOfUnsavedChanges += 1;
- }
+ const initialValues = [title, description, tags, image];
+ const updatedValues = [
+ updatedTitle,
+ updatedDescription,
+ updatedTags,
+ updatedImage,
+ ];
+ initialValues.forEach((val, index) => {
+ if (!isEqual(val, updatedValues[index])) {
+ numberOfUnsavedChanges += 1;
+ }
+ });
setNumberOfUnsavedChanges(numberOfUnsavedChanges);
}, [
- selectedData?.description,
- selectedData?.image,
- selectedData?.tags,
- selectedData?.title,
+ description,
+ image,
+ tags,
+ title,
updatedDescription,
updatedImage,
updatedTags,
@@ -167,7 +167,8 @@ function GeneralDashboardSettings(): JSX.Element {
- {numberOfUnsavedChanges} Unsaved change
+ {numberOfUnsavedChanges} unsaved change
+ {numberOfUnsavedChanges > 1 && 's'}
diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss
index f610198f4a..f7fcb83a53 100644
--- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss
+++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.styles.scss
@@ -40,12 +40,46 @@
}
.variable-select {
- .ant-select-dropdown {
- max-width: 300px;
+ .ant-select-item {
+ display: flex;
+ align-items: center;
+ }
+
+ .all-label {
+ display: flex;
+ gap: 16px;
+ }
+
+ .dropdown-checkbox-label {
+ display: grid;
+ grid-template-columns: 24px 1fr;
+ }
+
+ .dropdown-value {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .option-text {
+ max-width: 180px;
+ padding: 0 8px;
+ }
+
+ .toggle-tag-label {
+ padding-left: 8px;
+ right: 40px;
+ font-weight: normal;
+ position: absolute;
+ }
}
}
}
+.dropdown-styles {
+ min-width: 300px;
+ max-width: 350px;
+}
+
.lightMode {
.variable-item {
.variable-name {
diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx
index 0572196fbf..813185e0b6 100644
--- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx
+++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/DashboardVariableSelection.tsx
@@ -138,6 +138,7 @@ function DashboardVariableSelection(): JSX.Element | null {
}}
onValueUpdate={onValueUpdate}
variablesToGetUpdated={variablesToGetUpdated}
+ setVariablesToGetUpdated={setVariablesToGetUpdated}
/>
))}
diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx
index cd8b23ea46..0c8fbd51ae 100644
--- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx
+++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.test.tsx
@@ -54,6 +54,7 @@ describe('VariableItem', () => {
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
variablesToGetUpdated={[]}
+ setVariablesToGetUpdated={(): void => {}}
/>
,
);
@@ -69,6 +70,7 @@ describe('VariableItem', () => {
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
variablesToGetUpdated={[]}
+ setVariablesToGetUpdated={(): void => {}}
/>
,
);
@@ -83,6 +85,7 @@ describe('VariableItem', () => {
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
variablesToGetUpdated={[]}
+ setVariablesToGetUpdated={(): void => {}}
/>
,
);
@@ -111,6 +114,7 @@ describe('VariableItem', () => {
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
variablesToGetUpdated={[]}
+ setVariablesToGetUpdated={(): void => {}}
/>
,
);
@@ -123,6 +127,8 @@ describe('VariableItem', () => {
const customVariableData = {
...mockCustomVariableData,
allSelected: true,
+ showALLOption: true,
+ multiSelect: true,
};
render(
@@ -132,6 +138,7 @@ describe('VariableItem', () => {
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
variablesToGetUpdated={[]}
+ setVariablesToGetUpdated={(): void => {}}
/>
,
);
@@ -147,6 +154,7 @@ describe('VariableItem', () => {
existingVariables={{}}
onValueUpdate={mockOnValueUpdate}
variablesToGetUpdated={[]}
+ setVariablesToGetUpdated={(): void => {}}
/>
,
);
diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx
index 2a14aa19e5..baa8228b3c 100644
--- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx
+++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/VariableItem.tsx
@@ -1,15 +1,29 @@
+/* eslint-disable jsx-a11y/click-events-have-key-events */
+/* eslint-disable jsx-a11y/no-static-element-interactions */
+/* eslint-disable @typescript-eslint/no-explicit-any */
+/* eslint-disable react/jsx-props-no-spreading */
+/* eslint-disable no-nested-ternary */
import './DashboardVariableSelection.styles.scss';
import { orange } from '@ant-design/colors';
import { WarningOutlined } from '@ant-design/icons';
-import { Input, Popover, Select, Typography } from 'antd';
+import {
+ Checkbox,
+ Input,
+ Popover,
+ Select,
+ Tag,
+ Tooltip,
+ Typography,
+} from 'antd';
+import { CheckboxChangeEvent } from 'antd/es/checkbox';
import dashboardVariablesQuery from 'api/dashboard/variables/dashboardVariablesQuery';
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import { commaValuesParser } from 'lib/dashbaordVariables/customCommaValuesParser';
import sortValues from 'lib/dashbaordVariables/sortVariableValues';
import { debounce, isArray, isString } from 'lodash-es';
import map from 'lodash-es/map';
-import { memo, useEffect, useMemo, useState } from 'react';
+import { ChangeEvent, memo, useEffect, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { IDashboardVariable } from 'types/api/dashboard/getAll';
import { VariableResponseProps } from 'types/api/dashboard/variables/query';
@@ -23,6 +37,11 @@ const ALL_SELECT_VALUE = '__ALL__';
const variableRegexPattern = /\{\{\s*?\.([^\s}]+)\s*?\}\}/g;
+enum ToggleTagValue {
+ Only = 'Only',
+ All = 'All',
+}
+
interface VariableItemProps {
variableData: IDashboardVariable;
existingVariables: Record
;
@@ -33,12 +52,17 @@ interface VariableItemProps {
allSelected: boolean,
) => void;
variablesToGetUpdated: string[];
+ setVariablesToGetUpdated: React.Dispatch>;
}
const getSelectValue = (
selectedValue: IDashboardVariable['selectedValue'],
+ variableData: IDashboardVariable,
): string | string[] => {
if (Array.isArray(selectedValue)) {
+ if (!variableData.multiSelect && selectedValue.length === 1) {
+ return selectedValue[0]?.toString() || '';
+ }
return selectedValue.map((item) => item.toString());
}
return selectedValue?.toString() || '';
@@ -50,6 +74,7 @@ function VariableItem({
existingVariables,
onValueUpdate,
variablesToGetUpdated,
+ setVariablesToGetUpdated,
}: VariableItemProps): JSX.Element {
const [optionsData, setOptionsData] = useState<(string | number | boolean)[]>(
[],
@@ -148,6 +173,10 @@ function VariableItem({
}
setOptionsData(newOptionsData);
+ } else {
+ setVariablesToGetUpdated((prev) =>
+ prev.filter((name) => name !== variableData.name),
+ );
}
}
} catch (e) {
@@ -193,7 +222,7 @@ function VariableItem({
});
const handleChange = (value: string | string[]): void => {
- if (variableData.name)
+ if (variableData.name) {
if (
value === ALL_SELECT_VALUE ||
(Array.isArray(value) && value.includes(ALL_SELECT_VALUE)) ||
@@ -203,25 +232,29 @@ function VariableItem({
} else {
onValueUpdate(variableData.name, variableData.id, value, false);
}
+ }
};
// do not debounce the above function as we do not need debounce in select variables
const debouncedHandleChange = debounce(handleChange, 500);
const { selectedValue } = variableData;
- const selectedValueStringified = useMemo(() => getSelectValue(selectedValue), [
- selectedValue,
- ]);
+ const selectedValueStringified = useMemo(
+ () => getSelectValue(selectedValue, variableData),
+ [selectedValue, variableData],
+ );
- const selectValue = variableData.allSelected
- ? 'ALL'
- : selectedValueStringified;
+ const enableSelectAll = variableData.multiSelect && variableData.showALLOption;
- const mode =
+ const selectValue =
+ variableData.allSelected && enableSelectAll
+ ? 'ALL'
+ : selectedValueStringified;
+
+ const mode: 'multiple' | undefined =
variableData.multiSelect && !variableData.allSelected
? 'multiple'
: undefined;
- const enableSelectAll = variableData.multiSelect && variableData.showALLOption;
useEffect(() => {
// Fetch options for CUSTOM Type
@@ -231,6 +264,117 @@ function VariableItem({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [variableData.type, variableData.customValue]);
+ const checkAll = (e: MouseEvent): void => {
+ e.stopPropagation();
+ e.preventDefault();
+ const isChecked =
+ variableData.allSelected || selectValue.includes(ALL_SELECT_VALUE);
+
+ if (isChecked) {
+ handleChange([]);
+ } else {
+ handleChange(ALL_SELECT_VALUE);
+ }
+ };
+
+ const handleOptionSelect = (
+ e: CheckboxChangeEvent,
+ option: string | number | boolean,
+ ): void => {
+ const newSelectedValue = Array.isArray(selectedValue)
+ ? ((selectedValue.filter(
+ (val) => val.toString() !== option.toString(),
+ ) as unknown) as string[])
+ : [];
+
+ if (
+ !e.target.checked &&
+ Array.isArray(selectedValueStringified) &&
+ selectedValueStringified.includes(option.toString())
+ ) {
+ if (newSelectedValue.length === 0) {
+ handleChange(ALL_SELECT_VALUE);
+ return;
+ }
+ if (newSelectedValue.length === 1) {
+ handleChange(newSelectedValue[0].toString());
+ return;
+ }
+ handleChange(newSelectedValue);
+ } else if (!e.target.checked && selectedValue === option.toString()) {
+ handleChange(ALL_SELECT_VALUE);
+ } else if (newSelectedValue.length === optionsData.length - 1) {
+ handleChange(ALL_SELECT_VALUE);
+ }
+ };
+
+ const [optionState, setOptionState] = useState({
+ tag: '',
+ visible: false,
+ });
+
+ function currentToggleTagValue({
+ option,
+ }: {
+ option: string;
+ }): ToggleTagValue {
+ if (
+ option.toString() === selectValue ||
+ (Array.isArray(selectValue) &&
+ selectValue?.includes(option.toString()) &&
+ selectValue.length === 1)
+ ) {
+ return ToggleTagValue.All;
+ }
+ return ToggleTagValue.Only;
+ }
+
+ function handleToggle(e: ChangeEvent, option: string): void {
+ e.stopPropagation();
+ const mode = currentToggleTagValue({ option: option as string });
+ const isChecked =
+ variableData.allSelected ||
+ option.toString() === selectValue ||
+ (Array.isArray(selectValue) && selectValue?.includes(option.toString()));
+
+ if (isChecked) {
+ if (mode === ToggleTagValue.Only) {
+ handleChange(option.toString());
+ } else if (!variableData.multiSelect) {
+ handleChange(option.toString());
+ } else {
+ handleChange(ALL_SELECT_VALUE);
+ }
+ } else {
+ handleChange(option.toString());
+ }
+ }
+
+ function retProps(
+ option: string,
+ ): {
+ onMouseOver: () => void;
+ onMouseOut: () => void;
+ } {
+ return {
+ onMouseOver: (): void =>
+ setOptionState({
+ tag: option.toString(),
+ visible: true,
+ }),
+ onMouseOut: (): void =>
+ setOptionState({
+ tag: option.toString(),
+ visible: false,
+ }),
+ };
+ }
+
+ const ensureValidOption = (option: string): boolean =>
+ !(
+ currentToggleTagValue({ option }) === ToggleTagValue.All && !enableSelectAll
+ );
+
return (
@@ -264,19 +408,35 @@ function VariableItem({
onChange={handleChange}
bordered={false}
placeholder="Select value"
- placement="bottomRight"
+ placement="bottomLeft"
mode={mode}
- dropdownMatchSelectWidth={false}
style={SelectItemStyle}
loading={isLoading}
showSearch
data-testid="variable-select"
className="variable-select"
+ popupClassName="dropdown-styles"
+ maxTagCount={4}
getPopupContainer={popupContainer}
+ // eslint-disable-next-line react/no-unstable-nested-components
+ tagRender={(props): JSX.Element => (
+
+ {props.value}
+
+ )}
+ // eslint-disable-next-line react/no-unstable-nested-components
+ maxTagPlaceholder={(omittedValues): JSX.Element => (
+ value).join(', ')}>
+ + {omittedValues.length}
+
+ )}
>
{enableSelectAll && (
- ALL
+ checkAll(e as any)}>
+
+ ALL
+
)}
{map(optionsData, (option) => (
@@ -285,7 +445,45 @@ function VariableItem({
key={option.toString()}
value={option}
>
- {option.toString()}
+
+ {variableData.multiSelect && (
+
{
+ e.stopPropagation();
+ e.preventDefault();
+ handleOptionSelect(e, option);
+ }}
+ checked={
+ variableData.allSelected ||
+ option.toString() === selectValue ||
+ (Array.isArray(selectValue) &&
+ selectValue?.includes(option.toString()))
+ }
+ />
+ )}
+ handleToggle(e as any, option as string)}
+ >
+
+
+ {option.toString()}
+
+
+
+ {variableData.multiSelect &&
+ optionState.tag === option.toString() &&
+ optionState.visible &&
+ ensureValidOption(option as string) && (
+
+ {currentToggleTagValue({ option: option as string })}
+
+ )}
+
+
))}
diff --git a/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts b/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts
index 5c5de3e97e..02530dbd0f 100644
--- a/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts
+++ b/frontend/src/container/NewDashboard/DashboardVariablesSelection/styles.ts
@@ -42,4 +42,5 @@ export const VariableValue = styled(Typography)`
export const SelectItemStyle = {
minWidth: 120,
fontSize: '0.8rem',
+ width: '100%',
};
diff --git a/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx b/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx
index beed344d8b..3f6deab6f8 100644
--- a/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx
+++ b/frontend/src/container/NewWidget/LeftContainer/QuerySection/index.tsx
@@ -12,7 +12,6 @@ import { QueryBuilderProps } from 'container/QueryBuilder/QueryBuilder.interface
import { useKeyboardHotkeys } from 'hooks/hotkeys/useKeyboardHotkeys';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
-import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import { useIsDarkMode } from 'hooks/useDarkMode';
import useUrlQuery from 'hooks/useUrlQuery';
import { defaultTo } from 'lodash-es';
@@ -33,7 +32,6 @@ import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { EQueryType } from 'types/common/dashboard';
import AppReducer from 'types/reducer/app';
-import { GlobalReducer } from 'types/reducer/globalTime';
import ClickHouseQueryContainer from './QueryBuilder/clickHouse';
import PromQLQueryContainer from './QueryBuilder/promQL';
@@ -46,10 +44,6 @@ function QuerySection({
const urlQuery = useUrlQuery();
const { registerShortcut, deregisterShortcut } = useKeyboardHotkeys();
- const { minTime, maxTime } = useSelector(
- (state) => state.globalTime,
- );
-
const { featureResponse } = useSelector(
(state) => state.app,
);
@@ -80,8 +74,6 @@ function QuerySection({
return;
}
- const updatedQuery = updateStepInterval(query, maxTime, minTime);
-
const selectedWidgetIndex = getSelectedWidgetIndex(
selectedDashboard,
selectedWidget.id,
@@ -102,18 +94,16 @@ function QuerySection({
...previousWidgets,
{
...selectedWidget,
- query: updatedQuery,
+ query,
},
...nextWidgets,
],
},
});
- redirectWithQueryBuilderData(updatedQuery);
+ redirectWithQueryBuilderData(query);
},
[
selectedDashboard,
- maxTime,
- minTime,
selectedWidget,
setSelectedDashboard,
redirectWithQueryBuilderData,
@@ -137,7 +127,7 @@ function QuerySection({
const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
const config: QueryBuilderProps['filterConfigs'] = {
- stepInterval: { isHidden: false, isDisabled: true },
+ stepInterval: { isHidden: false, isDisabled: false },
};
return config;
diff --git a/frontend/src/container/NewWidget/LeftContainer/index.tsx b/frontend/src/container/NewWidget/LeftContainer/index.tsx
index e7c149c246..0363b4c6f8 100644
--- a/frontend/src/container/NewWidget/LeftContainer/index.tsx
+++ b/frontend/src/container/NewWidget/LeftContainer/index.tsx
@@ -72,10 +72,16 @@ function LeftContainer({
globalSelectedInterval,
graphType: getGraphType(selectedGraph || selectedWidget.panelTypes),
query: stagedQuery,
+ fillGaps: selectedWidget.fillSpans || false,
}));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [stagedQuery, selectedTime, globalSelectedInterval]);
+ }, [
+ stagedQuery,
+ selectedTime,
+ selectedWidget.fillSpans,
+ globalSelectedInterval,
+ ]);
const queryResponse = useGetQueryRange(
requestData,
diff --git a/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx b/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx
index 6eff73fdf6..8ed4c898a7 100644
--- a/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx
+++ b/frontend/src/container/NewWidget/RightContainer/ColumnUnitSelector/ColumnUnitSelector.tsx
@@ -4,6 +4,7 @@ import { Typography } from 'antd';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { Dispatch, SetStateAction } from 'react';
import { ColumnUnit } from 'types/api/dashboard/getAll';
+import { EQueryType } from 'types/common/dashboard';
import YAxisUnitSelector from '../YAxisUnitSelector';
@@ -18,7 +19,13 @@ export function ColumnUnitSelector(
const { currentQuery } = useQueryBuilder();
function getAggregateColumnsNamesAndLabels(): string[] {
- return currentQuery.builder.queryData.map((q) => q.queryName);
+ if (currentQuery.queryType === EQueryType.QUERY_BUILDER) {
+ return currentQuery.builder.queryData.map((q) => q.queryName);
+ }
+ if (currentQuery.queryType === EQueryType.CLICKHOUSE) {
+ return currentQuery.clickhouse_sql.map((q) => q.name);
+ }
+ return currentQuery.promql.map((q) => q.name);
}
const { columnUnits, setColumnUnits } = props;
diff --git a/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss b/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss
index ebcbbedbbc..55d717926a 100644
--- a/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss
+++ b/frontend/src/container/NewWidget/RightContainer/RightContainer.styles.scss
@@ -241,6 +241,24 @@
}
}
+ .stack-chart {
+ margin-top: 16px;
+ display: flex;
+ justify-content: space-between;
+ gap: 8px;
+
+ .label {
+ color: var(--bg-vanilla-400);
+ font-family: 'Space Mono';
+ font-size: 13px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 18px; /* 138.462% */
+ letter-spacing: 0.52px;
+ text-transform: uppercase;
+ }
+ }
+
.bucket-config {
margin-top: 16px;
display: flex;
@@ -411,6 +429,21 @@
}
}
+ .bucket-config {
+ .label {
+ color: var(--bg-ink-400);
+ }
+
+ .bucket-input {
+ border: 1px solid var(--bg-vanilla-300);
+ background: var(--bg-vanilla-300);
+
+ .ant-input {
+ background: var(--bg-vanilla-300);
+ }
+ }
+ }
+
.panel-time-text {
color: var(--bg-ink-400);
}
diff --git a/frontend/src/container/NewWidget/RightContainer/constants.ts b/frontend/src/container/NewWidget/RightContainer/constants.ts
index 5276fc2bcd..171f6b81d3 100644
--- a/frontend/src/container/NewWidget/RightContainer/constants.ts
+++ b/frontend/src/container/NewWidget/RightContainer/constants.ts
@@ -132,3 +132,17 @@ export const panelTypeVsColumnUnitPreferences: {
[PANEL_TYPES.HISTOGRAM]: false,
[PANEL_TYPES.EMPTY_WIDGET]: false,
} as const;
+
+export const panelTypeVsStackingChartPreferences: {
+ [key in PANEL_TYPES]: boolean;
+} = {
+ [PANEL_TYPES.TIME_SERIES]: false,
+ [PANEL_TYPES.VALUE]: false,
+ [PANEL_TYPES.TABLE]: false,
+ [PANEL_TYPES.LIST]: false,
+ [PANEL_TYPES.PIE]: false,
+ [PANEL_TYPES.BAR]: true,
+ [PANEL_TYPES.TRACE]: false,
+ [PANEL_TYPES.HISTOGRAM]: false,
+ [PANEL_TYPES.EMPTY_WIDGET]: false,
+} as const;
diff --git a/frontend/src/container/NewWidget/RightContainer/index.tsx b/frontend/src/container/NewWidget/RightContainer/index.tsx
index f615d37829..08387cd069 100644
--- a/frontend/src/container/NewWidget/RightContainer/index.tsx
+++ b/frontend/src/container/NewWidget/RightContainer/index.tsx
@@ -29,6 +29,7 @@ import {
panelTypeVsFillSpan,
panelTypeVsPanelTimePreferences,
panelTypeVsSoftMinMax,
+ panelTypeVsStackingChartPreferences,
panelTypeVsThreshold,
panelTypeVsYAxisUnit,
} from './constants';
@@ -48,6 +49,8 @@ function RightContainer({
selectedGraph,
bucketCount,
bucketWidth,
+ stackedBarChart,
+ setStackedBarChart,
setBucketCount,
setBucketWidth,
setSelectedTime,
@@ -87,6 +90,8 @@ function RightContainer({
const allowYAxisUnit = panelTypeVsYAxisUnit[selectedGraph];
const allowCreateAlerts = panelTypeVsCreateAlert[selectedGraph];
const allowBucketConfig = panelTypeVsBucketConfig[selectedGraph];
+ const allowStackingBarChart =
+ panelTypeVsStackingChartPreferences[selectedGraph];
const allowPanelTimePreference =
panelTypeVsPanelTimePreferences[selectedGraph];
@@ -231,6 +236,17 @@ function RightContainer({
)}
+ {allowStackingBarChart && (
+
+ Stack series
+ setStackedBarChart(checked)}
+ />
+
+ )}
+
{allowBucketConfig && (
Number of buckets
@@ -312,6 +328,8 @@ interface RightContainerProps {
setSelectedTime: Dispatch>;
selectedTime: timePreferance;
yAxisUnit: string;
+ stackedBarChart: boolean;
+ setStackedBarChart: Dispatch>;
bucketWidth: number;
bucketCount: number;
combineHistogram: boolean;
diff --git a/frontend/src/container/NewWidget/index.tsx b/frontend/src/container/NewWidget/index.tsx
index bc7f5bf1fd..79c9cb9028 100644
--- a/frontend/src/container/NewWidget/index.tsx
+++ b/frontend/src/container/NewWidget/index.tsx
@@ -126,6 +126,10 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
const [stacked, setStacked] = useState(
selectedWidget?.isStacked || false,
);
+
+ const [stackedBarChart, setStackedBarChart] = useState(
+ selectedWidget?.stackedBarChart || false,
+ );
const [opacity, setOpacity] = useState(selectedWidget?.opacity || '1');
const [thresholds, setThresholds] = useState(
selectedWidget?.thresholds || [],
@@ -195,6 +199,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
fillSpans: isFillSpans,
columnUnits,
bucketCount,
+ stackedBarChart,
bucketWidth,
mergeAllActiveQueries: combineHistogram,
selectedLogFields,
@@ -219,6 +224,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
bucketWidth,
bucketCount,
combineHistogram,
+ stackedBarChart,
]);
const closeModal = (): void => {
@@ -307,6 +313,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
opacity: selectedWidget?.opacity || '1',
nullZeroValues: selectedWidget?.nullZeroValues || 'zero',
title: selectedWidget?.title,
+ stackedBarChart: selectedWidget?.stackedBarChart || false,
yAxisUnit: selectedWidget?.yAxisUnit,
panelTypes: graphType,
query: currentQuery,
@@ -332,6 +339,7 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
opacity: selectedWidget?.opacity || '1',
nullZeroValues: selectedWidget?.nullZeroValues || 'zero',
title: selectedWidget?.title,
+ stackedBarChart: selectedWidget?.stackedBarChart || false,
yAxisUnit: selectedWidget?.yAxisUnit,
panelTypes: graphType,
query: currentQuery,
@@ -532,6 +540,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
setDescription={setDescription}
stacked={stacked}
setStacked={setStacked}
+ stackedBarChart={stackedBarChart}
+ setStackedBarChart={setStackedBarChart}
opacity={opacity}
yAxisUnit={yAxisUnit}
columnUnits={columnUnits}
diff --git a/frontend/src/container/NewWidget/styles.ts b/frontend/src/container/NewWidget/styles.ts
index 54a01817b4..6b52d1fee1 100644
--- a/frontend/src/container/NewWidget/styles.ts
+++ b/frontend/src/container/NewWidget/styles.ts
@@ -10,10 +10,9 @@ export const Container = styled.div`
export const RightContainerWrapper = styled(Col)`
&&& {
- min-width: 330px;
- overflow-y: auto;
max-width: 400px;
width: 30%;
+ overflow-y: auto;
}
&::-webkit-scrollbar {
width: 0rem;
@@ -26,7 +25,7 @@ interface LeftContainerWrapperProps {
export const LeftContainerWrapper = styled(Col)`
&&& {
- min-width: 70%;
+ width: 100%;
overflow-y: auto;
border-right: ${({ isDarkMode }): string =>
isDarkMode
diff --git a/frontend/src/container/NewWidget/utils.ts b/frontend/src/container/NewWidget/utils.ts
index a8ac095d1e..b840d6e71a 100644
--- a/frontend/src/container/NewWidget/utils.ts
+++ b/frontend/src/container/NewWidget/utils.ts
@@ -189,50 +189,6 @@ export const panelTypeDataSourceFormValuesMap: Record<
},
},
},
- [PANEL_TYPES.HISTOGRAM]: {
- [DataSource.LOGS]: {
- builder: {
- queryData: [
- 'filters',
- 'aggregateOperator',
- 'aggregateAttribute',
- 'groupBy',
- 'limit',
- 'having',
- 'orderBy',
- 'functions',
- ],
- },
- },
- [DataSource.METRICS]: {
- builder: {
- queryData: [
- 'filters',
- 'aggregateOperator',
- 'aggregateAttribute',
- 'groupBy',
- 'limit',
- 'having',
- 'orderBy',
- 'functions',
- 'spaceAggregation',
- ],
- },
- },
- [DataSource.TRACES]: {
- builder: {
- queryData: [
- 'filters',
- 'aggregateOperator',
- 'aggregateAttribute',
- 'groupBy',
- 'limit',
- 'having',
- 'orderBy',
- ],
- },
- },
- },
[PANEL_TYPES.TABLE]: {
[DataSource.LOGS]: {
builder: {
diff --git a/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx b/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx
index bfe6db81cd..a176247781 100644
--- a/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx
+++ b/frontend/src/container/PanelWrapper/PiePanelWrapper.tsx
@@ -60,7 +60,7 @@ function PiePanelWrapper({
d.series?.length === 1
? getLabel(Object.values(s.labels)[0], widget.query, d.queryName)
: getLabel(Object.values(s.labels)[0], {} as Query, d.queryName, true),
- themeColors.chartcolors,
+ isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor,
),
})),
)
diff --git a/frontend/src/container/PanelWrapper/UplotPanelWrapper.styles.scss b/frontend/src/container/PanelWrapper/UplotPanelWrapper.styles.scss
new file mode 100644
index 0000000000..a1ab2e3c9e
--- /dev/null
+++ b/frontend/src/container/PanelWrapper/UplotPanelWrapper.styles.scss
@@ -0,0 +1,4 @@
+.info-text {
+ margin-top: 8px;
+ padding: 8px;
+}
diff --git a/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx b/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx
index f95d5772af..dc404adabb 100644
--- a/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx
+++ b/frontend/src/container/PanelWrapper/UplotPanelWrapper.tsx
@@ -1,3 +1,6 @@
+import './UplotPanelWrapper.styles.scss';
+
+import { Alert } from 'antd';
import { ToggleGraphProps } from 'components/Graph/types';
import Uplot from 'components/Uplot';
import { PANEL_TYPES } from 'constants/queryBuilder';
@@ -8,6 +11,7 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
import { useResizeObserver } from 'hooks/useDimensions';
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
+import { cloneDeep, isEqual, isUndefined } from 'lodash-es';
import _noop from 'lodash-es/noop';
import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useEffect, useMemo, useRef, useState } from 'react';
@@ -35,6 +39,8 @@ function UplotPanelWrapper({
const [maxTimeScale, setMaxTimeScale] = useState();
const { currentQuery } = useQueryBuilder();
+ const [hiddenGraph, setHiddenGraph] = useState<{ [key: string]: boolean }>();
+
useEffect(() => {
if (toScrollWidgetId === widget.id) {
graphRef.current?.scrollIntoView({
@@ -78,8 +84,26 @@ function UplotPanelWrapper({
const chartData = getUPlotChartData(
queryResponse?.data?.payload,
widget.fillSpans,
+ widget?.stackedBarChart,
+ hiddenGraph,
);
+ useEffect(() => {
+ if (widget.panelTypes === PANEL_TYPES.BAR && widget?.stackedBarChart) {
+ const graphV = cloneDeep(graphVisibility)?.slice(1);
+ const isSomeSelectedLegend = graphV?.some((v) => v === false);
+ if (isSomeSelectedLegend) {
+ const hiddenIndex = graphV?.findIndex((v) => v === true);
+ if (!isUndefined(hiddenIndex) && hiddenIndex !== -1) {
+ const updatedHiddenGraph = { [hiddenIndex]: true };
+ if (!isEqual(hiddenGraph, updatedHiddenGraph)) {
+ setHiddenGraph(updatedHiddenGraph);
+ }
+ }
+ }
+ }
+ }, [graphVisibility, hiddenGraph, widget.panelTypes, widget?.stackedBarChart]);
+
const options = useMemo(
() =>
getUPlotChartOptions({
@@ -99,6 +123,9 @@ function UplotPanelWrapper({
setGraphsVisibilityStates: setGraphVisibility,
panelType: selectedGraph || widget.panelTypes,
currentQuery,
+ stackBarChart: widget?.stackedBarChart,
+ hiddenGraph,
+ setHiddenGraph,
}),
[
widget?.id,
@@ -107,6 +134,7 @@ function UplotPanelWrapper({
widget.softMax,
widget.softMin,
widget.panelTypes,
+ widget?.stackedBarChart,
queryResponse.data?.payload,
containerDimensions,
isDarkMode,
@@ -118,15 +146,23 @@ function UplotPanelWrapper({
setGraphVisibility,
selectedGraph,
currentQuery,
+ hiddenGraph,
],
);
return (
- {isFullViewMode && setGraphVisibility && (
+ {widget?.stackedBarChart && isFullViewMode && (
+
+ )}
+ {isFullViewMode && setGraphVisibility && !widget?.stackedBarChart && (
{
jest.advanceTimersByTime(299);
expect(setPipelineValue).not.toHaveBeenCalled();
- // Wait for the debounce delay to pass
+ // Fast-forward time by 1ms to reach the debounce delay
+ jest.advanceTimersByTime(1);
+
+ // Wait for the debounce delay to pass and expect the callback to be called
await waitFor(() => {
- // Expect the callback to be called after debounce delay
expect(setPipelineValue).toHaveBeenCalledWith('sample_pipeline');
});
diff --git a/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx b/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx
index b272a39475..372f301008 100644
--- a/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx
+++ b/frontend/src/container/ServiceApplication/Columns/GetColumnSearchProps.tsx
@@ -1,13 +1,26 @@
+import '../ServiceApplication.styles.scss';
+
import { SearchOutlined } from '@ant-design/icons';
+import { Popconfirm, PopconfirmProps } from 'antd';
import type { ColumnType } from 'antd/es/table';
import ROUTES from 'constants/routes';
import { routeConfig } from 'container/SideNav/config';
import { getQueryString } from 'container/SideNav/helper';
+import history from 'lib/history';
+import { Info } from 'lucide-react';
import { Link } from 'react-router-dom';
import { ServicesList } from 'types/api/metrics/getService';
import { filterDropdown } from '../Filter/FilterDropdown';
-import { Name } from '../styles';
+
+const MAX_TOP_LEVEL_OPERATIONS = 2500;
+
+const highTopLevelOperationsPopoverDesc = (metrics: string): JSX.Element => (
+
+ The service `{metrics}` has too many top level operations. It makes the
+ dashboard slow to load.
+
+);
export const getColumnSearchProps = (
dataIndex: keyof ServicesList,
@@ -15,24 +28,61 @@ export const getColumnSearchProps = (
): ColumnType => ({
filterDropdown,
filterIcon: ,
- onFilter: (value: string | number | boolean, record: ServicesList): boolean =>
- record[dataIndex]
- .toString()
- .toLowerCase()
- .includes(value.toString().toLowerCase()),
- render: (metrics: string): JSX.Element => {
+ onFilter: (
+ value: string | number | boolean,
+ record: ServicesList,
+ ): boolean => {
+ if (record[dataIndex]) {
+ record[dataIndex]
+ ?.toString()
+ .toLowerCase()
+ .includes(value.toString().toLowerCase());
+ }
+
+ return false;
+ },
+ render: (metrics: string, record: ServicesList): JSX.Element => {
const urlParams = new URLSearchParams(search);
const avialableParams = routeConfig[ROUTES.SERVICE_METRICS];
const queryString = getQueryString(avialableParams, urlParams);
+ const topLevelOperations = record?.dataWarning?.topLevelOps || [];
+
+ const handleShowTopLevelOperations: PopconfirmProps['onConfirm'] = () => {
+ history.push(
+ `${ROUTES.APPLICATION}/${encodeURIComponent(metrics)}/top-level-operations`,
+ );
+ };
+
+ const hasHighTopLevelOperations =
+ topLevelOperations &&
+ Array.isArray(topLevelOperations) &&
+ topLevelOperations.length > MAX_TOP_LEVEL_OPERATIONS;
return (
-
- {metrics}
-
+
+ {hasHighTopLevelOperations && (
+
+
+
+ )}
+
+
+ {metrics}
+
+
);
},
});
diff --git a/frontend/src/container/ServiceApplication/ServiceApplication.styles.scss b/frontend/src/container/ServiceApplication/ServiceApplication.styles.scss
new file mode 100644
index 0000000000..9cdbd2329c
--- /dev/null
+++ b/frontend/src/container/ServiceApplication/ServiceApplication.styles.scss
@@ -0,0 +1,25 @@
+.serviceName {
+ color: #4e74f8;
+ font-weight: 600;
+ cursor: pointer;
+
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.error {
+ color: var(--bg-cherry-500);
+
+ a {
+ color: var(--bg-cherry-500);
+ }
+}
+
+.service-high-top-level-operations {
+ width: 300px;
+
+ .popover-description {
+ padding: 16px 0;
+ }
+}
diff --git a/frontend/src/container/ServiceApplication/index.tsx b/frontend/src/container/ServiceApplication/index.tsx
index b7b22018e1..0afdc6950d 100644
--- a/frontend/src/container/ServiceApplication/index.tsx
+++ b/frontend/src/container/ServiceApplication/index.tsx
@@ -1,7 +1,7 @@
+import * as Sentry from '@sentry/react';
import { FeatureKeys } from 'constants/features';
import useFeatureFlag from 'hooks/useFeatureFlag';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
-import { ErrorBoundary } from 'react-error-boundary';
import ServiceMetrics from './ServiceMetrics';
import ServiceTraces from './ServiceTraces';
@@ -12,11 +12,11 @@ function Services(): JSX.Element {
?.active;
return (
-
+ }>
{isSpanMetricEnabled ? : }
-
+
);
}
diff --git a/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx b/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx
index 4257dc57ec..059063e5d9 100644
--- a/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx
+++ b/frontend/src/container/ServiceTable/Columns/GetColumnSearchProps.tsx
@@ -15,11 +15,19 @@ export const getColumnSearchProps = (
): ColumnType => ({
filterDropdown,
filterIcon: ,
- onFilter: (value: string | number | boolean, record: ServicesList): boolean =>
- record[dataIndex]
- .toString()
- .toLowerCase()
- .includes(value.toString().toLowerCase()),
+ onFilter: (
+ value: string | number | boolean,
+ record: ServicesList,
+ ): boolean => {
+ if (record[dataIndex]) {
+ record[dataIndex]
+ ?.toString()
+ .toLowerCase()
+ .includes(value.toString().toLowerCase());
+ }
+
+ return false;
+ },
render: (metrics: string): JSX.Element => {
const urlParams = new URLSearchParams(search);
const avialableParams = routeConfig[ROUTES.SERVICE_METRICS];
diff --git a/frontend/src/container/SideNav/SideNav.tsx b/frontend/src/container/SideNav/SideNav.tsx
index 3b35a75a81..6cec0448b2 100644
--- a/frontend/src/container/SideNav/SideNav.tsx
+++ b/frontend/src/container/SideNav/SideNav.tsx
@@ -209,7 +209,9 @@ function SideNav({
if (event && isCtrlMetaKey(event)) {
openInNewTab(`${key}?${queryString.join('&')}`);
} else {
- history.push(`${key}?${queryString.join('&')}`);
+ history.push(`${key}?${queryString.join('&')}`, {
+ from: pathname,
+ });
}
}
},
diff --git a/frontend/src/container/SideNav/menuItems.tsx b/frontend/src/container/SideNav/menuItems.tsx
index 6c9a87db02..31bd96333e 100644
--- a/frontend/src/container/SideNav/menuItems.tsx
+++ b/frontend/src/container/SideNav/menuItems.tsx
@@ -125,8 +125,8 @@ const menuItems: SidebarItem[] = [
/** Mapping of some newly added routes and their corresponding active sidebar menu key */
export const NEW_ROUTES_MENU_ITEM_KEY_MAP: Record = {
- [ROUTES.TRACES_EXPLORER]: ROUTES.TRACE,
- [ROUTES.TRACE_EXPLORER]: ROUTES.TRACE,
+ [ROUTES.TRACE]: ROUTES.TRACES_EXPLORER,
+ [ROUTES.TRACE_EXPLORER]: ROUTES.TRACES_EXPLORER,
[ROUTES.LOGS_BASE]: ROUTES.LOGS_EXPLORER,
};
diff --git a/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts b/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts
index 7909984592..7543e02a47 100644
--- a/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts
+++ b/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts
@@ -202,6 +202,7 @@ export const routesToSkip = [
ROUTES.INTEGRATIONS,
ROUTES.DASHBOARD,
ROUTES.DASHBOARD_WIDGET,
+ ROUTES.SERVICE_TOP_LEVEL_OPERATIONS,
];
export const routesToDisable = [ROUTES.LOGS_EXPLORER, ROUTES.LIVE_LOGS];
diff --git a/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx b/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx
index b5c8868184..427b57198c 100644
--- a/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx
+++ b/frontend/src/container/TopNav/DateTimeSelectionV2/index.tsx
@@ -22,7 +22,6 @@ import { QueryHistoryState } from 'container/LiveLogs/types';
import NewExplorerCTA from 'container/NewExplorerCTA';
import dayjs, { Dayjs } from 'dayjs';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
-import { updateStepInterval } from 'hooks/queryBuilder/useStepInterval';
import useUrlQuery from 'hooks/useUrlQuery';
import GetMinMax from 'lib/getMinMax';
import getTimeString from 'lib/getTimeString';
@@ -315,8 +314,6 @@ function DateTimeSelection({
return;
}
- const { maxTime, minTime } = GetMinMax(value, getTime());
-
if (!isLogsExplorerPage) {
urlQuery.delete('startTime');
urlQuery.delete('endTime');
@@ -333,7 +330,8 @@ function DateTimeSelection({
return;
}
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
- initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true);
+ // we removed update step interval to stop auto updating the value on time change
+ initQueryBuilderData(stagedQuery, true);
};
const onRefreshHandler = (): void => {
@@ -383,8 +381,6 @@ function DateTimeSelection({
setIsValidteRelativeTime(true);
- const { maxTime, minTime } = GetMinMax(dateTimeStr, getTime());
-
if (!isLogsExplorerPage) {
urlQuery.delete('startTime');
urlQuery.delete('endTime');
@@ -400,7 +396,8 @@ function DateTimeSelection({
}
// the second boolean param directs the qb about the time change so to merge the query and retain the current state
- initQueryBuilderData(updateStepInterval(stagedQuery, maxTime, minTime), true);
+ // we removed update step interval to stop auto updating the value on time change
+ initQueryBuilderData(stagedQuery, true);
};
const getCustomOrIntervalTime = (
diff --git a/frontend/src/container/TraceDetail/TraceDetails.styles.scss b/frontend/src/container/TraceDetail/TraceDetails.styles.scss
index 676160aecc..0c309bc83d 100644
--- a/frontend/src/container/TraceDetail/TraceDetails.styles.scss
+++ b/frontend/src/container/TraceDetail/TraceDetails.styles.scss
@@ -1,7 +1,17 @@
.span-details-sider {
+ padding-top: 16px;
+
+ ::-webkit-scrollbar {
+ width: 0.2em;
+ }
+
+ ::-webkit-scrollbar-track {
+ box-shadow: inset 0 0 6px rgba(18, 18, 18, 0.3);
+ }
+
&.dark {
.ant-layout-sider-trigger {
- background-color: black !important;
+ background-color: #0b0c0e !important;
}
}
diff --git a/frontend/src/container/TraceDetail/index.tsx b/frontend/src/container/TraceDetail/index.tsx
index 67b55a1bca..4b333e0dad 100644
--- a/frontend/src/container/TraceDetail/index.tsx
+++ b/frontend/src/container/TraceDetail/index.tsx
@@ -246,13 +246,14 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
setCollapsed(value)}
>
{!collapsed && (
diff --git a/frontend/src/container/TracesExplorer/ListView/utils.tsx b/frontend/src/container/TracesExplorer/ListView/utils.tsx
index 732c8eacdf..254ff93296 100644
--- a/frontend/src/container/TracesExplorer/ListView/utils.tsx
+++ b/frontend/src/container/TracesExplorer/ListView/utils.tsx
@@ -3,6 +3,7 @@ import { ColumnsType } from 'antd/es/table';
import ROUTES from 'constants/routes';
import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util';
import { formUrlParams } from 'container/TraceDetail/utils';
+import dayjs from 'dayjs';
import { RowData } from 'lib/query/createTableColumnsFromQuery';
import { ILog } from 'types/api/logs/log';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
@@ -30,6 +31,13 @@ export const getListColumns = (
key: 'date',
title: 'Timestamp',
width: 145,
+ render: (item): JSX.Element => {
+ const date =
+ typeof item === 'string'
+ ? dayjs(item).format('YYYY-MM-DD HH:mm:ss.SSS')
+ : dayjs(item / 1e6).format('YYYY-MM-DD HH:mm:ss.SSS');
+ return {date};
+ },
},
];
diff --git a/frontend/src/container/TracesExplorer/QuerySection/index.tsx b/frontend/src/container/TracesExplorer/QuerySection/index.tsx
index 0bd9515720..8f5d2606f0 100644
--- a/frontend/src/container/TracesExplorer/QuerySection/index.tsx
+++ b/frontend/src/container/TracesExplorer/QuerySection/index.tsx
@@ -19,7 +19,7 @@ function QuerySection(): JSX.Element {
const filterConfigs: QueryBuilderProps['filterConfigs'] = useMemo(() => {
const isList = panelTypes === PANEL_TYPES.LIST;
const config: QueryBuilderProps['filterConfigs'] = {
- stepInterval: { isHidden: false, isDisabled: true },
+ stepInterval: { isHidden: false, isDisabled: false },
limit: { isHidden: isList, isDisabled: true },
having: { isHidden: isList, isDisabled: true },
};
@@ -56,7 +56,7 @@ function QuerySection(): JSX.Element {
version="v3" // setting this to v3 as we this is rendered in logs explorer
actions={
-
+ handleRunQuery()} type="primary">
Run Query
diff --git a/frontend/src/container/TracesExplorer/TracesView/configs.tsx b/frontend/src/container/TracesExplorer/TracesView/configs.tsx
index a6296e362a..f5980a044d 100644
--- a/frontend/src/container/TracesExplorer/TracesView/configs.tsx
+++ b/frontend/src/container/TracesExplorer/TracesView/configs.tsx
@@ -3,7 +3,7 @@ import { ColumnsType } from 'antd/es/table';
import ROUTES from 'constants/routes';
import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util';
import { DEFAULT_PER_PAGE_OPTIONS } from 'hooks/queryPagination';
-import { generatePath } from 'react-router-dom';
+import { generatePath, Link } from 'react-router-dom';
import { ListItem } from 'types/api/widgets/getQuery';
export const PER_PAGE_OPTIONS: number[] = [10, ...DEFAULT_PER_PAGE_OPTIONS];
@@ -38,14 +38,14 @@ export const columns: ColumnsType = [
dataIndex: 'traceID',
key: 'traceID',
render: (traceID: string): JSX.Element => (
-
{traceID}
-
+
),
},
];
diff --git a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss
index 0787972eec..74e80f8764 100644
--- a/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss
+++ b/frontend/src/container/TracesTableComponent/TracesTableComponent.styles.scss
@@ -5,7 +5,7 @@
height: 100%;
.resize-table {
- height: calc(100% - 40px);
+ height: calc(100% - 70px);
overflow: scroll;
overflow-x: hidden;
diff --git a/frontend/src/hooks/dashboard/utils.ts b/frontend/src/hooks/dashboard/utils.ts
index ad3fadd8b9..ed61e25581 100644
--- a/frontend/src/hooks/dashboard/utils.ts
+++ b/frontend/src/hooks/dashboard/utils.ts
@@ -1,43 +1,61 @@
import { PANEL_TYPES } from 'constants/queryBuilder';
+import { convertKeysToColumnFields } from 'container/LogsExplorerList/utils';
import { Dashboard } from 'types/api/dashboard/getAll';
+import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
+const baseLogsSelectedColumns = {
+ dataType: 'string',
+ type: '',
+ name: 'timestamp',
+};
+
export const addEmptyWidgetInDashboardJSONWithQuery = (
dashboard: Dashboard,
query: Query,
widgetId: string,
- panelTypes?: PANEL_TYPES,
-): Dashboard => ({
- ...dashboard,
- data: {
- ...dashboard.data,
- layout: [
- {
- i: widgetId,
- w: 6,
- x: 0,
- h: 6,
- y: 0,
- },
- ...(dashboard?.data?.layout || []),
- ],
- widgets: [
- ...(dashboard?.data?.widgets || []),
- {
- id: widgetId,
- query,
- description: '',
- isStacked: false,
- nullZeroValues: '',
- opacity: '',
- title: '',
- timePreferance: 'GLOBAL_TIME',
- panelTypes: panelTypes || PANEL_TYPES.TIME_SERIES,
- softMax: null,
- softMin: null,
- selectedLogFields: [],
- selectedTracesFields: [],
- },
- ],
- },
-});
+ panelType?: PANEL_TYPES,
+ selectedColumns?: BaseAutocompleteData[] | null,
+): Dashboard => {
+ const logsSelectedColumns = [
+ baseLogsSelectedColumns,
+ ...convertKeysToColumnFields(selectedColumns || []),
+ ];
+
+ return {
+ ...dashboard,
+ data: {
+ ...dashboard.data,
+ layout: [
+ {
+ i: widgetId,
+ w: 6,
+ x: 0,
+ h: 6,
+ y: 0,
+ },
+ ...(dashboard?.data?.layout || []),
+ ],
+ widgets: [
+ ...(dashboard?.data?.widgets || []),
+ {
+ id: widgetId,
+ query,
+ description: '',
+ isStacked: false,
+ nullZeroValues: '',
+ opacity: '',
+ title: '',
+ timePreferance: 'GLOBAL_TIME',
+ panelTypes: panelType || PANEL_TYPES.TIME_SERIES,
+ softMax: null,
+ softMin: null,
+ selectedLogFields:
+ panelType === PANEL_TYPES.LIST ? logsSelectedColumns : [],
+ selectedTracesFields:
+ panelType === PANEL_TYPES.LIST ? selectedColumns || [] : [],
+ },
+ ],
+ },
+ };
+};
diff --git a/frontend/src/hooks/queryBuilder/useStepInterval.ts b/frontend/src/hooks/queryBuilder/useStepInterval.ts
index 55dad54664..62f8a0d7c1 100644
--- a/frontend/src/hooks/queryBuilder/useStepInterval.ts
+++ b/frontend/src/hooks/queryBuilder/useStepInterval.ts
@@ -8,6 +8,7 @@ export const updateStepInterval = (
query: Widgets['query'],
maxTime: number,
minTime: number,
+ shallUpdateStepInterval?: boolean,
): Widgets['query'] => {
const stepInterval = getStep({
start: minTime,
@@ -15,6 +16,14 @@ export const updateStepInterval = (
inputFormat: 'ns',
});
+ function getStepInterval(customInterval: number): number {
+ // if user enters some value then auto update should never come
+ if (shallUpdateStepInterval) {
+ return customInterval;
+ }
+ return stepInterval;
+ }
+
return {
...query,
builder: {
@@ -22,7 +31,7 @@ export const updateStepInterval = (
queryData:
query?.builder?.queryData?.map((item) => ({
...item,
- stepInterval,
+ stepInterval: getStepInterval(item.stepInterval),
})) || [],
},
};
diff --git a/frontend/src/hooks/useDarkMode/index.tsx b/frontend/src/hooks/useDarkMode/index.tsx
index d7e3a279e0..ef2883b4b3 100644
--- a/frontend/src/hooks/useDarkMode/index.tsx
+++ b/frontend/src/hooks/useDarkMode/index.tsx
@@ -30,7 +30,7 @@ export function ThemeProvider({ children }: ThemeProviderProps): JSX.Element {
setTheme(THEME_MODE.LIGHT);
set(LOCALSTORAGE.THEME, THEME_MODE.LIGHT);
}
- set(LOCALSTORAGE.THEME_ANALYTICS, '');
+ set(LOCALSTORAGE.THEME_ANALYTICS_V1, '');
}, [theme]);
const value = useMemo(
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index 570db8c1da..45a1b6f11a 100644
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -7,7 +7,6 @@ import { AxiosError } from 'axios';
import { ThemeProvider } from 'hooks/useDarkMode';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { createRoot } from 'react-dom/client';
-import { ErrorBoundary } from 'react-error-boundary';
import { HelmetProvider } from 'react-helmet-async';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Provider } from 'react-redux';
@@ -58,7 +57,7 @@ if (container) {
const root = createRoot(container);
root.render(
-
+ }>
@@ -68,6 +67,6 @@ if (container) {
- ,
+ ,
);
}
diff --git a/frontend/src/lib/dashboard/getQueryResults.ts b/frontend/src/lib/dashboard/getQueryResults.ts
index e3f956c32a..7b7276c378 100644
--- a/frontend/src/lib/dashboard/getQueryResults.ts
+++ b/frontend/src/lib/dashboard/getQueryResults.ts
@@ -75,6 +75,7 @@ export interface GetQueryResultsProps {
globalSelectedInterval: Time | TimeV2 | CustomTimeType;
variables?: Record;
params?: Record;
+ fillGaps?: boolean;
tableParams?: {
pagination?: Pagination;
selectColumns?: any;
diff --git a/frontend/src/lib/dashboard/prepareQueryRangePayload.ts b/frontend/src/lib/dashboard/prepareQueryRangePayload.ts
index 0b918bcb14..244e096079 100644
--- a/frontend/src/lib/dashboard/prepareQueryRangePayload.ts
+++ b/frontend/src/lib/dashboard/prepareQueryRangePayload.ts
@@ -20,6 +20,7 @@ export const prepareQueryRangePayload = ({
tableParams,
variables = {},
params = {},
+ fillGaps = false,
}: GetQueryResultsProps): PrepareQueryRangePayload => {
let legendMap: Record = {};
const { allowSelectedIntervalForStepGen, ...restParams } = params;
@@ -27,6 +28,7 @@ export const prepareQueryRangePayload = ({
const compositeQuery: QueryRangePayload['compositeQuery'] = {
queryType: query.queryType,
panelType: graphType,
+ fillGaps,
};
switch (query.queryType) {
diff --git a/frontend/src/lib/query/createTableColumnsFromQuery.ts b/frontend/src/lib/query/createTableColumnsFromQuery.ts
index 85b876dc11..18926f2f0c 100644
--- a/frontend/src/lib/query/createTableColumnsFromQuery.ts
+++ b/frontend/src/lib/query/createTableColumnsFromQuery.ts
@@ -1,20 +1,25 @@
import { ColumnsType } from 'antd/es/table';
import { ColumnType } from 'antd/lib/table';
import {
+ initialClickHouseData,
initialFormulaBuilderFormValues,
initialQueryBuilderFormValues,
+ initialQueryPromQLData,
} from 'constants/queryBuilder';
import { FORMULA_REGEXP } from 'constants/regExp';
import { QUERY_TABLE_CONFIG } from 'container/QueryTable/config';
import { QueryTableProps } from 'container/QueryTable/QueryTable.intefaces';
-import { isEqual, isNaN, isObject } from 'lodash-es';
+import { get, isEqual, isNaN, isObject } from 'lodash-es';
import { ReactNode } from 'react';
import {
IBuilderFormula,
IBuilderQuery,
+ IClickHouseQuery,
+ IPromQLQuery,
Query,
} from 'types/api/queryBuilder/queryBuilderData';
import { ListItem, QueryDataV3, SeriesItem } from 'types/api/widgets/getQuery';
+import { EQueryType } from 'types/common/dashboard';
import { QueryBuilderData } from 'types/common/queryBuilder';
import { v4 as uuid } from 'uuid';
@@ -30,7 +35,7 @@ export type RowData = {
};
export type DynamicColumn = {
- query: IBuilderQuery | IBuilderFormula;
+ query: IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery;
field: string;
dataIndex: string;
title: string;
@@ -75,24 +80,43 @@ const isValueExist = (
};
const getQueryByName = (
- builder: QueryBuilderData,
+ query: Query,
currentQueryName: string,
type: T,
-): T extends 'queryData' ? IBuilderQuery : IBuilderFormula => {
- const queryArray = builder[type];
- const defaultValue =
- type === 'queryData'
- ? initialQueryBuilderFormValues
- : initialFormulaBuilderFormValues;
+): IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery => {
+ if (query.queryType === EQueryType.CLICKHOUSE) {
+ const queryArray = query.clickhouse_sql;
+ const defaultQueryValue = initialClickHouseData;
- const currentQuery =
- queryArray.find((q) => q.queryName === currentQueryName) || defaultValue;
+ return (
+ queryArray.find((q) => q.name === currentQueryName) || defaultQueryValue
+ );
+ }
+ if (query.queryType === EQueryType.QUERY_BUILDER) {
+ const queryArray = query.builder[type];
+ const defaultValue =
+ type === 'queryData'
+ ? initialQueryBuilderFormValues
+ : initialFormulaBuilderFormValues;
- return currentQuery as T extends 'queryData' ? IBuilderQuery : IBuilderFormula;
+ const currentQuery =
+ queryArray.find((q) => q.queryName === currentQueryName) || defaultValue;
+
+ return currentQuery as T extends 'queryData'
+ ? IBuilderQuery
+ : IBuilderFormula;
+ }
+
+ const queryArray = query.promql;
+ const defaultQueryValue = initialQueryPromQLData;
+
+ return (
+ queryArray.find((q) => q.name === currentQueryName) || defaultQueryValue
+ );
};
const addLabels = (
- query: IBuilderQuery | IBuilderFormula,
+ query: IBuilderQuery | IBuilderFormula | IClickHouseQuery | IPromQLQuery,
label: string,
dynamicColumns: DynamicColumns,
): void => {
@@ -111,11 +135,13 @@ const addLabels = (
};
const addOperatorFormulaColumns = (
- query: IBuilderFormula | IBuilderQuery,
+ query: IBuilderFormula | IBuilderQuery | IClickHouseQuery | IPromQLQuery,
dynamicColumns: DynamicColumns,
+ queryType: EQueryType,
customLabel?: string,
+ // eslint-disable-next-line sonarjs/cognitive-complexity
): void => {
- if (isFormula(query.queryName)) {
+ if (isFormula(get(query, 'queryName', ''))) {
const formulaQuery = query as IBuilderFormula;
let formulaLabel = `${formulaQuery.queryName}(${formulaQuery.expression})`;
@@ -137,27 +163,68 @@ const addOperatorFormulaColumns = (
return;
}
- const currentQueryData = query as IBuilderQuery;
+ if (queryType === EQueryType.QUERY_BUILDER) {
+ const currentQueryData = query as IBuilderQuery;
+ let operatorLabel = `${currentQueryData.aggregateOperator}`;
+ if (currentQueryData.aggregateAttribute.key) {
+ operatorLabel += `(${currentQueryData.aggregateAttribute.key})`;
+ }
- let operatorLabel = `${currentQueryData.aggregateOperator}`;
- if (currentQueryData.aggregateAttribute.key) {
- operatorLabel += `(${currentQueryData.aggregateAttribute.key})`;
+ if (currentQueryData.legend) {
+ operatorLabel = currentQueryData.legend;
+ }
+
+ const operatorColumn: DynamicColumn = {
+ query,
+ field: currentQueryData.queryName,
+ dataIndex: currentQueryData.queryName,
+ title: customLabel || operatorLabel,
+ data: [],
+ type: 'operator',
+ };
+
+ dynamicColumns.push(operatorColumn);
}
- if (currentQueryData.legend) {
- operatorLabel = currentQueryData.legend;
+ if (queryType === EQueryType.CLICKHOUSE) {
+ const currentQueryData = query as IClickHouseQuery;
+ let operatorLabel = `${currentQueryData.name}`;
+
+ if (currentQueryData.legend) {
+ operatorLabel = currentQueryData.legend;
+ }
+
+ const operatorColumn: DynamicColumn = {
+ query,
+ field: currentQueryData.name,
+ dataIndex: currentQueryData.name,
+ title: customLabel || operatorLabel,
+ data: [],
+ type: 'operator',
+ };
+
+ dynamicColumns.push(operatorColumn);
}
- const operatorColumn: DynamicColumn = {
- query,
- field: currentQueryData.queryName,
- dataIndex: currentQueryData.queryName,
- title: customLabel || operatorLabel,
- data: [],
- type: 'operator',
- };
+ if (queryType === EQueryType.PROM) {
+ const currentQueryData = query as IPromQLQuery;
+ let operatorLabel = `${currentQueryData.name}`;
- dynamicColumns.push(operatorColumn);
+ if (currentQueryData.legend) {
+ operatorLabel = currentQueryData.legend;
+ }
+
+ const operatorColumn: DynamicColumn = {
+ query,
+ field: currentQueryData.name,
+ dataIndex: currentQueryData.name,
+ title: customLabel || operatorLabel,
+ data: [],
+ type: 'operator',
+ };
+
+ dynamicColumns.push(operatorColumn);
+ }
};
const transformColumnTitles = (
@@ -175,8 +242,16 @@ const transformColumnTitles = (
if (sameValues.length > 1) {
return {
...item,
- dataIndex: `${item.title} - ${item.query.queryName}`,
- title: `${item.title} - ${item.query.queryName}`,
+ dataIndex: `${item.title} - ${get(
+ item.query,
+ 'queryName',
+ get(item.query, 'name', ''),
+ )}`,
+ title: `${item.title} - ${get(
+ item.query,
+ 'queryName',
+ get(item.query, 'name', ''),
+ )}`,
};
}
@@ -190,7 +265,7 @@ const getDynamicColumns: GetDynamicColumns = (queryTableData, query) => {
const { series, queryName, list } = currentQuery;
const currentStagedQuery = getQueryByName(
- query.builder,
+ query,
queryName,
isFormula(queryName) ? 'queryFormulas' : 'queryData',
);
@@ -210,7 +285,8 @@ const getDynamicColumns: GetDynamicColumns = (queryTableData, query) => {
addOperatorFormulaColumns(
currentStagedQuery,
dynamicColumns,
- isEveryValuesExist ? undefined : currentStagedQuery.queryName,
+ query.queryType,
+ isEveryValuesExist ? undefined : get(currentStagedQuery, 'queryName', ''),
);
}
@@ -289,6 +365,7 @@ const fillRestAggregationData = (
queryTableData: QueryDataV3[],
seria: SeriesItem,
equalQueriesByLabels: string[],
+ isEqualQuery: boolean,
): void => {
const nextQueryData =
queryTableData.find((q) => q.queryName === column.field) || null;
@@ -298,13 +375,13 @@ const fillRestAggregationData = (
nextQueryData,
);
+ const isEqual = isEqualQueriesByLabel(equalQueriesByLabels, column.field);
if (targetSeria) {
- const isEqual = isEqualQueriesByLabel(equalQueriesByLabels, column.field);
if (!isEqual) {
// This line is crucial. It ensures that no additional rows are added to the table for similar labels across all formulas here is how this check is applied: signoz/frontend/src/lib/query/createTableColumnsFromQuery.ts line number 370
equalQueriesByLabels.push(column.field);
}
- } else {
+ } else if (!isEqualQuery) {
column.data.push('N/A');
}
};
@@ -359,6 +436,7 @@ const fillDataFromSeries = (
queryTableData,
seria,
equalQueriesByLabels,
+ isEqualQuery,
);
return;
@@ -461,8 +539,12 @@ const generateTableColumns = (
width: QUERY_TABLE_CONFIG.width,
render: renderColumnCell && renderColumnCell[item.dataIndex],
sorter: (a: RowData, b: RowData): number => {
- const valueA = Number(a[item.dataIndex]);
- const valueB = Number(b[item.dataIndex]);
+ const valueA = Number(
+ a[`${item.dataIndex}_without_unit`] ?? a[item.dataIndex],
+ );
+ const valueB = Number(
+ b[`${item.dataIndex}_without_unit`] ?? b[item.dataIndex],
+ );
if (!isNaN(valueA) && !isNaN(valueB)) {
return valueA - valueB;
@@ -490,6 +572,29 @@ export const createTableColumnsFromQuery: CreateTableDataFromQuery = ({
a.queryName < b.queryName ? -1 : 1,
);
+ // the reason we need this is because the filling of values in rows doesn't account for mismatch enteries
+ // in the response. Example : Series A -> [label1, label2] and Series B -> [label2,label1] this isn't accounted for
+ sortedQueryTableData.forEach((q) => {
+ q.series?.forEach((s) => {
+ s.labelsArray?.sort((a, b) =>
+ Object.keys(a)[0] < Object.keys(b)[0] ? -1 : 1,
+ );
+ });
+ q.series?.sort((a, b) => {
+ let labelA = '';
+ let labelB = '';
+ a.labelsArray.forEach((lab) => {
+ labelA += Object.values(lab)[0];
+ });
+
+ b.labelsArray.forEach((lab) => {
+ labelB += Object.values(lab)[0];
+ });
+
+ return labelA < labelB ? -1 : 1;
+ });
+ });
+
const dynamicColumns = getDynamicColumns(sortedQueryTableData, query);
const { filledDynamicColumns, rowsLength } = fillColumnsData(
diff --git a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts
index 2247ec90bd..dd08cbfff1 100644
--- a/frontend/src/lib/uPlotLib/getUplotChartOptions.ts
+++ b/frontend/src/lib/uPlotLib/getUplotChartOptions.ts
@@ -10,9 +10,11 @@ import { saveLegendEntriesToLocalStorage } from 'container/GridCardLayout/GridCa
import { ThresholdProps } from 'container/NewWidget/RightContainer/Threshold/types';
import { Dimensions } from 'hooks/useDimensions';
import { convertValue } from 'lib/getConvertedValue';
+import { cloneDeep, isUndefined } from 'lodash-es';
import _noop from 'lodash-es/noop';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
+import { QueryData, QueryDataV3 } from 'types/api/widgets/getQuery';
import uPlot from 'uplot';
import onClickPlugin, { OnClickPluginOpts } from './plugins/onClickPlugin';
@@ -42,6 +44,84 @@ export interface GetUPlotChartOptions {
softMin: number | null;
softMax: number | null;
currentQuery?: Query;
+ stackBarChart?: boolean;
+ hiddenGraph?: {
+ [key: string]: boolean;
+ };
+ setHiddenGraph?: Dispatch<
+ SetStateAction<{
+ [key: string]: boolean;
+ }>
+ >;
+}
+
+/** the function converts series A , series B , series C to
+ * series A , series A + series B , series A + series B + series C
+ * which helps us to always ensure the bar in the front is always
+ * of the smallest value.
+ */
+
+function getStackedSeries(apiResponse: QueryData[]): QueryData[] {
+ const series = cloneDeep(apiResponse);
+
+ for (let i = series.length - 2; i >= 0; i--) {
+ const { values } = series[i];
+ for (let j = 0; j < values.length; j++) {
+ values[j][1] = String(
+ parseFloat(values[j]?.[1] || '0') +
+ parseFloat(series[i + 1].values[j]?.[1] || '0'),
+ );
+ }
+
+ series[i].values = values;
+ }
+
+ return series;
+}
+
+/** this does the exact same operations as the function above for a different
+ * response format.
+ */
+function getStackedSeriesQueryFormat(apiResponse: QueryData[]): QueryData[] {
+ const series = cloneDeep(apiResponse);
+
+ for (let i = series.length - 2; i >= 0; i--) {
+ const { values } = series[i];
+ for (let j = 0; j < values.length; j++) {
+ values[j].value = String(
+ parseFloat(values[j]?.value || '0') +
+ parseFloat(series[i + 1].values[j]?.value || '0'),
+ );
+ }
+
+ series[i].values = values;
+ }
+
+ return series;
+}
+
+function getStackedSeriesYAxis(apiResponse: QueryDataV3[]): QueryDataV3[] {
+ const series = cloneDeep(apiResponse);
+
+ for (let i = 0; i < series.length; i++) {
+ series[i].series = getStackedSeriesQueryFormat(series[i].series);
+ }
+
+ return series;
+}
+
+/**
+ * here we define the different series bands which should get highlighted based
+ * on cursor hover. basically the to and the from destination of a particular band.
+ */
+function getBands(series): any[] {
+ const bands = [];
+ for (let i = 0; i < series.length; i++) {
+ bands.push({
+ series: [i === 0 ? -1 : i, i + 1],
+ });
+ }
+ return bands;
}
export const getUPlotChartOptions = ({
@@ -61,9 +141,18 @@ export const getUPlotChartOptions = ({
softMin,
panelType,
currentQuery,
+ stackBarChart: stackChart,
+ hiddenGraph,
+ setHiddenGraph,
}: GetUPlotChartOptions): uPlot.Options => {
const timeScaleProps = getXAxisScale(minTimeScale, maxTimeScale);
+ const stackBarChart = stackChart && isUndefined(hiddenGraph);
+
+ const series = getStackedSeries(apiResponse?.data?.result || []);
+
+ const bands = stackBarChart ? getBands(series) : null;
+
return {
id,
width: dimensions.width,
@@ -91,6 +180,7 @@ export const getUPlotChartOptions = ({
},
},
padding: [16, 16, 8, 8],
+ bands,
scales: {
x: {
spanGaps: true,
@@ -99,7 +189,9 @@ export const getUPlotChartOptions = ({
y: {
...getYAxisScale({
thresholds,
- series: apiResponse?.data?.newResult?.data?.result || [],
+ series: stackBarChart
+ ? getStackedSeriesYAxis(apiResponse?.data?.newResult?.data?.result || [])
+ : apiResponse?.data?.newResult?.data?.result || [],
yAxisUnit,
softMax,
softMin,
@@ -107,7 +199,7 @@ export const getUPlotChartOptions = ({
},
},
plugins: [
- tooltipPlugin({ apiResponse, yAxisUnit }),
+ tooltipPlugin({ apiResponse, yAxisUnit, stackBarChart, isDarkMode }),
onClickPlugin({
onClick: onClickHandler,
}),
@@ -192,6 +284,17 @@ export const getUPlotChartOptions = ({
const seriesArray = Array.from(seriesEls);
seriesArray.forEach((seriesEl, index) => {
seriesEl.addEventListener('click', () => {
+ if (stackChart) {
+ setHiddenGraph((prev) => {
+ if (isUndefined(prev)) {
+ return { [index]: true };
+ }
+ if (prev[index] === true) {
+ return undefined;
+ }
+ return { [index]: true };
+ });
+ }
if (graphsVisibilityStates) {
setGraphsVisibilityStates?.((prev) => {
const newGraphVisibilityStates = [...prev];
@@ -221,11 +324,17 @@ export const getUPlotChartOptions = ({
],
},
series: getSeries({
- apiResponse,
+ series:
+ stackBarChart && isUndefined(hiddenGraph)
+ ? series
+ : apiResponse?.data?.result,
widgetMetaData: apiResponse?.data.result,
graphsVisibilityStates,
panelType,
currentQuery,
+ stackBarChart,
+ hiddenGraph,
+ isDarkMode,
}),
axes: getAxes(isDarkMode, yAxisUnit),
};
diff --git a/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts b/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts
index 15bea36cba..2ff0f3051e 100644
--- a/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts
+++ b/frontend/src/lib/uPlotLib/getUplotHistogramChartOptions.ts
@@ -35,6 +35,7 @@ type GetHistogramSeriesProps = {
widgetMetaData?: QueryData[];
graphsVisibilityStates?: boolean[];
isMergedSeries?: boolean;
+ isDarkMode: boolean;
};
const { bars } = uPlot.paths;
@@ -56,6 +57,7 @@ const getHistogramSeries = ({
widgetMetaData,
graphsVisibilityStates,
isMergedSeries,
+ isDarkMode,
}: GetHistogramSeriesProps): uPlot.Options['series'] => {
const configurations: uPlot.Series[] = [
{ label: 'Timestamp', stroke: 'purple' },
@@ -75,10 +77,13 @@ const getHistogramSeries = ({
const legend = newLegend || lgd || '';
const label = isMergedSeries
- ? 'merged_series'
+ ? ''
: getLabelName(metric, queryName || '', legend);
- const color = generateColor(label, themeColors.chartcolors);
+ const color = generateColor(
+ label,
+ isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor,
+ );
const pointSize = seriesList[i].values.length > 1 ? 5 : 10;
const showPoints = !(seriesList[i].values.length > 1);
@@ -133,6 +138,7 @@ export const getUplotHistogramChartOptions = ({
apiResponse,
isHistogramGraphs: true,
isMergedSeries: mergeAllQueries,
+ isDarkMode,
}),
],
scales: {
@@ -157,6 +163,7 @@ export const getUplotHistogramChartOptions = ({
currentQuery,
graphsVisibilityStates,
isMergedSeries: mergeAllQueries,
+ isDarkMode,
}),
hooks: {
ready: [
diff --git a/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts b/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts
index 2c1040daf4..16178fe5f0 100644
--- a/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts
+++ b/frontend/src/lib/uPlotLib/plugins/tooltipPlugin.ts
@@ -22,15 +22,30 @@ interface UplotTooltipDataProps {
queryName: string;
}
+function getTooltipBaseValue(
+ data: any[],
+ index: number,
+ idx: number,
+ stackBarChart: boolean | undefined,
+): any {
+ if (stackBarChart && index + 1 < data.length) {
+ return data[index][idx] - data[index + 1][idx];
+ }
+
+ return data[index][idx];
+}
+
const generateTooltipContent = (
seriesList: any[],
data: any[],
idx: number,
+ isDarkMode: boolean,
yAxisUnit?: string,
series?: uPlot.Options['series'],
isBillingUsageGraphs?: boolean,
isHistogramGraphs?: boolean,
isMergedSeries?: boolean,
+ stackBarChart?: boolean,
// eslint-disable-next-line sonarjs/cognitive-complexity
): HTMLElement => {
const container = document.createElement('div');
@@ -67,13 +82,17 @@ const generateTooltipContent = (
unit = '',
} = seriesList[index - 1] || {};
- const value = data[index][idx];
+ const value = getTooltipBaseValue(data, index, idx, stackBarChart);
+
const dataIngested = quantity[idx];
const label = isMergedSeries
- ? 'merged_series'
+ ? ''
: getLabelName(metric, queryName || '', legend || '');
- let color = generateColor(label, themeColors.chartcolors);
+ let color = generateColor(
+ label,
+ isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor,
+ );
// in case of billing graph pick colors from the series options
if (isBillingUsageGraphs) {
@@ -201,6 +220,8 @@ type ToolTipPluginProps = {
isBillingUsageGraphs?: boolean;
isHistogramGraphs?: boolean;
isMergedSeries?: boolean;
+ stackBarChart?: boolean;
+ isDarkMode: boolean;
};
const tooltipPlugin = ({
@@ -209,6 +230,8 @@ const tooltipPlugin = ({
isBillingUsageGraphs,
isHistogramGraphs,
isMergedSeries,
+ stackBarChart,
+ isDarkMode,
}: ToolTipPluginProps): any => {
let over: HTMLElement;
let bound: HTMLElement;
@@ -267,11 +290,13 @@ const tooltipPlugin = ({
apiResult,
u.data,
idx,
+ isDarkMode,
yAxisUnit,
u.series,
isBillingUsageGraphs,
isHistogramGraphs,
isMergedSeries,
+ stackBarChart,
);
overlay.appendChild(content);
placement(overlay, anchor, 'right', 'start', { bound });
diff --git a/frontend/src/lib/uPlotLib/utils/getSeriesData.ts b/frontend/src/lib/uPlotLib/utils/getSeriesData.ts
index 92dbbab8bb..5de1f6d207 100644
--- a/frontend/src/lib/uPlotLib/utils/getSeriesData.ts
+++ b/frontend/src/lib/uPlotLib/utils/getSeriesData.ts
@@ -2,7 +2,7 @@
import { PANEL_TYPES } from 'constants/queryBuilder';
import { themeColors } from 'constants/theme';
import getLabelName from 'lib/getLabelName';
-import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
+import { isUndefined } from 'lodash-es';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { QueryData } from 'types/api/widgets/getQuery';
@@ -28,16 +28,19 @@ const paths = (
};
const getSeries = ({
- apiResponse,
+ series,
widgetMetaData,
graphsVisibilityStates,
panelType,
+ hiddenGraph,
+ isDarkMode,
}: GetSeriesProps): uPlot.Options['series'] => {
const configurations: uPlot.Series[] = [
{ label: 'Timestamp', stroke: 'purple' },
];
- const seriesList = apiResponse?.data.result || [];
+ const seriesList = series || [];
+
const newGraphVisibilityStates = graphsVisibilityStates?.slice(1);
for (let i = 0; i < seriesList?.length; i += 1) {
@@ -49,7 +52,10 @@ const getSeries = ({
legend || '',
);
- const color = generateColor(label, themeColors.chartcolors);
+ const color = generateColor(
+ label,
+ isDarkMode ? themeColors.chartcolors : themeColors.lightModeColor,
+ );
const pointSize = seriesList[i].values.length > 1 ? 5 : 10;
const showPoints = !(seriesList[i].values.length > 1);
@@ -64,7 +70,12 @@ const getSeries = ({
panelType && panelType === PANEL_TYPES.BAR
? null
: lineInterpolations.spline,
- show: newGraphVisibilityStates ? newGraphVisibilityStates[i] : true,
+ // eslint-disable-next-line no-nested-ternary
+ show: newGraphVisibilityStates
+ ? newGraphVisibilityStates[i]
+ : !isUndefined(hiddenGraph)
+ ? hiddenGraph[i]
+ : true,
label,
fill: panelType && panelType === PANEL_TYPES.BAR ? `${color}40` : undefined,
stroke: color,
@@ -84,11 +95,16 @@ const getSeries = ({
};
export type GetSeriesProps = {
- apiResponse?: MetricRangePayloadProps;
+ series?: QueryData[];
widgetMetaData: QueryData[];
+ isDarkMode: boolean;
graphsVisibilityStates?: boolean[];
panelType?: PANEL_TYPES;
currentQuery?: Query;
+ stackBarChart?: boolean;
+ hiddenGraph?: {
+ [key: string]: boolean;
+ };
};
export default getSeries;
diff --git a/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts b/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts
index d1f5a7ffbc..3e88f8769e 100644
--- a/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts
+++ b/frontend/src/lib/uPlotLib/utils/getUplotChartData.ts
@@ -1,3 +1,4 @@
+import { cloneDeep, isUndefined } from 'lodash-es';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { QueryData } from 'types/api/widgets/getQuery';
@@ -16,11 +17,7 @@ function getXAxisTimestamps(seriesList: QueryData[]): number[] {
return timestampsArr.sort((a, b) => a - b);
}
-function fillMissingXAxisTimestamps(
- timestampArr: number[],
- data: any[],
- fillSpans: boolean,
-): any {
+function fillMissingXAxisTimestamps(timestampArr: number[], data: any[]): any {
// Generate a set of all timestamps in the range
const allTimestampsSet = new Set(timestampArr);
const processedData = JSON.parse(JSON.stringify(data));
@@ -34,14 +31,14 @@ function fillMissingXAxisTimestamps(
);
missingTimestamps.forEach((timestamp) => {
- const value = fillSpans ? 0 : null;
+ const value = null;
entry.values.push([timestamp, value]);
});
entry.values.forEach((v) => {
if (Number.isNaN(v[1])) {
- const replaceValue = fillSpans ? 0 : null;
+ const replaceValue = null;
// eslint-disable-next-line no-param-reassign
v[1] = replaceValue;
} else if (v[1] !== null) {
@@ -62,17 +59,34 @@ function fillMissingXAxisTimestamps(
);
}
+function getStackedSeries(val: any): any {
+ const series = cloneDeep(val) || [];
+
+ for (let i = series.length - 2; i >= 0; i--) {
+ for (let j = 0; j < series[i].length; j++) {
+ series[i][j] += series[i + 1][j];
+ }
+ }
+
+ return series;
+}
+
export const getUPlotChartData = (
apiResponse?: MetricRangePayloadProps,
fillSpans?: boolean,
+ stackedBarChart?: boolean,
+ hiddenGraph?: {
+ [key: string]: boolean;
+ },
): any[] => {
const seriesList = apiResponse?.data?.result || [];
const timestampArr = getXAxisTimestamps(seriesList);
- const yAxisValuesArr = fillMissingXAxisTimestamps(
- timestampArr,
- seriesList,
- fillSpans || false,
- );
+ const yAxisValuesArr = fillMissingXAxisTimestamps(timestampArr, seriesList);
- return [timestampArr, ...yAxisValuesArr];
+ return [
+ timestampArr,
+ ...(stackedBarChart && isUndefined(hiddenGraph)
+ ? getStackedSeries(yAxisValuesArr)
+ : yAxisValuesArr),
+ ];
};
diff --git a/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts b/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts
index 2ff063e2ab..88e50ada6e 100644
--- a/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts
+++ b/frontend/src/lib/uPlotLib/utils/tests/__mocks__/seriesData.ts
@@ -3,360 +3,91 @@ import { PANEL_TYPES } from 'constants/queryBuilder';
import { GetSeriesProps } from '../../getSeriesData';
export const seriesBarChartData = {
- apiResponse: {
- data: {
- result: [
- {
- metric: {},
- values: [
- [1708683840, '6260'],
- [1708683240, '6251'],
- [1708683780, '6237'],
- [1708683660, '6188'],
- [1708683720, '6176'],
- [1708683360, '6169'],
- [1708683480, '6068'],
- [1708683540, '6025'],
- [1708683300, '6042'],
- [1708683420, '6001'],
- [1708683600, '5969'],
- [1708683900, '5955'],
- [1708683180, '4301'],
- ],
- queryName: 'F1',
- legend: 'firstLegend',
- },
- {
- metric: {},
- values: [
- [1708683240, '3378'],
- [1708683300, '3269'],
- [1708683360, '3341'],
- [1708683420, '3269'],
- [1708683480, '3296'],
- [1708683540, '3280'],
- [1708683600, '3260'],
- [1708683660, '3351'],
- [1708683720, '3345'],
- [1708683780, '3370'],
- [1708683840, '3382'],
- [1708683900, '3249'],
- [1708683960, '212'],
- ],
- queryName: 'A',
- legend: 'secondLegend',
- },
- {
- metric: {},
- values: [
- [1708683840, '2878'],
- [1708683240, '2873'],
- [1708683780, '2867'],
- [1708683660, '2837'],
- [1708683720, '2831'],
- [1708683360, '2828'],
- [1708683300, '2773'],
- [1708683480, '2772'],
- [1708683540, '2745'],
- [1708683420, '2732'],
- [1708683180, '2729'],
- [1708683600, '2709'],
- [1708683900, '2706'],
- ],
- queryName: 'B',
- legend: 'thirdLegend',
- },
- {
- metric: {
- F2: 'F2',
- },
- values: [
- [1708683840, '504'],
- [1708683240, '505'],
- [1708683780, '503'],
- [1708683660, '514'],
- [1708683720, '514'],
- [1708683360, '513'],
- [1708683480, '524'],
- [1708683540, '535'],
- [1708683300, '496'],
- [1708683420, '537'],
- [1708683600, '551'],
- [1708683900, '543'],
- [1708683180, '-1157'],
- ],
- queryName: 'F2',
- legend: 'forthLength',
- },
+ series: [
+ {
+ metric: {},
+ values: [
+ [1708683840, '6260'],
+ [1708683240, '6251'],
+ [1708683780, '6237'],
+ [1708683660, '6188'],
+ [1708683720, '6176'],
+ [1708683360, '6169'],
+ [1708683480, '6068'],
+ [1708683540, '6025'],
+ [1708683300, '6042'],
+ [1708683420, '6001'],
+ [1708683600, '5969'],
+ [1708683900, '5955'],
+ [1708683180, '4301'],
],
- resultType: '',
- newResult: {
- status: 'success',
- data: {
- resultType: '',
- result: [
- {
- queryName: 'A',
- series: [
- {
- labels: {},
- labelsArray: [],
- values: [
- {
- timestamp: 1708683240000,
- value: '3378',
- },
- {
- timestamp: 1708683300000,
- value: '3269',
- },
- {
- timestamp: 1708683360000,
- value: '3341',
- },
- {
- timestamp: 1708683420000,
- value: '3269',
- },
- {
- timestamp: 1708683480000,
- value: '3296',
- },
- {
- timestamp: 1708683540000,
- value: '3280',
- },
- {
- timestamp: 1708683600000,
- value: '3260',
- },
- {
- timestamp: 1708683660000,
- value: '3351',
- },
- {
- timestamp: 1708683720000,
- value: '3345',
- },
- {
- timestamp: 1708683780000,
- value: '3370',
- },
- {
- timestamp: 1708683840000,
- value: '3382',
- },
- {
- timestamp: 1708683900000,
- value: '3249',
- },
- {
- timestamp: 1708683960000,
- value: '212',
- },
- ],
- },
- ],
- list: null,
- },
- {
- queryName: 'B',
- series: [
- {
- labels: {},
- labelsArray: [],
- values: [
- {
- timestamp: 1708683840000,
- value: '2878',
- },
- {
- timestamp: 1708683240000,
- value: '2873',
- },
- {
- timestamp: 1708683780000,
- value: '2867',
- },
- {
- timestamp: 1708683660000,
- value: '2837',
- },
- {
- timestamp: 1708683720000,
- value: '2831',
- },
- {
- timestamp: 1708683360000,
- value: '2828',
- },
- {
- timestamp: 1708683300000,
- value: '2773',
- },
- {
- timestamp: 1708683480000,
- value: '2772',
- },
- {
- timestamp: 1708683540000,
- value: '2745',
- },
- {
- timestamp: 1708683420000,
- value: '2732',
- },
- {
- timestamp: 1708683180000,
- value: '2729',
- },
- {
- timestamp: 1708683600000,
- value: '2709',
- },
- {
- timestamp: 1708683900000,
- value: '2706',
- },
- ],
- },
- ],
- list: null,
- },
- {
- queryName: 'F2',
- series: [
- {
- labels: {
- F2: 'F2',
- },
- values: [
- {
- timestamp: 1708683840000,
- value: '504',
- },
- {
- timestamp: 1708683240000,
- value: '505',
- },
- {
- timestamp: 1708683780000,
- value: '503',
- },
- {
- timestamp: 1708683660000,
- value: '514',
- },
- {
- timestamp: 1708683720000,
- value: '514',
- },
- {
- timestamp: 1708683360000,
- value: '513',
- },
- {
- timestamp: 1708683480000,
- value: '524',
- },
- {
- timestamp: 1708683540000,
- value: '535',
- },
- {
- timestamp: 1708683300000,
- value: '496',
- },
- {
- timestamp: 1708683420000,
- value: '537',
- },
- {
- timestamp: 1708683600000,
- value: '551',
- },
- {
- timestamp: 1708683900000,
- value: '543',
- },
- {
- timestamp: 1708683180000,
- value: '-1157',
- },
- ],
- },
- ],
- list: null,
- },
- {
- queryName: 'F1',
- series: [
- {
- labels: {},
- labelsArray: null,
- values: [
- {
- timestamp: 1708683840000,
- value: '6260',
- },
- {
- timestamp: 1708683240000,
- value: '6251',
- },
- {
- timestamp: 1708683780000,
- value: '6237',
- },
- {
- timestamp: 1708683660000,
- value: '6188',
- },
- {
- timestamp: 1708683720000,
- value: '6176',
- },
- {
- timestamp: 1708683360000,
- value: '6169',
- },
- {
- timestamp: 1708683480000,
- value: '6068',
- },
- {
- timestamp: 1708683540000,
- value: '6025',
- },
- {
- timestamp: 1708683300000,
- value: '6042',
- },
- {
- timestamp: 1708683420000,
- value: '6001',
- },
- {
- timestamp: 1708683600000,
- value: '5969',
- },
- {
- timestamp: 1708683900000,
- value: '5955',
- },
- {
- timestamp: 1708683180000,
- value: '4301',
- },
- ],
- },
- ],
- list: null,
- },
- ],
- },
- },
+ queryName: 'F1',
+ legend: 'firstLegend',
},
- },
+ {
+ metric: {},
+ values: [
+ [1708683240, '3378'],
+ [1708683300, '3269'],
+ [1708683360, '3341'],
+ [1708683420, '3269'],
+ [1708683480, '3296'],
+ [1708683540, '3280'],
+ [1708683600, '3260'],
+ [1708683660, '3351'],
+ [1708683720, '3345'],
+ [1708683780, '3370'],
+ [1708683840, '3382'],
+ [1708683900, '3249'],
+ [1708683960, '212'],
+ ],
+ queryName: 'A',
+ legend: 'secondLegend',
+ },
+ {
+ metric: {},
+ values: [
+ [1708683840, '2878'],
+ [1708683240, '2873'],
+ [1708683780, '2867'],
+ [1708683660, '2837'],
+ [1708683720, '2831'],
+ [1708683360, '2828'],
+ [1708683300, '2773'],
+ [1708683480, '2772'],
+ [1708683540, '2745'],
+ [1708683420, '2732'],
+ [1708683180, '2729'],
+ [1708683600, '2709'],
+ [1708683900, '2706'],
+ ],
+ queryName: 'B',
+ legend: 'thirdLegend',
+ },
+ {
+ metric: {
+ F2: 'F2',
+ },
+ values: [
+ [1708683840, '504'],
+ [1708683240, '505'],
+ [1708683780, '503'],
+ [1708683660, '514'],
+ [1708683720, '514'],
+ [1708683360, '513'],
+ [1708683480, '524'],
+ [1708683540, '535'],
+ [1708683300, '496'],
+ [1708683420, '537'],
+ [1708683600, '551'],
+ [1708683900, '543'],
+ [1708683180, '-1157'],
+ ],
+ queryName: 'F2',
+ legend: 'forthLength',
+ },
+ ],
+
widgetMetaData: [
{
metric: {},
@@ -443,363 +174,95 @@ export const seriesBarChartData = {
],
graphsVisibilityStates: [true, true, true, true, true],
panelType: PANEL_TYPES.BAR,
+ isDarkMode: true,
} as GetSeriesProps;
export const seriesLineChartData = {
- apiResponse: {
- data: {
- result: [
- {
- metric: {},
- values: [
- [1708683840, '6260'],
- [1708683240, '6251'],
- [1708683780, '6237'],
- [1708683660, '6188'],
- [1708683720, '6176'],
- [1708683360, '6169'],
- [1708683480, '6068'],
- [1708683540, '6025'],
- [1708683300, '6042'],
- [1708683420, '6001'],
- [1708683600, '5969'],
- [1708683900, '5955'],
- [1708683180, '4301'],
- ],
- queryName: 'F1',
- legend: 'firstLegend',
- },
- {
- metric: {},
- values: [
- [1708683240, '3378'],
- [1708683300, '3269'],
- [1708683360, '3341'],
- [1708683420, '3269'],
- [1708683480, '3296'],
- [1708683540, '3280'],
- [1708683600, '3260'],
- [1708683660, '3351'],
- [1708683720, '3345'],
- [1708683780, '3370'],
- [1708683840, '3382'],
- [1708683900, '3249'],
- [1708683960, '212'],
- ],
- queryName: 'A',
- legend: 'secondLegend',
- },
- {
- metric: {},
- values: [
- [1708683840, '2878'],
- [1708683240, '2873'],
- [1708683780, '2867'],
- [1708683660, '2837'],
- [1708683720, '2831'],
- [1708683360, '2828'],
- [1708683300, '2773'],
- [1708683480, '2772'],
- [1708683540, '2745'],
- [1708683420, '2732'],
- [1708683180, '2729'],
- [1708683600, '2709'],
- [1708683900, '2706'],
- ],
- queryName: 'B',
- legend: 'thirdLegend',
- },
- {
- metric: {
- F2: 'F2',
- },
- values: [
- [1708683840, '504'],
- [1708683240, '505'],
- [1708683780, '503'],
- [1708683660, '514'],
- [1708683720, '514'],
- [1708683360, '513'],
- [1708683480, '524'],
- [1708683540, '535'],
- [1708683300, '496'],
- [1708683420, '537'],
- [1708683600, '551'],
- [1708683900, '543'],
- [1708683180, '-1157'],
- ],
- queryName: 'F2',
- legend: 'forthLength',
- },
+ series: [
+ {
+ metric: {},
+ values: [
+ [1708683840, '6260'],
+ [1708683240, '6251'],
+ [1708683780, '6237'],
+ [1708683660, '6188'],
+ [1708683720, '6176'],
+ [1708683360, '6169'],
+ [1708683480, '6068'],
+ [1708683540, '6025'],
+ [1708683300, '6042'],
+ [1708683420, '6001'],
+ [1708683600, '5969'],
+ [1708683900, '5955'],
+ [1708683180, '4301'],
],
- resultType: '',
- newResult: {
- status: 'success',
- data: {
- resultType: '',
- result: [
- {
- queryName: 'A',
- series: [
- {
- labels: {},
- labelsArray: [],
- values: [
- {
- timestamp: 1708683240000,
- value: '3378',
- },
- {
- timestamp: 1708683300000,
- value: '3269',
- },
- {
- timestamp: 1708683360000,
- value: '3341',
- },
- {
- timestamp: 1708683420000,
- value: '3269',
- },
- {
- timestamp: 1708683480000,
- value: '3296',
- },
- {
- timestamp: 1708683540000,
- value: '3280',
- },
- {
- timestamp: 1708683600000,
- value: '3260',
- },
- {
- timestamp: 1708683660000,
- value: '3351',
- },
- {
- timestamp: 1708683720000,
- value: '3345',
- },
- {
- timestamp: 1708683780000,
- value: '3370',
- },
- {
- timestamp: 1708683840000,
- value: '3382',
- },
- {
- timestamp: 1708683900000,
- value: '3249',
- },
- {
- timestamp: 1708683960000,
- value: '212',
- },
- ],
- },
- ],
- list: null,
- },
- {
- queryName: 'B',
- series: [
- {
- labels: {},
- labelsArray: [],
- values: [
- {
- timestamp: 1708683840000,
- value: '2878',
- },
- {
- timestamp: 1708683240000,
- value: '2873',
- },
- {
- timestamp: 1708683780000,
- value: '2867',
- },
- {
- timestamp: 1708683660000,
- value: '2837',
- },
- {
- timestamp: 1708683720000,
- value: '2831',
- },
- {
- timestamp: 1708683360000,
- value: '2828',
- },
- {
- timestamp: 1708683300000,
- value: '2773',
- },
- {
- timestamp: 1708683480000,
- value: '2772',
- },
- {
- timestamp: 1708683540000,
- value: '2745',
- },
- {
- timestamp: 1708683420000,
- value: '2732',
- },
- {
- timestamp: 1708683180000,
- value: '2729',
- },
- {
- timestamp: 1708683600000,
- value: '2709',
- },
- {
- timestamp: 1708683900000,
- value: '2706',
- },
- ],
- },
- ],
- list: null,
- },
- {
- queryName: 'F2',
- series: [
- {
- labels: {
- F2: 'F2',
- },
- values: [
- {
- timestamp: 1708683840000,
- value: '504',
- },
- {
- timestamp: 1708683240000,
- value: '505',
- },
- {
- timestamp: 1708683780000,
- value: '503',
- },
- {
- timestamp: 1708683660000,
- value: '514',
- },
- {
- timestamp: 1708683720000,
- value: '514',
- },
- {
- timestamp: 1708683360000,
- value: '513',
- },
- {
- timestamp: 1708683480000,
- value: '524',
- },
- {
- timestamp: 1708683540000,
- value: '535',
- },
- {
- timestamp: 1708683300000,
- value: '496',
- },
- {
- timestamp: 1708683420000,
- value: '537',
- },
- {
- timestamp: 1708683600000,
- value: '551',
- },
- {
- timestamp: 1708683900000,
- value: '543',
- },
- {
- timestamp: 1708683180000,
- value: '-1157',
- },
- ],
- },
- ],
- list: null,
- },
- {
- queryName: 'F1',
- series: [
- {
- labels: {},
- labelsArray: null,
- values: [
- {
- timestamp: 1708683840000,
- value: '6260',
- },
- {
- timestamp: 1708683240000,
- value: '6251',
- },
- {
- timestamp: 1708683780000,
- value: '6237',
- },
- {
- timestamp: 1708683660000,
- value: '6188',
- },
- {
- timestamp: 1708683720000,
- value: '6176',
- },
- {
- timestamp: 1708683360000,
- value: '6169',
- },
- {
- timestamp: 1708683480000,
- value: '6068',
- },
- {
- timestamp: 1708683540000,
- value: '6025',
- },
- {
- timestamp: 1708683300000,
- value: '6042',
- },
- {
- timestamp: 1708683420000,
- value: '6001',
- },
- {
- timestamp: 1708683600000,
- value: '5969',
- },
- {
- timestamp: 1708683900000,
- value: '5955',
- },
- {
- timestamp: 1708683180000,
- value: '4301',
- },
- ],
- },
- ],
- list: null,
- },
- ],
- },
- },
+ queryName: 'F1',
+ legend: 'firstLegend',
},
- },
+ {
+ metric: {},
+ values: [
+ [1708683240, '3378'],
+ [1708683300, '3269'],
+ [1708683360, '3341'],
+ [1708683420, '3269'],
+ [1708683480, '3296'],
+ [1708683540, '3280'],
+ [1708683600, '3260'],
+ [1708683660, '3351'],
+ [1708683720, '3345'],
+ [1708683780, '3370'],
+ [1708683840, '3382'],
+ [1708683900, '3249'],
+ [1708683960, '212'],
+ ],
+ queryName: 'A',
+ legend: 'secondLegend',
+ },
+ {
+ metric: {},
+ values: [
+ [1708683840, '2878'],
+ [1708683240, '2873'],
+ [1708683780, '2867'],
+ [1708683660, '2837'],
+ [1708683720, '2831'],
+ [1708683360, '2828'],
+ [1708683300, '2773'],
+ [1708683480, '2772'],
+ [1708683540, '2745'],
+ [1708683420, '2732'],
+ [1708683180, '2729'],
+ [1708683600, '2709'],
+ [1708683900, '2706'],
+ ],
+ queryName: 'B',
+ legend: 'thirdLegend',
+ },
+ {
+ metric: {
+ F2: 'F2',
+ },
+ values: [
+ [1708683840, '504'],
+ [1708683240, '505'],
+ [1708683780, '503'],
+ [1708683660, '514'],
+ [1708683720, '514'],
+ [1708683360, '513'],
+ [1708683480, '524'],
+ [1708683540, '535'],
+ [1708683300, '496'],
+ [1708683420, '537'],
+ [1708683600, '551'],
+ [1708683900, '543'],
+ [1708683180, '-1157'],
+ ],
+ queryName: 'F2',
+ legend: 'forthLength',
+ },
+ ],
+
widgetMetaData: [
{
metric: {},
@@ -886,4 +349,5 @@ export const seriesLineChartData = {
],
graphsVisibilityStates: [true, true, true, true, true],
panelType: PANEL_TYPES.TIME_SERIES,
+ isDarkMode: false,
} as GetSeriesProps;
diff --git a/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts b/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts
index 75ee3c7f58..199df6f540 100644
--- a/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts
+++ b/frontend/src/lib/uPlotLib/utils/tests/getSeriesData.test.ts
@@ -27,6 +27,7 @@ describe('Get Series Data', () => {
test('Should return seris drawline line chart for panel type time series', () => {
const seriesData = getSeries(seriesLineChartData);
// @ts-ignore
+
expect(seriesData[1].drawStyle).toBe('line');
});
});
diff --git a/frontend/src/pages/LogsExplorer/index.tsx b/frontend/src/pages/LogsExplorer/index.tsx
index 0cc2c07b4d..d8f5f38804 100644
--- a/frontend/src/pages/LogsExplorer/index.tsx
+++ b/frontend/src/pages/LogsExplorer/index.tsx
@@ -1,5 +1,6 @@
import './LogsExplorer.styles.scss';
+import * as Sentry from '@sentry/react';
import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
import LogExplorerQuerySection from 'container/LogExplorerQuerySection';
import LogsExplorerViews from 'container/LogsExplorerViews';
@@ -9,7 +10,6 @@ import Toolbar from 'container/Toolbar/Toolbar';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useEffect, useMemo, useState } from 'react';
-import { ErrorBoundary } from 'react-error-boundary';
import { DataSource } from 'types/common/queryBuilder';
import { WrapperStyled } from './styles';
@@ -70,7 +70,7 @@ function LogsExplorer(): JSX.Element {
);
return (
-
+ }>
-
+
);
}
diff --git a/frontend/src/pages/LogsExplorer/utils.ts b/frontend/src/pages/LogsExplorer/utils.ts
index 485aa22eef..0fedaaece4 100644
--- a/frontend/src/pages/LogsExplorer/utils.ts
+++ b/frontend/src/pages/LogsExplorer/utils.ts
@@ -4,7 +4,7 @@ export const prepareQueryWithDefaultTimestamp = (query: Query): Query => ({
...query,
builder: {
...query.builder,
- queryData: query.builder.queryData.map((item) => ({
+ queryData: query.builder.queryData?.map((item) => ({
...item,
orderBy: [{ columnName: 'timestamp', order: 'desc' }],
})),
diff --git a/frontend/src/pages/Pipelines/index.tsx b/frontend/src/pages/Pipelines/index.tsx
index 81b3b503f9..a1ae05c30c 100644
--- a/frontend/src/pages/Pipelines/index.tsx
+++ b/frontend/src/pages/Pipelines/index.tsx
@@ -1,5 +1,6 @@
import './Pipelines.styles.scss';
+import * as Sentry from '@sentry/react';
import type { TabsProps } from 'antd';
import { Tabs } from 'antd';
import getPipeline from 'api/pipeline/get';
@@ -9,7 +10,6 @@ import PipelinePage from 'container/PipelinePage/Layouts/Pipeline';
import { useNotifications } from 'hooks/useNotifications';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useEffect, useMemo } from 'react';
-import { ErrorBoundary } from 'react-error-boundary';
import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query';
import { SuccessResponse } from 'types/api';
@@ -82,13 +82,13 @@ function Pipelines(): JSX.Element {
}
return (
-
+ }>
-
+
);
}
diff --git a/frontend/src/pages/ServiceTopLevelOperations/ServiceTopLevelOperations.styles.scss b/frontend/src/pages/ServiceTopLevelOperations/ServiceTopLevelOperations.styles.scss
new file mode 100644
index 0000000000..e7c5dfcda4
--- /dev/null
+++ b/frontend/src/pages/ServiceTopLevelOperations/ServiceTopLevelOperations.styles.scss
@@ -0,0 +1,26 @@
+.title {
+ font-weight: 500;
+ font-size: 14px;
+
+ margin: 16px 0;
+}
+
+.info-alert {
+ margin: 16px 0;
+}
+
+.top-level-operations-header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.breadcrumb {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.top-level-operations-list {
+ margin-top: 16px;
+}
diff --git a/frontend/src/pages/ServiceTopLevelOperations/index.tsx b/frontend/src/pages/ServiceTopLevelOperations/index.tsx
new file mode 100644
index 0000000000..38a2ae2807
--- /dev/null
+++ b/frontend/src/pages/ServiceTopLevelOperations/index.tsx
@@ -0,0 +1,142 @@
+import './ServiceTopLevelOperations.styles.scss';
+
+import { SyncOutlined } from '@ant-design/icons';
+import { Alert, Table, Typography } from 'antd';
+import ROUTES from 'constants/routes';
+import { IServiceName } from 'container/MetricsApplication/Tabs/types';
+import useErrorNotification from 'hooks/useErrorNotification';
+import { useQueryService } from 'hooks/useQueryService';
+import useResourceAttribute from 'hooks/useResourceAttribute';
+import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils';
+import { BarChart2 } from 'lucide-react';
+import { ReactNode, useEffect, useMemo, useState } from 'react';
+import { useSelector } from 'react-redux';
+import { Link, useParams } from 'react-router-dom';
+import { AppState } from 'store/reducers';
+import { GlobalReducer } from 'types/reducer/globalTime';
+import { Tags } from 'types/reducer/trace';
+
+export default function ServiceTopLevelOperations(): JSX.Element {
+ const { servicename: encodedServiceName } = useParams();
+ const { maxTime, minTime, selectedTime } = useSelector<
+ AppState,
+ GlobalReducer
+ >((state) => state.globalTime);
+ const servicename = decodeURIComponent(encodedServiceName);
+ const { queries } = useResourceAttribute();
+ const selectedTags = useMemo(
+ () => (convertRawQueriesToTraceSelectedTags(queries) as Tags[]) || [],
+ [queries],
+ );
+
+ const [topLevelOperations, setTopLevelOperations] = useState([]);
+
+ const { data, error, isLoading } = useQueryService({
+ minTime,
+ maxTime,
+ selectedTime,
+ selectedTags,
+ });
+
+ useErrorNotification(error);
+
+ useEffect(() => {
+ const selectedService = data?.find(
+ (service) => service.serviceName === servicename,
+ );
+
+ setTopLevelOperations(selectedService?.dataWarning?.topLevelOps || []);
+ }, [servicename, data]);
+
+ const alertDesc = (): ReactNode => (
+
+ SigNoz calculates the RED metrics for a service using the entry-point spans.
+ For more details, you can check out our
+
+ {' '}
+ docs
+
+ . We expect the number of unique entry-point operations to be no more than
+ 2500. The high number of top level operations might be due to an
+ instrumentation issue in your service. Below table shows the sample top level
+ operations. Please refer to official docs for span name guidelines{' '}
+
+ {' '}
+ here
+ {' '}
+ and update the instrumentation to to follow the guidelines. If there are any
+ dynamic IDs in the span name, make sure to use the span attributes instead.
+ If you have more questions, please reach out to us via support.
+
+ );
+
+ const columns = [
+ {
+ title: 'Top Level Operation',
+ key: 'top-level-operation',
+ render: (operation: string): JSX.Element => (
+
+ {operation}
+
+ ),
+ },
+ ];
+
+ return (
+
+
+
+
+ {' '}
+ services{' '}
+
+
+ /
+
+ {servicename}
+
+
+
+
+
+ {isLoading && (
+
+
+ Loading ...
+
+
+ )}
+
+ {!isLoading && (
+
+
'Top Level Operations'}
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ dataSource={topLevelOperations}
+ loading={isLoading}
+ showHeader={false}
+ pagination={{
+ pageSize: 100,
+ hideOnSinglePage: true,
+ showTotal: (total: number, range: number[]): string =>
+ `${range[0]}-${range[1]} of ${total}`,
+ }}
+ />
+
+ )}
+
+ );
+}
diff --git a/frontend/src/pages/Support/Support.tsx b/frontend/src/pages/Support/Support.tsx
index 96276507f9..2d156a3816 100644
--- a/frontend/src/pages/Support/Support.tsx
+++ b/frontend/src/pages/Support/Support.tsx
@@ -10,6 +10,8 @@ import {
MessageSquare,
Slack,
} from 'lucide-react';
+import { useEffect } from 'react';
+import { useHistory } from 'react-router-dom';
const { Title, Text } = Typography;
@@ -84,11 +86,24 @@ const supportChannels = [
export default function Support(): JSX.Element {
const { trackEvent } = useAnalytics();
+ const history = useHistory();
const handleChannelWithRedirects = (url: string): void => {
window.open(url, '_blank');
};
+ useEffect(() => {
+ if (history?.location?.state) {
+ const histroyState = history?.location?.state as any;
+
+ if (histroyState && histroyState?.from) {
+ trackEvent(`Support : From URL : ${histroyState.from}`);
+ }
+ }
+
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
const handleSlackConnectRequest = (): void => {
const recipient = 'support@signoz.io';
const subject = 'Slack Connect Request';
diff --git a/frontend/src/pages/Trace/index.tsx b/frontend/src/pages/Trace/index.tsx
index 75bf58f1bd..3d31271c18 100644
--- a/frontend/src/pages/Trace/index.tsx
+++ b/frontend/src/pages/Trace/index.tsx
@@ -1,3 +1,4 @@
+import * as Sentry from '@sentry/react';
import { Card } from 'antd';
import { NotificationInstance } from 'antd/es/notification/interface';
import ROUTES from 'constants/routes';
@@ -11,7 +12,6 @@ import getStep from 'lib/getStep';
import history from 'lib/history';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { MouseEventHandler, useCallback, useEffect, useState } from 'react';
-import { ErrorBoundary } from 'react-error-boundary';
import { connect, useDispatch, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
@@ -146,7 +146,7 @@ function Trace({
);
return (
-
+ }>
@@ -169,7 +169,7 @@ function Trace({
-
+
);
}
diff --git a/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts b/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts
index ede7615e47..86b52fdbb0 100644
--- a/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts
+++ b/frontend/src/pages/TracesExplorer/Filter/filterUtils.ts
@@ -328,17 +328,17 @@ export function unionTagFilterItems(
): TagFilterItem[] {
const unionMap = new Map
();
- items1.forEach((item) => {
- const keyOp = `${item?.key?.key}_${item.op}`;
+ items1?.forEach((item) => {
+ const keyOp = `${item?.key?.key}_${item?.op}`;
unionMap.set(keyOp, item);
});
- items2.forEach((item) => {
- const keyOp = `${item?.key?.key}_${item.op}`;
+ items2?.forEach((item) => {
+ const keyOp = `${item?.key?.key}_${item?.op}`;
unionMap.set(keyOp, item);
});
- return Array.from(unionMap.values());
+ return Array.from(unionMap?.values());
}
export interface HandleRunProps {
diff --git a/frontend/src/pages/TracesExplorer/index.tsx b/frontend/src/pages/TracesExplorer/index.tsx
index 6c4057332f..ab022bfeee 100644
--- a/frontend/src/pages/TracesExplorer/index.tsx
+++ b/frontend/src/pages/TracesExplorer/index.tsx
@@ -1,15 +1,19 @@
import './TracesExplorer.styles.scss';
import { FilterOutlined } from '@ant-design/icons';
+import * as Sentry from '@sentry/react';
import { Button, Card, Tabs, Tooltip } from 'antd';
import axios from 'axios';
import ExplorerCard from 'components/ExplorerCard/ExplorerCard';
+import { LOCALSTORAGE } from 'constants/localStorage';
import { AVAILABLE_EXPORT_PANEL_TYPES } from 'constants/panelTypes';
import { initialQueriesMap, PANEL_TYPES } from 'constants/queryBuilder';
import ExplorerOptionWrapper from 'container/ExplorerOptions/ExplorerOptionWrapper';
import ExportPanel from 'container/ExportPanel';
+import { useOptionsMenu } from 'container/OptionsMenu';
import RightToolbarActions from 'container/QueryBuilder/components/ToolbarActions/RightToolbarActions';
import DateTimeSelector from 'container/TopNav/DateTimeSelectionV2';
+import { defaultSelectedColumns } from 'container/TracesExplorer/ListView/configs';
import QuerySection from 'container/TracesExplorer/QuerySection';
import { useUpdateDashboard } from 'hooks/dashboard/useUpdateDashboard';
import { addEmptyWidgetInDashboardJSONWithQuery } from 'hooks/dashboard/utils';
@@ -19,10 +23,11 @@ import { useShareBuilderUrl } from 'hooks/queryBuilder/useShareBuilderUrl';
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history';
+import { cloneDeep, set } from 'lodash-es';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { useCallback, useEffect, useMemo, useState } from 'react';
-import { ErrorBoundary } from 'react-error-boundary';
import { Dashboard } from 'types/api/dashboard/getAll';
+import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { generateExportToDashboardLink } from 'utils/dashboard/generateExportToDashboardLink';
import { v4 } from 'uuid';
@@ -42,6 +47,15 @@ function TracesExplorer(): JSX.Element {
stagedQuery,
} = useQueryBuilder();
+ const { options } = useOptionsMenu({
+ storageKey: LOCALSTORAGE.TRACES_LIST_OPTIONS,
+ dataSource: DataSource.TRACES,
+ aggregateOperator: 'noop',
+ initialOptions: {
+ selectColumns: defaultSelectedColumns,
+ },
+ });
+
const currentPanelType = useGetPanelTypesQueryParam();
const { handleExplorerTabChange } = useHandleExplorerTabChange();
@@ -101,6 +115,18 @@ function TracesExplorer(): JSX.Element {
const { mutate: updateDashboard, isLoading } = useUpdateDashboard();
+ const getUpdatedQueryForExport = (): Query => {
+ const updatedQuery = cloneDeep(currentQuery);
+
+ set(
+ updatedQuery,
+ 'builder.queryData[0].selectColumns',
+ options.selectColumns,
+ );
+
+ return updatedQuery;
+ };
+
const handleExport = useCallback(
(dashboard: Dashboard | null): void => {
if (!dashboard || !panelType) return;
@@ -111,11 +137,17 @@ function TracesExplorer(): JSX.Element {
const widgetId = v4();
+ const query =
+ panelType === PANEL_TYPES.LIST
+ ? getUpdatedQueryForExport()
+ : exportDefaultQuery;
+
const updatedDashboard = addEmptyWidgetInDashboardJSONWithQuery(
dashboard,
- exportDefaultQuery,
+ query,
widgetId,
panelTypeParam,
+ options.selectColumns,
);
updateDashboard(updatedDashboard, {
@@ -144,7 +176,7 @@ function TracesExplorer(): JSX.Element {
return;
}
const dashboardEditView = generateExportToDashboardLink({
- query: exportDefaultQuery,
+ query,
panelType: panelTypeParam,
dashboardId: data.payload?.uuid || '',
widgetId,
@@ -161,6 +193,7 @@ function TracesExplorer(): JSX.Element {
},
});
},
+ // eslint-disable-next-line react-hooks/exhaustive-deps
[exportDefaultQuery, notifications, panelType, updateDashboard],
);
@@ -185,7 +218,7 @@ function TracesExplorer(): JSX.Element {
const [isOpen, setOpen] = useState(true);
return (
-
+ }>
@@ -236,7 +269,7 @@ function TracesExplorer(): JSX.Element {
/>
-
+
);
}
diff --git a/frontend/src/providers/Dashboard/Dashboard.tsx b/frontend/src/providers/Dashboard/Dashboard.tsx
index 0f8307aaa1..6e15b9e3b2 100644
--- a/frontend/src/providers/Dashboard/Dashboard.tsx
+++ b/frontend/src/providers/Dashboard/Dashboard.tsx
@@ -9,6 +9,7 @@ import dayjs, { Dayjs } from 'dayjs';
import { useDashboardVariablesFromLocalStorage } from 'hooks/dashboard/useDashboardFromLocalStorage';
import useAxiosError from 'hooks/useAxiosError';
import useTabVisibility from 'hooks/useTabFocus';
+import useUrlQuery from 'hooks/useUrlQuery';
import { getUpdatedLayout } from 'lib/dashboard/getUpdatedLayout';
import { defaultTo } from 'lodash-es';
import isEqual from 'lodash-es/isEqual';
@@ -51,6 +52,8 @@ const DashboardContext = createContext({
layouts: [],
panelMap: {},
setPanelMap: () => {},
+ listSortOrder: { columnKey: 'createdAt', order: 'descend', pagination: '1' },
+ setListSortOrder: () => {},
setLayouts: () => {},
setSelectedDashboard: () => {},
updatedTimeRef: {} as React.MutableRefObject,
@@ -79,6 +82,17 @@ export function DashboardProvider({
exact: true,
});
+ const params = useUrlQuery();
+ const orderColumnParam = params.get('columnKey');
+ const orderQueryParam = params.get('order');
+ const paginationParam = params.get('page');
+
+ const [listSortOrder, setListSortOrder] = useState({
+ columnKey: orderColumnParam || 'updatedAt',
+ order: orderQueryParam || 'descend',
+ pagination: paginationParam || '1',
+ });
+
const dispatch = useDispatch>();
const globalTime = useSelector(
@@ -341,6 +355,8 @@ export function DashboardProvider({
selectedDashboard,
dashboardId,
layouts,
+ listSortOrder,
+ setListSortOrder,
panelMap,
setLayouts,
setPanelMap,
@@ -359,6 +375,8 @@ export function DashboardProvider({
selectedDashboard,
dashboardId,
layouts,
+ listSortOrder,
+ setListSortOrder,
panelMap,
toScrollWidgetId,
updateLocalStorageDashboardVariables,
diff --git a/frontend/src/providers/Dashboard/types.ts b/frontend/src/providers/Dashboard/types.ts
index 6f78d804b1..d72c1839f5 100644
--- a/frontend/src/providers/Dashboard/types.ts
+++ b/frontend/src/providers/Dashboard/types.ts
@@ -1,4 +1,5 @@
import dayjs from 'dayjs';
+import { Dispatch, SetStateAction } from 'react';
import { Layout } from 'react-grid-layout';
import { UseQueryResult } from 'react-query';
import { Dashboard } from 'types/api/dashboard/getAll';
@@ -14,6 +15,18 @@ export interface IDashboardContext {
layouts: Layout[];
panelMap: Record;
setPanelMap: React.Dispatch>>;
+ listSortOrder: {
+ columnKey: string;
+ order: string;
+ pagination: string;
+ };
+ setListSortOrder: Dispatch<
+ SetStateAction<{
+ columnKey: string;
+ order: string;
+ pagination: string;
+ }>
+ >;
setLayouts: React.Dispatch>;
setSelectedDashboard: React.Dispatch<
React.SetStateAction
diff --git a/frontend/src/providers/QueryBuilder.tsx b/frontend/src/providers/QueryBuilder.tsx
index 77fa791b14..5e1eda5714 100644
--- a/frontend/src/providers/QueryBuilder.tsx
+++ b/frontend/src/providers/QueryBuilder.tsx
@@ -148,13 +148,13 @@ export function QueryBuilderProvider({
const prepareQueryBuilderData = useCallback(
(query: Query): Query => {
const builder: QueryBuilderData = {
- queryData: query.builder.queryData.map((item) => ({
+ queryData: query.builder.queryData?.map((item) => ({
...initialQueryBuilderFormValuesMap[
initialDataSource || DataSource.METRICS
],
...item,
})),
- queryFormulas: query.builder.queryFormulas.map((item) => ({
+ queryFormulas: query.builder.queryFormulas?.map((item) => ({
...initialFormulaBuilderFormValues,
...item,
})),
@@ -236,7 +236,7 @@ export function QueryBuilderProvider({
const updateAllQueriesOperators = useCallback(
(query: Query, panelType: PANEL_TYPES, dataSource: DataSource): Query => {
- const queryData = query.builder.queryData.map((item) =>
+ const queryData = query.builder.queryData?.map((item) =>
getElementWithActualOperator(item, dataSource, panelType),
);
@@ -682,7 +682,7 @@ export function QueryBuilderProvider({
: query.queryType;
const builder =
- !query.builder || query.builder.queryData.length === 0
+ !query.builder || query.builder.queryData?.length === 0
? initialQueryState.builder
: query.builder;
@@ -752,26 +752,30 @@ export function QueryBuilderProvider({
[],
);
- const handleRunQuery = useCallback(() => {
- redirectWithQueryBuilderData({
- ...{
- ...currentQuery,
- ...updateStepInterval(
- {
- builder: currentQuery.builder,
- clickhouse_sql: currentQuery.clickhouse_sql,
- promql: currentQuery.promql,
- id: currentQuery.id,
- queryType,
- unit: currentQuery.unit,
- },
- maxTime,
- minTime,
- ),
- },
- queryType,
- });
- }, [currentQuery, queryType, maxTime, minTime, redirectWithQueryBuilderData]);
+ const handleRunQuery = useCallback(
+ (shallUpdateStepInterval?: boolean) => {
+ redirectWithQueryBuilderData({
+ ...{
+ ...currentQuery,
+ ...updateStepInterval(
+ {
+ builder: currentQuery.builder,
+ clickhouse_sql: currentQuery.clickhouse_sql,
+ promql: currentQuery.promql,
+ id: currentQuery.id,
+ queryType,
+ unit: currentQuery.unit,
+ },
+ maxTime,
+ minTime,
+ !!shallUpdateStepInterval,
+ ),
+ },
+ queryType,
+ });
+ },
+ [currentQuery, queryType, maxTime, minTime, redirectWithQueryBuilderData],
+ );
useEffect(() => {
if (!compositeQueryParam) return;
diff --git a/frontend/src/types/api/dashboard/getAll.ts b/frontend/src/types/api/dashboard/getAll.ts
index af254e032e..c73884c926 100644
--- a/frontend/src/types/api/dashboard/getAll.ts
+++ b/frontend/src/types/api/dashboard/getAll.ts
@@ -97,6 +97,7 @@ export interface IBaseWidget {
timePreferance: timePreferenceType;
stepSize?: number;
yAxisUnit?: string;
+ stackedBarChart?: boolean;
bucketCount?: number;
bucketWidth?: number;
mergeAllActiveQueries?: boolean;
diff --git a/frontend/src/types/api/metrics/getQueryRange.ts b/frontend/src/types/api/metrics/getQueryRange.ts
index b5dcba2d77..5409eba346 100644
--- a/frontend/src/types/api/metrics/getQueryRange.ts
+++ b/frontend/src/types/api/metrics/getQueryRange.ts
@@ -18,6 +18,7 @@ export type QueryRangePayload = {
promQueries?: Record;
queryType: EQueryType;
panelType: PANEL_TYPES;
+ fillGaps?: boolean;
};
end: number;
start: number;
diff --git a/frontend/src/types/api/metrics/getService.ts b/frontend/src/types/api/metrics/getService.ts
index bb9d6db941..d931197433 100644
--- a/frontend/src/types/api/metrics/getService.ts
+++ b/frontend/src/types/api/metrics/getService.ts
@@ -15,6 +15,9 @@ export interface ServicesList {
callRate: number;
numErrors: number;
errorRate: number;
+ dataWarning?: {
+ topLevelOps?: string[];
+ };
}
export type PayloadProps = ServicesList[];
diff --git a/frontend/src/types/api/queryBuilder/queryBuilderData.ts b/frontend/src/types/api/queryBuilder/queryBuilderData.ts
index 6a54254617..832bd09411 100644
--- a/frontend/src/types/api/queryBuilder/queryBuilderData.ts
+++ b/frontend/src/types/api/queryBuilder/queryBuilderData.ts
@@ -74,6 +74,7 @@ export type IBuilderQuery = {
legend: string;
pageSize?: number;
offset?: number;
+ selectColumns?: BaseAutocompleteData[];
};
export interface IClickHouseQuery {
diff --git a/frontend/src/types/common/queryBuilder.ts b/frontend/src/types/common/queryBuilder.ts
index 6ba9faf3be..7d566283e6 100644
--- a/frontend/src/types/common/queryBuilder.ts
+++ b/frontend/src/types/common/queryBuilder.ts
@@ -222,7 +222,7 @@ export type QueryBuilderContextType = {
redirectToUrl?: typeof ROUTES[keyof typeof ROUTES],
shallStringify?: boolean,
) => void;
- handleRunQuery: () => void;
+ handleRunQuery: (shallUpdateStepInterval?: boolean) => void;
resetQuery: (newCurrentQuery?: QueryState) => void;
handleOnUnitsChange: (units: Format['id']) => void;
updateAllQueriesOperators: (
diff --git a/frontend/src/utils/permission/index.ts b/frontend/src/utils/permission/index.ts
index 1c992965d4..44757e3508 100644
--- a/frontend/src/utils/permission/index.ts
+++ b/frontend/src/utils/permission/index.ts
@@ -97,4 +97,5 @@ export const routePermission: Record = {
OLD_LOGS_EXPLORER: [],
SHORTCUTS: ['ADMIN', 'EDITOR', 'VIEWER'],
INTEGRATIONS: ['ADMIN', 'EDITOR', 'VIEWER'],
+ SERVICE_TOP_LEVEL_OPERATIONS: ['ADMIN', 'EDITOR', 'VIEWER'],
};
diff --git a/go.mod b/go.mod
index a8de8d1c41..4a52cead08 100644
--- a/go.mod
+++ b/go.mod
@@ -6,23 +6,22 @@ require (
github.com/ClickHouse/clickhouse-go/v2 v2.20.0
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/SigNoz/govaluate v0.0.0-20240203125216-988004ccc7fd
- github.com/SigNoz/signoz-otel-collector v0.88.26
+ github.com/SigNoz/signoz-otel-collector v0.102.0
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/antonmedv/expr v1.15.3
github.com/auth0/go-jwt-middleware v1.0.1
github.com/cespare/xxhash v1.1.0
- github.com/coreos/go-oidc/v3 v3.4.0
+ github.com/coreos/go-oidc/v3 v3.10.0
github.com/dustin/go-humanize v1.0.1
github.com/go-co-op/gocron v1.30.1
- github.com/go-kit/kit v0.13.0
github.com/go-kit/log v0.2.1
github.com/go-redis/redis/v8 v8.11.5
github.com/go-redis/redismock/v8 v8.11.5
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.6.0
github.com/gorilla/handlers v1.5.1
- github.com/gorilla/mux v1.8.0
+ github.com/gorilla/mux v1.8.1
github.com/gosimple/slug v1.10.0
github.com/jmoiron/sqlx v1.3.4
github.com/json-iterator/go v1.1.12
@@ -30,18 +29,18 @@ require (
github.com/mailru/easyjson v0.7.7
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/minio/minio-go/v6 v6.0.57
- github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4
+ github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c
github.com/oklog/oklog v0.3.2
github.com/open-telemetry/opamp-go v0.5.0
- github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.88.0
- github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.88.0
+ github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0
+ github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.102.0
github.com/opentracing/opentracing-go v1.2.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.1
github.com/posthog/posthog-go v0.0.0-20220817142604-0b0bbf0f9c0f
- github.com/prometheus/common v0.44.0
+ github.com/prometheus/common v0.54.0
github.com/prometheus/prometheus v2.5.0+incompatible
- github.com/rs/cors v1.10.1
+ github.com/rs/cors v1.11.0
github.com/russellhaering/gosaml2 v0.9.0
github.com/russellhaering/goxmldsig v1.2.0
github.com/samber/lo v1.38.1
@@ -49,94 +48,91 @@ require (
github.com/smartystreets/goconvey v1.8.1
github.com/soheilhy/cmux v0.1.5
github.com/srikanthccv/ClickHouse-go-mock v0.7.0
- github.com/stretchr/testify v1.8.4
- go.opentelemetry.io/collector/component v0.88.0
- go.opentelemetry.io/collector/confmap v0.88.0
- go.opentelemetry.io/collector/connector v0.88.0
- go.opentelemetry.io/collector/consumer v0.88.0
- go.opentelemetry.io/collector/exporter v0.88.0
- go.opentelemetry.io/collector/extension v0.88.0
- go.opentelemetry.io/collector/otelcol v0.88.0
- go.opentelemetry.io/collector/pdata v1.3.0
- go.opentelemetry.io/collector/processor v0.88.0
- go.opentelemetry.io/collector/receiver v0.88.0
- go.opentelemetry.io/collector/service v0.88.0
- go.opentelemetry.io/otel v1.24.0
- go.opentelemetry.io/otel/sdk v1.23.1
+ github.com/stretchr/testify v1.9.0
+ go.opentelemetry.io/collector/component v0.102.1
+ go.opentelemetry.io/collector/confmap v0.102.1
+ go.opentelemetry.io/collector/confmap/converter/expandconverter v0.102.0
+ go.opentelemetry.io/collector/confmap/provider/fileprovider v0.102.0
+ go.opentelemetry.io/collector/connector v0.102.0
+ go.opentelemetry.io/collector/consumer v0.102.1
+ go.opentelemetry.io/collector/exporter v0.102.0
+ go.opentelemetry.io/collector/extension v0.102.1
+ go.opentelemetry.io/collector/otelcol v0.102.0
+ go.opentelemetry.io/collector/pdata v1.9.0
+ go.opentelemetry.io/collector/processor v0.102.0
+ go.opentelemetry.io/collector/receiver v0.102.0
+ go.opentelemetry.io/collector/service v0.102.0
+ go.opentelemetry.io/otel v1.27.0
+ go.opentelemetry.io/otel/sdk v1.27.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
- golang.org/x/crypto v0.21.0
- golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1
- golang.org/x/net v0.23.0
- golang.org/x/oauth2 v0.16.0
- google.golang.org/grpc v1.62.0
- google.golang.org/protobuf v1.33.0
+ golang.org/x/crypto v0.24.0
+ golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
+ golang.org/x/net v0.26.0
+ golang.org/x/oauth2 v0.21.0
+ golang.org/x/text v0.16.0
+ google.golang.org/grpc v1.64.0
+ google.golang.org/protobuf v1.34.1
gopkg.in/segmentio/analytics-go.v3 v3.1.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
- k8s.io/apimachinery v0.28.2
+ k8s.io/apimachinery v0.29.3
)
require (
- github.com/emicklei/go-restful/v3 v3.11.0 // indirect
- golang.org/x/tools v0.16.1 // indirect
- k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
- sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
- sigs.k8s.io/yaml v1.4.0 // indirect
-)
-
-require (
- contrib.go.opencensus.io/exporter/prometheus v0.4.2 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect
- github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
- github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 // indirect
+ github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect
+ github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/ClickHouse/ch-go v0.61.3 // indirect
- github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
+ github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect
- github.com/aws/aws-sdk-go v1.45.26 // indirect
+ github.com/aws/aws-sdk-go v1.53.16 // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
- github.com/cenkalti/backoff/v4 v4.2.1 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/cenkalti/backoff/v4 v4.3.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dennwc/varint v1.0.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
- github.com/felixge/httpsnoop v1.0.3 // indirect
+ github.com/expr-lang/expr v1.16.9 // indirect
+ github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
+ github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
github.com/go-faster/city v1.0.1 // indirect
github.com/go-faster/errors v0.7.1 // indirect
+ github.com/go-jose/go-jose/v4 v4.0.1 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
- github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
+ github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
- github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gosimple/unidecode v1.0.0 // indirect
- github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
+ github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
+ github.com/hashicorp/go-version v1.7.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/influxdata/go-syslog/v3 v3.0.1-0.20210608084020-ac565dc76ba6 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
- github.com/klauspost/compress v1.17.7 // indirect
+ github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid v1.2.3 // indirect
- github.com/knadh/koanf/v2 v2.0.1 // indirect
+ github.com/knadh/koanf/v2 v2.1.1 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
- github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 // indirect
- github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
+ github.com/leodido/go-syslog/v4 v4.1.0 // indirect
+ github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect
+ github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/minio/md5-simd v1.1.0 // indirect
github.com/minio/sha256-simd v0.1.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
@@ -146,69 +142,67 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/oklog/run v1.1.0 // indirect
- github.com/oklog/ulid v1.3.1 // indirect
- github.com/onsi/gomega v1.19.0 // indirect
- github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.88.0 // indirect
+ github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.102.0 // indirect
github.com/paulmach/orb v0.11.1 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
- github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
+ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
- github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
- github.com/prometheus/client_golang v1.17.0 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
+ github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect
+ github.com/prometheus/client_golang v1.19.1 // indirect
+ github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common/sigv4 v0.1.0 // indirect
- github.com/prometheus/procfs v0.11.1 // indirect
- github.com/prometheus/statsd_exporter v0.22.7 // indirect
+ github.com/prometheus/procfs v0.15.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/segmentio/backo-go v1.0.1 // indirect
- github.com/shirou/gopsutil/v3 v3.23.12 // indirect
+ github.com/shirou/gopsutil/v3 v3.24.4 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smarty/assertions v1.15.0 // indirect
- github.com/spf13/cobra v1.7.0 // indirect
+ github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
+ github.com/valyala/fastjson v1.6.4 // indirect
github.com/vjeantet/grok v1.0.1 // indirect
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
- github.com/yusufpapurcu/wmi v1.2.3 // indirect
+ github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
- go.opentelemetry.io/collector v0.88.0 // indirect
- go.opentelemetry.io/collector/config/configtelemetry v0.88.0 // indirect
- go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 // indirect
- go.opentelemetry.io/collector/semconv v0.88.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
- go.opentelemetry.io/contrib/propagators/b3 v1.20.0 // indirect
- go.opentelemetry.io/otel/bridge/opencensus v0.42.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 // indirect
- go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect
- go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 // indirect
- go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 // indirect
- go.opentelemetry.io/otel/metric v1.24.0 // indirect
- go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect
- go.opentelemetry.io/otel/trace v1.24.0 // indirect
- go.opentelemetry.io/proto/otlp v1.0.0 // indirect
+ go.opentelemetry.io/collector v0.102.1 // indirect
+ go.opentelemetry.io/collector/config/configtelemetry v0.102.1 // indirect
+ go.opentelemetry.io/collector/confmap/provider/envprovider v0.102.0 // indirect
+ go.opentelemetry.io/collector/confmap/provider/httpprovider v0.102.0 // indirect
+ go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.102.0 // indirect
+ go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.102.0 // indirect
+ go.opentelemetry.io/collector/featuregate v1.9.0 // indirect
+ go.opentelemetry.io/collector/semconv v0.102.0 // indirect
+ go.opentelemetry.io/contrib/config v0.7.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
+ go.opentelemetry.io/contrib/propagators/b3 v1.27.0 // indirect
+ go.opentelemetry.io/otel/bridge/opencensus v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/prometheus v0.49.0 // indirect
+ go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0 // indirect
+ go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0 // indirect
+ go.opentelemetry.io/otel/metric v1.27.0 // indirect
+ go.opentelemetry.io/otel/sdk/metric v1.27.0 // indirect
+ go.opentelemetry.io/otel/trace v1.27.0 // indirect
+ go.opentelemetry.io/proto/otlp v1.2.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
- go.uber.org/goleak v1.3.0 // indirect
- golang.org/x/sync v0.6.0 // indirect
- golang.org/x/sys v0.18.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- golang.org/x/time v0.3.0 // indirect
- gonum.org/v1/gonum v0.14.0 // indirect
- google.golang.org/appengine v1.6.8 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
+ golang.org/x/sys v0.21.0 // indirect
+ golang.org/x/time v0.5.0 // indirect
+ gonum.org/v1/gonum v0.15.0 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
- gopkg.in/square/go-jose.v2 v2.6.0 // indirect
- k8s.io/klog/v2 v2.110.1 // indirect
- k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect
+ k8s.io/client-go v0.29.3 // indirect
+ k8s.io/klog/v2 v2.120.1 // indirect
+ k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect
)
-replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.11.0
+replace github.com/prometheus/prometheus => github.com/SigNoz/prometheus v1.11.1
diff --git a/go.sum b/go.sum
index e6d22788a4..cb3f0f902e 100644
--- a/go.sum
+++ b/go.sum
@@ -13,36 +13,14 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
-cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
-cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
-cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
-cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
-cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
-cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
-cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
-cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
-cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
-cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
-cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
-cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
-cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
-cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -52,42 +30,30 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
-contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg=
-contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
+filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
-github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 h1:8q4SaHjFsClSvuVne0ID/5Ka8u3fcIHyqkLjcFpNRHQ=
-github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg=
-github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY=
-github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM=
-github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
-github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
-github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw=
-github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs=
-github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8=
-github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c=
-github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
-github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
-github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
-github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
-github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
-github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
-github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
-github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
-github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
-github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
-github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
+github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg=
+github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo=
+github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0 h1:LkHbJbgF3YyvC53aqYGR+wWQDn2Rdp9AQdGndf9QvY4=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.7.0/go.mod h1:QyiQdW4f4/BIfB8ZutZ2s+28RAgfa/pT+zS++ZHyM1I=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
+github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ClickHouse/ch-go v0.61.3 h1:MmBwUhXrAOBZK7n/sWBzq6FdIQ01cuF2SaaO8KlDRzI=
github.com/ClickHouse/ch-go v0.61.3/go.mod h1:1PqXjMz/7S1ZUaKvwPA3i35W2bz2mAMFeCi6DIXgGwQ=
github.com/ClickHouse/clickhouse-go/v2 v2.20.0 h1:bvlLQ31XJfl7MxIqAq2l1G6JhHYzqEXdvfpMeU6bkKc=
github.com/ClickHouse/clickhouse-go/v2 v2.20.0/go.mod h1:VQfyA+tCwCRw2G7ogfY8V0fq/r0yJWzy8UDrjiP/Lbs=
+github.com/Code-Hex/go-generics-cache v1.5.1 h1:6vhZGc5M7Y/YD8cIUcY8kcuQLB4cHR7U+0KMqAA0KcU=
+github.com/Code-Hex/go-generics-cache v1.5.1/go.mod h1:qxcC9kRVrct9rHeiYpFWSoW1vxyillCVzX13KZG8dl4=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
@@ -96,10 +62,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/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/prometheus v1.11.0 h1:toX7fU2wqY1TnzvPzDglIYx6OxpqrZ0NNlM/H5S5+u8=
-github.com/SigNoz/prometheus v1.11.0/go.mod h1:MffmFu2qFILQrOHehx3D0XjYtaZMVfI+Ppeiv98x4Ww=
-github.com/SigNoz/signoz-otel-collector v0.88.26 h1:+dbBOzIN6nKWD6DSAbsTtm9fcsUC5dSkhDLk6IfQuxg=
-github.com/SigNoz/signoz-otel-collector v0.88.26/go.mod h1:sT1EM9PFDaOJLbAz5npWpgXK6OhpWJ9PpSwyhHWs9rU=
+github.com/SigNoz/prometheus v1.11.1 h1:roM8ugYf4UxaeKKujEeBvoX7ybq3IrS+TB26KiRtIJg=
+github.com/SigNoz/prometheus v1.11.1/go.mod h1:uv4mQwZQtx7y4GQ6EdHOi8Wsk07uHNn2XHd1zM85m6I=
+github.com/SigNoz/signoz-otel-collector v0.102.0 h1:v6ap+gdvrKklMwU+M9FJgrn28vN0YxrINl3kvdcLonA=
+github.com/SigNoz/signoz-otel-collector v0.102.0/go.mod h1:kCx5BfzDujq6C0+kotiqLp5COG2ut4Cb039+55rbWE0=
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/zap_otlp_encoder v0.0.0-20230822164844-1b861a431974 h1:PKVgdf83Yw+lZJbFtNGBgqXiXNf3+kOXW2qZ7Ms7OaY=
@@ -111,8 +77,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
-github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
-github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
+github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4L0zgAOR8lTQK9VlyBVVd7G4omaOQs=
+github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
@@ -127,8 +93,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/auth0/go-jwt-middleware v1.0.1 h1:/fsQ4vRr4zod1wKReUH+0A3ySRjGiT9G34kypO/EKwI=
github.com/auth0/go-jwt-middleware v1.0.1/go.mod h1:YSeUX3z6+TF2H+7padiEqNJ73Zy9vXW72U//IgN0BIM=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
-github.com/aws/aws-sdk-go v1.45.26 h1:PJ2NJNY5N/yeobLYe1Y+xLdavBi67ZI8gvph6ftwVCg=
-github.com/aws/aws-sdk-go v1.45.26/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.53.16 h1:8oZjKQO/ml1WLUZw5hvF7pvYjPf8o9f57Wldoy/q9Qc=
+github.com/aws/aws-sdk-go v1.53.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw=
github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ=
@@ -139,6 +105,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72H
github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk=
github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
+github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps=
+github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0=
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -148,36 +116,29 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
-github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
-github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
+github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
+github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
-github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
-github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
-github.com/coreos/go-oidc/v3 v3.4.0 h1:xz7elHb/LDwm/ERpwHd+5nb7wFHL32rsr6bBOgaeu6g=
-github.com/coreos/go-oidc/v3 v3.4.0/go.mod h1:eHUXhZtXPQLgEaDrOVTgwbgmz1xGOkJNye6h3zkD2Pw=
+github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc=
+github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM=
+github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoEaJU=
+github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -187,14 +148,12 @@ github.com/dennwc/varint v1.0.0 h1:kGNFFSSw8ToIy3obO/kKr8U9GZYUAxQEVuix4zfDWzE=
github.com/dennwc/varint v1.0.0/go.mod h1:hnItb35rvZvJrbTALZtY/iQfDs48JKRG1RPpgziApxA=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
-github.com/digitalocean/godo v1.99.0 h1:gUHO7n9bDaZFWvbzOum4bXE0/09ZuYA9yA8idQHX57E=
-github.com/digitalocean/godo v1.99.0/go.mod h1:SsS2oXo2rznfM/nORlZ/6JaUJZFhmKTib1YhopUc8NA=
+github.com/digitalocean/godo v1.117.0 h1:WVlTe09melDYTd7VCVyvHcNWbgB+uI1O115+5LOtdSw=
+github.com/digitalocean/godo v1.117.0/go.mod h1:Vk0vpCot2HOAJwc5WE8wljZGtJ3ZtWIc8MQ8rF38sdo=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
-github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
-github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
-github.com/docker/docker v25.0.3+incompatible h1:D5fy/lYmY7bvZa0XTZ5/UJPljor41F+vdyJG5luQLfQ=
-github.com/docker/docker v25.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v26.1.3+incompatible h1:lLCzRbrVZrljpVNobJu1J2FHk8V0s4BawoZippkc+xo=
+github.com/docker/docker v26.1.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -209,32 +168,31 @@ github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRr
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
-github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
-github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A=
github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew=
+github.com/expr-lang/expr v1.16.9 h1:WUAzmR0JNI9JCiF0/ewwHB1gmcGw5wW7nWt8gc6PpCI=
+github.com/expr-lang/expr v1.16.9/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4=
+github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM=
+github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb/go.mod h1:bH6Xx7IW64qjjJq8M2u4dxNaBiDfKK+z/3eGDpXEQhc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
-github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
-github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
-github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
-github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8=
github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-co-op/gocron v1.30.1 h1:tjWUvJl5KrcwpkEkSXFSQFr4F9h5SfV/m4+RX0cV2fs=
github.com/go-co-op/gocron v1.30.1/go.mod h1:39f6KNSGVOU1LO/ZOoZfcSxwlsJDQOKSu8erN0SH48Y=
@@ -245,47 +203,46 @@ github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7F
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-jose/go-jose/v4 v4.0.1 h1:QVEPDE3OluqXBQZDcnNvQrInro2h0e4eqNbnZSWqS6U=
+github.com/go-jose/go-jose/v4 v4.0.1/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.13.0 h1:OoneCcHKHQ03LfBpoQCUfCluwd2Vt3ohz+kvbJneZAU=
-github.com/go-kit/kit v0.13.0/go.mod h1:phqEHMMUbyrCFCTgH48JueqrM3md2HcAZ8N3XE4FKDg=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
-github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
-github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
-github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
-github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
-github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
-github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
-github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
+github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
+github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
+github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
+github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
+github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-redis/redismock/v8 v8.11.5 h1:RJFIiua58hrBrSpXhnGX3on79AU3S271H4ZhRI1wyVo=
github.com/go-redis/redismock/v8 v8.11.5/go.mod h1:UaAU9dEe1C+eGr+FHV5prCWIt0hafyPWbGMEWE0UWdA=
-github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
-github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
+github.com/go-resty/resty/v2 v2.13.1 h1:x+LHXBI2nMB1vqndymf26quycC4aggYJ7DECYbiz03g=
+github.com/go-resty/resty/v2 v2.13.1/go.mod h1:GznXlLxkq6Nh4sU59rPmUw3VtgpO3aS96ORAI6Q7d+0=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
-github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
+github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
+github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c=
+github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-zookeeper/zk v1.0.3 h1:7M2kwOsc//9VeeFiPtf+uSJlVpU66x9Ba5+8XK7/TDg=
github.com/go-zookeeper/zk v1.0.3/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -294,11 +251,9 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
-github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
+github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
+github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
-github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -311,8 +266,6 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
-github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -328,12 +281,10 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
-github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
+github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -353,7 +304,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
@@ -364,8 +314,6 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -373,29 +321,15 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
-github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
-github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
-github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
-github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
-github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
-github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo=
-github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
+github.com/gophercloud/gophercloud v1.12.0 h1:Jrz16vPAL93l80q16fp8NplrTCp93y7rZh2P3Q4Yq7g=
+github.com/gophercloud/gophercloud v1.12.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
@@ -403,23 +337,23 @@ github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfre
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
+github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gosimple/slug v1.10.0 h1:3XbiQua1IpCdrvuntWvGBxVm+K99wCSxJjlxkP49GGQ=
github.com/gosimple/slug v1.10.0/go.mod h1:MICb3w495l9KNdZm+Xn5b6T2Hn831f9DMxiJ1r+bAjw=
github.com/gosimple/unidecode v1.0.0 h1:kPdvM+qy0tnk4/BrnkrbdJ82xe88xn7c9hcaipDz4dQ=
github.com/gosimple/unidecode v1.0.0/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
-github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww=
-github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A=
+github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248=
+github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
-github.com/hashicorp/consul/api v1.25.1 h1:CqrdhYzc8XZuPnhIYZWH45toM0LB9ZeYr/gvpLVI3PE=
-github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
+github.com/hashicorp/consul/api v1.29.1 h1:UEwOjYJrd3lG1x5w7HxDRMGiAUPrb3f103EoeKuuEcc=
+github.com/hashicorp/consul/api v1.29.1/go.mod h1:lumfRkY/coLuqMICkI7Fh3ylMG31mQSRZyef2c5YvJI=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A=
github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4=
@@ -433,8 +367,8 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
-github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c=
-github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
+github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@@ -456,6 +390,8 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY=
+github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
@@ -465,8 +401,8 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
-github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e h1:sr4lujmn9heD030xx/Pd4B/JSmvRhFzuotNXaaV0WLs=
-github.com/hashicorp/nomad/api v0.0.0-20230718173136-3a687930bd3e/go.mod h1:O23qLAZuCx4htdY9zBaO4cJPXgleSFEdq6D/sezGgYE=
+github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d h1:KHq+mAzWSkumj4PDoXc5VZbycPGcmYu8tohgVLQ6SIc=
+github.com/hashicorp/nomad/api v0.0.0-20240604134157-e73d8bb1140d/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY=
github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4=
@@ -474,8 +410,8 @@ github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoI
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
-github.com/hetznercloud/hcloud-go/v2 v2.0.0 h1:Sg1DJ+MAKvbYAqaBaq9tPbwXBS2ckPIaMtVdUjKu+4g=
-github.com/hetznercloud/hcloud-go/v2 v2.0.0/go.mod h1:4iUG2NG8b61IAwNx6UsMWQ6IfIf/i1RsG0BbsKAyR5Q=
+github.com/hetznercloud/hcloud-go/v2 v2.9.0 h1:s0N6R7Zoi2DPfMtUF5o9VeUBzTtHVY6MIkHOQnfu/AY=
+github.com/hetznercloud/hcloud-go/v2 v2.9.0/go.mod h1:qtW/TuU7Bs16ibXl/ktJarWqU2LwHr7eGlwoilHxtgg=
github.com/hjson/hjson-go/v4 v4.0.0 h1:wlm6IYYqHjOdXH1gHev4VoXCaW20HdQAGCxdOEEg2cs=
github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
@@ -485,10 +421,8 @@ github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/influxdata/go-syslog/v3 v3.0.1-0.20210608084020-ac565dc76ba6 h1:s9ZL6ZhFF8y6ebnm1FLvobkzoIu5xwDQUcRPk/IEhpM=
-github.com/influxdata/go-syslog/v3 v3.0.1-0.20210608084020-ac565dc76ba6/go.mod h1:aXdIdfn2OcGnMhOTojXmwZqXKgC3MU5riiNvzwwG9OY=
-github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0=
-github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k=
+github.com/ionos-cloud/sdk-go/v6 v6.1.11 h1:J/uRN4UWO3wCyGOeDdMKv8LWRzKu6UIkLEaes38Kzh8=
+github.com/ionos-cloud/sdk-go/v6 v6.1.11/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
@@ -519,14 +453,14 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
-github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
+github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
+github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs=
github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs=
-github.com/knadh/koanf/v2 v2.0.1 h1:1dYGITt1I23x8cfx8ZnldtezdyaZtfAuRtIFOiRzK7g=
-github.com/knadh/koanf/v2 v2.0.1/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus=
+github.com/knadh/koanf/v2 v2.1.1 h1:/R8eXqasSTsmDCsAyYj+81Wteg8AqrV9CP6gvsTsOmM=
+github.com/knadh/koanf/v2 v2.1.1/go.mod h1:4mnTRbZCK+ALuBXHZMjDfG9y714L7TykVnZkXbMU3Es=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00=
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -544,15 +478,18 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 h1:bCiVCRCs1Heq84lurVinUPy19keqGEe4jh5vtK37jcg=
-github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg=
+github.com/leodido/go-syslog/v4 v4.1.0 h1:Wsl194qyWXr7V6DrGWC3xmxA9Ra6XgWO+toNt2fmCaI=
+github.com/leodido/go-syslog/v4 v4.1.0/go.mod h1:eJ8rUfDN5OS6dOkCOBYlg2a+hbAg6pJa99QXXgMrd98=
+github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b h1:11UHH39z1RhZ5dc4y4r/4koJo6IYFgTRMe/LlwRTEw0=
+github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YUw=
-github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ=
-github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
+github.com/linode/linodego v1.35.0 h1:rIhUeCHBLEDlkoRnOTwzSGzljQ3ksXwLxacmXnrV+Do=
+github.com/linode/linodego v1.35.0/go.mod h1:JxuhOEAMfSxun6RU5/MgTKH2GGTmFrhKRj3wL1NFin0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
+github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY=
+github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
@@ -567,18 +504,16 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
-github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
-github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo=
-github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
+github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
+github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go/v6 v6.0.57 h1:ixPkbKkyD7IhnluRgQpGSpHdpvNVaW6OD5R9IAO/9Tw=
@@ -598,11 +533,13 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 h1:BpfhmLKZf+SjVanKKhCgf3bg+511DmU9eDQTen7LLbY=
-github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE=
+github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -637,30 +574,32 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
-github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw=
-github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
+github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
+github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/open-telemetry/opamp-go v0.5.0 h1:2YFbb6G4qBkq3yTRdVb5Nfz9hKHW/ldUyex352e1J7g=
github.com/open-telemetry/opamp-go v0.5.0/go.mod h1:IMdeuHGVc5CjKSu5/oNV0o+UmiXuahoHvoZ4GOmAI9M=
-github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.88.0 h1:9gjzrpUlzGC5BebgO1cxb/9KQ9yuIIE6B+6wLySKVCQ=
-github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.88.0/go.mod h1:GXfK9q6RosmltLUcOdrQMS3hF1RYuwIgFTIa4RRR5J4=
-github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.88.0 h1:2HoGcjmHHIDMafd3Uj3flQJrV8TC2FAnUiTKD8FH0G8=
-github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.88.0/go.mod h1:JvXKcDtcOQRkz/Sw1m27K4QA3OwMbUvifoeEX2NQC6k=
-github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.88.0 h1:jqdkgfHXcjvk6L2CyTUv3Rn+whX3TfFWd0Mz4QNAV1c=
-github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.88.0/go.mod h1:5QXLdN4gdjAEcMHNEK/RrDdp+FObca0bS4/pRauyZs8=
-github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.88.0 h1:S1FEVDH5GEMZQuHg8jfv47lCHHDFVjZBpO/Yrb/vKpE=
-github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.88.0/go.mod h1:IJqzjDv6ZFeu7cYGCUzQ5/3CuTPVIo3UAGK3o2jK/Sw=
-github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.88.0 h1:Ezi3FyxGbetZ12yAinyif/aabc9J7VyFdOvdufPCaUU=
-github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.88.0/go.mod h1:6nO6NG5H5V5YGRp5onf9JnitXwhMfNXLSfZNyVwRPuw=
-github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.88.0 h1:meHyTMeWC3xYativnHwYdnT9XwHWtfjioPRqgzaDJXA=
-github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.88.0/go.mod h1:Vhb+pyxTKFjAoLaaJCiYHbJS6o56vQEvnJDhh/ws6yY=
+github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.102.0 h1:7QHxeMnKzMXMw9oh5lnOHakfPpGSglxiZfbYUn6l6yc=
+github.com/open-telemetry/opentelemetry-collector-contrib/extension/storage v0.102.0/go.mod h1:BtKaHa1yDHfhM9qjGUHweb0HgqFGxFSM7AMzwLXVR98=
+github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.102.0 h1:PNLVcz8kJLE9V5kGnbBh277Bvl4WwiVZ+NbFbOB80WY=
+github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.102.0/go.mod h1:cBbjwd8m4rBVgCQksUbAVQX1EoM5IuCyNQw2mzvibEM=
+github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.102.0 h1:qsM5HhWpAfIMg8LdO4u+CHofu4UuCuJwg/M+ySO9uZA=
+github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.102.0/go.mod h1:wBJlGy9Wx6s7AxIMcSne2sGw73e5ZUy1AQ/duYwpFf8=
+github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.102.0 h1:vJL6lDaeI3pVA7ADnWKD3HMpI80BSrZ2UnGc+qkwqoY=
+github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.102.0/go.mod h1:xtE7tds5j8PtI/wMuGb+Em5K9rJH8hm6t28Qe4QrpoU=
+github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.102.0 h1:TvJYcU/DLRFCgHr7nT98k5D+qkZ4syKVxc8OJjv+K4c=
+github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatautil v0.102.0/go.mod h1:WzD3Ox7tywAQHknxAFpAC1oZJGItMp5mbvgUGjvzNY8=
+github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0 h1:J8GFYxKLWG1360XRukc1tY5K9BF80MFXcO91UpCMgcQ=
+github.com/open-telemetry/opentelemetry-collector-contrib/pkg/stanza v0.102.0/go.mod h1:GNxigQNap2jyOEPdOedAKqCbh61y576ND4BKn/7i8xY=
+github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.102.0 h1:XOoV42CE0BJUsKJQ7+Fie2jusw0MBzzOc79IoQONJAk=
+github.com/open-telemetry/opentelemetry-collector-contrib/processor/logstransformprocessor v0.102.0/go.mod h1:nCpPHY7XLM+zbJxKxP132IuV0xHCu5E6oa3ZLpmBPl4=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
-github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
+github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
-github.com/ovh/go-ovh v1.4.1 h1:VBGa5wMyQtTP7Zb+w97zRCh9sLtM/2YKRyy+MEJmWaM=
-github.com/ovh/go-ovh v1.4.1/go.mod h1:6bL6pPyUT7tBfI0pqOegJgRjgjuO+mOo+MyXd1EEC0M=
+github.com/ovh/go-ovh v1.5.1 h1:P8O+7H+NQuFK9P/j4sFW5C0fvSS2DnHYGPwdVCp45wI=
+github.com/ovh/go-ovh v1.5.1/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
@@ -674,8 +613,8 @@ github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCko
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
-github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
+github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -688,45 +627,36 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/posthog/posthog-go v0.0.0-20220817142604-0b0bbf0f9c0f h1:h0p1aZ9F5d6IXOygysob3g4B07b+HuVUQC0VJKD8wA4=
github.com/posthog/posthog-go v0.0.0-20220817142604-0b0bbf0f9c0f/go.mod h1:oa2sAs9tGai3VldabTV0eWejt/O4/OOD7azP8GaikqU=
-github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI=
+github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_golang v1.13.0/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
-github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
-github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
+github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
+github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
+github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
+github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
-github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8=
+github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ=
github.com/prometheus/common/sigv4 v0.1.0 h1:qoVebwtwwEhS85Czm2dSROY5fTo2PAPEVdDeppTwGX4=
github.com/prometheus/common/sigv4 v0.1.0/go.mod h1:2Jkxxk9yYvCkE5G1sQT7GuEXm57JrvHu9k5YwTjsNtI=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
-github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
-github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
-github.com/prometheus/statsd_exporter v0.22.7 h1:7Pji/i2GuhK6Lu7DHrtTkFmNBCudCPT1pX2CziuyQR0=
-github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
+github.com/prometheus/procfs v0.15.0 h1:A82kmvXJq2jTu5YUhSGNlYoxh85zLnKgPz4bMZgI5Ek=
+github.com/prometheus/procfs v0.15.0/go.mod h1:Y0RJ/Y5g5wJpkTisOtqwDSo4HwhGmLB4VQSw2sQJLHk=
github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
@@ -735,10 +665,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
-github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
-github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
-github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
-github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
+github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
+github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
+github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
+github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russellhaering/gosaml2 v0.9.0 h1:CNMnH42z/GirrKjdmNrSS6bAAs47F9bPdl4PfRmVOIk=
github.com/russellhaering/gosaml2 v0.9.0/go.mod h1:byViER/1YPUa0Puj9ROZblpoq2jsE7h/CJmitzX0geU=
github.com/russellhaering/goxmldsig v1.2.0 h1:Y6GTTc9Un5hCxSzVz4UIWQ/zuVwDvzJk80guqzwx6Vg=
@@ -750,8 +680,8 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFo
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
-github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20 h1:a9hSJdJcd16e0HoMsnFvaHvxB3pxSD+SC7+CISp7xY0=
-github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
+github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27 h1:yGAraK1uUjlhSXgNMIy8o/J4LFNcy7yeipBqt9N9mVg=
+github.com/scaleway/scaleway-sdk-go v1.0.0-beta.27/go.mod h1:fCa7OJZ/9DRTnOKmxvT6pn+LPWUptQAmHF/SBJUGEcg=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
@@ -759,8 +689,8 @@ github.com/segmentio/backo-go v1.0.1 h1:68RQccglxZeyURy93ASB/2kc9QudzgIDexJ927N+
github.com/segmentio/backo-go v1.0.1/go.mod h1:9/Rh6yILuLysoQnZ2oNooD2g7aBnvM7r/fNVxRNWfBc=
github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI=
github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE=
-github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4=
-github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
+github.com/shirou/gopsutil/v3 v3.24.4 h1:dEHgzZXt4LMNm+oYELpzl9YCqV65Yr/6SfrvgRBtXeU=
+github.com/shirou/gopsutil/v3 v3.24.4/go.mod h1:lTd2mdiOspcqLgAnr9/nGi71NkeMpWKdmhuxm9GusH8=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@@ -787,8 +717,8 @@ github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
-github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
+github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/srikanthccv/ClickHouse-go-mock v0.7.0 h1:XhRMX2663xkDGq3DYavw8m75O94s9u76hOIjo9QBl8c=
@@ -796,8 +726,9 @@ github.com/srikanthccv/ClickHouse-go-mock v0.7.0/go.mod h1:IJZ/eL1h4cOy/Jo3PzNKX
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -808,9 +739,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
@@ -819,6 +750,8 @@ github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9f
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
+github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
+github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/vjeantet/grok v1.0.1 h1:2rhIR7J4gThTgcZ1m2JY4TrJZNgjn985U28kT2wQrJ4=
github.com/vjeantet/grok v1.0.1/go.mod h1:ax1aAchzC6/QMXMcyzHQGZWaW1l195+uMYIkCWPCNIo=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
@@ -834,9 +767,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
-github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
+github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
@@ -846,83 +778,94 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
-go.opentelemetry.io/collector v0.88.0 h1:I0lerJK1h88vk7enriSgLV+h7dM099G9FgwkfmIZaf0=
-go.opentelemetry.io/collector v0.88.0/go.mod h1:we0quZ+4txHS3Sfb0VdjFv95KYLGmto4ZAThCHiYgGA=
-go.opentelemetry.io/collector/component v0.88.0 h1:LU/1ov5D/O/gv9D2Uv88EjNKHn7DHcUCZn1qQsb/zgw=
-go.opentelemetry.io/collector/component v0.88.0/go.mod h1:4utKxz4Lilym3SPxNXJHosdaTjT1aQxI+TCmnJO54pU=
-go.opentelemetry.io/collector/config/confignet v0.88.0 h1:CbVZQpWC8Bm/BKo3x2mnQZVdQKClU0gCa6SVbRCc930=
-go.opentelemetry.io/collector/config/confignet v0.88.0/go.mod h1:cpO8JYWGONaViOygKVw+Hd2UoBcn2cUiyi0WWeFTwJY=
-go.opentelemetry.io/collector/config/configtelemetry v0.88.0 h1:54Z9uoSTpbkq3esDwHvJMChoUH8p/nfesG2xJTOXayY=
-go.opentelemetry.io/collector/config/configtelemetry v0.88.0/go.mod h1:+LAXM5WFMW/UbTlAuSs6L/W72WC+q8TBJt/6z39FPOU=
-go.opentelemetry.io/collector/confmap v0.88.0 h1:tOgY6NXMXAL2hz2+zVDQ0jvBlCUHprSf90bw5ktbdaI=
-go.opentelemetry.io/collector/confmap v0.88.0/go.mod h1:CSJlMk1KRZloXAygpiPeCLpuQiLVDEZYbGsGHIKHeUg=
-go.opentelemetry.io/collector/connector v0.88.0 h1:hUTSMexixSx4rWExBfr5p3YzDdj9a9+cUveaRK0EdnQ=
-go.opentelemetry.io/collector/connector v0.88.0/go.mod h1:vkOHpyWNlHQVFHKUB4Dp1yYCIpAFnouZ2REupkzL/PU=
-go.opentelemetry.io/collector/consumer v0.88.0 h1:l8Ty5UHhZ2U6WCp4yHt97uW6vN1vMP0JbFeQEaVnEgY=
-go.opentelemetry.io/collector/consumer v0.88.0/go.mod h1:VVoafgyhjpO6fuJu12GqspmuLrn91JCOou0sOtb9GOg=
-go.opentelemetry.io/collector/exporter v0.88.0 h1:bDXltsjQslhT7tlObQzKJiHuP5LDPeZHrkpUh4cT6Kk=
-go.opentelemetry.io/collector/exporter v0.88.0/go.mod h1:0KQKlbUlYBwNJ9Dfapn6mRLhdhtM3tUlDGgN88oDVug=
-go.opentelemetry.io/collector/extension v0.88.0 h1:/WH97pQYypL7ZC5OEccoE0gFs6fjBC/Uh9NuVEYEoZ0=
-go.opentelemetry.io/collector/extension v0.88.0/go.mod h1:5wPlOyWtVJcZS9CMhFUnuRvNQ0XIoV/iUSaZWtCjoHA=
-go.opentelemetry.io/collector/extension/zpagesextension v0.88.0 h1:cpkwzjhq6jfkVq3ltUl9wdb/8RrWbn0utHTCU3K5Mhc=
-go.opentelemetry.io/collector/extension/zpagesextension v0.88.0/go.mod h1:8LPmV8UkQgDAfNaAizQqLzYnYibzQv81eBGKv0Mk6wU=
-go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 h1:DtJQalPXMWQqT6jd2LZ1oKrOfLJJRCi+rh2LKnkj4Zo=
-go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017/go.mod h1:fLmJMf1AoHttkF8p5oJAc4o5ZpHu8yO5XYJ7gbLCLzo=
-go.opentelemetry.io/collector/otelcol v0.88.0 h1:f2eRVLJY66w9WFj5iT1Tg6Qxtlljagov9v8TPStuK2g=
-go.opentelemetry.io/collector/otelcol v0.88.0/go.mod h1:F85TtMPt+ySe29HD6DOyvsMFCV3onaB3VJzky7qrtzQ=
-go.opentelemetry.io/collector/pdata v1.3.0 h1:JRYN7tVHYFwmtQhIYbxWeiKSa2L1nCohyAs8sYqKFZo=
-go.opentelemetry.io/collector/pdata v1.3.0/go.mod h1:t7W0Undtes53HODPdSujPLTnfSR5fzT+WpL+RTaaayo=
-go.opentelemetry.io/collector/processor v0.88.0 h1:5BUZaH+RhTpgTVqBZCrBnN/vl0M1CtwQsZ8ek4iH1lc=
-go.opentelemetry.io/collector/processor v0.88.0/go.mod h1:2T5KxgBQxXuuyMu9dh+PIBxQ/geCFYcdnjmlWZx8o3E=
-go.opentelemetry.io/collector/receiver v0.88.0 h1:MPvVAFOfjl0+Ylka7so8QoK8T2Za2471rv5t3sqbbSY=
-go.opentelemetry.io/collector/receiver v0.88.0/go.mod h1:MIZ6jPPZ+I8XibZm6I3RAn9h7Wcy2ZJsPmtXd2BLr60=
-go.opentelemetry.io/collector/semconv v0.88.0 h1:8TVP4hYaUC87S6CCLKNoSxsUE0ChldE4vqotvNHHUnE=
-go.opentelemetry.io/collector/semconv v0.88.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw=
-go.opentelemetry.io/collector/service v0.88.0 h1:KSue2w94Tb2xjenlm+SC2y2g87hdhFJeHMT9pEshKAE=
-go.opentelemetry.io/collector/service v0.88.0/go.mod h1:+Fov4arJzWl8SBuMonvM7gOrfK72G+d+2WotRjR5c2I=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
-go.opentelemetry.io/contrib/propagators/b3 v1.20.0 h1:Yty9Vs4F3D6/liF1o6FNt0PvN85h/BJJ6DQKJ3nrcM0=
-go.opentelemetry.io/contrib/propagators/b3 v1.20.0/go.mod h1:On4VgbkqYL18kbJlWsa18+cMNe6rYpBnPi1ARI/BrsU=
-go.opentelemetry.io/contrib/zpages v0.45.0 h1:jIwHHGoWzJoZdbIUtWdErjL85Gni6BignnAFqDtMRL4=
-go.opentelemetry.io/contrib/zpages v0.45.0/go.mod h1:4mIdA5hqH6hEx9sZgV50qKfQO8aIYolUZboHmz+G7vw=
-go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
-go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
-go.opentelemetry.io/otel/bridge/opencensus v0.42.0 h1:QvC+bcZkWMphWPiVqRQygMj6M0/3TOuJEO+erRA7kI8=
-go.opentelemetry.io/otel/bridge/opencensus v0.42.0/go.mod h1:XJojP7g5DqYdiyArix/H9i1XzPPlIUc9dGLKtF9copI=
-go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU=
-go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU=
-go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM=
-go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ=
-go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8=
-go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 h1:3d+S281UTjM+AbF31XSOYn1qXn3BgIdWl8HNEpx08Jk=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0/go.mod h1:0+KuTDyKL4gjKCF75pHOX4wuzYDUZYfAQdSu43o+Z2I=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
-go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA=
-go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA=
-go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0 h1:4jJuoeOo9W6hZnz+r046fyoH5kykZPRvKfUXJVfMpB0=
-go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v0.42.0/go.mod h1:/MtYTE1SfC2QIcE0bDot6fIX+h+WvXjgTqgn9P0LNPE=
-go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0 h1:Nw7Dv4lwvGrI68+wULbcq7su9K2cebeCUrDjVrUJHxM=
-go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.19.0/go.mod h1:1MsF6Y7gTqosgoZvHlzcaaM8DIMNZgJh87ykokoNH7Y=
-go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
-go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
-go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E=
-go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk=
-go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k=
-go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY=
-go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
-go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
-go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
+go.opentelemetry.io/collector v0.102.1 h1:M/ciCcReQsSDYG9bJ2Qwqk7pQILDJ2bM/l0MdeCAvJE=
+go.opentelemetry.io/collector v0.102.1/go.mod h1:yF1lDRgL/Eksb4/LUnkMjvLvHHpi6wqBVlzp+dACnPM=
+go.opentelemetry.io/collector/component v0.102.1 h1:66z+LN5dVCXhvuVKD1b56/3cYLK+mtYSLIwlskYA9IQ=
+go.opentelemetry.io/collector/component v0.102.1/go.mod h1:XfkiSeImKYaewT2DavA80l0VZ3JjvGndZ8ayPXfp8d0=
+go.opentelemetry.io/collector/config/confignet v0.102.1 h1:nSiAFQMzNCO4sDBztUxY73qFw4Vh0hVePq8+3wXUHtU=
+go.opentelemetry.io/collector/config/confignet v0.102.1/go.mod h1:pfOrCTfSZEB6H2rKtx41/3RN4dKs+X2EKQbw3MGRh0E=
+go.opentelemetry.io/collector/config/configtelemetry v0.102.1 h1:f/CYcrOkaHd+COIJ2lWnEgBCHfhEycpbow4ZhrGwAlA=
+go.opentelemetry.io/collector/config/configtelemetry v0.102.1/go.mod h1:WxWKNVAQJg/Io1nA3xLgn/DWLE/W1QOB2+/Js3ACi40=
+go.opentelemetry.io/collector/confmap v0.102.1 h1:wZuH+d/P11Suz8wbp+xQCJ0BPE9m5pybtUe74c+rU7E=
+go.opentelemetry.io/collector/confmap v0.102.1/go.mod h1:KgpS7UxH5rkd69CzAzlY2I1heH8Z7eNCZlHmwQBMxNg=
+go.opentelemetry.io/collector/confmap/converter/expandconverter v0.102.0 h1:8Ne/oL6M4kMWK0P3FKV9EduQa+1UOGyVAnFHfSo4c1A=
+go.opentelemetry.io/collector/confmap/converter/expandconverter v0.102.0/go.mod h1:Xj4Ld/RriP/Bj+5oPpaYJsLNs2wWRDN2TvzX3Lbi6+M=
+go.opentelemetry.io/collector/confmap/provider/envprovider v0.102.0 h1:o1iKqN+oM+TZqHoGdnKw1Am2BQlIGCYbxCRzU8T3jbM=
+go.opentelemetry.io/collector/confmap/provider/envprovider v0.102.0/go.mod h1:JpCemLtL/sXQ2Rk3Bx7OPPA7Qt/9NVH91q0bR655gSo=
+go.opentelemetry.io/collector/confmap/provider/fileprovider v0.102.0 h1:SfASE6lxXjrmYj/UibcWdOiFWvRG0zt4hJgenloEhlY=
+go.opentelemetry.io/collector/confmap/provider/fileprovider v0.102.0/go.mod h1:+Ku0Fvdb5f6e9UkfqJXAV5FaUJVxxg6Ykfx7Js8y+V4=
+go.opentelemetry.io/collector/confmap/provider/httpprovider v0.102.0 h1:GwJQTXs7pYPUv/fVf+0nBgsJdlrTuY/PfwQ/TRA/sIk=
+go.opentelemetry.io/collector/confmap/provider/httpprovider v0.102.0/go.mod h1:PGE3DcRgqYWWC2cq2hYZoET1d3Q8JZyPNmgvqXPFWEU=
+go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.102.0 h1:zdYZLiHHtDf4Kk9WU7mW9dW6WAXtBF54I5jmTMRJtiw=
+go.opentelemetry.io/collector/confmap/provider/httpsprovider v0.102.0/go.mod h1:yFsgUM0PbUJkPlbpJfOG6da+YiF0Z80tv7YcnL3qwv4=
+go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.102.0 h1:Y4H+GaCQl2URp9mEJMV5CYOhw+erONqNyvtFoKQfIoA=
+go.opentelemetry.io/collector/confmap/provider/yamlprovider v0.102.0/go.mod h1:g1RjfVD0gHAf/mPOIs3zBoKBeuDsN+rc5x0lZtgA8tI=
+go.opentelemetry.io/collector/connector v0.102.0 h1:IvAsVfYRxP0ajmKbUovF8qugkcUtHq6RuYNtjcMa63E=
+go.opentelemetry.io/collector/connector v0.102.0/go.mod h1:f4M7wZ/9+XtgTE0fivBFH3WlwntaEd0qFFA0giFkdnY=
+go.opentelemetry.io/collector/consumer v0.102.1 h1:0CkgHhxwx4lI/m+hWjh607xyjooW5CObZ8hFQy5vvo0=
+go.opentelemetry.io/collector/consumer v0.102.1/go.mod h1:HoXqmrRV13jLnP3/Gg3fYNdRkDPoO7UW58hKiLyFF60=
+go.opentelemetry.io/collector/exporter v0.102.0 h1:hvyTyyGVx5FIikA6HzlTeZHILJ62hrIBsoZCoKlpX3A=
+go.opentelemetry.io/collector/exporter v0.102.0/go.mod h1:JWE+1qNoSVBSelzhI3Iao/VkYVssY+sXaTPK1JOmpQ0=
+go.opentelemetry.io/collector/extension v0.102.1 h1:gAvE3w15q+Vv0Tj100jzcDpeMTyc8dAiemHRtJbspLg=
+go.opentelemetry.io/collector/extension v0.102.1/go.mod h1:XBxUOXjZpwYLZYOK5u3GWlbBTOKmzStY5eU1R/aXkIo=
+go.opentelemetry.io/collector/extension/zpagesextension v0.102.0 h1:BPq98py8nwzaV7KAsxt4ZZAF9LiSRu7ZjHNGavFNyKo=
+go.opentelemetry.io/collector/extension/zpagesextension v0.102.0/go.mod h1:P86HW3x3epDS5F4yP0gAvsZiw4xxP1OupTEx2o6UqjY=
+go.opentelemetry.io/collector/featuregate v1.9.0 h1:mC4/HnR5cx/kkG1RKOQAvHxxg5Ktmd9gpFdttPEXQtA=
+go.opentelemetry.io/collector/featuregate v1.9.0/go.mod h1:PsOINaGgTiFc+Tzu2K/X2jP+Ngmlp7YKGV1XrnBkH7U=
+go.opentelemetry.io/collector/otelcol v0.102.0 h1:HuE+ok4iUjOrmYhQBSWpG5kBTVhcA24ljPL4pBERZ5E=
+go.opentelemetry.io/collector/otelcol v0.102.0/go.mod h1:w8pCRu2nM/jAkLlEAS6ccKtJv5ylUQe6Ugl98zzTfyE=
+go.opentelemetry.io/collector/pdata v1.9.0 h1:qyXe3HEVYYxerIYu0rzgo1Tx2d1Zs6iF+TCckbHLFOw=
+go.opentelemetry.io/collector/pdata v1.9.0/go.mod h1:vk7LrfpyVpGZrRWcpjyy0DDZzL3SZiYMQxfap25551w=
+go.opentelemetry.io/collector/pdata/testdata v0.102.1 h1:S3idZaJxy8M7mCC4PG4EegmtiSaOuh6wXWatKIui8xU=
+go.opentelemetry.io/collector/pdata/testdata v0.102.1/go.mod h1:JEoSJTMgeTKyGxoMRy48RMYyhkA5vCCq/abJq9B6vXs=
+go.opentelemetry.io/collector/processor v0.102.0 h1:JsjTlpBRmoSYxcu3cAbKBchOmL6aNUxLa03ZkWIqZr8=
+go.opentelemetry.io/collector/processor v0.102.0/go.mod h1:IaCSDcfy75uQTaOM+LgR1bMf/bUw2eFfzn20uvWYfLQ=
+go.opentelemetry.io/collector/receiver v0.102.0 h1:8rHNjWjV90bL0dgvKVc/7D10NCbM7bXCiqpcLRz5jBI=
+go.opentelemetry.io/collector/receiver v0.102.0/go.mod h1:bYDwYItMrj7Drx0Pn4wZQ8Ii67lp9Nta62gbau93FhA=
+go.opentelemetry.io/collector/semconv v0.102.0 h1:VEOdog9IbSfaGR7yg4AVmT54MwHAgH9lzITH6C33uyc=
+go.opentelemetry.io/collector/semconv v0.102.0/go.mod h1:yMVUCNoQPZVq/IPfrHrnntZTWsLf5YGZ7qwKulIl5hw=
+go.opentelemetry.io/collector/service v0.102.0 h1:B5nfyQZF7eB/y+yucl9G/7VsusbXixYXWingXn7VszM=
+go.opentelemetry.io/collector/service v0.102.0/go.mod h1:c+0n0DfQeCjgrdplNHYwYbG/5aupTZVYU/50nMQraoc=
+go.opentelemetry.io/contrib/config v0.7.0 h1:b1rK5tGTuhhPirJiMxOcyQfZs76j2VapY6ODn3b2Dbs=
+go.opentelemetry.io/contrib/config v0.7.0/go.mod h1:8tdiFd8N5etOi3XzBmAoMxplEzI3TcL8dU5rM5/xcOQ=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0=
+go.opentelemetry.io/contrib/propagators/b3 v1.27.0 h1:IjgxbomVrV9za6bRi8fWCNXENs0co37SZedQilP2hm0=
+go.opentelemetry.io/contrib/propagators/b3 v1.27.0/go.mod h1:Dv9obQz25lCisDvvs4dy28UPh974CxkahRDUPsY7y9E=
+go.opentelemetry.io/contrib/zpages v0.52.0 h1:MPgkMy0Cp3O5EdfVXP0ss3ujhEibysTM4eszx7E7d+E=
+go.opentelemetry.io/contrib/zpages v0.52.0/go.mod h1:fqG5AFdoYru3A3DnhibVuaaEfQV2WKxE7fYE1jgDRwk=
+go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
+go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
+go.opentelemetry.io/otel/bridge/opencensus v1.27.0 h1:ao9aGGHd+G4YfjBpGs6vbkvt5hoC67STlJA9fCnOAcs=
+go.opentelemetry.io/otel/bridge/opencensus v1.27.0/go.mod h1:uRvWtAAXzyVOST0WMPX5JHGBaAvBws+2F8PcC5gMnTk=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0 h1:bFgvUr3/O4PHj3VQcFEuYKvRZJX1SJDQ+11JXuSB3/w=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.27.0/go.mod h1:xJntEd2KL6Qdg5lwp97HMLQDVeAhrYxmzFseAMDPQ8I=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0 h1:CIHWikMsN3wO+wq1Tp5VGdVRTcON+DmOJSfDjXypKOc=
+go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.27.0/go.mod h1:TNupZ6cxqyFEpLXAZW7On+mLFL0/g0TE3unIYL91xWc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY=
+go.opentelemetry.io/otel/exporters/prometheus v0.49.0 h1:Er5I1g/YhfYv9Affk9nJLfH/+qCCVVg1f2R9AbJfqDQ=
+go.opentelemetry.io/otel/exporters/prometheus v0.49.0/go.mod h1:KfQ1wpjf3zsHjzP149P4LyAwWRupc6c7t1ZJ9eXpKQM=
+go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0 h1:/jlt1Y8gXWiHG9FBx6cJaIC5hYx5Fe64nC8w5Cylt/0=
+go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.27.0/go.mod h1:bmToOGOBZ4hA9ghphIc1PAf66VA8KOtsuy3+ScStG20=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0 h1:/0YaXu3755A/cFbtXp+21lkXgI0QE5avTWA2HjU9/WE=
+go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.27.0/go.mod h1:m7SFxp0/7IxmJPLIY3JhOcU9CoFzDaCPL6xxQIxhA+o=
+go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
+go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
+go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
+go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
+go.opentelemetry.io/otel/sdk/metric v1.27.0 h1:5uGNOlpXi+Hbo/DRoI31BSb1v+OGcpv2NemcCrOL8gI=
+go.opentelemetry.io/otel/sdk/metric v1.27.0/go.mod h1:we7jJVrYN2kh3mVBlswtPU22K0SA+769l93J6bsyvqw=
+go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
+go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
+go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
+go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
@@ -943,10 +886,9 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
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-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
-golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
+golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
+golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -957,8 +899,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
-golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
+golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
+golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -971,7 +913,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -981,12 +922,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
-golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
+golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1020,54 +958,24 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
-golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/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.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
-golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
-golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
+golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
+golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
-golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
-golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
-golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
-golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
+golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
+golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1079,10 +987,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
-golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
+golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1129,81 +1035,45 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
-golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
+golang.org/x/sys v0.21.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-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.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
-golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
+golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
+golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
+golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
+golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -1247,31 +1117,17 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
-golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
+golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
+golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
-gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
-gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
+gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ=
+gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -1288,38 +1144,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
-google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
-google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
-google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
-google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
-google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
-google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
-google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
-google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
-google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
-google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
-google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
-google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
-google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
-google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
-google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
-google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
-google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1351,60 +1181,11 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
-google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
-google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
-google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
-google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
-google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
-google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
-google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
-google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
-google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
-google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
-google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU=
-google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
+google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -1419,28 +1200,11 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
-google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
-google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
-google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
-google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
-google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
-google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
+google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
+google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1454,10 +1218,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
+google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -1475,8 +1237,6 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/segmentio/analytics-go.v3 v3.1.0 h1:UzxH1uaGZRpMKDhJyBz0pexz6yUoBU3x8bJsRk/HV6U=
gopkg.in/segmentio/analytics-go.v3 v3.1.0/go.mod h1:4QqqlTlSSpVlWA9/9nDcPw+FkM2yv1NQoYjUbL9/JAw=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
-gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
-gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -1499,18 +1259,18 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
-k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
-k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
-k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
-k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
-k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
-k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
-k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
-k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
-k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
-k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc=
-k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
+k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
+k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
+k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
+k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
+k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
+k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
+k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
+k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
+k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
+k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak=
+k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
diff --git a/pkg/query-service/agentConf/db.go b/pkg/query-service/agentConf/db.go
index 04ab780db6..30ec1caef3 100644
--- a/pkg/query-service/agentConf/db.go
+++ b/pkg/query-service/agentConf/db.go
@@ -4,7 +4,6 @@ import (
"context"
"database/sql"
"fmt"
- "math/rand"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
@@ -15,10 +14,6 @@ import (
"golang.org/x/exp/slices"
)
-func init() {
- rand.Seed(2000)
-}
-
// Repo handles DDL and DML ops on ingestion rules
type Repo struct {
db *sqlx.DB
diff --git a/pkg/query-service/app/auth.go b/pkg/query-service/app/auth.go
index f771a7cbfe..abdbdc9c9c 100644
--- a/pkg/query-service/app/auth.go
+++ b/pkg/query-service/app/auth.go
@@ -64,7 +64,7 @@ func (am *AuthMiddleware) EditAccess(f func(http.ResponseWriter, *http.Request))
if !(auth.IsEditor(user) || auth.IsAdmin(user)) {
RespondError(w, &model.ApiError{
Typ: model.ErrorForbidden,
- Err: errors.New("API is accessible to editors/admins."),
+ Err: errors.New("API is accessible to editors/admins"),
}, nil)
return
}
@@ -88,7 +88,7 @@ func (am *AuthMiddleware) SelfAccess(f func(http.ResponseWriter, *http.Request))
if !(auth.IsSelfAccessRequest(user, id) || auth.IsAdmin(user)) {
RespondError(w, &model.ApiError{
Typ: model.ErrorForbidden,
- Err: errors.New("API is accessible for self access or to the admins."),
+ Err: errors.New("API is accessible for self access or to the admins"),
}, nil)
return
}
diff --git a/pkg/query-service/app/clickhouseReader/options.go b/pkg/query-service/app/clickhouseReader/options.go
index d92b5ee38f..538cef33e5 100644
--- a/pkg/query-service/app/clickhouseReader/options.go
+++ b/pkg/query-service/app/clickhouseReader/options.go
@@ -42,17 +42,6 @@ const (
defaultEncoding Encoding = EncodingJSON
)
-const (
- suffixEnabled = ".enabled"
- suffixDatasource = ".datasource"
- suffixOperationsTable = ".operations-table"
- suffixIndexTable = ".index-table"
- suffixSpansTable = ".spans-table"
- suffixWriteBatchDelay = ".write-batch-delay"
- suffixWriteBatchSize = ".write-batch-size"
- suffixEncoding = ".encoding"
-)
-
// NamespaceConfig is Clickhouse's internal configuration data
type namespaceConfig struct {
namespace string
diff --git a/pkg/query-service/app/clickhouseReader/reader.go b/pkg/query-service/app/clickhouseReader/reader.go
index c4a3de87eb..320f7fe5b3 100644
--- a/pkg/query-service/app/clickhouseReader/reader.go
+++ b/pkg/query-service/app/clickhouseReader/reader.go
@@ -27,11 +27,8 @@ import (
"github.com/pkg/errors"
"github.com/prometheus/common/promlog"
"github.com/prometheus/prometheus/config"
- "github.com/prometheus/prometheus/discovery"
- sd_config "github.com/prometheus/prometheus/discovery"
"github.com/prometheus/prometheus/promql"
- "github.com/prometheus/prometheus/scrape"
"github.com/prometheus/prometheus/storage"
"github.com/prometheus/prometheus/storage/remote"
"github.com/prometheus/prometheus/util/stats"
@@ -263,14 +260,8 @@ func (r *ClickHouseReader) Start(readerReady chan bool) {
configFile: r.promConfigFile,
}
- // fanoutStorage := remoteStorage
fanoutStorage := storage.NewFanout(logger, remoteStorage)
- ctxScrape, cancelScrape := context.WithCancel(context.Background())
- discoveryManagerScrape := discovery.NewManager(ctxScrape, log.With(logger, "component", "discovery manager scrape"), discovery.Name("scrape"))
-
- scrapeManager := scrape.NewManager(nil, log.With(logger, "component", "scrape manager"), fanoutStorage)
-
opts := promql.EngineOpts{
Logger: log.With(logger, "component", "query engine"),
Reg: nil,
@@ -287,16 +278,6 @@ func (r *ClickHouseReader) Start(readerReady chan bool) {
reloaders := []func(cfg *config.Config) error{
remoteStorage.ApplyConfig,
- // The Scrape managers need to reload before the Discovery manager as
- // they need to read the most updated config when receiving the new targets list.
- scrapeManager.ApplyConfig,
- func(cfg *config.Config) error {
- c := make(map[string]sd_config.Configs)
- for _, v := range cfg.ScrapeConfigs {
- c[v.JobName] = v.ServiceDiscoveryConfigs
- }
- return discoveryManagerScrape.ApplyConfig(c)
- },
}
// sync.Once is used to make sure we can close the channel at different execution stages(SIGTERM or when the config is loaded).
@@ -316,55 +297,11 @@ func (r *ClickHouseReader) Start(readerReady chan bool) {
}
var g group.Group
- {
- // Scrape discovery manager.
- g.Add(
- func() error {
- err := discoveryManagerScrape.Run()
- level.Info(logger).Log("msg", "Scrape discovery manager stopped")
- return err
- },
- func(err error) {
- level.Info(logger).Log("msg", "Stopping scrape discovery manager...")
- cancelScrape()
- },
- )
- }
- {
- // Scrape manager.
- g.Add(
- func() error {
- // When the scrape manager receives a new targets list
- // it needs to read a valid config for each job.
- // It depends on the config being in sync with the discovery manager so
- // we wait until the config is fully loaded.
- <-reloadReady.C
-
- err := scrapeManager.Run(discoveryManagerScrape.SyncCh())
- level.Info(logger).Log("msg", "Scrape manager stopped")
- return err
- },
- func(err error) {
- // Scrape manager needs to be stopped before closing the local TSDB
- // so that it doesn't try to write samples to a closed storage.
- level.Info(logger).Log("msg", "Stopping scrape manager...")
- scrapeManager.Stop()
- },
- )
- }
{
// Initial configuration loading.
cancel := make(chan struct{})
g.Add(
func() error {
- // select {
- // case <-dbOpen:
- // break
- // // In case a shutdown is initiated before the dbOpen is released
- // case <-cancel:
- // reloadReady.Close()
- // return nil
- // }
var err error
r.promConfig, err = reloadConfig(cfg.configFile, logger, reloaders...)
if err != nil {
@@ -462,7 +399,7 @@ func (r *ClickHouseReader) LoadChannel(channel *model.ChannelItem) *model.ApiErr
if response.StatusCode > 299 {
responseData, _ := io.ReadAll(response.Body)
- err := fmt.Errorf("Error in getting 2xx response in API call to alertmanager/v1/receivers")
+ err := fmt.Errorf("error in getting 2xx response in API call to alertmanager/v1/receivers")
zap.L().Error("Error in getting 2xx response in API call to alertmanager/v1/receivers", zap.String("Status", response.Status), zap.String("Data", string(responseData)))
return &model.ApiError{Typ: model.ErrorInternal, Err: err}
@@ -547,7 +484,7 @@ func (r *ClickHouseReader) GetChannels() (*[]model.ChannelItem, *model.ApiError)
channels := []model.ChannelItem{}
- query := fmt.Sprintf("SELECT id, created_at, updated_at, name, type, data data FROM notification_channels")
+ query := "SELECT id, created_at, updated_at, name, type, data data FROM notification_channels"
err := r.localDB.Select(&channels, query)
@@ -756,7 +693,7 @@ func (r *ClickHouseReader) GetServicesList(ctx context.Context) (*[]string, erro
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, fmt.Errorf("Error in processing sql query")
+ return nil, fmt.Errorf("error in processing sql query")
}
defer rows.Close()
@@ -938,7 +875,7 @@ func (r *ClickHouseReader) GetServiceOverview(ctx context.Context, queryParams *
}
ops, ok := (*topLevelOps)[queryParams.ServiceName]
if !ok {
- return nil, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf("Service not found")}
+ return nil, &model.ApiError{Typ: model.ErrorNotFound, Err: fmt.Errorf("service not found")}
}
namedArgs := []interface{}{
@@ -1006,7 +943,7 @@ func (r *ClickHouseReader) GetServiceOverview(ctx context.Context, queryParams *
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
m := make(map[int64]int)
@@ -1137,7 +1074,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
for _, service := range dBResponse {
if service.ServiceName != "" {
@@ -1154,7 +1091,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
for _, service := range dBResponse {
if service.HttpRoute != "" {
@@ -1171,7 +1108,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
for _, service := range dBResponse {
if service.HttpUrl != "" {
@@ -1188,7 +1125,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
for _, service := range dBResponse {
if service.HttpMethod != "" {
@@ -1205,7 +1142,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
for _, service := range dBResponse {
if service.HttpHost != "" {
@@ -1222,7 +1159,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
for _, service := range dBResponse {
if service.Operation != "" {
@@ -1238,7 +1175,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
finalQuery2 := fmt.Sprintf("SELECT COUNT(*) as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU AND hasError = false", r.TraceDB, r.indexTable)
@@ -1249,7 +1186,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
if len(dBResponse) > 0 && len(dBResponse2) > 0 {
traceFilterReponse.Status = map[string]uint64{"ok": dBResponse2[0].NumTotal, "error": dBResponse[0].NumTotal}
@@ -1273,7 +1210,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
zap.L().Info(finalQuery)
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
if len(dBResponse) > 0 {
traceFilterReponse.Duration = map[string]uint64{"minDuration": dBResponse[0].Min, "maxDuration": dBResponse[0].Max}
@@ -1289,7 +1226,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
finalQuery = fmt.Sprintf("SELECT durationNano as numTotal FROM %s.%s WHERE timestamp >= @timestampL AND timestamp <= @timestampU", r.TraceDB, r.durationTable)
@@ -1301,7 +1238,7 @@ func (r *ClickHouseReader) GetSpanFilters(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query: %s", err)}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query: %s", err)}
}
if len(dBResponse) > 0 {
traceFilterReponse.Duration["minDuration"] = dBResponse[0].NumTotal
@@ -1460,7 +1397,7 @@ func (r *ClickHouseReader) GetFilteredSpans(ctx context.Context, queryParams *mo
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if queryParams.Order == constants.Descending {
query = query + " ORDER BY timestamp DESC"
@@ -1498,7 +1435,7 @@ func (r *ClickHouseReader) GetFilteredSpans(ctx context.Context, queryParams *mo
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
getFilterSpansResponse := model.GetFilterSpansResponse{
@@ -1732,7 +1669,7 @@ func (r *ClickHouseReader) GetTagFilters(ctx context.Context, queryParams *model
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
tagFiltersResult := model.TagFilters{
StringTagKeys: make([]string, 0),
@@ -1847,7 +1784,7 @@ func (r *ClickHouseReader) GetTagValues(ctx context.Context, queryParams *model.
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
cleanedTagValues := model.TagValues{
@@ -1939,7 +1876,7 @@ func (r *ClickHouseReader) GetUsage(ctx context.Context, queryParams *model.GetU
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, fmt.Errorf("Error in processing sql query")
+ return nil, fmt.Errorf("error in processing sql query")
}
for i := range usageItems {
@@ -1976,7 +1913,7 @@ func (r *ClickHouseReader) SearchTraces(ctx context.Context, params *model.Searc
}
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_MAX_SPANS_ALLOWED_LIMIT_REACHED, data, userEmail, true, false)
}
- return nil, fmt.Errorf("Max spans allowed in trace limit reached, please contact support for more details")
+ return nil, fmt.Errorf("max spans allowed in trace limit reached, please contact support for more details")
}
userEmail, err := auth.GetEmailFromJwt(ctx)
@@ -2130,7 +2067,7 @@ func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, query
case "sum":
aggregation_query = " sum(durationNano) as value "
default:
- return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("Aggregate type: %s not supported", queryParams.AggregationOption)}
+ return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("aggregate type: %s not supported", queryParams.AggregationOption)}
}
} else if queryParams.Dimension == "calls" {
aggregation_query = " count(*) as value "
@@ -2236,7 +2173,7 @@ func (r *ClickHouseReader) GetFilteredSpansAggregates(ctx context.Context, query
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
GetFilteredSpansAggregatesResponse := model.GetFilteredSpansAggregatesResponse{
@@ -2306,7 +2243,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
tableName := getLocalTableName(tableName)
statusItem, err := r.checkTTLStatusItem(ctx, tableName)
if err != nil {
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing ttl_status check sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing ttl_status check sql query")}
}
if statusItem.Status == constants.StatusPending {
return nil, &model.ApiError{Typ: model.ErrorConflict, Err: fmt.Errorf("TTL is already running")}
@@ -2341,7 +2278,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
}
return
}
- req += fmt.Sprint(" SETTINGS distributed_ddl_task_timeout = -1;")
+ req += " SETTINGS distributed_ddl_task_timeout = -1;"
zap.L().Error("Executing TTL request: ", zap.String("request", req))
statusItem, _ := r.checkTTLStatusItem(ctx, tableName)
if err := r.db.Exec(context.Background(), req); err != nil {
@@ -2378,13 +2315,18 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
zap.L().Error("Error in inserting to ttl_status table", zap.Error(dbErr))
return
}
+ timeColumn := "timestamp_ms"
+ if strings.Contains(tableName, "v4") {
+ timeColumn = "unix_milli"
+ }
+
req := fmt.Sprintf(
- "ALTER TABLE %v ON CLUSTER %s MODIFY TTL toDateTime(toUInt32(timestamp_ms / 1000), 'UTC') + "+
- "INTERVAL %v SECOND DELETE", tableName, r.cluster, params.DelDuration)
+ "ALTER TABLE %v ON CLUSTER %s MODIFY TTL toDateTime(toUInt32(%s / 1000), 'UTC') + "+
+ "INTERVAL %v SECOND DELETE", tableName, r.cluster, timeColumn, params.DelDuration)
if len(params.ColdStorageVolume) > 0 {
- req += fmt.Sprintf(", toDateTime(toUInt32(timestamp_ms / 1000), 'UTC')"+
+ req += fmt.Sprintf(", toDateTime(toUInt32(%s / 1000), 'UTC')"+
" + INTERVAL %v SECOND TO VOLUME '%s'",
- params.ToColdStorageDuration, params.ColdStorageVolume)
+ timeColumn, params.ToColdStorageDuration, params.ColdStorageVolume)
}
err := r.setColdStorage(context.Background(), tableName, params.ColdStorageVolume)
if err != nil {
@@ -2399,7 +2341,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
}
return
}
- req += fmt.Sprint(" SETTINGS distributed_ddl_task_timeout = -1")
+ req += " SETTINGS distributed_ddl_task_timeout = -1"
zap.L().Info("Executing TTL request: ", zap.String("request", req))
statusItem, _ := r.checkTTLStatusItem(ctx, tableName)
if err := r.db.Exec(ctx, req); err != nil {
@@ -2456,7 +2398,7 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
}
return
}
- req += fmt.Sprint(" SETTINGS distributed_ddl_task_timeout = -1")
+ req += " SETTINGS distributed_ddl_task_timeout = -1"
zap.L().Info("Executing TTL request: ", zap.String("request", req))
statusItem, _ := r.checkTTLStatusItem(ctx, tableName)
if err := r.db.Exec(ctx, req); err != nil {
@@ -2512,7 +2454,7 @@ func (r *ClickHouseReader) checkTTLStatusItem(ctx context.Context, tableName str
}
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return model.TTLStatusItem{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing ttl_status check sql query")}
+ return model.TTLStatusItem{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing ttl_status check sql query")}
}
return statusItem[0], nil
}
@@ -2528,7 +2470,7 @@ func (r *ClickHouseReader) setTTLQueryStatus(ctx context.Context, tableNameArray
return "", nil
}
if err != nil {
- return "", &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing ttl_status check sql query")}
+ return "", &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing ttl_status check sql query")}
}
if statusItem.Status == constants.StatusPending && statusItem.UpdatedAt.Unix()-time.Now().Unix() < 3600 {
status = constants.StatusPending
@@ -2813,7 +2755,7 @@ func (r *ClickHouseReader) ListErrors(ctx context.Context, queryParams *model.Li
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
return &getErrorResponses, nil
@@ -2850,7 +2792,7 @@ func (r *ClickHouseReader) CountErrors(ctx context.Context, queryParams *model.C
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return 0, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return 0, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
return errorCount, nil
@@ -2872,7 +2814,7 @@ func (r *ClickHouseReader) GetErrorFromErrorID(ctx context.Context, queryParams
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getErrorWithSpanReponse) > 0 {
@@ -2896,7 +2838,7 @@ func (r *ClickHouseReader) GetErrorFromGroupID(ctx context.Context, queryParams
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return nil, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getErrorWithSpanReponse) > 0 {
@@ -2944,7 +2886,7 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getNextErrorIDReponse) == 0 {
zap.L().Info("NextErrorID not found")
@@ -2965,7 +2907,7 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getNextErrorIDReponse) == 0 {
var getNextErrorIDReponse []model.NextPrevErrorIDsDBResponse
@@ -2979,7 +2921,7 @@ func (r *ClickHouseReader) getNextErrorID(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getNextErrorIDReponse) == 0 {
@@ -3013,7 +2955,7 @@ func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getPrevErrorIDReponse) == 0 {
zap.L().Info("PrevErrorID not found")
@@ -3034,7 +2976,7 @@ func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getPrevErrorIDReponse) == 0 {
var getPrevErrorIDReponse []model.NextPrevErrorIDsDBResponse
@@ -3048,7 +2990,7 @@ func (r *ClickHouseReader) getPrevErrorID(ctx context.Context, queryParams *mode
if err != nil {
zap.L().Error("Error in processing sql query", zap.Error(err))
- return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("Error in processing sql query")}
+ return "", time.Time{}, &model.ApiError{Typ: model.ErrorExec, Err: fmt.Errorf("error in processing sql query")}
}
if len(getPrevErrorIDReponse) == 0 {
@@ -3077,7 +3019,7 @@ func (r *ClickHouseReader) GetMetricResultEE(ctx context.Context, query string)
// GetMetricResult runs the query and returns list of time series
func (r *ClickHouseReader) GetMetricResult(ctx context.Context, query string) ([]*model.Series, error) {
- defer utils.Elapsed("GetMetricResult")()
+ defer utils.Elapsed("GetMetricResult", nil)()
zap.L().Info("Executing metric result query: ", zap.String("query", query))
@@ -3409,7 +3351,7 @@ func isDashboardWithPanelAndName(data map[string]interface{}) bool {
if ok && title != "Sample Title" {
isDashboardName = true
}
- widgets, ok := data["widgets"].(interface{})
+ widgets, ok := data["widgets"]
if ok && isDashboardName {
data, ok := widgets.([]interface{})
if ok && len(data) > 0 {
@@ -3424,7 +3366,7 @@ func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo {
var logsPanelCount, tracesPanelCount, metricsPanelCount int
// totalPanels := 0
if data != nil && data["widgets"] != nil {
- widgets, ok := data["widgets"].(interface{})
+ widgets, ok := data["widgets"]
if ok {
data, ok := widgets.([]interface{})
if ok {
@@ -3432,9 +3374,9 @@ func countPanelsInDashboard(data map[string]interface{}) model.DashboardsInfo {
sData, ok := widget.(map[string]interface{})
if ok && sData["query"] != nil {
// totalPanels++
- query, ok := sData["query"].(interface{}).(map[string]interface{})
+ query, ok := sData["query"].(map[string]interface{})
if ok && query["queryType"] == "builder" && query["builder"] != nil {
- builderData, ok := query["builder"].(interface{}).(map[string]interface{})
+ builderData, ok := query["builder"].(map[string]interface{})
if ok && builderData["queryData"] != nil {
builderQueryData, ok := builderData["queryData"].([]interface{})
if ok {
@@ -3578,7 +3520,7 @@ func isSelectedField(tableStatement string, field model.LogField) bool {
// in case of attributes and resources, if there is a materialized column present then it is selected
// TODO: handle partial change complete eg:- index is removed but materialized column is still present
name := utils.GetClickhouseColumnName(field.Type, field.DataType, field.Name)
- return strings.Contains(tableStatement, fmt.Sprintf("%s", name))
+ return strings.Contains(tableStatement, name)
}
func (r *ClickHouseReader) UpdateLogField(ctx context.Context, field *model.UpdateField) *model.ApiError {
@@ -4433,7 +4375,7 @@ func (r *ClickHouseReader) GetLogAttributeValues(ctx context.Context, req *v3.Fi
}
-func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([]string, map[string]string, []map[string]string, v3.Point) {
+func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([]string, map[string]string, []map[string]string, *v3.Point) {
// Each row will have a value and a timestamp, and an optional list of label values
// example: {Timestamp: ..., Value: ...}
// The timestamp may also not present in some cases where the time series is reduced to single value
@@ -4449,6 +4391,8 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([
// example: {"serviceName": "frontend", "operation": "/fetch"}
groupAttributes := make(map[string]string)
+ isValidPoint := false
+
for idx, v := range vars {
colName := columnNames[idx]
switch v := v.(type) {
@@ -4477,6 +4421,7 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([
case *time.Time:
point.Timestamp = v.UnixMilli()
case *float64, *float32:
+ isValidPoint = true
if _, ok := constants.ReservedColumnTargetAliases[colName]; ok || countOfNumberCols == 1 {
point.Value = float64(reflect.ValueOf(v).Elem().Float())
} else {
@@ -4487,6 +4432,7 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([
groupAttributes[colName] = fmt.Sprintf("%v", reflect.ValueOf(v).Elem().Float())
}
case *uint, *uint8, *uint64, *uint16, *uint32:
+ isValidPoint = true
if _, ok := constants.ReservedColumnTargetAliases[colName]; ok || countOfNumberCols == 1 {
point.Value = float64(reflect.ValueOf(v).Elem().Uint())
} else {
@@ -4497,6 +4443,7 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([
groupAttributes[colName] = fmt.Sprintf("%v", reflect.ValueOf(v).Elem().Uint())
}
case *int, *int8, *int16, *int32, *int64:
+ isValidPoint = true
if _, ok := constants.ReservedColumnTargetAliases[colName]; ok || countOfNumberCols == 1 {
point.Value = float64(reflect.ValueOf(v).Elem().Int())
} else {
@@ -4517,7 +4464,10 @@ func readRow(vars []interface{}, columnNames []string, countOfNumberCols int) ([
zap.L().Error("unsupported var type found in query builder query result", zap.Any("v", v), zap.String("colName", colName))
}
}
- return groupBy, groupAttributes, groupAttributesArray, point
+ if isValidPoint {
+ return groupBy, groupAttributes, groupAttributesArray, &point
+ }
+ return groupBy, groupAttributes, groupAttributesArray, nil
}
func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNames []string, countOfNumberCols int) ([]*v3.Series, error) {
@@ -4558,7 +4508,7 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam
groupBy, groupAttributes, groupAttributesArray, metricPoint := readRow(vars, columnNames, countOfNumberCols)
// skip the point if the value is NaN or Inf
// are they ever useful enough to be returned?
- if math.IsNaN(metricPoint.Value) || math.IsInf(metricPoint.Value, 0) {
+ if metricPoint != nil && (math.IsNaN(metricPoint.Value) || math.IsInf(metricPoint.Value, 0)) {
continue
}
sort.Strings(groupBy)
@@ -4568,7 +4518,9 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam
}
seriesToAttrs[key] = groupAttributes
labelsArray[key] = groupAttributesArray
- seriesToPoints[key] = append(seriesToPoints[key], metricPoint)
+ if metricPoint != nil {
+ seriesToPoints[key] = append(seriesToPoints[key], *metricPoint)
+ }
}
var seriesList []*v3.Series
@@ -4580,26 +4532,27 @@ func readRowsForTimeSeriesResult(rows driver.Rows, vars []interface{}, columnNam
return seriesList, getPersonalisedError(rows.Err())
}
-func logComment(ctx context.Context) string {
- // Get the key-value pairs from context for log comment
- kv := ctx.Value("log_comment")
+func logCommentKVs(ctx context.Context) map[string]string {
+ kv := ctx.Value(common.LogCommentKey)
if kv == nil {
- return ""
+ return nil
}
-
logCommentKVs, ok := kv.(map[string]string)
if !ok {
- return ""
+ return nil
}
-
- x, _ := json.Marshal(logCommentKVs)
- return string(x)
+ return logCommentKVs
}
// GetTimeSeriesResultV3 runs the query and returns list of time series
func (r *ClickHouseReader) GetTimeSeriesResultV3(ctx context.Context, query string) ([]*v3.Series, error) {
- defer utils.Elapsed("GetTimeSeriesResultV3", query, fmt.Sprintf("logComment: %s", logComment(ctx)))()
+ ctxArgs := map[string]interface{}{"query": query}
+ for k, v := range logCommentKVs(ctx) {
+ ctxArgs[k] = v
+ }
+
+ defer utils.Elapsed("GetTimeSeriesResultV3", ctxArgs)()
rows, err := r.db.Query(ctx, query)
@@ -4641,7 +4594,12 @@ func (r *ClickHouseReader) GetTimeSeriesResultV3(ctx context.Context, query stri
// GetListResultV3 runs the query and returns list of rows
func (r *ClickHouseReader) GetListResultV3(ctx context.Context, query string) ([]*v3.Row, error) {
- defer utils.Elapsed("GetListResultV3", query, fmt.Sprintf("logComment: %s", logComment(ctx)))()
+ ctxArgs := map[string]interface{}{"query": query}
+ for k, v := range logCommentKVs(ctx) {
+ ctxArgs[k] = v
+ }
+
+ defer utils.Elapsed("GetListResultV3", ctxArgs)()
rows, err := r.db.Query(ctx, query)
diff --git a/pkg/query-service/app/clickhouseReader/wrapper.go b/pkg/query-service/app/clickhouseReader/wrapper.go
index c21fde0ceb..c575aa7226 100644
--- a/pkg/query-service/app/clickhouseReader/wrapper.go
+++ b/pkg/query-service/app/clickhouseReader/wrapper.go
@@ -7,6 +7,7 @@ import (
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
+ "go.signoz.io/signoz/pkg/query-service/common"
)
type ClickhouseQuerySettings struct {
@@ -65,7 +66,7 @@ func (c clickhouseConnWrapper) addClickHouseSettings(ctx context.Context, query
func (c clickhouseConnWrapper) getLogComment(ctx context.Context) string {
// Get the key-value pairs from context for log comment
- kv := ctx.Value("log_comment")
+ kv := ctx.Value(common.LogCommentKey)
if kv == nil {
return ""
}
diff --git a/pkg/query-service/app/dashboards/model.go b/pkg/query-service/app/dashboards/model.go
index 64e4abcf3e..a6c5d35c9e 100644
--- a/pkg/query-service/app/dashboards/model.go
+++ b/pkg/query-service/app/dashboards/model.go
@@ -706,7 +706,7 @@ func countTraceAndLogsPanel(data map[string]interface{}) (int64, int64) {
count := int64(0)
totalPanels := int64(0)
if data != nil && data["widgets"] != nil {
- widgets, ok := data["widgets"].(interface{})
+ widgets, ok := data["widgets"]
if ok {
data, ok := widgets.([]interface{})
if ok {
@@ -714,9 +714,9 @@ func countTraceAndLogsPanel(data map[string]interface{}) (int64, int64) {
sData, ok := widget.(map[string]interface{})
if ok && sData["query"] != nil {
totalPanels++
- query, ok := sData["query"].(interface{}).(map[string]interface{})
+ query, ok := sData["query"].(map[string]interface{})
if ok && query["queryType"] == "builder" && query["builder"] != nil {
- builderData, ok := query["builder"].(interface{}).(map[string]interface{})
+ builderData, ok := query["builder"].(map[string]interface{})
if ok && builderData["queryData"] != nil {
builderQueryData, ok := builderData["queryData"].([]interface{})
if ok {
@@ -742,7 +742,7 @@ func countTraceAndLogsPanel(data map[string]interface{}) (int64, int64) {
func getWidgetIds(data map[string]interface{}) []string {
widgetIds := []string{}
if data != nil && data["widgets"] != nil {
- widgets, ok := data["widgets"].(interface{})
+ widgets, ok := data["widgets"]
if ok {
data, ok := widgets.([]interface{})
if ok {
diff --git a/pkg/query-service/app/http_handler.go b/pkg/query-service/app/http_handler.go
index 6792e58008..1f0769bb08 100644
--- a/pkg/query-service/app/http_handler.go
+++ b/pkg/query-service/app/http_handler.go
@@ -39,7 +39,6 @@ import (
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/postprocess"
- "go.uber.org/multierr"
"go.uber.org/zap"
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
@@ -66,19 +65,14 @@ func NewRouter() *mux.Router {
return mux.NewRouter().UseEncodedPath()
}
-// APIHandler implements the query service public API by registering routes at httpPrefix
+// APIHandler implements the query service public API
type APIHandler struct {
- // queryService *querysvc.QueryService
- // queryParser queryParser
- basePath string
- apiPrefix string
reader interfaces.Reader
skipConfig *model.SkipConfig
appDao dao.ModelDao
alertManager am.Manager
ruleManager *rules.Manager
featureFlags interfaces.FeatureLookup
- ready func(http.HandlerFunc) http.HandlerFunc
querier interfaces.Querier
querierV2 interfaces.Querier
queryBuilder *queryBuilder.QueryBuilder
@@ -194,8 +188,6 @@ func NewAPIHandler(opts APIHandlerOpts) (*APIHandler, error) {
}
aH.queryBuilder = queryBuilder.NewQueryBuilder(builderOpts, aH.featureFlags)
- aH.ready = aH.testReady
-
dashboards.LoadDashboardFiles(aH.featureFlags)
// if errReadingDashboards != nil {
// return nil, errReadingDashboards
@@ -227,32 +219,6 @@ type structuredResponse struct {
type structuredError struct {
Code int `json:"code,omitempty"`
Msg string `json:"msg"`
- // TraceID ui.TraceID `json:"traceID,omitempty"`
-}
-
-var corsHeaders = map[string]string{
- "Access-Control-Allow-Headers": "Accept, Authorization, Content-Type, Origin",
- "Access-Control-Allow-Methods": "GET, OPTIONS",
- "Access-Control-Allow-Origin": "*",
- "Access-Control-Expose-Headers": "Date",
-}
-
-// Enables cross-site script calls.
-func setCORS(w http.ResponseWriter) {
- for h, v := range corsHeaders {
- w.Header().Set(h, v)
- }
-}
-
-type apiFunc func(r *http.Request) (interface{}, *model.ApiError, func())
-
-// Checks if server is ready, calls f if it is, returns 503 if it is not.
-func (aH *APIHandler) testReady(f http.HandlerFunc) http.HandlerFunc {
- return func(w http.ResponseWriter, r *http.Request) {
-
- f(w, r)
-
- }
}
type ApiResponse struct {
@@ -660,6 +626,9 @@ func (aH *APIHandler) getDashboards(w http.ResponseWriter, r *http.Request) {
ic := aH.IntegrationsController
installedIntegrationDashboards, err := ic.GetDashboardsForInstalledIntegrations(r.Context())
+ if err != nil {
+ zap.L().Error("failed to get dashboards for installed integrations", zap.Error(err))
+ }
allDashboards = append(allDashboards, installedIntegrationDashboards...)
tagsFromReq, ok := r.URL.Query()["tags"]
@@ -761,7 +730,7 @@ func prepareQuery(r *http.Request) (string, error) {
for _, op := range notAllowedOps {
if strings.Contains(strings.ToLower(query), op) {
- return "", fmt.Errorf("Operation %s is not allowed", op)
+ return "", fmt.Errorf("operation %s is not allowed", op)
}
}
@@ -864,7 +833,6 @@ func (aH *APIHandler) saveAndReturn(w http.ResponseWriter, r *http.Request, sign
return
}
aH.Respond(w, dashboard)
- return
}
func (aH *APIHandler) createDashboardsTransform(w http.ResponseWriter, r *http.Request) {
@@ -872,6 +840,11 @@ func (aH *APIHandler) createDashboardsTransform(w http.ResponseWriter, r *http.R
defer r.Body.Close()
b, err := io.ReadAll(r.Body)
+ if err != nil {
+ RespondError(w, &model.ApiError{Typ: model.ErrorBadData, Err: err}, "Error reading request body")
+ return
+ }
+
var importData model.GrafanaJSON
err = json.Unmarshal(b, &importData)
@@ -1147,9 +1120,6 @@ func (aH *APIHandler) createRule(w http.ResponseWriter, r *http.Request) {
}
-func (aH *APIHandler) queryRangeMetricsFromClickhouse(w http.ResponseWriter, r *http.Request) {
-
-}
func (aH *APIHandler) queryRangeMetrics(w http.ResponseWriter, r *http.Request) {
query, apiErrorObj := parseQueryRangeRequest(r)
@@ -1187,11 +1157,11 @@ func (aH *APIHandler) queryRangeMetrics(w http.ResponseWriter, r *http.Request)
if res.Err != nil {
switch res.Err.(type) {
case promql.ErrQueryCanceled:
- RespondError(w, &model.ApiError{model.ErrorCanceled, res.Err}, nil)
+ RespondError(w, &model.ApiError{Typ: model.ErrorCanceled, Err: res.Err}, nil)
case promql.ErrQueryTimeout:
- RespondError(w, &model.ApiError{model.ErrorTimeout, res.Err}, nil)
+ RespondError(w, &model.ApiError{Typ: model.ErrorTimeout, Err: res.Err}, nil)
}
- RespondError(w, &model.ApiError{model.ErrorExec, res.Err}, nil)
+ RespondError(w, &model.ApiError{Typ: model.ErrorExec, Err: res.Err}, nil)
return
}
@@ -1242,11 +1212,11 @@ func (aH *APIHandler) queryMetrics(w http.ResponseWriter, r *http.Request) {
if res.Err != nil {
switch res.Err.(type) {
case promql.ErrQueryCanceled:
- RespondError(w, &model.ApiError{model.ErrorCanceled, res.Err}, nil)
+ RespondError(w, &model.ApiError{Typ: model.ErrorCanceled, Err: res.Err}, nil)
case promql.ErrQueryTimeout:
- RespondError(w, &model.ApiError{model.ErrorTimeout, res.Err}, nil)
+ RespondError(w, &model.ApiError{Typ: model.ErrorTimeout, Err: res.Err}, nil)
}
- RespondError(w, &model.ApiError{model.ErrorExec, res.Err}, nil)
+ RespondError(w, &model.ApiError{Typ: model.ErrorExec, Err: res.Err}, nil)
}
response_data := &model.QueryData{
@@ -1869,7 +1839,7 @@ func (aH *APIHandler) getUser(w http.ResponseWriter, r *http.Request) {
if user == nil {
RespondError(w, &model.ApiError{
Typ: model.ErrorInternal,
- Err: errors.New("User not found"),
+ Err: errors.New("user not found"),
}, nil)
return
}
@@ -1936,7 +1906,7 @@ func (aH *APIHandler) deleteUser(w http.ResponseWriter, r *http.Request) {
if user == nil {
RespondError(w, &model.ApiError{
Typ: model.ErrorNotFound,
- Err: errors.New("User not found"),
+ Err: errors.New("no user found"),
}, nil)
return
}
@@ -2009,7 +1979,7 @@ func (aH *APIHandler) getRole(w http.ResponseWriter, r *http.Request) {
if user == nil {
RespondError(w, &model.ApiError{
Typ: model.ErrorNotFound,
- Err: errors.New("No user found"),
+ Err: errors.New("no user found"),
}, nil)
return
}
@@ -2058,7 +2028,7 @@ func (aH *APIHandler) editRole(w http.ResponseWriter, r *http.Request) {
if len(adminUsers) == 1 {
RespondError(w, &model.ApiError{
- Err: errors.New("Cannot demote the last admin"),
+ Err: errors.New("cannot demote the last admin"),
Typ: model.ErrorInternal}, nil)
return
}
@@ -2110,6 +2080,9 @@ func (aH *APIHandler) editOrg(w http.ResponseWriter, r *http.Request) {
"organizationName": req.Name,
}
userEmail, err := auth.GetEmailFromJwt(r.Context())
+ if err != nil {
+ zap.L().Error("failed to get user email from jwt", zap.Error(err))
+ }
telemetry.GetInstance().SendEvent(telemetry.TELEMETRY_EVENT_ORG_SETTINGS, data, userEmail, true, false)
aH.WriteJSON(w, r, map[string]string{"data": "org updated successfully"})
@@ -2447,7 +2420,7 @@ func (ah *APIHandler) calculateLogsConnectionStatus(
},
},
}
- queryRes, err, _ := ah.querier.QueryRange(
+ queryRes, _, err := ah.querier.QueryRange(
ctx, qrParams, map[string]v3.AttributeKey{},
)
if err != nil {
@@ -2967,185 +2940,6 @@ func (aH *APIHandler) autoCompleteAttributeValues(w http.ResponseWriter, r *http
aH.Respond(w, response)
}
-func (aH *APIHandler) execClickHouseGraphQueries(ctx context.Context, queries map[string]string) ([]*v3.Result, error, map[string]error) {
- type channelResult struct {
- Series []*v3.Series
- Err error
- Name string
- Query string
- }
-
- ch := make(chan channelResult, len(queries))
- var wg sync.WaitGroup
-
- for name, query := range queries {
- wg.Add(1)
- go func(name, query string) {
- defer wg.Done()
-
- seriesList, err := aH.reader.GetTimeSeriesResultV3(ctx, query)
-
- if err != nil {
- ch <- channelResult{Err: fmt.Errorf("error in query-%s: %v", name, err), Name: name, Query: query}
- return
- }
- ch <- channelResult{Series: seriesList, Name: name, Query: query}
- }(name, query)
- }
-
- wg.Wait()
- close(ch)
-
- var errs []error
- errQuriesByName := make(map[string]error)
- res := make([]*v3.Result, 0)
- // read values from the channel
- for r := range ch {
- if r.Err != nil {
- errs = append(errs, r.Err)
- errQuriesByName[r.Name] = r.Err
- continue
- }
- res = append(res, &v3.Result{
- QueryName: r.Name,
- Series: r.Series,
- })
- }
- if len(errs) != 0 {
- return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName
- }
- return res, nil, nil
-}
-
-func (aH *APIHandler) execClickHouseListQueries(ctx context.Context, queries map[string]string) ([]*v3.Result, error, map[string]error) {
- type channelResult struct {
- List []*v3.Row
- Err error
- Name string
- Query string
- }
-
- ch := make(chan channelResult, len(queries))
- var wg sync.WaitGroup
-
- for name, query := range queries {
- wg.Add(1)
- go func(name, query string) {
- defer wg.Done()
- rowList, err := aH.reader.GetListResultV3(ctx, query)
-
- if err != nil {
- ch <- channelResult{Err: fmt.Errorf("error in query-%s: %v", name, err), Name: name, Query: query}
- return
- }
- ch <- channelResult{List: rowList, Name: name, Query: query}
- }(name, query)
- }
-
- wg.Wait()
- close(ch)
-
- var errs []error
- errQuriesByName := make(map[string]error)
- res := make([]*v3.Result, 0)
- // read values from the channel
- for r := range ch {
- if r.Err != nil {
- errs = append(errs, r.Err)
- errQuriesByName[r.Name] = r.Err
- continue
- }
- res = append(res, &v3.Result{
- QueryName: r.Name,
- List: r.List,
- })
- }
- if len(errs) != 0 {
- return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName
- }
- return res, nil, nil
-}
-
-func (aH *APIHandler) execPromQueries(ctx context.Context, metricsQueryRangeParams *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) {
- type channelResult struct {
- Series []*v3.Series
- Err error
- Name string
- Query string
- }
-
- ch := make(chan channelResult, len(metricsQueryRangeParams.CompositeQuery.PromQueries))
- var wg sync.WaitGroup
-
- for name, query := range metricsQueryRangeParams.CompositeQuery.PromQueries {
- if query.Disabled {
- continue
- }
- wg.Add(1)
- go func(name string, query *v3.PromQuery) {
- var seriesList []*v3.Series
- defer wg.Done()
- tmpl := template.New("promql-query")
- tmpl, tmplErr := tmpl.Parse(query.Query)
- if tmplErr != nil {
- ch <- channelResult{Err: fmt.Errorf("error in parsing query-%s: %v", name, tmplErr), Name: name, Query: query.Query}
- return
- }
- var queryBuf bytes.Buffer
- tmplErr = tmpl.Execute(&queryBuf, metricsQueryRangeParams.Variables)
- if tmplErr != nil {
- ch <- channelResult{Err: fmt.Errorf("error in parsing query-%s: %v", name, tmplErr), Name: name, Query: query.Query}
- return
- }
- query.Query = queryBuf.String()
- queryModel := model.QueryRangeParams{
- Start: time.UnixMilli(metricsQueryRangeParams.Start),
- End: time.UnixMilli(metricsQueryRangeParams.End),
- Step: time.Duration(metricsQueryRangeParams.Step * int64(time.Second)),
- Query: query.Query,
- }
- promResult, _, err := aH.reader.GetQueryRangeResult(ctx, &queryModel)
- if err != nil {
- ch <- channelResult{Err: fmt.Errorf("error in query-%s: %v", name, err), Name: name, Query: query.Query}
- return
- }
- matrix, _ := promResult.Matrix()
- for _, v := range matrix {
- var s v3.Series
- s.Labels = v.Metric.Copy().Map()
- for _, p := range v.Floats {
- s.Points = append(s.Points, v3.Point{Timestamp: p.T, Value: p.F})
- }
- seriesList = append(seriesList, &s)
- }
- ch <- channelResult{Series: seriesList, Name: name, Query: query.Query}
- }(name, query)
- }
-
- wg.Wait()
- close(ch)
-
- var errs []error
- errQuriesByName := make(map[string]error)
- res := make([]*v3.Result, 0)
- // read values from the channel
- for r := range ch {
- if r.Err != nil {
- errs = append(errs, r.Err)
- errQuriesByName[r.Name] = r.Err
- continue
- }
- res = append(res, &v3.Result{
- QueryName: r.Name,
- Series: r.Series,
- })
- }
- if len(errs) != 0 {
- return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName
- }
- return res, nil, nil
-}
-
func (aH *APIHandler) getLogFieldsV3(ctx context.Context, queryRangeParams *v3.QueryRangeParamsV3) (map[string]v3.AttributeKey, error) {
data := map[string]v3.AttributeKey{}
for _, query := range queryRangeParams.CompositeQuery.BuilderQueries {
@@ -3254,7 +3048,7 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que
}
}
- result, err, errQuriesByName = aH.querier.QueryRange(ctx, queryRangeParams, spanKeys)
+ result, errQuriesByName, err = aH.querier.QueryRange(ctx, queryRangeParams, spanKeys)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
@@ -3262,6 +3056,7 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que
return
}
+ postprocess.ApplyHavingClause(result, queryRangeParams)
postprocess.ApplyMetricLimit(result, queryRangeParams)
sendQueryResultEvents(r, result, queryRangeParams)
@@ -3271,6 +3066,10 @@ func (aH *APIHandler) queryRangeV3(ctx context.Context, queryRangeParams *v3.Que
postprocess.ApplyFunctions(result, queryRangeParams)
}
+ if queryRangeParams.CompositeQuery.FillGaps {
+ postprocess.FillGaps(result, queryRangeParams)
+ }
+
resp := v3.QueryRangeResponse{
Result: result,
}
@@ -3510,7 +3309,7 @@ func (aH *APIHandler) queryRangeV4(ctx context.Context, queryRangeParams *v3.Que
}
}
- result, err, errQuriesByName = aH.querierV2.QueryRange(ctx, queryRangeParams, spanKeys)
+ result, errQuriesByName, err = aH.querierV2.QueryRange(ctx, queryRangeParams, spanKeys)
if err != nil {
apiErrObj := &model.ApiError{Typ: model.ErrorBadData, Err: err}
diff --git a/pkg/query-service/app/http_handler_test.go b/pkg/query-service/app/http_handler_test.go
index 84782f7cae..6993d37168 100644
--- a/pkg/query-service/app/http_handler_test.go
+++ b/pkg/query-service/app/http_handler_test.go
@@ -67,7 +67,7 @@ func TestPrepareQuery(t *testing.T) {
Query: "ALTER TABLE signoz_table DELETE where true",
},
expectedErr: true,
- errMsg: "Operation alter table is not allowed",
+ errMsg: "operation alter table is not allowed",
},
{
name: "query text produces template exec error",
diff --git a/pkg/query-service/app/integrations/builtin.go b/pkg/query-service/app/integrations/builtin.go
index 00810cacc1..d8099633ab 100644
--- a/pkg/query-service/app/integrations/builtin.go
+++ b/pkg/query-service/app/integrations/builtin.go
@@ -27,8 +27,8 @@ func (bi *BuiltInIntegrations) list(ctx context.Context) (
[]IntegrationDetails, *model.ApiError,
) {
integrations := maps.Values(builtInIntegrations)
- slices.SortFunc(integrations, func(i1, i2 IntegrationDetails) bool {
- return i1.Id < i2.Id
+ slices.SortFunc(integrations, func(i1, i2 IntegrationDetails) int {
+ return strings.Compare(i1.Id, i2.Id)
})
return integrations, nil
}
diff --git a/pkg/query-service/app/integrations/controller.go b/pkg/query-service/app/integrations/controller.go
index 8695c4b1cd..530bf40c3c 100644
--- a/pkg/query-service/app/integrations/controller.go
+++ b/pkg/query-service/app/integrations/controller.go
@@ -108,7 +108,7 @@ func (c *Controller) Uninstall(
) *model.ApiError {
if len(req.IntegrationId) < 1 {
return model.BadRequest(fmt.Errorf(
- "integration_id is required.",
+ "integration_id is required",
))
}
diff --git a/pkg/query-service/app/integrations/sqlite_repo.go b/pkg/query-service/app/integrations/sqlite_repo.go
index 2c3e9fc699..64c8f58c93 100644
--- a/pkg/query-service/app/integrations/sqlite_repo.go
+++ b/pkg/query-service/app/integrations/sqlite_repo.go
@@ -11,7 +11,7 @@ import (
func InitSqliteDBIfNeeded(db *sqlx.DB) error {
if db == nil {
- return fmt.Errorf("db is required.")
+ return fmt.Errorf("db is required")
}
createTablesStatements := `
diff --git a/pkg/query-service/app/logparsingpipeline/db.go b/pkg/query-service/app/logparsingpipeline/db.go
index 618060d105..318f23a035 100644
--- a/pkg/query-service/app/logparsingpipeline/db.go
+++ b/pkg/query-service/app/logparsingpipeline/db.go
@@ -177,7 +177,7 @@ func (r *Repo) GetPipeline(
if len(pipelines) == 0 {
zap.L().Warn("No row found for ingestion pipeline id", zap.String("id", id))
- return nil, model.NotFoundError(fmt.Errorf("No row found for ingestion pipeline id %v", id))
+ return nil, model.NotFoundError(fmt.Errorf("no row found for ingestion pipeline id %v", id))
}
if len(pipelines) == 1 {
diff --git a/pkg/query-service/app/logparsingpipeline/postablePipeline.go b/pkg/query-service/app/logparsingpipeline/postablePipeline.go
index 790c8c5915..535f47d989 100644
--- a/pkg/query-service/app/logparsingpipeline/postablePipeline.go
+++ b/pkg/query-service/app/logparsingpipeline/postablePipeline.go
@@ -93,7 +93,7 @@ func (p *PostablePipeline) IsValid() error {
func isValidOperator(op PipelineOperator) error {
if op.ID == "" {
- return errors.New("PipelineOperator.ID is required.")
+ return errors.New("PipelineOperator.ID is required")
}
switch op.Type {
@@ -204,7 +204,7 @@ func isValidOperator(op PipelineOperator) error {
}
validMappingLevels := []string{"trace", "debug", "info", "warn", "error", "fatal"}
- for k, _ := range op.SeverityMapping {
+ for k := range op.SeverityMapping {
if !slices.Contains(validMappingLevels, strings.ToLower(k)) {
return fmt.Errorf("%s is not a valid severity in processor %s", k, op.ID)
}
diff --git a/pkg/query-service/app/logparsingpipeline/preview.go b/pkg/query-service/app/logparsingpipeline/preview.go
index 8f991ee3da..b37295eb96 100644
--- a/pkg/query-service/app/logparsingpipeline/preview.go
+++ b/pkg/query-service/app/logparsingpipeline/preview.go
@@ -2,8 +2,8 @@ package logparsingpipeline
import (
"context"
- "fmt"
"sort"
+ "strings"
"time"
_ "github.com/SigNoz/signoz-otel-collector/pkg/parser/grok"
@@ -74,9 +74,9 @@ func SimulatePipelinesProcessing(
timeout,
)
if apiErr != nil {
- return nil, collectorErrs, model.WrapApiError(apiErr, fmt.Sprintf(
+ return nil, collectorErrs, model.WrapApiError(apiErr,
"could not simulate log pipelines processing.\nCollector errors",
- ))
+ )
}
outputSignozLogs := PLogsToSignozLogs(outputPLogs)
@@ -91,7 +91,15 @@ func SimulatePipelinesProcessing(
delete(sigLog.Attributes_int64, inputOrderAttribute)
}
- return outputSignozLogs, collectorErrs, nil
+ for _, log := range collectorErrs {
+ // if log is empty or log comes from featuregate.go, then remove it
+ if log == "" || strings.Contains(log, "featuregate.go") {
+ continue
+ }
+ collectorWarnAndErrorLogs = append(collectorWarnAndErrorLogs, log)
+ }
+
+ return outputSignozLogs, collectorWarnAndErrorLogs, nil
}
// plog doesn't contain an ID field.
diff --git a/pkg/query-service/app/logparsingpipeline/preview_test.go b/pkg/query-service/app/logparsingpipeline/preview_test.go
index a9c9f43d2e..0dd421dad4 100644
--- a/pkg/query-service/app/logparsingpipeline/preview_test.go
+++ b/pkg/query-service/app/logparsingpipeline/preview_test.go
@@ -225,15 +225,15 @@ func makeTestSignozLog(
}
for k, v := range attributes {
- switch v.(type) {
+ switch v := v.(type) {
case bool:
- testLog.Attributes_bool[k] = v.(bool)
+ testLog.Attributes_bool[k] = v
case string:
- testLog.Attributes_string[k] = v.(string)
+ testLog.Attributes_string[k] = v
case int:
- testLog.Attributes_int64[k] = int64(v.(int))
+ testLog.Attributes_int64[k] = int64(v)
case float64:
- testLog.Attributes_float64[k] = v.(float64)
+ testLog.Attributes_float64[k] = v
default:
panic(fmt.Sprintf("found attribute value of unsupported type %T in test log", v))
}
diff --git a/pkg/query-service/app/metrics/v3/query_builder.go b/pkg/query-service/app/metrics/v3/query_builder.go
index 9307363361..bb13937d4e 100644
--- a/pkg/query-service/app/metrics/v3/query_builder.go
+++ b/pkg/query-service/app/metrics/v3/query_builder.go
@@ -2,11 +2,11 @@ package v3
import (
"fmt"
- "math"
"strings"
"time"
"go.signoz.io/signoz/pkg/query-service/app/metrics/v4/helpers"
+ "go.signoz.io/signoz/pkg/query-service/common"
"go.signoz.io/signoz/pkg/query-service/constants"
"go.signoz.io/signoz/pkg/query-service/model"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
@@ -332,14 +332,8 @@ func reduceQuery(query string, reduceTo v3.ReduceToOperator, aggregateOperator v
// start and end are in milliseconds
// step is in seconds
func PrepareMetricQuery(start, end int64, queryType v3.QueryType, panelType v3.PanelType, mq *v3.BuilderQuery, options Options) (string, error) {
- start = start - (start % (mq.StepInterval * 1000))
- // if the query is a rate query, we adjust the start time by one more step
- // so that we can calculate the rate for the first data point
- if mq.AggregateOperator.IsRateOperator() && mq.Temporality != v3.Delta {
- start -= mq.StepInterval * 1000
- }
- adjustStep := int64(math.Min(float64(mq.StepInterval), 60))
- end = end - (end % (adjustStep * 1000))
+
+ start, end = common.AdjustedMetricTimeRange(start, end, mq.StepInterval, *mq)
// if the aggregate operator is a histogram quantile, and user has not forgotten
// the le tag in the group by then add the le tag to the group by
diff --git a/pkg/query-service/app/metrics/v4/query_builder.go b/pkg/query-service/app/metrics/v4/query_builder.go
index bd8813dd3a..380fb44f22 100644
--- a/pkg/query-service/app/metrics/v4/query_builder.go
+++ b/pkg/query-service/app/metrics/v4/query_builder.go
@@ -19,7 +19,7 @@ import (
// step is in seconds
func PrepareMetricQuery(start, end int64, queryType v3.QueryType, panelType v3.PanelType, mq *v3.BuilderQuery, options metricsV3.Options) (string, error) {
- start, end = common.AdjustedMetricTimeRange(start, end, mq.StepInterval, mq.TimeAggregation)
+ start, end = common.AdjustedMetricTimeRange(start, end, mq.StepInterval, *mq)
var quantile float64
diff --git a/pkg/query-service/app/metrics/v4/query_builder_test.go b/pkg/query-service/app/metrics/v4/query_builder_test.go
index 790fa670c8..08d0f087ff 100644
--- a/pkg/query-service/app/metrics/v4/query_builder_test.go
+++ b/pkg/query-service/app/metrics/v4/query_builder_test.go
@@ -266,7 +266,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 signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 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 signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT fingerprint FROM signoz_metrics.time_series_v4_6hrs WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650974400000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 GROUP BY ts ORDER BY ts ASC",
},
{
name: "test time aggregation = rate, space aggregation = sum, temporality = delta, group by service_name",
@@ -292,7 +292,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 signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM signoz_metrics.time_series_v4_1day WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650931200000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991920000 AND unix_milli < 1651078380000 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 signoz_metrics.distributed_samples_v4 INNER JOIN (SELECT DISTINCT JSONExtractString(labels, 'service_name') as service_name, fingerprint FROM signoz_metrics.time_series_v4_6hrs WHERE metric_name = 'signoz_calls_total' AND temporality = 'Delta' AND unix_milli >= 1650974400000 AND unix_milli < 1651078380000) as filtered_time_series USING fingerprint WHERE metric_name = 'signoz_calls_total' AND unix_milli >= 1650991980000 AND unix_milli < 1651078380000 GROUP BY service_name, ts ORDER BY service_name ASC, ts ASC",
},
}
diff --git a/pkg/query-service/app/opamp/model/agents.go b/pkg/query-service/app/opamp/model/agents.go
index e984cafce2..2bedc24d5d 100644
--- a/pkg/query-service/app/opamp/model/agents.go
+++ b/pkg/query-service/app/opamp/model/agents.go
@@ -43,7 +43,7 @@ func InitDB(qsDB *sqlx.DB) (*sqlx.DB, error) {
_, err := db.Exec(tableSchema)
if err != nil {
- return nil, fmt.Errorf("Error in creating agents table: %s", err.Error())
+ return nil, fmt.Errorf("error in creating agents table: %s", err.Error())
}
AllAgents = Agents{
diff --git a/pkg/query-service/app/opamp/opamp_server.go b/pkg/query-service/app/opamp/opamp_server.go
index 75d8d877be..adc72ccdc1 100644
--- a/pkg/query-service/app/opamp/opamp_server.go
+++ b/pkg/query-service/app/opamp/opamp_server.go
@@ -14,10 +14,8 @@ import (
var opAmpServer *Server
type Server struct {
- server server.OpAMPServer
- agents *model.Agents
- logger *zap.Logger
- capabilities int32
+ server server.OpAMPServer
+ agents *model.Agents
agentConfigProvider AgentConfigProvider
@@ -98,8 +96,7 @@ func (srv *Server) OnMessage(conn types.Connection, msg *protobufs.AgentToServer
)
}
- var response *protobufs.ServerToAgent
- response = &protobufs.ServerToAgent{
+ response := &protobufs.ServerToAgent{
InstanceUid: agentID,
Capabilities: uint64(capabilities),
}
diff --git a/pkg/query-service/app/parser.go b/pkg/query-service/app/parser.go
index 679b7581aa..47da531d0b 100644
--- a/pkg/query-service/app/parser.go
+++ b/pkg/query-service/app/parser.go
@@ -21,8 +21,8 @@ import (
"go.signoz.io/signoz/pkg/query-service/app/metrics"
"go.signoz.io/signoz/pkg/query-service/app/queryBuilder"
"go.signoz.io/signoz/pkg/query-service/auth"
- baseconstants "go.signoz.io/signoz/pkg/query-service/constants"
"go.signoz.io/signoz/pkg/query-service/common"
+ baseconstants "go.signoz.io/signoz/pkg/query-service/constants"
"go.signoz.io/signoz/pkg/query-service/model"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/postprocess"
@@ -32,19 +32,6 @@ import (
var allowedFunctions = []string{"count", "ratePerSec", "sum", "avg", "min", "max", "p50", "p90", "p95", "p99"}
-func parseUser(r *http.Request) (*model.User, error) {
-
- var user model.User
- if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
- return nil, err
- }
- if len(user.Email) == 0 {
- return nil, fmt.Errorf("email field not found")
- }
-
- return &user, nil
-}
-
func parseGetTopOperationsRequest(r *http.Request) (*model.GetTopOperationsParams, error) {
var postData *model.GetTopOperationsParams
err := json.NewDecoder(r.Body).Decode(&postData)
@@ -394,7 +381,7 @@ func parseFilteredSpanAggregatesRequest(r *http.Request) (*model.GetFilteredSpan
return nil, errors.New("function param missing in query")
} else {
if !DoesExistInSlice(function, allowedFunctions) {
- return nil, errors.New(fmt.Sprintf("given function: %s is not allowed in query", function))
+ return nil, fmt.Errorf("given function: %s is not allowed in query", function)
}
}
@@ -549,11 +536,11 @@ func parseListErrorsRequest(r *http.Request) (*model.ListErrorsParams, error) {
}
if len(postData.Order) > 0 && !DoesExistInSlice(postData.Order, allowedOrderDirections) {
- return nil, errors.New(fmt.Sprintf("given order: %s is not allowed in query", postData.Order))
+ return nil, fmt.Errorf("given order: %s is not allowed in query", postData.Order)
}
if len(postData.Order) > 0 && !DoesExistInSlice(postData.OrderParam, allowedOrderParams) {
- return nil, errors.New(fmt.Sprintf("given orderParam: %s is not allowed in query", postData.OrderParam))
+ return nil, fmt.Errorf("given orderParam: %s is not allowed in query", postData.OrderParam)
}
return postData, nil
@@ -659,29 +646,6 @@ func parseTime(param string, r *http.Request) (*time.Time, error) {
}
-func parseTimeMinusBuffer(param string, r *http.Request) (*time.Time, error) {
-
- timeStr := r.URL.Query().Get(param)
- if len(timeStr) == 0 {
- return nil, fmt.Errorf("%s param missing in query", param)
- }
-
- timeUnix, err := strconv.ParseInt(timeStr, 10, 64)
- if err != nil || len(timeStr) == 0 {
- return nil, fmt.Errorf("%s param is not in correct timestamp format", param)
- }
-
- timeUnixNow := time.Now().UnixNano()
- if timeUnix > timeUnixNow-30000000000 {
- timeUnix = timeUnix - 30000000000
- }
-
- timeFmt := time.Unix(0, timeUnix)
-
- return &timeFmt, nil
-
-}
-
func parseTTLParams(r *http.Request) (*model.TTLParams, error) {
// make sure either of the query params are present
@@ -702,7 +666,7 @@ func parseTTLParams(r *http.Request) (*model.TTLParams, error) {
// Validate the TTL duration.
durationParsed, err := time.ParseDuration(delDuration)
if err != nil || durationParsed.Seconds() <= 0 {
- return nil, fmt.Errorf("Not a valid TTL duration %v", delDuration)
+ return nil, fmt.Errorf("not a valid TTL duration %v", delDuration)
}
var toColdParsed time.Duration
@@ -711,10 +675,10 @@ func parseTTLParams(r *http.Request) (*model.TTLParams, error) {
if len(coldStorage) > 0 {
toColdParsed, err = time.ParseDuration(toColdDuration)
if err != nil || toColdParsed.Seconds() <= 0 {
- return nil, fmt.Errorf("Not a valid toCold TTL duration %v", toColdDuration)
+ return nil, fmt.Errorf("not a valid toCold TTL duration %v", toColdDuration)
}
if toColdParsed.Seconds() != 0 && toColdParsed.Seconds() >= durationParsed.Seconds() {
- return nil, fmt.Errorf("Delete TTL should be greater than cold storage move TTL.")
+ return nil, fmt.Errorf("delete TTL should be greater than cold storage move TTL")
}
}
@@ -842,15 +806,6 @@ func parseChangePasswordRequest(r *http.Request) (*model.ChangePasswordRequest,
return &req, nil
}
-func parseFilterSet(r *http.Request) (*model.FilterSet, error) {
- var filterSet model.FilterSet
- err := json.NewDecoder(r.Body).Decode(&filterSet)
- if err != nil {
- return nil, err
- }
- return &filterSet, nil
-}
-
func parseAggregateAttributeRequest(r *http.Request) (*v3.AggregateAttributeRequest, error) {
var req v3.AggregateAttributeRequest
@@ -1003,6 +958,9 @@ func ParseQueryRangeParams(r *http.Request) (*v3.QueryRangeParamsV3, *model.ApiE
return nil, &model.ApiError{Typ: model.ErrorBadData, Err: fmt.Errorf("cannot parse the request body: %v", err)}
}
+ // sanitize the request body
+ queryRangeParams.CompositeQuery.Sanitize()
+
// validate the request body
if err := validateQueryRangeParamsV3(queryRangeParams); err != nil {
return nil, &model.ApiError{Typ: model.ErrorBadData, Err: err}
diff --git a/pkg/query-service/app/querier/helper.go b/pkg/query-service/app/querier/helper.go
index 71ee5da72d..d65627bd92 100644
--- a/pkg/query-service/app/querier/helper.go
+++ b/pkg/query-service/app/querier/helper.go
@@ -14,6 +14,7 @@ import (
"go.signoz.io/signoz/pkg/query-service/cache/status"
"go.signoz.io/signoz/pkg/query-service/constants"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
+ "go.signoz.io/signoz/pkg/query-service/postprocess"
"go.uber.org/zap"
)
@@ -121,7 +122,7 @@ func (q *querier) runBuilderQuery(
cachedData = data
}
}
- misses := q.findMissingTimeRanges(start, end, params.Step, cachedData)
+ misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData)
missedSeries := make([]*v3.Series, 0)
cachedSeries := make([]*v3.Series, 0)
for _, miss := range misses {
@@ -256,7 +257,7 @@ func (q *querier) runBuilderQuery(
cachedData = data
}
}
- misses := q.findMissingTimeRanges(start, end, params.Step, cachedData)
+ misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData)
missedSeries := make([]*v3.Series, 0)
cachedSeries := make([]*v3.Series, 0)
for _, miss := range misses {
@@ -358,7 +359,8 @@ func (q *querier) runBuilderExpression(
cachedData = data
}
}
- misses := q.findMissingTimeRanges(params.Start, params.End, params.Step, cachedData)
+ step := postprocess.StepIntervalForFunction(params, queryName)
+ misses := q.findMissingTimeRanges(params.Start, params.End, step, cachedData)
missedSeries := make([]*v3.Series, 0)
cachedSeries := make([]*v3.Series, 0)
for _, miss := range misses {
diff --git a/pkg/query-service/app/querier/querier.go b/pkg/query-service/app/querier/querier.go
index d07ee4f60d..7668d401cd 100644
--- a/pkg/query-service/app/querier/querier.go
+++ b/pkg/query-service/app/querier/querier.go
@@ -284,7 +284,7 @@ func mergeSerieses(cachedSeries, missedSeries []*v3.Series) []*v3.Series {
return mergedSeries
}
-func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) {
cacheKeys := q.keyGenerator.GenerateKeys(params)
@@ -327,10 +327,10 @@ func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangePa
err = fmt.Errorf("error in builder queries")
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
-func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) {
channelResults := make(chan channelResult, len(params.CompositeQuery.PromQueries))
var wg sync.WaitGroup
cacheKeys := q.keyGenerator.GenerateKeys(params)
@@ -411,10 +411,10 @@ func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParam
err = fmt.Errorf("error in prom queries")
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
-func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) {
channelResults := make(chan channelResult, len(params.CompositeQuery.ClickHouseQueries))
var wg sync.WaitGroup
for queryName, clickHouseQuery := range params.CompositeQuery.ClickHouseQueries {
@@ -451,15 +451,15 @@ func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRang
if len(errs) > 0 {
err = fmt.Errorf("error in clickhouse queries")
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
-func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) {
queries, err := q.builder.PrepareQueries(params, keys)
if err != nil {
- return nil, err, nil
+ return nil, nil, err
}
ch := make(chan channelResult, len(queries))
@@ -498,12 +498,12 @@ func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRan
})
}
if len(errs) != 0 {
- return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName
+ return nil, errQuriesByName, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...))
}
return res, nil, nil
}
-func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) {
+func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) {
var results []*v3.Result
var err error
var errQueriesByName map[string]error
@@ -511,9 +511,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3,
switch params.CompositeQuery.QueryType {
case v3.QueryTypeBuilder:
if params.CompositeQuery.PanelType == v3.PanelTypeList || params.CompositeQuery.PanelType == v3.PanelTypeTrace {
- results, err, errQueriesByName = q.runBuilderListQueries(ctx, params, keys)
+ results, errQueriesByName, err = q.runBuilderListQueries(ctx, params, keys)
} else {
- results, err, errQueriesByName = q.runBuilderQueries(ctx, params, keys)
+ results, errQueriesByName, err = q.runBuilderQueries(ctx, params, keys)
}
// in builder query, the only errors we expose are the ones that exceed the resource limits
// everything else is internal error as they are not actionable by the user
@@ -523,9 +523,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3,
}
}
case v3.QueryTypePromQL:
- results, err, errQueriesByName = q.runPromQueries(ctx, params)
+ results, errQueriesByName, err = q.runPromQueries(ctx, params)
case v3.QueryTypeClickHouseSQL:
- results, err, errQueriesByName = q.runClickHouseQueries(ctx, params)
+ results, errQueriesByName, err = q.runClickHouseQueries(ctx, params)
default:
err = fmt.Errorf("invalid query type")
}
@@ -540,7 +540,7 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3,
}
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
func (q *querier) QueriesExecuted() []string {
diff --git a/pkg/query-service/app/querier/querier_test.go b/pkg/query-service/app/querier/querier_test.go
index 80a3a07422..a9f8cc4030 100644
--- a/pkg/query-service/app/querier/querier_test.go
+++ b/pkg/query-service/app/querier/querier_test.go
@@ -579,7 +579,7 @@ func TestQueryRange(t *testing.T) {
}
for i, param := range params {
- _, err, errByName := q.QueryRange(context.Background(), param, nil)
+ _, errByName, err := q.QueryRange(context.Background(), param, nil)
if err != nil {
t.Errorf("expected no error, got %s", err)
}
@@ -688,7 +688,7 @@ func TestQueryRangeValueType(t *testing.T) {
}
for i, param := range params {
- _, err, errByName := q.QueryRange(context.Background(), param, nil)
+ _, errByName, err := q.QueryRange(context.Background(), param, nil)
if err != nil {
t.Errorf("expected no error, got %s", err)
}
@@ -741,7 +741,7 @@ func TestQueryRangeTimeShift(t *testing.T) {
expectedTimeRangeInQueryString := fmt.Sprintf("timestamp >= %d AND timestamp <= %d", (1675115596722-86400*1000)*1000000, ((1675115596722+120*60*1000)-86400*1000)*1000000)
for i, param := range params {
- _, err, errByName := q.QueryRange(context.Background(), param, nil)
+ _, errByName, err := q.QueryRange(context.Background(), param, nil)
if err != nil {
t.Errorf("expected no error, got %s", err)
}
@@ -839,7 +839,7 @@ func TestQueryRangeTimeShiftWithCache(t *testing.T) {
}
for i, param := range params {
- _, err, errByName := q.QueryRange(context.Background(), param, nil)
+ _, errByName, err := q.QueryRange(context.Background(), param, nil)
if err != nil {
t.Errorf("expected no error, got %s", err)
}
@@ -939,7 +939,7 @@ func TestQueryRangeTimeShiftWithLimitAndCache(t *testing.T) {
}
for i, param := range params {
- _, err, errByName := q.QueryRange(context.Background(), param, nil)
+ _, errByName, err := q.QueryRange(context.Background(), param, nil)
if err != nil {
t.Errorf("expected no error, got %s", err)
}
diff --git a/pkg/query-service/app/querier/v2/helper.go b/pkg/query-service/app/querier/v2/helper.go
index cc4e83b702..04f798ad1b 100644
--- a/pkg/query-service/app/querier/v2/helper.go
+++ b/pkg/query-service/app/querier/v2/helper.go
@@ -123,7 +123,7 @@ func (q *querier) runBuilderQuery(
cachedData = data
}
}
- misses := q.findMissingTimeRanges(start, end, params.Step, cachedData)
+ misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData)
missedSeries := make([]*v3.Series, 0)
cachedSeries := make([]*v3.Series, 0)
for _, miss := range misses {
@@ -257,7 +257,7 @@ func (q *querier) runBuilderQuery(
cachedData = data
}
}
- misses := q.findMissingTimeRanges(start, end, params.Step, cachedData)
+ misses := q.findMissingTimeRanges(start, end, builderQuery.StepInterval, cachedData)
missedSeries := make([]*v3.Series, 0)
cachedSeries := make([]*v3.Series, 0)
for _, miss := range misses {
@@ -322,93 +322,3 @@ func (q *querier) runBuilderQuery(
}
}
}
-
-func (q *querier) runBuilderExpression(
- ctx context.Context,
- builderQuery *v3.BuilderQuery,
- params *v3.QueryRangeParamsV3,
- keys map[string]v3.AttributeKey,
- cacheKeys map[string]string,
- ch chan channelResult,
- wg *sync.WaitGroup,
-) {
- defer wg.Done()
-
- queryName := builderQuery.QueryName
-
- queries, err := q.builder.PrepareQueries(params, keys)
- if err != nil {
- ch <- channelResult{Err: err, Name: queryName, Query: "", Series: nil}
- return
- }
-
- if _, ok := cacheKeys[queryName]; !ok {
- query := queries[queryName]
- series, err := q.execClickHouseQuery(ctx, query)
- ch <- channelResult{Err: err, Name: queryName, Query: query, Series: series}
- return
- }
-
- cacheKey := cacheKeys[queryName]
- var cachedData []byte
- if !params.NoCache && q.cache != nil {
- var retrieveStatus status.RetrieveStatus
- data, retrieveStatus, err := q.cache.Retrieve(cacheKey, true)
- zap.L().Info("cache retrieve status", zap.String("status", retrieveStatus.String()))
- if err == nil {
- cachedData = data
- }
- }
- misses := q.findMissingTimeRanges(params.Start, params.End, params.Step, cachedData)
- missedSeries := make([]*v3.Series, 0)
- cachedSeries := make([]*v3.Series, 0)
- for _, miss := range misses {
- missQueries, _ := q.builder.PrepareQueries(&v3.QueryRangeParamsV3{
- Start: miss.start,
- End: miss.end,
- Step: params.Step,
- NoCache: params.NoCache,
- CompositeQuery: params.CompositeQuery,
- Variables: params.Variables,
- }, keys)
- query := missQueries[queryName]
- series, err := q.execClickHouseQuery(ctx, query)
- if err != nil {
- ch <- channelResult{Err: err, Name: queryName, Query: query, Series: nil}
- return
- }
- missedSeries = append(missedSeries, series...)
- }
- if err := json.Unmarshal(cachedData, &cachedSeries); err != nil && cachedData != nil {
- zap.L().Error("error unmarshalling cached data", zap.Error(err))
- }
- mergedSeries := mergeSerieses(cachedSeries, missedSeries)
-
- var mergedSeriesData []byte
- missedSeriesLen := len(missedSeries)
- var marshallingErr error
- if missedSeriesLen > 0 && !params.NoCache && q.cache != nil {
- // caching the data
- mergedSeriesData, marshallingErr = json.Marshal(mergedSeries)
- if marshallingErr != nil {
- zap.S().Error("error marshalling merged series", zap.Error(marshallingErr))
- }
- }
-
- // response doesn't need everything
- filterCachedPoints(mergedSeries, params.Start, params.End)
-
- ch <- channelResult{
- Err: nil,
- Name: queryName,
- Series: mergedSeries,
- }
- // Cache the seriesList for future queries
- if len(missedSeries) > 0 && !params.NoCache && q.cache != nil && marshallingErr == nil {
- err = q.cache.Store(cacheKey, mergedSeriesData, time.Hour)
- if err != nil {
- zap.L().Error("error storing merged series", zap.Error(err))
- return
- }
- }
-}
diff --git a/pkg/query-service/app/querier/v2/querier.go b/pkg/query-service/app/querier/v2/querier.go
index 6754c03ddc..e6915ef078 100644
--- a/pkg/query-service/app/querier/v2/querier.go
+++ b/pkg/query-service/app/querier/v2/querier.go
@@ -282,7 +282,7 @@ func mergeSerieses(cachedSeries, missedSeries []*v3.Series) []*v3.Series {
return mergedSeries
}
-func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) {
cacheKeys := q.keyGenerator.GenerateKeys(params)
@@ -320,10 +320,10 @@ func (q *querier) runBuilderQueries(ctx context.Context, params *v3.QueryRangePa
err = fmt.Errorf("error in builder queries")
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
-func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) {
channelResults := make(chan channelResult, len(params.CompositeQuery.PromQueries))
var wg sync.WaitGroup
cacheKeys := q.keyGenerator.GenerateKeys(params)
@@ -404,10 +404,10 @@ func (q *querier) runPromQueries(ctx context.Context, params *v3.QueryRangeParam
err = fmt.Errorf("error in prom queries")
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
-func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRangeParamsV3) ([]*v3.Result, map[string]error, error) {
channelResults := make(chan channelResult, len(params.CompositeQuery.ClickHouseQueries))
var wg sync.WaitGroup
for queryName, clickHouseQuery := range params.CompositeQuery.ClickHouseQueries {
@@ -444,15 +444,15 @@ func (q *querier) runClickHouseQueries(ctx context.Context, params *v3.QueryRang
if len(errs) > 0 {
err = fmt.Errorf("error in clickhouse queries")
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
-func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) {
+func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) {
queries, err := q.builder.PrepareQueries(params, keys)
if err != nil {
- return nil, err, nil
+ return nil, nil, err
}
ch := make(chan channelResult, len(queries))
@@ -491,12 +491,12 @@ func (q *querier) runBuilderListQueries(ctx context.Context, params *v3.QueryRan
})
}
if len(errs) != 0 {
- return nil, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...)), errQuriesByName
+ return nil, errQuriesByName, fmt.Errorf("encountered multiple errors: %s", multierr.Combine(errs...))
}
return res, nil, nil
}
-func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error) {
+func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3, keys map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error) {
var results []*v3.Result
var err error
var errQueriesByName map[string]error
@@ -504,9 +504,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3,
switch params.CompositeQuery.QueryType {
case v3.QueryTypeBuilder:
if params.CompositeQuery.PanelType == v3.PanelTypeList || params.CompositeQuery.PanelType == v3.PanelTypeTrace {
- results, err, errQueriesByName = q.runBuilderListQueries(ctx, params, keys)
+ results, errQueriesByName, err = q.runBuilderListQueries(ctx, params, keys)
} else {
- results, err, errQueriesByName = q.runBuilderQueries(ctx, params, keys)
+ results, errQueriesByName, err = q.runBuilderQueries(ctx, params, keys)
}
// in builder query, the only errors we expose are the ones that exceed the resource limits
// everything else is internal error as they are not actionable by the user
@@ -516,9 +516,9 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3,
}
}
case v3.QueryTypePromQL:
- results, err, errQueriesByName = q.runPromQueries(ctx, params)
+ results, errQueriesByName, err = q.runPromQueries(ctx, params)
case v3.QueryTypeClickHouseSQL:
- results, err, errQueriesByName = q.runClickHouseQueries(ctx, params)
+ results, errQueriesByName, err = q.runClickHouseQueries(ctx, params)
default:
err = fmt.Errorf("invalid query type")
}
@@ -533,7 +533,7 @@ func (q *querier) QueryRange(ctx context.Context, params *v3.QueryRangeParamsV3,
}
}
- return results, err, errQueriesByName
+ return results, errQueriesByName, err
}
func (q *querier) QueriesExecuted() []string {
diff --git a/pkg/query-service/app/server.go b/pkg/query-service/app/server.go
index 773cd7218d..92b879fcc9 100644
--- a/pkg/query-service/app/server.go
+++ b/pkg/query-service/app/server.go
@@ -27,6 +27,7 @@ import (
"go.signoz.io/signoz/pkg/query-service/app/logparsingpipeline"
"go.signoz.io/signoz/pkg/query-service/app/opamp"
opAmpModel "go.signoz.io/signoz/pkg/query-service/app/opamp/model"
+ "go.signoz.io/signoz/pkg/query-service/common"
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
"go.signoz.io/signoz/pkg/query-service/app/explorer"
@@ -66,12 +67,8 @@ type ServerOptions struct {
// Server runs HTTP, Mux and a grpc server
type Server struct {
- // logger *zap.Logger
- // tracer opentracing.Tracer // TODO make part of flags.Service
serverOptions *ServerOptions
- conn net.Listener
ruleManager *rules.Manager
- separatePorts bool
// public http router
httpConn net.Listener
@@ -128,7 +125,7 @@ func NewServer(serverOptions *ServerOptions) (*Server, error) {
go clickhouseReader.Start(readerReady)
reader = clickhouseReader
} else {
- return nil, fmt.Errorf("Storage type: %s is not supported in query service", storage)
+ return nil, fmt.Errorf("storage type: %s is not supported in query service", storage)
}
skipConfig := &model.SkipConfig{}
if serverOptions.SkipTopLvlOpsPath != "" {
@@ -303,7 +300,7 @@ func loggingMiddleware(next http.Handler) http.Handler {
path, _ := route.GetPathTemplate()
startTime := time.Now()
next.ServeHTTP(w, r)
- zap.L().Info(path+"\ttimeTaken:"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path))
+ zap.L().Info(path, zap.Duration("timeTaken", time.Since(startTime)), zap.String("path", path))
})
}
@@ -361,7 +358,7 @@ func LogCommentEnricher(next http.Handler) http.Handler {
"servicesTab": tab,
}
- r = r.WithContext(context.WithValue(r.Context(), "log_comment", kvs))
+ r = r.WithContext(context.WithValue(r.Context(), common.LogCommentKey, kvs))
next.ServeHTTP(w, r)
})
}
@@ -374,7 +371,7 @@ func loggingMiddlewarePrivate(next http.Handler) http.Handler {
path, _ := route.GetPathTemplate()
startTime := time.Now()
next.ServeHTTP(w, r)
- zap.L().Info(path+"\tprivatePort: true \ttimeTaken"+time.Now().Sub(startTime).String(), zap.Duration("timeTaken", time.Now().Sub(startTime)), zap.String("path", path), zap.Bool("tprivatePort", true))
+ zap.L().Info(path, zap.Duration("timeTaken", time.Since(startTime)), zap.String("path", path), zap.Bool("privatePort", true))
})
}
diff --git a/pkg/query-service/auth/auth.go b/pkg/query-service/auth/auth.go
index f0d220df81..6041b3c1af 100644
--- a/pkg/query-service/auth/auth.go
+++ b/pkg/query-service/auth/auth.go
@@ -22,13 +22,18 @@ import (
"golang.org/x/crypto/bcrypt"
)
+type JwtContextKeyType string
+
+const AccessJwtKey JwtContextKeyType = "accessJwt"
+const RefreshJwtKey JwtContextKeyType = "refreshJwt"
+
const (
opaqueTokenSize = 16
minimumPasswordLength = 8
)
var (
- ErrorInvalidCreds = fmt.Errorf("Invalid credentials")
+ ErrorInvalidCreds = fmt.Errorf("invalid credentials")
)
type InviteEmailData struct {
@@ -129,7 +134,6 @@ func inviteEmail(req *model.InviteRequest, au *model.UserPayload, token string)
zap.L().Error("failed to send email", zap.Error(err))
return
}
- return
}
// RevokeInvite is used to revoke the invitation for the given email.
@@ -488,10 +492,7 @@ func PasswordHash(pass string) (string, error) {
// Checks if the given password results in the given hash.
func passwordMatch(hash, password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
- if err != nil {
- return false
- }
- return true
+ return err == nil
}
func GenerateJWTForUser(user *model.User) (model.UserJwtObject, error) {
diff --git a/pkg/query-service/auth/jwt.go b/pkg/query-service/auth/jwt.go
index b27d43fb9d..7fe70e2c71 100644
--- a/pkg/query-service/auth/jwt.go
+++ b/pkg/query-service/auth/jwt.go
@@ -64,11 +64,11 @@ func AttachJwtToContext(ctx context.Context, r *http.Request) context.Context {
return ctx
}
- return context.WithValue(ctx, "accessJwt", token)
+ return context.WithValue(ctx, AccessJwtKey, token)
}
func ExtractJwtFromContext(ctx context.Context) (string, bool) {
- jwtToken, ok := ctx.Value("accessJwt").(string)
+ jwtToken, ok := ctx.Value(AccessJwtKey).(string)
return jwtToken, ok
}
diff --git a/pkg/query-service/auth/utils.go b/pkg/query-service/auth/utils.go
index a6a639c710..8157bf3f07 100644
--- a/pkg/query-service/auth/utils.go
+++ b/pkg/query-service/auth/utils.go
@@ -19,8 +19,6 @@ func isValidRole(role string) bool {
switch role {
case constants.AdminGroup, constants.EditorGroup, constants.ViewerGroup:
return true
- default:
- return false
}
return false
}
diff --git a/pkg/query-service/collectorsimulator/collectorsimulator.go b/pkg/query-service/collectorsimulator/collectorsimulator.go
index e45c2d168a..cf9e6cbafd 100644
--- a/pkg/query-service/collectorsimulator/collectorsimulator.go
+++ b/pkg/query-service/collectorsimulator/collectorsimulator.go
@@ -119,12 +119,12 @@ func NewCollectorSimulator(
return nil, cleanupFn, model.InternalError(errors.Wrap(err, "could not close tmp simulation config file"))
}
- fp := fileprovider.New()
+ fp := fileprovider.NewFactory()
confProvider, err := otelcol.NewConfigProvider(otelcol.ConfigProviderSettings{
ResolverSettings: confmap.ResolverSettings{
- URIs: []string{simulationConfigPath},
- Providers: map[string]confmap.Provider{fp.Scheme(): fp},
- Converters: []confmap.Converter{expandconverter.New()},
+ URIs: []string{simulationConfigPath},
+ ProviderFactories: []confmap.ProviderFactory{fp},
+ ConverterFactories: []confmap.ConverterFactory{expandconverter.NewFactory()},
},
})
if err != nil {
diff --git a/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go b/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go
index 7752693060..6bcc3a1226 100644
--- a/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go
+++ b/pkg/query-service/collectorsimulator/inmemoryexporter/factory.go
@@ -28,7 +28,7 @@ func createLogsExporter(
func NewFactory() exporter.Factory {
return exporter.NewFactory(
- "memory",
+ component.MustNewType("memory"),
createDefaultConfig,
exporter.WithLogs(createLogsExporter, component.StabilityLevelBeta))
}
diff --git a/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go b/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go
index 9db222cc43..584fbb28fb 100644
--- a/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go
+++ b/pkg/query-service/collectorsimulator/inmemoryreceiver/factory.go
@@ -35,7 +35,7 @@ func createLogsReceiver(
// NewFactory creates a new OTLP receiver factory.
func NewFactory() receiver.Factory {
return receiver.NewFactory(
- "memory",
+ component.MustNewType("memory"),
createDefaultConfig,
receiver.WithLogs(createLogsReceiver, component.StabilityLevelBeta))
}
diff --git a/pkg/query-service/collectorsimulator/logs.go b/pkg/query-service/collectorsimulator/logs.go
index dc84e6fe56..d1b4f01abb 100644
--- a/pkg/query-service/collectorsimulator/logs.go
+++ b/pkg/query-service/collectorsimulator/logs.go
@@ -3,6 +3,7 @@ package collectorsimulator
import (
"context"
"fmt"
+ "strings"
"time"
"github.com/pkg/errors"
@@ -68,7 +69,15 @@ func SimulateLogsProcessing(
)
}
- return result, simulationErrs, nil
+ for _, log := range simulationErrs {
+ // if log is empty or log comes from featuregate.go, then remove it
+ if log == "" || strings.Contains(log, "featuregate.go") {
+ continue
+ }
+ collectorErrs = append(collectorErrs, log)
+ }
+
+ return result, collectorErrs, nil
}
func SendLogsToSimulator(
diff --git a/pkg/query-service/common/ctx.go b/pkg/query-service/common/ctx.go
new file mode 100644
index 0000000000..e1599508da
--- /dev/null
+++ b/pkg/query-service/common/ctx.go
@@ -0,0 +1,5 @@
+package common
+
+type LogCommentContextKeyType string
+
+const LogCommentKey LogCommentContextKeyType = "logComment"
diff --git a/pkg/query-service/common/metrics.go b/pkg/query-service/common/query_range.go
similarity index 56%
rename from pkg/query-service/common/metrics.go
rename to pkg/query-service/common/query_range.go
index 3a14e06439..c119f2d25e 100644
--- a/pkg/query-service/common/metrics.go
+++ b/pkg/query-service/common/query_range.go
@@ -8,13 +8,16 @@ import (
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)
-func AdjustedMetricTimeRange(start, end, step int64, aggregaOperator v3.TimeAggregation) (int64, int64) {
+func AdjustedMetricTimeRange(start, end, step int64, mq v3.BuilderQuery) (int64, int64) {
+ // align the start to the step interval
start = start - (start % (step * 1000))
// if the query is a rate query, we adjust the start time by one more step
// so that we can calculate the rate for the first data point
- if aggregaOperator.IsRateOperator() {
+ if (mq.AggregateOperator.IsRateOperator() || mq.TimeAggregation.IsRateOperator()) &&
+ mq.Temporality != v3.Delta {
start -= step * 1000
}
+ // align the end to the nearest minute
adjustStep := int64(math.Min(float64(step), 60))
end = end - (end % (adjustStep * 1000))
return start, end
@@ -28,6 +31,32 @@ func PastDayRoundOff() int64 {
// start and end are in milliseconds
func MinAllowedStepInterval(start, end int64) int64 {
step := (end - start) / constants.MaxAllowedPointsInTimeSeries / 1000
+ if step < 60 {
+ return step
+ }
// return the nearest lower multiple of 60
return step - step%60
}
+
+func GCD(a, b int64) int64 {
+ for b != 0 {
+ a, b = b, a%b
+ }
+ return a
+}
+
+func LCM(a, b int64) int64 {
+ return (a * b) / GCD(a, b)
+}
+
+// LCMList computes the LCM of a list of int64 numbers.
+func LCMList(nums []int64) int64 {
+ if len(nums) == 0 {
+ return 1
+ }
+ result := nums[0]
+ for _, num := range nums[1:] {
+ result = LCM(result, num)
+ }
+ return result
+}
diff --git a/pkg/query-service/dao/sqlite/connection.go b/pkg/query-service/dao/sqlite/connection.go
index a2545e9531..d7e5ad5de9 100644
--- a/pkg/query-service/dao/sqlite/connection.go
+++ b/pkg/query-service/dao/sqlite/connection.go
@@ -90,7 +90,7 @@ func InitDB(dataSourceName string) (*ModelDaoSqlite, error) {
_, err = db.Exec(table_schema)
if err != nil {
- return nil, fmt.Errorf("Error in creating tables: %v", err.Error())
+ return nil, fmt.Errorf("error in creating tables: %v", err.Error())
}
mds := &ModelDaoSqlite{db: db}
diff --git a/pkg/query-service/integrations/alertManager/notifier.go b/pkg/query-service/integrations/alertManager/notifier.go
index e86cf28c5e..e29879f10a 100644
--- a/pkg/query-service/integrations/alertManager/notifier.go
+++ b/pkg/query-service/integrations/alertManager/notifier.go
@@ -14,7 +14,7 @@ import (
old_ctx "golang.org/x/net/context"
- "github.com/go-kit/kit/log"
+ "github.com/go-kit/log"
"github.com/go-kit/log/level"
"go.uber.org/zap"
diff --git a/pkg/query-service/interfaces/interface.go b/pkg/query-service/interfaces/interface.go
index a0631eb70a..9a5e33e5ff 100644
--- a/pkg/query-service/interfaces/interface.go
+++ b/pkg/query-service/interfaces/interface.go
@@ -107,7 +107,7 @@ type Reader interface {
}
type Querier interface {
- QueryRange(context.Context, *v3.QueryRangeParamsV3, map[string]v3.AttributeKey) ([]*v3.Result, error, map[string]error)
+ QueryRange(context.Context, *v3.QueryRangeParamsV3, map[string]v3.AttributeKey) ([]*v3.Result, map[string]error, error)
// test helpers
QueriesExecuted() []string
diff --git a/pkg/query-service/migrate/0_47_alerts_custom_step/run.go b/pkg/query-service/migrate/0_47_alerts_custom_step/run.go
new file mode 100644
index 0000000000..b25705aaf2
--- /dev/null
+++ b/pkg/query-service/migrate/0_47_alerts_custom_step/run.go
@@ -0,0 +1,70 @@
+package alertscustomstep
+
+import (
+ "context"
+ "encoding/json"
+ "time"
+
+ "github.com/jmoiron/sqlx"
+ v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
+ "go.signoz.io/signoz/pkg/query-service/rules"
+ "go.uber.org/multierr"
+ "go.uber.org/zap"
+)
+
+var Version = "0.47-alerts-custom-step"
+
+func Migrate(conn *sqlx.DB) error {
+ ruleDB := rules.NewRuleDB(conn)
+ storedRules, err := ruleDB.GetStoredRules(context.Background())
+ if err != nil {
+ return err
+ }
+
+ for _, storedRule := range storedRules {
+ parsedRule, errs := rules.ParsePostableRule([]byte(storedRule.Data))
+ if len(errs) > 0 {
+ // this should not happen but if it does, we should not stop the migration
+ zap.L().Error("Error parsing rule", zap.Error(multierr.Combine(errs...)), zap.Int("rule", storedRule.Id))
+ continue
+ }
+ zap.L().Info("Rule parsed", zap.Int("rule", storedRule.Id))
+ updated := false
+ if parsedRule.RuleCondition != nil {
+ if parsedRule.RuleCondition.QueryType() == v3.QueryTypeBuilder {
+ if parsedRule.EvalWindow <= rules.Duration(6*time.Hour) {
+ for _, query := range parsedRule.RuleCondition.CompositeQuery.BuilderQueries {
+ if query.StepInterval > 60 {
+ updated = true
+ zap.L().Info("Updating step interval", zap.Int("rule", storedRule.Id), zap.Int64("old", query.StepInterval), zap.Int64("new", 60))
+ query.StepInterval = 60
+ }
+ }
+ }
+ }
+ }
+
+ if !updated {
+ zap.L().Info("Rule not updated", zap.Int("rule", storedRule.Id))
+ continue
+ }
+
+ ruleJSON, jsonErr := json.Marshal(parsedRule)
+ if jsonErr != nil {
+ zap.L().Error("Error marshalling rule; skipping rule migration", zap.Error(jsonErr), zap.Int("rule", storedRule.Id))
+ continue
+ }
+
+ stmt, prepareError := conn.PrepareContext(context.Background(), `UPDATE rules SET data=$3 WHERE id=$4;`)
+ if prepareError != nil {
+ zap.L().Error("Error in preparing statement for UPDATE to rules", zap.Error(prepareError))
+ continue
+ }
+ defer stmt.Close()
+
+ if _, err := stmt.Exec(ruleJSON, storedRule.Id); err != nil {
+ zap.L().Error("Error in Executing prepared statement for UPDATE to rules", zap.Error(err))
+ }
+ }
+ return nil
+}
diff --git a/pkg/query-service/migrate/migate.go b/pkg/query-service/migrate/migate.go
index f9d15a1567..4fe61764bc 100644
--- a/pkg/query-service/migrate/migate.go
+++ b/pkg/query-service/migrate/migate.go
@@ -5,6 +5,7 @@ import (
"github.com/jmoiron/sqlx"
alertstov4 "go.signoz.io/signoz/pkg/query-service/migrate/0_45_alerts_to_v4"
+ alertscustomstep "go.signoz.io/signoz/pkg/query-service/migrate/0_47_alerts_custom_step"
"go.uber.org/zap"
)
@@ -63,5 +64,16 @@ func Migrate(dsn string) error {
}
}
+ if m, err := getMigrationVersion(conn, "0.47_alerts_custom_step"); err == nil && m == nil {
+ if err := alertscustomstep.Migrate(conn); err != nil {
+ zap.L().Error("failed to migrate 0.47_alerts_custom_step", zap.Error(err))
+ } else {
+ _, err := conn.Exec("INSERT INTO data_migrations (version, succeeded) VALUES ('0.47_alerts_custom_step', true)")
+ if err != nil {
+ return err
+ }
+ }
+ }
+
return nil
}
diff --git a/pkg/query-service/model/v3/v3.go b/pkg/query-service/model/v3/v3.go
index 731a1edcac..2a12c8e1fa 100644
--- a/pkg/query-service/model/v3/v3.go
+++ b/pkg/query-service/model/v3/v3.go
@@ -400,6 +400,7 @@ type CompositeQuery struct {
PanelType PanelType `json:"panelType"`
QueryType QueryType `json:"queryType"`
Unit string `json:"unit,omitempty"`
+ FillGaps bool `json:"fillGaps,omitempty"`
}
func (c *CompositeQuery) EnabledQueries() int {
@@ -427,6 +428,16 @@ func (c *CompositeQuery) EnabledQueries() int {
return count
}
+func (c *CompositeQuery) Sanitize() {
+ // remove groupBy for queries with list panel type
+ for _, query := range c.BuilderQueries {
+ if len(query.GroupBy) > 0 && c.PanelType == PanelTypeList {
+ query.GroupBy = []AttributeKey{}
+ }
+ }
+
+}
+
func (c *CompositeQuery) Validate() error {
if c == nil {
return fmt.Errorf("composite query is required")
@@ -746,9 +757,9 @@ func (b *BuilderQuery) Validate(panelType PanelType) error {
}
}
if b.GroupBy != nil {
- if len(b.GroupBy) > 0 && panelType == PanelTypeList {
- return fmt.Errorf("group by is not supported for list panel type")
- }
+ // if len(b.GroupBy) > 0 && panelType == PanelTypeList {
+ // return fmt.Errorf("group by is not supported for list panel type")
+ // }
for _, groupBy := range b.GroupBy {
if err := groupBy.Validate(); err != nil {
diff --git a/pkg/query-service/postprocess/gaps.go b/pkg/query-service/postprocess/gaps.go
new file mode 100644
index 0000000000..170d77844d
--- /dev/null
+++ b/pkg/query-service/postprocess/gaps.go
@@ -0,0 +1,70 @@
+package postprocess
+
+import (
+ "github.com/SigNoz/govaluate"
+ "go.signoz.io/signoz/pkg/query-service/common"
+ v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
+)
+
+func StepIntervalForFunction(params *v3.QueryRangeParamsV3, query string) int64 {
+ q := params.CompositeQuery.BuilderQueries[query]
+ if q.QueryName != q.Expression {
+ expression, _ := govaluate.NewEvaluableExpressionWithFunctions(q.Expression, EvalFuncs())
+ steps := []int64{}
+ for _, v := range expression.Vars() {
+ steps = append(steps, params.CompositeQuery.BuilderQueries[v].StepInterval)
+ }
+ return common.LCMList(steps)
+ }
+ return q.StepInterval
+}
+
+func fillGap(series *v3.Series, start, end, step int64) *v3.Series {
+ v := make(map[int64]float64)
+ for _, point := range series.Points {
+ v[point.Timestamp] = point.Value
+ }
+
+ // For all the values from start to end, find the timestamps
+ // that don't have value and add zero point
+ start = start - (start % (step * 1000))
+ for i := start; i <= end; i += step * 1000 {
+ if _, ok := v[i]; !ok {
+ v[i] = 0
+ }
+ }
+ newSeries := &v3.Series{
+ Labels: series.Labels,
+ LabelsArray: series.LabelsArray,
+ Points: make([]v3.Point, 0),
+ }
+ for i := start; i <= end; i += step * 1000 {
+ newSeries.Points = append(newSeries.Points, v3.Point{Timestamp: i, Value: v[i]})
+ }
+ return newSeries
+}
+
+// TODO(srikanthccv): can WITH FILL be perfect substitute for all cases https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier
+func FillGaps(results []*v3.Result, params *v3.QueryRangeParamsV3) {
+ for _, result := range results {
+ // A `result` item in `results` contains the query result for individual query.
+ // If there are no series in the result, we add empty series and `fillGap` adds all zeros
+ if len(result.Series) == 0 {
+ result.Series = []*v3.Series{
+ {
+ Labels: make(map[string]string),
+ LabelsArray: make([]map[string]string, 0),
+ },
+ }
+ }
+
+ builderQueries := params.CompositeQuery.BuilderQueries
+ if builderQueries != nil {
+ // The values should be added at the intervals of `step`
+ step := StepIntervalForFunction(params, result.QueryName)
+ for idx := range result.Series {
+ result.Series[idx] = fillGap(result.Series[idx], params.Start, params.End, step)
+ }
+ }
+ }
+}
diff --git a/pkg/query-service/postprocess/gaps_test.go b/pkg/query-service/postprocess/gaps_test.go
new file mode 100644
index 0000000000..999176a830
--- /dev/null
+++ b/pkg/query-service/postprocess/gaps_test.go
@@ -0,0 +1,166 @@
+package postprocess
+
+import (
+ "testing"
+
+ v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
+)
+
+func TestFillGaps(t *testing.T) {
+ // Helper function to create a sample series
+ createSeries := func(points []v3.Point) *v3.Series {
+ return &v3.Series{
+ Points: points,
+ }
+ }
+
+ // Helper function to create a sample result
+ createResult := func(queryName string, series []*v3.Series) *v3.Result {
+ return &v3.Result{
+ QueryName: queryName,
+ Series: series,
+ }
+ }
+
+ // Define test cases
+ tests := []struct {
+ name string
+ results []*v3.Result
+ params *v3.QueryRangeParamsV3
+ expected []*v3.Result
+ }{
+ {
+ name: "Single series with gaps",
+ results: []*v3.Result{
+ createResult("query1", []*v3.Series{
+ createSeries([]v3.Point{
+ {Timestamp: 1000, Value: 1.0},
+ {Timestamp: 3000, Value: 3.0},
+ }),
+ }),
+ },
+ params: &v3.QueryRangeParamsV3{
+ Start: 1000,
+ End: 5000,
+ CompositeQuery: &v3.CompositeQuery{
+ BuilderQueries: map[string]*v3.BuilderQuery{
+ "query1": {
+ QueryName: "query1",
+ Expression: "query1",
+ StepInterval: 1,
+ },
+ },
+ },
+ },
+ expected: []*v3.Result{
+ createResult("query1", []*v3.Series{
+ createSeries([]v3.Point{
+ {Timestamp: 1000, Value: 1.0},
+ {Timestamp: 2000, Value: 0.0},
+ {Timestamp: 3000, Value: 3.0},
+ {Timestamp: 4000, Value: 0.0},
+ {Timestamp: 5000, Value: 0.0},
+ }),
+ }),
+ },
+ },
+ {
+ name: "Multiple series with gaps",
+ results: []*v3.Result{
+ createResult("query1", []*v3.Series{
+ createSeries([]v3.Point{
+ {Timestamp: 1000, Value: 1.0},
+ {Timestamp: 3000, Value: 3.0},
+ }),
+ createSeries([]v3.Point{
+ {Timestamp: 2000, Value: 2.0},
+ {Timestamp: 4000, Value: 4.0},
+ }),
+ }),
+ },
+ params: &v3.QueryRangeParamsV3{
+ Start: 1000,
+ End: 5000,
+ CompositeQuery: &v3.CompositeQuery{
+ BuilderQueries: map[string]*v3.BuilderQuery{
+ "query1": {
+ QueryName: "query1",
+ Expression: "query1",
+ StepInterval: 1,
+ },
+ },
+ },
+ },
+ expected: []*v3.Result{
+ createResult("query1", []*v3.Series{
+ createSeries([]v3.Point{
+ {Timestamp: 1000, Value: 1.0},
+ {Timestamp: 2000, Value: 0.0},
+ {Timestamp: 3000, Value: 3.0},
+ {Timestamp: 4000, Value: 0.0},
+ {Timestamp: 5000, Value: 0.0},
+ }),
+ createSeries([]v3.Point{
+ {Timestamp: 1000, Value: 0.0},
+ {Timestamp: 2000, Value: 2.0},
+ {Timestamp: 3000, Value: 0.0},
+ {Timestamp: 4000, Value: 4.0},
+ {Timestamp: 5000, Value: 0.0},
+ }),
+ }),
+ },
+ },
+ {
+ name: "Single series with no data",
+ results: []*v3.Result{
+ createResult("query1", []*v3.Series{
+ createSeries([]v3.Point{}),
+ }),
+ },
+ params: &v3.QueryRangeParamsV3{
+ Start: 1000,
+ End: 5000,
+ CompositeQuery: &v3.CompositeQuery{
+ BuilderQueries: map[string]*v3.BuilderQuery{
+ "query1": {
+ QueryName: "query1",
+ Expression: "query1",
+ StepInterval: 1,
+ },
+ },
+ },
+ },
+ expected: []*v3.Result{
+ createResult("query1", []*v3.Series{
+ createSeries([]v3.Point{
+ {Timestamp: 1000, Value: 0.0},
+ {Timestamp: 2000, Value: 0.0},
+ {Timestamp: 3000, Value: 0.0},
+ {Timestamp: 4000, Value: 0.0},
+ {Timestamp: 5000, Value: 0.0},
+ }),
+ }),
+ },
+ },
+ }
+
+ // Execute test cases
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ FillGaps(tt.results, tt.params)
+ for i, result := range tt.results {
+ for j, series := range result.Series {
+ for k, point := range series.Points {
+ if point.Timestamp != tt.expected[i].Series[j].Points[k].Timestamp ||
+ point.Value != tt.expected[i].Series[j].Points[k].Value {
+ t.Errorf("Test %s failed: expected (%v, %v), got (%v, %v)", tt.name,
+ tt.expected[i].Series[j].Points[k].Timestamp,
+ tt.expected[i].Series[j].Points[k].Value,
+ point.Timestamp, point.Value)
+ }
+ }
+ }
+ }
+ })
+ }
+}
diff --git a/pkg/query-service/postprocess/having.go b/pkg/query-service/postprocess/having.go
index a37ba70379..5c2be7ce8b 100644
--- a/pkg/query-service/postprocess/having.go
+++ b/pkg/query-service/postprocess/having.go
@@ -6,14 +6,17 @@ import (
v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
)
-// applyHavingClause applies the having clause to the result
+// ApplyHavingClause applies the having clause to the result
// each query has its own having clause
// there can be multiple having clauses for each query
-func applyHavingClause(result []*v3.Result, queryRangeParams *v3.QueryRangeParamsV3) {
+func ApplyHavingClause(result []*v3.Result, queryRangeParams *v3.QueryRangeParamsV3) {
for _, result := range result {
builderQueries := queryRangeParams.CompositeQuery.BuilderQueries
- if builderQueries != nil && (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics) {
+ // apply having clause for metrics and formula
+ if builderQueries != nil &&
+ (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics ||
+ builderQueries[result.QueryName].QueryName != builderQueries[result.QueryName].Expression) {
havingClause := builderQueries[result.QueryName].Having
for i := 0; i < len(result.Series); i++ {
@@ -37,46 +40,38 @@ func evaluateHavingClause(having []v3.Having, value float64) bool {
return true
}
+ satisfied := true
+
for _, h := range having {
switch h.Operator {
case v3.HavingOperatorEqual:
- if value == h.Value.(float64) {
- return true
+ if value != h.Value.(float64) {
+ satisfied = false
}
case v3.HavingOperatorNotEqual:
- if value != h.Value.(float64) {
- return true
+ if value == h.Value.(float64) {
+ satisfied = false
}
case v3.HavingOperatorGreaterThan:
- if value > h.Value.(float64) {
- return true
+ if value <= h.Value.(float64) {
+ satisfied = false
}
case v3.HavingOperatorGreaterThanOrEq:
- if value >= h.Value.(float64) {
- return true
+ if value < h.Value.(float64) {
+ satisfied = false
}
case v3.HavingOperatorLessThan:
- if value < h.Value.(float64) {
- return true
+ if value >= h.Value.(float64) {
+ satisfied = false
}
case v3.HavingOperatorLessThanOrEq:
- if value <= h.Value.(float64) {
- return true
+ if value > h.Value.(float64) {
+ satisfied = false
}
case v3.HavingOperatorIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorIn))):
values, ok := h.Value.([]interface{})
if !ok {
- return false
- }
- for _, v := range values {
- if value == v.(float64) {
- return true
- }
- }
- case v3.HavingOperatorNotIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorNotIn))):
- values, ok := h.Value.([]interface{})
- if !ok {
- return true
+ satisfied = false
}
found := false
for _, v := range values {
@@ -86,9 +81,24 @@ func evaluateHavingClause(having []v3.Having, value float64) bool {
}
}
if !found {
- return true
+ satisfied = false
+ }
+ case v3.HavingOperatorNotIn, v3.HavingOperator(strings.ToLower(string(v3.HavingOperatorNotIn))):
+ values, ok := h.Value.([]interface{})
+ if !ok {
+ satisfied = false
+ }
+ found := false
+ for _, v := range values {
+ if value == v.(float64) {
+ found = true
+ break
+ }
+ }
+ if found {
+ satisfied = false
}
}
}
- return false
+ return satisfied
}
diff --git a/pkg/query-service/postprocess/having_test.go b/pkg/query-service/postprocess/having_test.go
index e7e37095fb..90986d14a9 100644
--- a/pkg/query-service/postprocess/having_test.go
+++ b/pkg/query-service/postprocess/having_test.go
@@ -248,22 +248,86 @@ func TestApplyHavingCaluse(t *testing.T) {
},
},
},
+ {
+ name: "test multiple having clause",
+ results: []*v3.Result{
+ {
+ QueryName: "A",
+ Series: []*v3.Series{
+ {
+ Points: []v3.Point{
+ {
+ Value: 0.5,
+ },
+ {
+ Value: 0.4,
+ },
+ {
+ Value: 0.3,
+ },
+ {
+ Value: 0.2,
+ },
+ {
+ Value: 0.1,
+ },
+ },
+ },
+ },
+ },
+ },
+ params: &v3.QueryRangeParamsV3{
+ CompositeQuery: &v3.CompositeQuery{
+ BuilderQueries: map[string]*v3.BuilderQuery{
+ "A": {
+ DataSource: v3.DataSourceMetrics,
+ Having: []v3.Having{
+ {
+ Operator: v3.HavingOperatorGreaterThanOrEq,
+ Value: 0.3,
+ },
+ {
+ Operator: v3.HavingOperatorLessThanOrEq,
+ Value: 0.4,
+ },
+ },
+ },
+ },
+ },
+ },
+ want: []*v3.Result{
+ {
+ Series: []*v3.Series{
+ {
+ Points: []v3.Point{
+ {
+ Value: 0.4,
+ },
+ {
+ Value: 0.3,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- applyHavingClause(tc.results, tc.params)
+ ApplyHavingClause(tc.results, tc.params)
got := tc.results
if len(got) != len(tc.want) {
- t.Errorf("got %v, want %v", got, tc.want)
+ t.Errorf("got %v, want %v", len(got), len(tc.want))
}
for i := range got {
if len(got[i].Series) != len(tc.want[i].Series) {
- t.Errorf("got %v, want %v", got, tc.want)
+ t.Errorf("got %v, want %v", len(got[i].Series), len(tc.want[i].Series))
}
for j := range got[i].Series {
@@ -273,7 +337,7 @@ func TestApplyHavingCaluse(t *testing.T) {
for k := range got[i].Series[j].Points {
if got[i].Series[j].Points[k].Value != tc.want[i].Series[j].Points[k].Value {
- t.Errorf("got %v, want %v", got, tc.want)
+ t.Errorf("got %v, want %v", got[i].Series[j].Points[k].Value, tc.want[i].Series[j].Points[k].Value)
}
}
}
diff --git a/pkg/query-service/postprocess/limit.go b/pkg/query-service/postprocess/limit.go
index 491c91da54..49cd5d04b9 100644
--- a/pkg/query-service/postprocess/limit.go
+++ b/pkg/query-service/postprocess/limit.go
@@ -17,7 +17,10 @@ func ApplyMetricLimit(results []*v3.Result, queryRangeParams *v3.QueryRangeParam
for _, result := range results {
builderQueries := queryRangeParams.CompositeQuery.BuilderQueries
- if builderQueries != nil && (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics) {
+ // apply limit for metrics and formula
+ if builderQueries != nil &&
+ (builderQueries[result.QueryName].DataSource == v3.DataSourceMetrics ||
+ builderQueries[result.QueryName].QueryName != builderQueries[result.QueryName].Expression) {
limit := builderQueries[result.QueryName].Limit
orderByList := builderQueries[result.QueryName].OrderBy
diff --git a/pkg/query-service/postprocess/query_range.go b/pkg/query-service/postprocess/process.go
similarity index 94%
rename from pkg/query-service/postprocess/query_range.go
rename to pkg/query-service/postprocess/process.go
index b6bd6461f3..fc35b404de 100644
--- a/pkg/query-service/postprocess/query_range.go
+++ b/pkg/query-service/postprocess/process.go
@@ -18,7 +18,7 @@ func PostProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam
// It's not included in the query because it doesn't work nicely with caching
// With this change, if you have a query with a having clause, and then you change the having clause
// to something else, the query will still be cached.
- applyHavingClause(result, queryRangeParams)
+ ApplyHavingClause(result, queryRangeParams)
// We apply the metric limit here because it's not part of the clickhouse query
// The limit in the context of the time series query is the number of time series
// So for the limit to work, we need to know what series to keep and what to discard
@@ -64,6 +64,8 @@ func PostProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam
return nil, err
}
formulaResult.QueryName = query.QueryName
+ ApplyHavingClause([]*v3.Result{formulaResult}, queryRangeParams)
+ ApplyMetricLimit([]*v3.Result{formulaResult}, queryRangeParams)
result = append(result, formulaResult)
}
}
@@ -81,6 +83,9 @@ func PostProcessResult(result []*v3.Result, queryRangeParams *v3.QueryRangeParam
if queryRangeParams.CompositeQuery.QueryType == v3.QueryTypeBuilder {
result = removeDisabledQueries(result)
}
+ if queryRangeParams.CompositeQuery.FillGaps {
+ FillGaps(result, queryRangeParams)
+ }
return result, nil
}
diff --git a/pkg/query-service/postprocess/process_test.go b/pkg/query-service/postprocess/process_test.go
new file mode 100644
index 0000000000..5f599f7be0
--- /dev/null
+++ b/pkg/query-service/postprocess/process_test.go
@@ -0,0 +1,222 @@
+package postprocess
+
+import (
+ "reflect"
+ "testing"
+
+ v3 "go.signoz.io/signoz/pkg/query-service/model/v3"
+)
+
+func TestPostProcessResult(t *testing.T) {
+ testCases := []struct {
+ name string
+ results []*v3.Result
+ queryRangeParams *v3.QueryRangeParamsV3
+ want []*v3.Result
+ }{
+ {
+ name: "test1",
+ results: []*v3.Result{
+ {
+ QueryName: "A",
+ Series: []*v3.Series{
+ {
+ Labels: map[string]string{
+ "service_name": "frontend",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 10,
+ },
+ {
+ Timestamp: 2,
+ Value: 20,
+ },
+ },
+ },
+ {
+ Labels: map[string]string{
+ "service_name": "redis",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 12,
+ },
+ {
+ Timestamp: 2,
+ Value: 45,
+ },
+ },
+ },
+ {
+ Labels: map[string]string{
+ "service_name": "route",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 2,
+ },
+ {
+ Timestamp: 2,
+ Value: 45,
+ },
+ },
+ },
+ },
+ },
+ {
+ QueryName: "B",
+ Series: []*v3.Series{
+ {
+ Labels: map[string]string{
+ "service_name": "redis",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 6,
+ },
+ {
+ Timestamp: 2,
+ Value: 9,
+ },
+ },
+ },
+ },
+ },
+ },
+ want: []*v3.Result{
+ {
+ QueryName: "A",
+ Series: []*v3.Series{
+ {
+ Labels: map[string]string{
+ "service_name": "redis",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 12,
+ },
+ {
+ Timestamp: 2,
+ Value: 45,
+ },
+ },
+ },
+ {
+ Labels: map[string]string{
+ "service_name": "route",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 2,
+ },
+ {
+ Timestamp: 2,
+ Value: 45,
+ },
+ },
+ },
+ {
+ Labels: map[string]string{
+ "service_name": "frontend",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 10,
+ },
+ {
+ Timestamp: 2,
+ Value: 20,
+ },
+ },
+ },
+ },
+ },
+ {
+ QueryName: "B",
+ Series: []*v3.Series{
+ {
+ Labels: map[string]string{
+ "service_name": "redis",
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 6,
+ },
+ {
+ Timestamp: 2,
+ Value: 9,
+ },
+ },
+ },
+ },
+ },
+ {
+ QueryName: "F1",
+ Series: []*v3.Series{
+ {
+ Labels: map[string]string{
+ "service_name": "redis",
+ },
+ LabelsArray: []map[string]string{
+ {
+ "service_name": "redis",
+ },
+ },
+ Points: []v3.Point{
+ {
+ Timestamp: 1,
+ Value: 0.5,
+ },
+ {
+ Timestamp: 2,
+ Value: 0.2,
+ },
+ },
+ },
+ },
+ },
+ },
+ queryRangeParams: &v3.QueryRangeParamsV3{
+ CompositeQuery: &v3.CompositeQuery{
+ BuilderQueries: map[string]*v3.BuilderQuery{
+ "A": {
+ DataSource: v3.DataSourceMetrics,
+ QueryName: "A",
+ Expression: "A",
+ },
+ "B": {
+ DataSource: v3.DataSourceMetrics,
+ QueryName: "B",
+ Expression: "B",
+ },
+ "F1": {
+ Expression: "B/A",
+ QueryName: "F1",
+ Limit: 1,
+ },
+ },
+ },
+ },
+ },
+ }
+ for _, tt := range testCases {
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := PostProcessResult(tt.results, tt.queryRangeParams)
+ if err != nil {
+ t.Errorf("PostProcessResult() error = %v", err)
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("PostProcessResult() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/pkg/query-service/pqlEngine/engine.go b/pkg/query-service/pqlEngine/engine.go
index 99cd4ea6df..0ecb7fc766 100644
--- a/pkg/query-service/pqlEngine/engine.go
+++ b/pkg/query-service/pqlEngine/engine.go
@@ -8,7 +8,6 @@ import (
"github.com/go-kit/log"
pmodel "github.com/prometheus/common/model"
"github.com/prometheus/common/promlog"
- plog "github.com/prometheus/common/promlog"
pconfig "github.com/prometheus/prometheus/config"
pql "github.com/prometheus/prometheus/promql"
pstorage "github.com/prometheus/prometheus/storage"
@@ -40,7 +39,7 @@ func FromReader(ch interfaces.Reader) (*PqlEngine, error) {
func NewPqlEngine(config *pconfig.Config) (*PqlEngine, error) {
- logLevel := plog.AllowedLevel{}
+ logLevel := promlog.AllowedLevel{}
logLevel.Set("debug")
allowedFormat := promlog.AllowedFormat{}
@@ -51,7 +50,7 @@ func NewPqlEngine(config *pconfig.Config) (*PqlEngine, error) {
Format: &allowedFormat,
}
- logger := plog.New(&promlogConfig)
+ logger := promlog.New(&promlogConfig)
opts := pql.EngineOpts{
Logger: log.With(logger, "component", "promql evaluator"),
diff --git a/pkg/query-service/rules/promRuleTask.go b/pkg/query-service/rules/promRuleTask.go
index 57b7a58dc7..13c24ca1fa 100644
--- a/pkg/query-service/rules/promRuleTask.go
+++ b/pkg/query-service/rules/promRuleTask.go
@@ -10,6 +10,7 @@ import (
"github.com/go-kit/log"
opentracing "github.com/opentracing/opentracing-go"
plabels "github.com/prometheus/prometheus/model/labels"
+ "go.signoz.io/signoz/pkg/query-service/common"
"go.uber.org/zap"
)
@@ -364,7 +365,7 @@ func (g *PromRuleTask) Eval(ctx context.Context, ts time.Time) {
"source": "alerts",
"client": "query-service",
}
- ctx = context.WithValue(ctx, "log_comment", kvs)
+ ctx = context.WithValue(ctx, common.LogCommentKey, kvs)
_, err := rule.Eval(ctx, ts, g.opts.Queriers)
if err != nil {
diff --git a/pkg/query-service/rules/ruleTask.go b/pkg/query-service/rules/ruleTask.go
index 577bd453a5..eb657c9f7c 100644
--- a/pkg/query-service/rules/ruleTask.go
+++ b/pkg/query-service/rules/ruleTask.go
@@ -8,6 +8,7 @@ import (
"time"
opentracing "github.com/opentracing/opentracing-go"
+ "go.signoz.io/signoz/pkg/query-service/common"
"go.signoz.io/signoz/pkg/query-service/utils/labels"
"go.uber.org/zap"
)
@@ -345,7 +346,7 @@ func (g *RuleTask) Eval(ctx context.Context, ts time.Time) {
"source": "alerts",
"client": "query-service",
}
- ctx = context.WithValue(ctx, "log_comment", kvs)
+ ctx = context.WithValue(ctx, common.LogCommentKey, kvs)
_, err := rule.Eval(ctx, ts, g.opts.Queriers)
if err != nil {
diff --git a/pkg/query-service/rules/templates.go b/pkg/query-service/rules/templates.go
index 9cc49f787d..5f29621c68 100644
--- a/pkg/query-service/rules/templates.go
+++ b/pkg/query-service/rules/templates.go
@@ -14,6 +14,8 @@ import (
html_template "html/template"
text_template "text/template"
+ "golang.org/x/text/cases"
+
"go.signoz.io/signoz/pkg/query-service/utils/times"
)
@@ -96,7 +98,7 @@ func NewTemplateExpander(
return html_template.HTML(text)
},
"match": regexp.MatchString,
- "title": strings.Title,
+ "title": cases.Title,
"toUpper": strings.ToUpper,
"toLower": strings.ToLower,
"sortByLabel": func(label string, v tmplQueryResults) tmplQueryResults {
diff --git a/pkg/query-service/rules/thresholdRule.go b/pkg/query-service/rules/thresholdRule.go
index 0b8d080bd9..051476e6b8 100644
--- a/pkg/query-service/rules/thresholdRule.go
+++ b/pkg/query-service/rules/thresholdRule.go
@@ -427,7 +427,6 @@ func (r *ThresholdRule) prepareQueryRange(ts time.Time) *v3.QueryRangeParamsV3 {
// 60 seconds (SDK) + 10 seconds (batch) + rest for n/w + serialization + write to disk etc..
start := ts.Add(-time.Duration(r.evalWindow)).UnixMilli() - 2*60*1000
end := ts.UnixMilli() - 2*60*1000
-
// round to minute otherwise we could potentially miss data
start = start - (start % (60 * 1000))
end = end - (end % (60 * 1000))
@@ -478,10 +477,17 @@ func (r *ThresholdRule) prepareQueryRange(ts time.Time) *v3.QueryRangeParamsV3 {
if r.ruleCondition.CompositeQuery != nil && r.ruleCondition.CompositeQuery.BuilderQueries != nil {
for _, q := range r.ruleCondition.CompositeQuery.BuilderQueries {
- q.StepInterval = int64(math.Max(float64(common.MinAllowedStepInterval(start, end)), 60))
+ // If the step interval is less than the minimum allowed step interval, set it to the minimum allowed step interval
+ if minStep := common.MinAllowedStepInterval(start, end); q.StepInterval < minStep {
+ q.StepInterval = minStep
+ }
}
}
+ if r.ruleCondition.CompositeQuery.PanelType != v3.PanelTypeGraph {
+ r.ruleCondition.CompositeQuery.PanelType = v3.PanelTypeGraph
+ }
+
// default mode
return &v3.QueryRangeParamsV3{
Start: start,
@@ -767,9 +773,9 @@ func (r *ThresholdRule) buildAndRunQuery(ctx context.Context, ts time.Time, ch c
var errQuriesByName map[string]error
if r.version == "v4" {
- results, err, errQuriesByName = r.querierV2.QueryRange(ctx, params, map[string]v3.AttributeKey{})
+ results, errQuriesByName, err = r.querierV2.QueryRange(ctx, params, map[string]v3.AttributeKey{})
} else {
- results, err, errQuriesByName = r.querier.QueryRange(ctx, params, map[string]v3.AttributeKey{})
+ results, errQuriesByName, err = r.querier.QueryRange(ctx, params, map[string]v3.AttributeKey{})
}
if err != nil {
diff --git a/pkg/query-service/rules/thresholdRule_test.go b/pkg/query-service/rules/thresholdRule_test.go
index 762666cbf3..115ccddc4c 100644
--- a/pkg/query-service/rules/thresholdRule_test.go
+++ b/pkg/query-service/rules/thresholdRule_test.go
@@ -797,7 +797,7 @@ func TestThresholdRuleLabelNormalization(t *testing.T) {
"service.name": "frontend",
},
LabelsArray: []map[string]string{
- map[string]string{
+ {
"service.name": "frontend",
},
},
diff --git a/pkg/query-service/telemetry/telemetry.go b/pkg/query-service/telemetry/telemetry.go
index 3625a3c9e2..22be2a8648 100644
--- a/pkg/query-service/telemetry/telemetry.go
+++ b/pkg/query-service/telemetry/telemetry.go
@@ -197,8 +197,6 @@ func createTelemetry() {
telemetry.minRandInt = 0
telemetry.maxRandInt = int(1 / DEFAULT_SAMPLING)
- rand.Seed(time.Now().UnixNano())
-
telemetry.SetTelemetryEnabled(constants.IsTelemetryEnabled())
ticker := time.NewTicker(HEART_BEAT_DURATION)
@@ -207,6 +205,7 @@ func createTelemetry() {
rateLimitTicker := time.NewTicker(RATE_LIMIT_CHECK_DURATION)
go func() {
+ //lint:ignore S1000 false positive
for {
select {
case <-rateLimitTicker.C:
@@ -461,6 +460,7 @@ func (a *Telemetry) SendEvent(event string, data map[string]interface{}, userEma
if userEmail != "" {
a.SetUserEmail(userEmail)
+ a.SetCompanyDomain(userEmail)
}
if !a.isTelemetryEnabled() {
diff --git a/pkg/query-service/tests/auth_test.go b/pkg/query-service/tests/auth_test.go
index e5ca9ed4a2..7c7d5277b6 100644
--- a/pkg/query-service/tests/auth_test.go
+++ b/pkg/query-service/tests/auth_test.go
@@ -31,7 +31,7 @@ func invite(t *testing.T, email string) *model.InviteResponse {
}
func register(email, password, token string) (string, error) {
- q := endpoint + fmt.Sprintf("/api/v1/register")
+ q := endpoint + "/api/v1/register"
req := auth.RegisterRequest{
Email: email,
@@ -58,7 +58,7 @@ func register(email, password, token string) (string, error) {
}
func login(email, password, refreshToken string) (*model.LoginResponse, error) {
- q := endpoint + fmt.Sprintf("/api/v1/login")
+ q := endpoint + "/api/v1/login"
req := model.LoginRequest{
Email: email,
diff --git a/pkg/query-service/tests/integration/logparsingpipeline_test.go b/pkg/query-service/tests/integration/logparsingpipeline_test.go
index 9ef47171a4..93efe30dc2 100644
--- a/pkg/query-service/tests/integration/logparsingpipeline_test.go
+++ b/pkg/query-service/tests/integration/logparsingpipeline_test.go
@@ -645,6 +645,7 @@ func assertPipelinesRecommendedInRemoteConfig(
}
_, expectedLogProcessorNames, err := logparsingpipeline.PreparePipelineProcessor(pipelines)
+ require.NoError(t, err)
require.Equal(
t, expectedLogProcessorNames, collectorConfLogsPipelineProcNames,
"config sent to opamp client doesn't contain expected log pipelines",
diff --git a/pkg/query-service/tests/integration/test_utils.go b/pkg/query-service/tests/integration/test_utils.go
index ac6e1db7c5..7775171310 100644
--- a/pkg/query-service/tests/integration/test_utils.go
+++ b/pkg/query-service/tests/integration/test_utils.go
@@ -123,15 +123,15 @@ func makeTestSignozLog(
}
for k, v := range attributes {
- switch v.(type) {
+ switch v := v.(type) {
case bool:
- testLog.Attributes_bool[k] = v.(bool)
+ testLog.Attributes_bool[k] = v
case string:
- testLog.Attributes_string[k] = v.(string)
+ testLog.Attributes_string[k] = v
case int:
- testLog.Attributes_int64[k] = int64(v.(int))
+ testLog.Attributes_int64[k] = int64(v)
case float64:
- testLog.Attributes_float64[k] = v.(float64)
+ testLog.Attributes_float64[k] = v
default:
panic(fmt.Sprintf("found attribute value of unsupported type %T in test log", v))
}
diff --git a/pkg/query-service/tests/test-deploy/docker-compose.yaml b/pkg/query-service/tests/test-deploy/docker-compose.yaml
index 67d6f6d508..1fb37ce2ff 100644
--- a/pkg/query-service/tests/test-deploy/docker-compose.yaml
+++ b/pkg/query-service/tests/test-deploy/docker-compose.yaml
@@ -192,7 +192,7 @@ services:
<<: *db-depend
otel-collector-migrator:
- image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.88.26}
+ image: signoz/signoz-schema-migrator:${OTELCOL_TAG:-0.102.0}
container_name: otel-migrator
command:
- "--dsn=tcp://clickhouse:9000"
@@ -205,7 +205,7 @@ services:
# condition: service_healthy
otel-collector:
- image: signoz/signoz-otel-collector:0.88.26
+ image: signoz/signoz-otel-collector:0.102.0
container_name: signoz-otel-collector
command:
[
diff --git a/pkg/query-service/utils/time.go b/pkg/query-service/utils/time.go
index 274b032cdb..612da4f4bc 100644
--- a/pkg/query-service/utils/time.go
+++ b/pkg/query-service/utils/time.go
@@ -1,20 +1,19 @@
package utils
import (
- "fmt"
"time"
"go.uber.org/zap"
)
-func Elapsed(funcName string, args ...interface{}) func() {
+func Elapsed(funcName string, args map[string]interface{}) func() {
start := time.Now()
- argsStr := ""
- for _, v := range args {
- argsStr += fmt.Sprintf("%v, ", v)
- }
- argsStr = argsStr[:len(argsStr)-2]
return func() {
- zap.L().Info("Elapsed time", zap.String("func_name", funcName), zap.Duration("duration", time.Since(start)), zap.String("args", argsStr))
+ var zapFields []zap.Field
+ zapFields = append(zapFields, zap.String("func_name", funcName), zap.Duration("duration", time.Since(start)))
+ for k, v := range args {
+ zapFields = append(zapFields, zap.Any(k, v))
+ }
+ zap.L().Info("Elapsed time", zapFields...)
}
}