mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-26 03:40:33 +01:00
Compare commits
7 Commits
fix/ext-ap
...
feat/use-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cabba73d72 | ||
|
|
a1cfa3e221 | ||
|
|
f47f1ad92b | ||
|
|
539eac2c4d | ||
|
|
bb51a79056 | ||
|
|
7f0cf8ab24 | ||
|
|
934d8f243c |
@@ -5686,12 +5686,6 @@ components:
|
||||
type: string
|
||||
rootServiceName:
|
||||
type: string
|
||||
serviceNameToTotalDurationMap:
|
||||
additionalProperties:
|
||||
minimum: 0
|
||||
type: integer
|
||||
nullable: true
|
||||
type: object
|
||||
spans:
|
||||
items:
|
||||
$ref: '#/components/schemas/SpantypesWaterfallSpan'
|
||||
|
||||
@@ -6743,15 +6743,6 @@ export interface SpantypesGettableSpanMapperGroupsDTO {
|
||||
items: SpantypesSpanMapperGroupDTO[];
|
||||
}
|
||||
|
||||
export type SpantypesGettableWaterfallTraceDTOServiceNameToTotalDurationMapAnyOf =
|
||||
{ [key: string]: number };
|
||||
|
||||
/**
|
||||
* @nullable
|
||||
*/
|
||||
export type SpantypesGettableWaterfallTraceDTOServiceNameToTotalDurationMap =
|
||||
SpantypesGettableWaterfallTraceDTOServiceNameToTotalDurationMapAnyOf | null;
|
||||
|
||||
export enum SpantypesSpanAggregationTypeDTO {
|
||||
span_count = 'span_count',
|
||||
execution_time_percentage = 'execution_time_percentage',
|
||||
@@ -6940,10 +6931,6 @@ export interface SpantypesGettableWaterfallTraceDTO {
|
||||
* @type string
|
||||
*/
|
||||
rootServiceName?: string;
|
||||
/**
|
||||
* @type object,null
|
||||
*/
|
||||
serviceNameToTotalDurationMap?: SpantypesGettableWaterfallTraceDTOServiceNameToTotalDurationMap;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,8 @@ import {
|
||||
RefreshCw,
|
||||
} from '@signozhq/icons';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Checkbox, Select } from 'antd';
|
||||
import { Button, Select } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import TextToolTip from 'components/TextToolTip/TextToolTip';
|
||||
@@ -749,7 +750,7 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
<Checkbox
|
||||
checked={isSelected}
|
||||
value={isSelected}
|
||||
className="option-checkbox"
|
||||
onClick={(e): void => {
|
||||
e.stopPropagation();
|
||||
@@ -1584,7 +1585,7 @@ const CustomMultiSelect: React.FC<CustomMultiSelectProps> = ({
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
|
||||
<Checkbox checked={allOptionsSelected} className="option-checkbox">
|
||||
<Checkbox value={allOptionsSelected} className="option-checkbox">
|
||||
<div className="option-content">
|
||||
<div className="all-option-text">ALL</div>
|
||||
</div>
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-height: 24px;
|
||||
|
||||
.checkbox-value-section {
|
||||
display: flex;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable sonarjs/no-identical-functions */
|
||||
import { Fragment, useMemo, useState } from 'react';
|
||||
import { Button, Checkbox, Input, Skeleton } from 'antd';
|
||||
import { Button, Input, Skeleton } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import { removeKeysFromExpression } from 'components/QueryBuilderV2/utils';
|
||||
@@ -634,10 +635,12 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
|
||||
)}
|
||||
<div className="value">
|
||||
<Checkbox
|
||||
onChange={(e): void => onChange(value, e.target.checked, false)}
|
||||
checked={currentFilterState[value]}
|
||||
onChange={(checked): void =>
|
||||
onChange(value, checked === true, false)
|
||||
}
|
||||
value={currentFilterState[value]}
|
||||
disabled={isFilterDisabled}
|
||||
rootClassName="check-box"
|
||||
className="check-box"
|
||||
/>
|
||||
|
||||
<div
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { CircleAlert, RefreshCw } from '@signozhq/icons';
|
||||
import { Checkbox, Select } from 'antd';
|
||||
import { Select } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { convertToApiError } from 'api/ErrorResponseHandlerForGeneratedAPIs';
|
||||
import { useListRoles } from 'api/generated/services/role';
|
||||
import type { AuthtypesRoleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
@@ -146,12 +147,11 @@ function RolesSelect(props: RolesSelectProps): JSX.Element {
|
||||
options={options}
|
||||
optionFilterProp="label"
|
||||
optionRender={(option): JSX.Element => (
|
||||
<Checkbox
|
||||
checked={value.includes(option.value as string)}
|
||||
style={{ pointerEvents: 'none' }}
|
||||
>
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
<div style={{ pointerEvents: 'none' }}>
|
||||
<Checkbox value={value.includes(option.value as string)}>
|
||||
{option.label}
|
||||
</Checkbox>
|
||||
</div>
|
||||
)}
|
||||
getPopupContainer={getPopupContainer}
|
||||
disabled={disabled}
|
||||
|
||||
@@ -2,7 +2,8 @@ import { useState } from 'react';
|
||||
import cx from 'classnames';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { Checkbox, Radio } from 'antd';
|
||||
import { Radio } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
|
||||
import { AIAssistantEvents } from '../../../events';
|
||||
import { useAIAssistantAnalyticsContext } from '../../../hooks/useAIAssistantAnalyticsContext';
|
||||
@@ -96,16 +97,24 @@ export default function InteractiveQuestion({
|
||||
</Radio.Group>
|
||||
) : (
|
||||
<>
|
||||
<Checkbox.Group
|
||||
className={cx(styles.options, styles.checkbox)}
|
||||
onChange={(vals): void => setSelected(vals as string[])}
|
||||
>
|
||||
<div className={cx(styles.options, styles.checkbox)}>
|
||||
{normalized.map((opt) => (
|
||||
<Checkbox key={opt.value} value={opt.value} className={styles.option}>
|
||||
<Checkbox
|
||||
key={opt.value}
|
||||
value={selected.includes(opt.value)}
|
||||
onChange={(checked): void => {
|
||||
setSelected((prev) =>
|
||||
checked === true
|
||||
? [...prev, opt.value]
|
||||
: prev.filter((v) => v !== opt.value),
|
||||
);
|
||||
}}
|
||||
className={styles.option}
|
||||
>
|
||||
{opt.label}
|
||||
</Checkbox>
|
||||
))}
|
||||
</Checkbox.Group>
|
||||
</div>
|
||||
<Button
|
||||
variant="solid"
|
||||
size="sm"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Checkbox, Input } from 'antd';
|
||||
import { Input } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
@@ -320,10 +321,8 @@ function AnomalyAlertEvaluationView({
|
||||
{filteredSeriesKeys.length > 0 && (
|
||||
<Checkbox
|
||||
className="anomaly-alert-evaluation-view-series-list-item"
|
||||
type="checkbox"
|
||||
name="series"
|
||||
value="all"
|
||||
checked={selectedSeries === null}
|
||||
value={selectedSeries === null}
|
||||
onChange={(): void => handleSeriesChange(null)}
|
||||
>
|
||||
Show All
|
||||
@@ -335,10 +334,8 @@ function AnomalyAlertEvaluationView({
|
||||
<Checkbox
|
||||
className="anomaly-alert-evaluation-view-series-list-item"
|
||||
key={seriesKey}
|
||||
type="checkbox"
|
||||
name="series"
|
||||
value={seriesKey}
|
||||
checked={selectedSeries === seriesKey}
|
||||
value={selectedSeries === seriesKey}
|
||||
onChange={(): void => handleSeriesChange(seriesKey)}
|
||||
>
|
||||
<div
|
||||
|
||||
@@ -395,8 +395,8 @@ describe('Dynamic Variable Default Behavior', () => {
|
||||
|
||||
// Check if the checkbox exists (it should be unchecked initially)
|
||||
const checkbox = allOptionContainer?.querySelector(
|
||||
'input[type="checkbox"]',
|
||||
) as HTMLInputElement;
|
||||
'[role="checkbox"]',
|
||||
) as HTMLElement;
|
||||
expect(checkbox).toBeInTheDocument();
|
||||
|
||||
// Should call onValueUpdate with all values (ALL selection)
|
||||
@@ -516,10 +516,10 @@ describe('Dynamic Variable Default Behavior', () => {
|
||||
|
||||
// Check if the checkbox for ALL option is checked
|
||||
const checkbox = dropdownAllOption.querySelector(
|
||||
'input[type="checkbox"]',
|
||||
) as HTMLInputElement;
|
||||
'[role="checkbox"]',
|
||||
) as HTMLElement;
|
||||
expect(checkbox).toBeInTheDocument();
|
||||
expect(checkbox.checked).toBe(true);
|
||||
expect(checkbox).toHaveAttribute('data-state', 'checked');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -196,10 +196,10 @@ describe('Panel Management Tests', () => {
|
||||
expect(allOption).toHaveClass('selected');
|
||||
|
||||
const allCheckbox = allOption.querySelector(
|
||||
'input[type="checkbox"]',
|
||||
) as HTMLInputElement;
|
||||
'[role="checkbox"]',
|
||||
) as HTMLElement;
|
||||
expect(allCheckbox).toBeInTheDocument();
|
||||
expect(allCheckbox.checked).toBe(true);
|
||||
expect(allCheckbox).toHaveAttribute('data-state', 'checked');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -160,8 +160,8 @@ describe('getChartManagerColumns', () => {
|
||||
expect(renderFn).toBeDefined();
|
||||
const { container } = render(renderFn!(null, tableDataSet[1], 1));
|
||||
|
||||
const checkbox = container.querySelector('input[type="checkbox"]');
|
||||
const checkbox = container.querySelector('[role="checkbox"]');
|
||||
expect(checkbox).toBeInTheDocument();
|
||||
expect(checkbox).toBeChecked(); // graphVisibilityState[1] is true
|
||||
expect(checkbox).toHaveAttribute('data-state', 'checked'); // graphVisibilityState[1] is true
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { grey } from '@ant-design/colors';
|
||||
import { Checkbox, ConfigProvider } from 'antd';
|
||||
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
import { CheckBoxProps } from '../types';
|
||||
|
||||
@@ -11,30 +11,22 @@ function CustomCheckBox({
|
||||
checkBoxOnChangeHandler,
|
||||
disabled = false,
|
||||
}: CheckBoxProps): JSX.Element {
|
||||
const onChangeHandler = (e: CheckboxChangeEvent): void => {
|
||||
checkBoxOnChangeHandler(e, index);
|
||||
};
|
||||
|
||||
const color = data[index]?.stroke?.toString() || grey[0];
|
||||
|
||||
const isChecked = graphVisibilityState[index] || false;
|
||||
|
||||
const colorStyle = {
|
||||
'--checkbox-checked-background': color,
|
||||
'--checkbox-border-color': color,
|
||||
} as CSSProperties;
|
||||
|
||||
return (
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
token: {
|
||||
colorPrimary: color,
|
||||
colorBorder: color,
|
||||
colorBgContainer: color,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<span style={colorStyle}>
|
||||
<Checkbox
|
||||
onChange={onChangeHandler}
|
||||
checked={isChecked}
|
||||
onChange={(checked): void => checkBoxOnChangeHandler(checked, index)}
|
||||
value={isChecked}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</ConfigProvider>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Dispatch, MutableRefObject, RefObject, SetStateAction } from 'react';
|
||||
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
|
||||
import { ToggleGraphProps } from 'components/Graph/types';
|
||||
import { UplotProps } from 'components/Uplot/Uplot';
|
||||
import { PANEL_TYPES } from 'constants/queryBuilder';
|
||||
@@ -77,7 +76,10 @@ export interface CheckBoxProps {
|
||||
data: ExtendedChartDataset[];
|
||||
index: number;
|
||||
graphVisibilityState: boolean[];
|
||||
checkBoxOnChangeHandler: (e: CheckboxChangeEvent, index: number) => void;
|
||||
checkBoxOnChangeHandler: (
|
||||
checked: boolean | 'indeterminate',
|
||||
index: number,
|
||||
) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Checkbox } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { useRegionSelection } from 'hooks/integration/aws/useRegionSelection';
|
||||
import { regions } from 'utils/regions';
|
||||
|
||||
@@ -21,18 +21,18 @@ export function RegionSelector({
|
||||
setIncludeAllRegions,
|
||||
});
|
||||
|
||||
const allSelected =
|
||||
allRegionIds.length > 0 &&
|
||||
allRegionIds.every((regionId) => selectedRegions.includes(regionId));
|
||||
const someSelected =
|
||||
selectedRegions.length > 0 && selectedRegions.length < allRegionIds.length;
|
||||
|
||||
return (
|
||||
<div className="region-selector">
|
||||
<div className="select-all">
|
||||
<Checkbox
|
||||
checked={
|
||||
allRegionIds.length > 0 &&
|
||||
allRegionIds.every((regionId) => selectedRegions.includes(regionId))
|
||||
}
|
||||
indeterminate={
|
||||
selectedRegions.length > 0 && selectedRegions.length < allRegionIds.length
|
||||
}
|
||||
onChange={(e): void => handleSelectAll(e.target.checked)}
|
||||
value={allSelected ? true : someSelected ? 'indeterminate' : false}
|
||||
onChange={(checked): void => handleSelectAll(checked === true)}
|
||||
>
|
||||
Select All Regions
|
||||
</Checkbox>
|
||||
@@ -45,7 +45,7 @@ export function RegionSelector({
|
||||
{region.subRegions.map((subRegion) => (
|
||||
<Checkbox
|
||||
key={subRegion.id}
|
||||
checked={selectedRegions.includes(subRegion.id)}
|
||||
value={selectedRegions.includes(subRegion.id)}
|
||||
onChange={(): void => handleRegionSelect(subRegion.id)}
|
||||
>
|
||||
{subRegion.name}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Checkbox, Empty } from 'antd';
|
||||
import { Empty } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { EXCLUDED_COLUMNS } from 'container/OptionsMenu/constants';
|
||||
@@ -50,9 +51,8 @@ function ExplorerAttributeColumns({
|
||||
<div className="attribute-columns">
|
||||
{filteredAttributeKeys.map((attributeKey: any) => (
|
||||
<Checkbox
|
||||
checked={isAttributeKeySelected(attributeKey.name)}
|
||||
value={isAttributeKeySelected(attributeKey.name)}
|
||||
onChange={(): void => handleCheckboxChange(attributeKey.name)}
|
||||
style={{ padding: 0 }}
|
||||
key={attributeKey.name}
|
||||
>
|
||||
{attributeKey.name}
|
||||
|
||||
@@ -4,9 +4,9 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useInterval } from 'react-use';
|
||||
import { Check, ChevronDown } from '@signozhq/icons';
|
||||
import { Button, Checkbox, Popover } from 'antd';
|
||||
import { Button, Popover } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { CheckboxChangeEvent } from 'antd/lib/checkbox';
|
||||
import get from 'api/browser/localstorage/get';
|
||||
import set from 'api/browser/localstorage/set';
|
||||
import { DASHBOARD_TIME_IN_DURATION } from 'constants/app';
|
||||
@@ -132,8 +132,8 @@ function AutoRefresh({
|
||||
);
|
||||
|
||||
const onChangeAutoRefreshHandler = useCallback(
|
||||
(event: CheckboxChangeEvent) => {
|
||||
const { checked } = event.target;
|
||||
(value: boolean | 'indeterminate') => {
|
||||
const checked = value === true;
|
||||
if (!checked) {
|
||||
// remove the path from localstorage
|
||||
set(
|
||||
@@ -168,7 +168,7 @@ function AutoRefresh({
|
||||
<div className="auto-refresh-menu">
|
||||
<Checkbox
|
||||
onChange={onChangeAutoRefreshHandler}
|
||||
checked={isAutoRefreshEnabled}
|
||||
value={isAutoRefreshEnabled}
|
||||
disabled={isDisabled}
|
||||
className="auto-refresh-checkbox"
|
||||
>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { Checkbox, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import getFilters from 'api/trace/getFilters';
|
||||
import { AxiosError } from 'axios';
|
||||
@@ -174,8 +175,7 @@ function CheckBoxComponent(props: CheckBoxProps): JSX.Element {
|
||||
<Checkbox
|
||||
disabled={isLoading || filterLoading}
|
||||
onClick={onCheckHandler}
|
||||
checked={isCheckBoxSelected}
|
||||
defaultChecked
|
||||
value={isCheckBoxSelected}
|
||||
key={keyValue}
|
||||
>
|
||||
<Tooltip overlay={TooTipOverLay}>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Checkbox, Input, Select, Skeleton } from 'antd';
|
||||
import { Input, Select, Skeleton } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
@@ -104,12 +105,12 @@ function SpanPercentilePanel({
|
||||
.map((attr) => (
|
||||
<div className={styles.resourceSelectorItem} key={attr.key}>
|
||||
<Checkbox
|
||||
checked={attr.isSelected}
|
||||
onChange={(e): void => {
|
||||
value={attr.isSelected}
|
||||
onChange={(checked): void => {
|
||||
handleResourceAttributeChange(
|
||||
attr.key,
|
||||
attr.value,
|
||||
e.target.checked,
|
||||
checked === true,
|
||||
);
|
||||
}}
|
||||
disabled={
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Button, Card, Checkbox, Input, Tooltip } from 'antd';
|
||||
import type { CheckboxChangeEvent } from 'antd/es/checkbox';
|
||||
import { Button, Card, Input, Tooltip } from 'antd';
|
||||
import { Checkbox } from '@signozhq/ui/checkbox';
|
||||
import { ParaGraph } from 'container/Trace/Filters/Panel/PanelBody/Common/styles';
|
||||
import useDebouncedFn from 'hooks/useDebouncedFunction';
|
||||
import { isArray, isEmpty } from 'lodash-es';
|
||||
@@ -87,8 +87,11 @@ export function SectionBody(props: SectionBodyProps): JSX.Element {
|
||||
[results, searchFilter, type, visibleItemsCount],
|
||||
);
|
||||
|
||||
const onCheckHandler = (event: CheckboxChangeEvent, value: string): void => {
|
||||
const { checked } = event.target;
|
||||
const onCheckHandler = (
|
||||
checkedState: boolean | 'indeterminate',
|
||||
value: string,
|
||||
): void => {
|
||||
const checked = checkedState === true;
|
||||
let newValue = value;
|
||||
if (type === 'hasError') {
|
||||
newValue = String(value === 'Error');
|
||||
@@ -147,9 +150,9 @@ export function SectionBody(props: SectionBodyProps): JSX.Element {
|
||||
<Checkbox
|
||||
className="submenu-checkbox"
|
||||
key={`${type}-${item}`}
|
||||
onChange={(e): void => onCheckHandler(e, item)}
|
||||
checked={checkboxMatcher(item)}
|
||||
data-testid={`${type}-${item}`}
|
||||
onChange={(checked): void => onCheckHandler(checked, item)}
|
||||
value={checkboxMatcher(item)}
|
||||
testId={`${type}-${item}`}
|
||||
>
|
||||
<div className="checkbox-label">
|
||||
<div className={labelClassname(item)} />
|
||||
|
||||
@@ -327,9 +327,13 @@ describe('TracesExplorer - Filters', () => {
|
||||
|
||||
// check if the default query is applied - composite query has filters - serviceName : demo-app and name : HTTP GET /customer
|
||||
await expect(findByText('demo-app')).resolves.toBeInTheDocument();
|
||||
expect(getByTestId('serviceName-demo-app')).toBeChecked();
|
||||
expect(
|
||||
getByTestId('serviceName-demo-app').querySelector('[role="checkbox"]'),
|
||||
).toHaveAttribute('data-state', 'checked');
|
||||
await expect(findByText('HTTP GET /customer')).resolves.toBeInTheDocument();
|
||||
expect(getByTestId('name-HTTP GET /customer')).toBeChecked();
|
||||
expect(
|
||||
getByTestId('name-HTTP GET /customer').querySelector('[role="checkbox"]'),
|
||||
).toHaveAttribute('data-state', 'checked');
|
||||
});
|
||||
|
||||
it('test edge cases of undefined filters', async () => {
|
||||
|
||||
@@ -97,7 +97,7 @@ func makeChain(n int) (*spantypes.WaterfallSpan, map[string]*spantypes.Waterfall
|
||||
}
|
||||
|
||||
func getWaterfallTrace(roots []*spantypes.WaterfallSpan, spanMap map[string]*spantypes.WaterfallSpan) *spantypes.WaterfallTrace {
|
||||
return spantypes.NewWaterfallTrace(0, 0, uint64(len(spanMap)), 0, spanMap, nil, roots, false)
|
||||
return spantypes.NewWaterfallTrace(0, 0, uint64(len(spanMap)), 0, spanMap, roots, false)
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -33,7 +33,7 @@ func buildTraceFromSpans(spans ...*WaterfallSpan) *WaterfallTrace {
|
||||
endTime = end
|
||||
}
|
||||
}
|
||||
return NewWaterfallTrace(startTime, endTime, uint64(len(spanMap)), 0, spanMap, nil, nil, false)
|
||||
return NewWaterfallTrace(startTime, endTime, uint64(len(spanMap)), 0, spanMap, nil, false)
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -20,50 +20,45 @@ type TraceSummary struct {
|
||||
|
||||
// WaterfallTrace holds processed trace data with childern populated in spans.
|
||||
type WaterfallTrace struct {
|
||||
StartTime uint64 `json:"startTime"`
|
||||
EndTime uint64 `json:"endTime"`
|
||||
TotalSpans uint64 `json:"totalSpans"`
|
||||
TotalErrorSpans uint64 `json:"totalErrorSpans"`
|
||||
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
|
||||
SpanIDToSpanNodeMap map[string]*WaterfallSpan `json:"spanIdToSpanNodeMap"`
|
||||
TraceRoots []*WaterfallSpan `json:"traceRoots"`
|
||||
HasMissingSpans bool `json:"hasMissingSpans"`
|
||||
StartTime uint64 `json:"startTime"`
|
||||
EndTime uint64 `json:"endTime"`
|
||||
TotalSpans uint64 `json:"totalSpans"`
|
||||
TotalErrorSpans uint64 `json:"totalErrorSpans"`
|
||||
SpanIDToSpanNodeMap map[string]*WaterfallSpan `json:"spanIdToSpanNodeMap"`
|
||||
TraceRoots []*WaterfallSpan `json:"traceRoots"`
|
||||
HasMissingSpans bool `json:"hasMissingSpans"`
|
||||
}
|
||||
|
||||
// GettableWaterfallTrace is the response for the v3 waterfall API.
|
||||
type GettableWaterfallTrace struct {
|
||||
StartTimestampMillis uint64 `json:"startTimestampMillis"`
|
||||
EndTimestampMillis uint64 `json:"endTimestampMillis"`
|
||||
RootServiceName string `json:"rootServiceName"`
|
||||
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
|
||||
TotalSpansCount uint64 `json:"totalSpansCount"`
|
||||
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
|
||||
// Deprecated: use Aggregations with SpanAggregationExecutionTimePercentage on the service.name field instead.
|
||||
ServiceNameToTotalDurationMap map[string]uint64 `json:"serviceNameToTotalDurationMap"`
|
||||
Spans []*WaterfallSpan `json:"spans"`
|
||||
HasMissingSpans bool `json:"hasMissingSpans"`
|
||||
UncollapsedSpans []string `json:"uncollapsedSpans"`
|
||||
HasMore bool `json:"hasMore"`
|
||||
Aggregations []SpanAggregationResult `json:"aggregations"`
|
||||
StartTimestampMillis uint64 `json:"startTimestampMillis"`
|
||||
EndTimestampMillis uint64 `json:"endTimestampMillis"`
|
||||
RootServiceName string `json:"rootServiceName"`
|
||||
RootServiceEntryPoint string `json:"rootServiceEntryPoint"`
|
||||
TotalSpansCount uint64 `json:"totalSpansCount"`
|
||||
TotalErrorSpansCount uint64 `json:"totalErrorSpansCount"`
|
||||
Spans []*WaterfallSpan `json:"spans"`
|
||||
HasMissingSpans bool `json:"hasMissingSpans"`
|
||||
UncollapsedSpans []string `json:"uncollapsedSpans"`
|
||||
HasMore bool `json:"hasMore"`
|
||||
Aggregations []SpanAggregationResult `json:"aggregations"`
|
||||
}
|
||||
|
||||
// NewWaterfallTrace constructs a WaterfallTrace from processed span data.
|
||||
func NewWaterfallTrace(
|
||||
startTime, endTime, totalSpans, totalErrorSpans uint64,
|
||||
spanIDToSpanNodeMap map[string]*WaterfallSpan,
|
||||
serviceNameToTotalDurationMap map[string]uint64,
|
||||
traceRoots []*WaterfallSpan,
|
||||
hasMissingSpans bool,
|
||||
) *WaterfallTrace {
|
||||
return &WaterfallTrace{
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
TotalSpans: totalSpans,
|
||||
TotalErrorSpans: totalErrorSpans,
|
||||
SpanIDToSpanNodeMap: spanIDToSpanNodeMap,
|
||||
ServiceNameToTotalDurationMap: serviceNameToTotalDurationMap,
|
||||
TraceRoots: traceRoots,
|
||||
HasMissingSpans: hasMissingSpans,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
TotalSpans: totalSpans,
|
||||
TotalErrorSpans: totalErrorSpans,
|
||||
SpanIDToSpanNodeMap: spanIDToSpanNodeMap,
|
||||
TraceRoots: traceRoots,
|
||||
HasMissingSpans: hasMissingSpans,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +119,6 @@ func NewWaterfallTraceFromSpans(spans []StorableSpan) *WaterfallTrace {
|
||||
uint64(len(spans)),
|
||||
totalErrorSpans,
|
||||
spanIDToSpanNodeMap,
|
||||
calculateServiceTime(spanIDToSpanNodeMap),
|
||||
traceRoots,
|
||||
hasMissingSpans,
|
||||
)
|
||||
@@ -206,23 +200,19 @@ func (wt *WaterfallTrace) CalculateUncollapsedSpanIDs(uncollapsedSpanIDs []strin
|
||||
}
|
||||
|
||||
func (wt *WaterfallTrace) Clone() cachetypes.Cacheable {
|
||||
copyOfServiceNameToTotalDurationMap := make(map[string]uint64)
|
||||
maps.Copy(copyOfServiceNameToTotalDurationMap, wt.ServiceNameToTotalDurationMap)
|
||||
|
||||
copyOfSpanIDToSpanNodeMap := make(map[string]*WaterfallSpan)
|
||||
maps.Copy(copyOfSpanIDToSpanNodeMap, wt.SpanIDToSpanNodeMap)
|
||||
|
||||
copyOfTraceRoots := make([]*WaterfallSpan, len(wt.TraceRoots))
|
||||
copy(copyOfTraceRoots, wt.TraceRoots)
|
||||
return &WaterfallTrace{
|
||||
StartTime: wt.StartTime,
|
||||
EndTime: wt.EndTime,
|
||||
TotalSpans: wt.TotalSpans,
|
||||
TotalErrorSpans: wt.TotalErrorSpans,
|
||||
ServiceNameToTotalDurationMap: copyOfServiceNameToTotalDurationMap,
|
||||
SpanIDToSpanNodeMap: copyOfSpanIDToSpanNodeMap,
|
||||
TraceRoots: copyOfTraceRoots,
|
||||
HasMissingSpans: wt.HasMissingSpans,
|
||||
StartTime: wt.StartTime,
|
||||
EndTime: wt.EndTime,
|
||||
TotalSpans: wt.TotalSpans,
|
||||
TotalErrorSpans: wt.TotalErrorSpans,
|
||||
SpanIDToSpanNodeMap: copyOfSpanIDToSpanNodeMap,
|
||||
TraceRoots: copyOfTraceRoots,
|
||||
HasMissingSpans: wt.HasMissingSpans,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,11 +247,6 @@ func NewGettableWaterfallTrace(
|
||||
rootServiceEntryPoint = traceData.TraceRoots[0].Name
|
||||
}
|
||||
|
||||
serviceDurationsMillis := make(map[string]uint64, len(traceData.ServiceNameToTotalDurationMap))
|
||||
for svc, dur := range traceData.ServiceNameToTotalDurationMap {
|
||||
serviceDurationsMillis[svc] = dur / 1_000_000
|
||||
}
|
||||
|
||||
// convert start timestamp to millis because client is expecting it in millis
|
||||
for _, span := range selectedSpans {
|
||||
span.TimeUnix = span.TimeUnix / 1_000_000
|
||||
@@ -277,18 +262,17 @@ func NewGettableWaterfallTrace(
|
||||
}
|
||||
|
||||
return &GettableWaterfallTrace{
|
||||
Spans: selectedSpans,
|
||||
UncollapsedSpans: uncollapsedSpans,
|
||||
StartTimestampMillis: traceData.StartTime / 1_000_000,
|
||||
EndTimestampMillis: traceData.EndTime / 1_000_000,
|
||||
TotalSpansCount: traceData.TotalSpans,
|
||||
TotalErrorSpansCount: traceData.TotalErrorSpans,
|
||||
RootServiceName: rootServiceName,
|
||||
RootServiceEntryPoint: rootServiceEntryPoint,
|
||||
ServiceNameToTotalDurationMap: serviceDurationsMillis,
|
||||
HasMissingSpans: traceData.HasMissingSpans,
|
||||
HasMore: !selectAllSpans,
|
||||
Aggregations: aggregations,
|
||||
Spans: selectedSpans,
|
||||
UncollapsedSpans: uncollapsedSpans,
|
||||
StartTimestampMillis: traceData.StartTime / 1_000_000,
|
||||
EndTimestampMillis: traceData.EndTime / 1_000_000,
|
||||
TotalSpansCount: traceData.TotalSpans,
|
||||
TotalErrorSpansCount: traceData.TotalErrorSpans,
|
||||
RootServiceName: rootServiceName,
|
||||
RootServiceEntryPoint: rootServiceEntryPoint,
|
||||
HasMissingSpans: traceData.HasMissingSpans,
|
||||
HasMore: !selectAllSpans,
|
||||
Aggregations: aggregations,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,21 +295,6 @@ func windowAroundIndex(selectedIndex, total int, spanLimitPerRequest float64) (s
|
||||
return
|
||||
}
|
||||
|
||||
func calculateServiceTime(spanIDToSpanNodeMap map[string]*WaterfallSpan) map[string]uint64 {
|
||||
serviceSpans := make(map[string][]*WaterfallSpan)
|
||||
for _, span := range spanIDToSpanNodeMap {
|
||||
if span.ServiceName != "" {
|
||||
serviceSpans[span.ServiceName] = append(serviceSpans[span.ServiceName], span)
|
||||
}
|
||||
}
|
||||
|
||||
totalTimes := make(map[string]uint64)
|
||||
for service, spans := range serviceSpans {
|
||||
totalTimes[service] = mergeSpanIntervals(spans)
|
||||
}
|
||||
return totalTimes
|
||||
}
|
||||
|
||||
// mergeSpanIntervals computes non-overlapping execution time for a set of spans.
|
||||
func mergeSpanIntervals(spans []*WaterfallSpan) uint64 {
|
||||
if len(spans) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user