mirror of
https://github.com/SigNoz/signoz.git
synced 2026-05-22 18:00:25 +01:00
Compare commits
6 Commits
issue_8965
...
chore/migr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e0bfc6384 | ||
|
|
06045ee8c7 | ||
|
|
1aca69bf3d | ||
|
|
f2a18e8b6c | ||
|
|
db59109e03 | ||
|
|
630442f391 |
@@ -19,6 +19,7 @@ const BANNED_COMPONENTS = {
|
||||
Switch: 'Use @signozhq/ui/switch Switch instead of antd Switch.',
|
||||
Badge: 'Use @signozhq/ui/badge instead of antd Badge.',
|
||||
Progress: 'Use @signozhq/ui/progress instead of antd Progress.',
|
||||
Tag: 'Use @signozhq/ui/badge Bagde instead of antd Tag.',
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Select, Tag, Tooltip } from 'antd';
|
||||
import { Select, Tooltip } from 'antd';
|
||||
import {
|
||||
OPERATORS,
|
||||
QUERY_BUILDER_OPERATORS_BY_TYPES,
|
||||
@@ -37,7 +37,7 @@ import { validationMapper } from 'hooks/queryBuilder/useIsValidTag';
|
||||
import { operatorTypeMapper } from 'hooks/queryBuilder/useOperatorType';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { isArray, isEmpty, isEqual, isObject } from 'lodash-es';
|
||||
import { ChevronDown, ChevronUp } from '@signozhq/icons';
|
||||
import { ChevronDown, ChevronUp, X } from '@signozhq/icons';
|
||||
import type { BaseSelectRef } from 'rc-select';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
@@ -51,6 +51,7 @@ import { popupContainer } from 'utils/selectPopupContainer';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import './ClientSideQBSearch.styles.scss';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
export interface AttributeKey {
|
||||
key: string;
|
||||
@@ -547,11 +548,7 @@ function ClientSideQBSearch(
|
||||
|
||||
return (
|
||||
<span className="qb-search-bar-tokenised-tags">
|
||||
<Tag
|
||||
closable={!searchValue && closable}
|
||||
onClose={onCloseHandler}
|
||||
className={tagDetails?.key?.type || ''}
|
||||
>
|
||||
<Badge color="vanilla" className={tagDetails?.key?.type || ''}>
|
||||
<Tooltip title={chipValue}>
|
||||
<TypographyText
|
||||
$isInNin={isInNin}
|
||||
@@ -566,7 +563,15 @@ function ClientSideQBSearch(
|
||||
{chipValue}
|
||||
</TypographyText>
|
||||
</Tooltip>
|
||||
</Tag>
|
||||
{!searchValue && closable && (
|
||||
<X
|
||||
size={12}
|
||||
className="close-icon"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={onCloseHandler}
|
||||
/>
|
||||
)}
|
||||
</Badge>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Modal, Tag } from 'antd';
|
||||
import { Button, Modal } from 'antd';
|
||||
import { CircleAlert, X } from '@signozhq/icons';
|
||||
import KeyValueLabel from 'periscope/components/KeyValueLabel';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
@@ -9,6 +9,7 @@ import APIError from 'types/api/error';
|
||||
import ErrorContent from './components/ErrorContent';
|
||||
|
||||
import './ErrorModal.styles.scss';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
type Props = {
|
||||
error: APIError;
|
||||
@@ -45,14 +46,17 @@ function ErrorModal({
|
||||
return (
|
||||
<>
|
||||
{!triggerComponent ? (
|
||||
<Tag
|
||||
<span
|
||||
className="error-modal__trigger"
|
||||
icon={<CircleAlert size={14} color={Color.BG_CHERRY_500} />}
|
||||
color="error"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={(): void => setVisible(true)}
|
||||
onKeyDown={undefined}
|
||||
>
|
||||
error
|
||||
</Tag>
|
||||
<Badge color="error">
|
||||
<CircleAlert size={14} color={Color.BG_CHERRY_500} /> error
|
||||
</Badge>
|
||||
</span>
|
||||
) : (
|
||||
React.cloneElement(triggerComponent, {
|
||||
onClick: () => setVisible(true),
|
||||
|
||||
@@ -14,7 +14,8 @@ import { Color } from '@signozhq/design-tokens';
|
||||
import { copilot } from '@uiw/codemirror-theme-copilot';
|
||||
import { githubLight } from '@uiw/codemirror-theme-github';
|
||||
import CodeMirror, { EditorView, keymap, Prec } from '@uiw/react-codemirror';
|
||||
import { Button, Card, Collapse, Popover, Tag, Tooltip } from 'antd';
|
||||
import { Button, Card, Collapse, Popover, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { getKeySuggestions } from 'api/querySuggestions/getKeySuggestions';
|
||||
import { getValueSuggestions } from 'api/querySuggestions/getValueSuggestion';
|
||||
import cx from 'classnames';
|
||||
@@ -664,26 +665,26 @@ function QuerySearch({
|
||||
// Helper function to render a badge for the current context mode
|
||||
const renderContextBadge = (): JSX.Element => {
|
||||
if (!editingMode) {
|
||||
return <Tag>Unknown</Tag>;
|
||||
return <Badge color="vanilla">Unknown</Badge>;
|
||||
}
|
||||
|
||||
switch (editingMode) {
|
||||
case 'key':
|
||||
return <Tag color="blue">Key</Tag>;
|
||||
return <Badge color="robin">Key</Badge>;
|
||||
case 'operator':
|
||||
return <Tag color="purple">Operator</Tag>;
|
||||
return <Badge color="sakura">Operator</Badge>;
|
||||
case 'value':
|
||||
return <Tag color="green">Value</Tag>;
|
||||
return <Badge color="forest">Value</Badge>;
|
||||
case 'conjunction':
|
||||
return <Tag color="orange">Conjunction</Tag>;
|
||||
return <Badge color="amber">Conjunction</Badge>;
|
||||
case 'function':
|
||||
return <Tag color="cyan">Function</Tag>;
|
||||
return <Badge color="aqua">Function</Badge>;
|
||||
case 'parenthesis':
|
||||
return <Tag color="magenta">Parenthesis</Tag>;
|
||||
return <Badge color="sakura">Parenthesis</Badge>;
|
||||
case 'bracketList':
|
||||
return <Tag color="red">Bracket List</Tag>;
|
||||
return <Badge color="cherry">Bracket List</Badge>;
|
||||
default:
|
||||
return <Tag>Unknown</Tag>;
|
||||
return <Badge color="vanilla">Unknown</Badge>;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1304,34 +1305,37 @@ function QuerySearch({
|
||||
Currently editing: {renderContextBadge()}
|
||||
{queryContext?.keyToken && (
|
||||
<span className="triplet-info">
|
||||
Key: <Tag>{queryContext.keyToken}</Tag>
|
||||
Key: <Badge color="vanilla">{queryContext.keyToken}</Badge>
|
||||
</span>
|
||||
)}
|
||||
{queryContext?.operatorToken && (
|
||||
<span className="triplet-info">
|
||||
Operator: <Tag>{queryContext.operatorToken}</Tag>
|
||||
Operator: <Badge color="vanilla">{queryContext.operatorToken}</Badge>
|
||||
</span>
|
||||
)}
|
||||
{queryContext?.valueToken && (
|
||||
<span className="triplet-info">
|
||||
Value: <Tag>{queryContext.valueToken}</Tag>
|
||||
Value: <Badge color="vanilla">{queryContext.valueToken}</Badge>
|
||||
</span>
|
||||
)}
|
||||
{queryContext?.currentPair && (
|
||||
<span className="triplet-info query-pair-info">
|
||||
Current pair: <Tag color="blue">{queryContext.currentPair.key}</Tag>
|
||||
<Tag color="purple">{queryContext.currentPair.operator}</Tag>
|
||||
Current pair: <Badge color="robin">{queryContext.currentPair.key}</Badge>
|
||||
<Badge color="sakura">{queryContext.currentPair.operator}</Badge>
|
||||
{queryContext.currentPair.value && (
|
||||
<Tag color="green">{queryContext.currentPair.value}</Tag>
|
||||
<Badge color="forest">{queryContext.currentPair.value}</Badge>
|
||||
)}
|
||||
<Tag color={queryContext.currentPair.isComplete ? 'success' : 'warning'}>
|
||||
<Badge
|
||||
color={queryContext.currentPair.isComplete ? 'success' : 'warning'}
|
||||
>
|
||||
{queryContext.currentPair.isComplete ? 'Complete' : 'Incomplete'}
|
||||
</Tag>
|
||||
</Badge>
|
||||
</span>
|
||||
)}
|
||||
{queryContext?.queryPairs && queryContext.queryPairs.length > 0 && (
|
||||
<span className="triplet-info">
|
||||
Total pairs: <Tag color="blue">{queryContext.queryPairs.length}</Tag>
|
||||
Total pairs:{' '}
|
||||
<Badge color="robin">{queryContext.queryPairs.length}</Badge>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Popover, Tag } from 'antd';
|
||||
import { Popover } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
import { LabelColumnProps } from './TableRenderer.types';
|
||||
import TagWithToolTip from './TagWithToolTip';
|
||||
@@ -6,7 +7,7 @@ import { getLabelAndValueContent } from './utils';
|
||||
|
||||
import './LabelColumn.styles.scss';
|
||||
|
||||
function LabelColumn({ labels, value, color }: LabelColumnProps): JSX.Element {
|
||||
function LabelColumn({ labels, value }: LabelColumnProps): JSX.Element {
|
||||
const newLabels = labels.length > 3 ? labels.slice(0, 3) : labels;
|
||||
const remainingLabels = labels.length > 3 ? labels.slice(3) : [];
|
||||
|
||||
@@ -14,7 +15,7 @@ function LabelColumn({ labels, value, color }: LabelColumnProps): JSX.Element {
|
||||
<div className="label-column">
|
||||
{newLabels.map(
|
||||
(label: string): JSX.Element => (
|
||||
<TagWithToolTip key={label} label={label} color={color} value={value} />
|
||||
<TagWithToolTip key={label} label={label} value={value} />
|
||||
),
|
||||
)}
|
||||
{remainingLabels.length > 0 && (
|
||||
@@ -26,9 +27,9 @@ function LabelColumn({ labels, value, color }: LabelColumnProps): JSX.Element {
|
||||
{labels.map(
|
||||
(label: string): JSX.Element => (
|
||||
<div key={label}>
|
||||
<Tag className="label-column--tag" color={color}>
|
||||
<Badge className="label-column--tag" color="vanilla">
|
||||
{getLabelAndValueContent(label, value && value[label])}
|
||||
</Tag>
|
||||
</Badge>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
@@ -36,9 +37,9 @@ function LabelColumn({ labels, value, color }: LabelColumnProps): JSX.Element {
|
||||
}
|
||||
trigger="hover"
|
||||
>
|
||||
<Tag className="label-column--tag" color={color}>
|
||||
<Badge className="label-column--tag" color="vanilla">
|
||||
+{remainingLabels.length}
|
||||
</Tag>
|
||||
</Badge>
|
||||
</Popover>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import { Tag, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
import { getLabelRenderingValue } from './utils';
|
||||
|
||||
function TagWithToolTip({
|
||||
label,
|
||||
value,
|
||||
color,
|
||||
}: TagWithToolTipProps): JSX.Element {
|
||||
function TagWithToolTip({ label, value }: TagWithToolTipProps): JSX.Element {
|
||||
const tooltipTitle =
|
||||
value && value[label] ? `${label}: ${value[label]}` : label;
|
||||
return (
|
||||
<div key={label}>
|
||||
<Tooltip title={tooltipTitle}>
|
||||
<Tag className="label-column--tag" color={color}>
|
||||
<Badge className="label-column--tag" color="vanilla">
|
||||
{getLabelRenderingValue(label, value && value[label])}
|
||||
</Tag>
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
@@ -22,7 +19,6 @@ function TagWithToolTip({
|
||||
|
||||
type TagWithToolTipProps = {
|
||||
label: string;
|
||||
color?: string;
|
||||
value?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
@@ -30,7 +26,6 @@ type TagWithToolTipProps = {
|
||||
|
||||
TagWithToolTip.defaultProps = {
|
||||
value: undefined,
|
||||
color: undefined,
|
||||
};
|
||||
|
||||
export default TagWithToolTip;
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ant-tag {
|
||||
margin-right: 0;
|
||||
background: var(--card);
|
||||
}
|
||||
}
|
||||
|
||||
.add-tag-container {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { Check, Plus, X } from '@signozhq/icons';
|
||||
import { Button, Flex, Tag } from 'antd';
|
||||
import { Button, Flex } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import Input from 'components/Input';
|
||||
|
||||
import './Tags.styles.scss';
|
||||
@@ -46,14 +47,14 @@ function Tags({ tags, setTags }: AddTagsProps): JSX.Element {
|
||||
return (
|
||||
<div className="tags-container">
|
||||
{tags.map<React.ReactNode>((tag) => (
|
||||
<Tag
|
||||
key={tag}
|
||||
closable
|
||||
style={{ userSelect: 'none' }}
|
||||
onClose={(): void => handleClose(tag)}
|
||||
>
|
||||
<Badge key={tag} color="vanilla" style={{ userSelect: 'none' }}>
|
||||
<span>{tag}</span>
|
||||
</Tag>
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={(): void => handleClose(tag)}
|
||||
/>
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
{inputVisible && (
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { TableColumnType as ColumnType, Tag, Tooltip } from 'antd';
|
||||
import { TableColumnType as ColumnType, Tooltip } from 'antd';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { convertFiltersToExpressionWithExistingQuery } from 'components/QueryBuilderV2/utils';
|
||||
import {
|
||||
FiltersType,
|
||||
@@ -972,13 +973,9 @@ export const getEndPointsColumnsConfig = (
|
||||
})()}
|
||||
{isGroupedByAttribute
|
||||
? text.split(',').map((value) => (
|
||||
<Tag
|
||||
key={value}
|
||||
color={Color.BG_SLATE_100}
|
||||
className="endpoint-group-tag-item"
|
||||
>
|
||||
<Badge key={value} color="vanilla" className="endpoint-group-tag-item">
|
||||
{value === '' ? '<no-value>' : value}
|
||||
</Tag>
|
||||
</Badge>
|
||||
))
|
||||
: endPointName}
|
||||
</div>
|
||||
|
||||
@@ -14,8 +14,8 @@ import {
|
||||
Skeleton,
|
||||
Table,
|
||||
TableColumnsType as ColumnsType,
|
||||
Tag,
|
||||
} from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import getUsage, { UsageResponsePayloadProps } from 'api/billing/getUsage';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import updateCreditCardApi from 'api/v1/checkout/create';
|
||||
@@ -434,7 +434,7 @@ export default function BillingContainer(): JSX.Element {
|
||||
<Flex vertical>
|
||||
<Typography.Title level={5} style={{ marginTop: 2, fontWeight: 500 }}>
|
||||
{isCloudUserVal ? t('teams_cloud') : t('teams')}{' '}
|
||||
{isFreeTrial ? <Tag color="success"> Free Trial </Tag> : ''}
|
||||
{isFreeTrial ? <Badge color="success"> Free Trial </Badge> : ''}
|
||||
</Typography.Title>
|
||||
|
||||
{!isLoading && !isFetchingBillingData && !showGracePeriodMessage ? (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Row, Tag } from 'antd';
|
||||
import { Row } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { ALERTS_DATA_SOURCE_MAP } from 'constants/alerts';
|
||||
@@ -66,13 +67,7 @@ function SelectAlertType({ onSelect }: SelectAlertTypeProps): JSX.Element {
|
||||
<AlertTypeCard
|
||||
key={option.selection}
|
||||
title={option.title}
|
||||
extra={
|
||||
option.isBeta ? (
|
||||
<Tag bordered={false} color="geekblue">
|
||||
Beta
|
||||
</Tag>
|
||||
) : undefined
|
||||
}
|
||||
extra={option.isBeta ? <Badge color="robin">Beta</Badge> : undefined}
|
||||
onClick={(e): void => {
|
||||
onSelect(option.selection, isModifierKeyPressed(e));
|
||||
}}
|
||||
|
||||
@@ -16,7 +16,8 @@ import {
|
||||
Plus,
|
||||
X,
|
||||
} from '@signozhq/icons';
|
||||
import { Button, Card, Input, Modal, Popover, Tag, Tooltip } from 'antd';
|
||||
import { Button, Card, Input, Modal, Popover, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ConfigureIcon from 'assets/Integrations/ConfigureIcon';
|
||||
@@ -506,9 +507,9 @@ function DashboardDescription(props: DashboardDescriptionProps): JSX.Element {
|
||||
{(tags?.length || 0) > 0 && (
|
||||
<div className="dashboard-tags">
|
||||
{tags?.map((tag) => (
|
||||
<Tag key={tag} className="tag">
|
||||
<Badge key={tag} className="tag" color="vanilla">
|
||||
{tag}
|
||||
</Tag>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
flex-flow: wrap;
|
||||
gap: 8px;
|
||||
|
||||
.ant-tag {
|
||||
[data-slot='badge'] {
|
||||
height: 30px;
|
||||
color: var(--l1-foreground);
|
||||
font-family: 'Space Mono';
|
||||
|
||||
@@ -5,7 +5,8 @@ import { useQuery } from 'react-query';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { orange } from '@ant-design/colors';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Collapse, Input, Select, Tag } from 'antd';
|
||||
import { Button, Collapse, Input, Select } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import dashboardVariablesQuery from 'api/dashboard/variables/dashboardVariablesQuery';
|
||||
@@ -542,9 +543,9 @@ function VariableItem({
|
||||
}}
|
||||
>
|
||||
Dynamic
|
||||
<Tag bordered={false} className="sidenav-beta-tag" color="geekblue">
|
||||
<Badge color="robin" className="sidenav-beta-tag">
|
||||
Beta
|
||||
</Tag>
|
||||
</Badge>
|
||||
</Button>
|
||||
<Button
|
||||
type="text"
|
||||
@@ -599,9 +600,9 @@ function VariableItem({
|
||||
}}
|
||||
>
|
||||
Query
|
||||
<Tag bordered={false} className="sidenav-beta-tag" color="warning">
|
||||
<Badge color="amber" className="sidenav-beta-tag">
|
||||
Not Recommended
|
||||
</Tag>
|
||||
</Badge>
|
||||
<div onClick={(e): void => e.stopPropagation()}>
|
||||
<TextToolTip
|
||||
text="Learn why we don't recommend"
|
||||
@@ -733,7 +734,9 @@ function VariableItem({
|
||||
<Typography style={{ color: orange[5] }}>{errorPreview}</Typography>
|
||||
) : (
|
||||
map(previewValues, (value, idx) => (
|
||||
<Tag key={`${value}${idx}`}>{value.toString()}</Tag>
|
||||
<Badge key={`${value}${idx}`} color="vanilla">
|
||||
{value.toString()}
|
||||
</Badge>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Dispatch, SetStateAction, useState } from 'react';
|
||||
import { X } from '@signozhq/icons';
|
||||
import { Col, Tooltip } from 'antd';
|
||||
import Input from 'components/Input';
|
||||
|
||||
@@ -60,12 +61,7 @@ function AddTags({ tags, setTags }: AddTagsProps): JSX.Element {
|
||||
const isLongTag = tag.length > 20;
|
||||
|
||||
const tagElem = (
|
||||
<NewTagContainer
|
||||
closable
|
||||
key={tag}
|
||||
onClose={(): void => handleClose(tag)}
|
||||
className="tag-container"
|
||||
>
|
||||
<NewTagContainer key={tag} color="vanilla" className="tag-container">
|
||||
<span
|
||||
onDoubleClick={(e): void => {
|
||||
setEditInputIndex(index);
|
||||
@@ -75,6 +71,11 @@ function AddTags({ tags, setTags }: AddTagsProps): JSX.Element {
|
||||
>
|
||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
||||
</span>
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={(): void => handleClose(tag)}
|
||||
/>
|
||||
</NewTagContainer>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Col, Tag } from 'antd';
|
||||
import { Col } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const TagsContainer = styled.div`
|
||||
@@ -8,7 +9,7 @@ export const TagsContainer = styled.div`
|
||||
gap: 6px;
|
||||
`;
|
||||
|
||||
export const NewTagContainer = styled(Tag)`
|
||||
export const NewTagContainer = styled(Badge)`
|
||||
&&& {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { X } from '@signozhq/icons';
|
||||
import { QueryChipContainer, QueryChipItem } from './styles';
|
||||
import { ILabelRecord } from './types';
|
||||
|
||||
@@ -13,11 +14,15 @@ export default function QueryChip({
|
||||
const { key, value } = queryData;
|
||||
return (
|
||||
<QueryChipContainer>
|
||||
<QueryChipItem
|
||||
closable={key !== 'severity' && key !== 'description'}
|
||||
onClose={(): void => onRemove(key)}
|
||||
>
|
||||
<QueryChipItem color="vanilla">
|
||||
{key}: {value}
|
||||
{key !== 'severity' && key !== 'description' && (
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={(): void => onRemove(key)}
|
||||
/>
|
||||
)}
|
||||
</QueryChipItem>
|
||||
</QueryChipContainer>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { grey } from '@ant-design/colors';
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface SearchContainerProps {
|
||||
@@ -29,6 +29,6 @@ export const QueryChipContainer = styled.span`
|
||||
}
|
||||
`;
|
||||
|
||||
export const QueryChipItem = styled(Tag)`
|
||||
export const QueryChipItem = styled(Badge)`
|
||||
margin-right: 0.1rem;
|
||||
`;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { Button, Skeleton, Tag } from 'antd';
|
||||
import { Button, Skeleton } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { useListRules } from 'api/generated/services/rules';
|
||||
import type { RuletypesRuleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
@@ -177,12 +178,14 @@ export default function AlertRules({
|
||||
</div>
|
||||
|
||||
<div className="alert-rule-item-description home-data-item-tag">
|
||||
<Tag color={rule?.labels?.severity}>{rule?.labels?.severity}</Tag>
|
||||
<Badge color="sienna" variant="outline">
|
||||
{rule?.labels?.severity}
|
||||
</Badge>
|
||||
|
||||
{rule.state === 'firing' && (
|
||||
<Tag color="red" className="firing-tag">
|
||||
<Badge color="cherry" variant="outline" className="firing-tag">
|
||||
{rule.state}
|
||||
</Tag>
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button, Skeleton, Tag } from 'antd';
|
||||
import { Button, Skeleton } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { useGetAllDashboard } from 'hooks/dashboard/useGetAllDashboard';
|
||||
@@ -148,9 +149,9 @@ export default function Dashboards({
|
||||
|
||||
<div className="alert-rule-item-description home-data-item-tag">
|
||||
{dashboard.data.tags?.map((tag) => (
|
||||
<Tag color={tag} key={tag}>
|
||||
<Badge color="sienna" variant="outline" key={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -574,30 +574,7 @@
|
||||
|
||||
.home-data-item-tag {
|
||||
display: flex;
|
||||
|
||||
.ant-tag {
|
||||
display: flex;
|
||||
padding: 2px 12px;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
border-radius: 20px;
|
||||
border: 1px solid color-mix(in srgb, var(--bg-sienna-500) 20%, transparent);
|
||||
background: color-mix(in srgb, var(--bg-sienna-500) 10%, transparent);
|
||||
|
||||
color: var(--bg-sienna-400);
|
||||
text-align: center;
|
||||
font-family: Inter;
|
||||
font-size: 12px;
|
||||
font-style: normal;
|
||||
line-height: 20px; /* 142.857% */
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
|
||||
.firing-tag {
|
||||
color: var(--bg-sakura-500);
|
||||
background: color-mix(in srgb, var(--danger-background) 10%, transparent);
|
||||
}
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
&.services-list-container {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button, Skeleton, Tag } from 'antd';
|
||||
import { Button, Skeleton } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
import { getViewDetailsUsingViewKey } from 'components/ExplorerCard/utils';
|
||||
import ROUTES from 'constants/routes';
|
||||
@@ -249,9 +250,9 @@ export default function SavedViews({
|
||||
}
|
||||
|
||||
return (
|
||||
<Tag color={tag} key={tag}>
|
||||
<Badge color="sienna" key={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
</Badge>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Progress } from '@signozhq/ui/progress';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import {
|
||||
@@ -52,14 +52,14 @@ export const hostDetailsMetadataConfig: K8sDetailsMetadataConfig<HostData>[] = [
|
||||
label: 'STATUS',
|
||||
getValue: (h): string => (h.active ? 'ACTIVE' : 'INACTIVE'),
|
||||
render: (value, h): React.ReactNode => (
|
||||
<Tag
|
||||
<Badge
|
||||
variant="outline"
|
||||
className={`${infraHostsStyles.infraMonitoringTags} ${
|
||||
h.active ? infraHostsStyles.tagsActive : infraHostsStyles.tagsInactive
|
||||
}`}
|
||||
bordered
|
||||
>
|
||||
{value}
|
||||
</Tag>
|
||||
</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -67,9 +67,9 @@ export const hostDetailsMetadataConfig: K8sDetailsMetadataConfig<HostData>[] = [
|
||||
getValue: (h): string => h.os || '-',
|
||||
render: (value): React.ReactNode =>
|
||||
value !== '-' ? (
|
||||
<Tag className={infraHostsStyles.infraMonitoringTags} bordered>
|
||||
<Badge variant="outline" className={infraHostsStyles.infraMonitoringTags}>
|
||||
{value}
|
||||
</Tag>
|
||||
</Badge>
|
||||
) : (
|
||||
<Typography.Text>-</Typography.Text>
|
||||
),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Tag, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { HostData } from 'api/infraMonitoring/getHostLists';
|
||||
import TanStackTable, { TableColumnDef } from 'components/TanStackTableView';
|
||||
import { getGroupByEl } from 'container/InfraMonitoringK8s/Base/utils';
|
||||
@@ -92,14 +93,13 @@ export const hostColumnsConfig: TableColumnDef<HostData>[] = [
|
||||
cell: ({ value }): React.ReactNode => {
|
||||
const active = value as boolean;
|
||||
return (
|
||||
<Tag
|
||||
bordered
|
||||
<Badge
|
||||
className={`${styles.statusTag} ${
|
||||
active ? styles.statusTagActive : styles.statusTagInactive
|
||||
}`}
|
||||
>
|
||||
{active ? 'ACTIVE' : 'INACTIVE'}
|
||||
</Tag>
|
||||
</Badge>
|
||||
);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:global(.ant-tag .ant-typography) {
|
||||
:global([data-slot='badge'] .ant-typography) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:global(.ant-tag .ant-typography) {
|
||||
:global([data-slot='badge'] .ant-typography) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:global(.ant-tag .ant-typography) {
|
||||
:global([data-slot='badge'] .ant-typography) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:global(.ant-tag .ant-typography) {
|
||||
:global([data-slot='badge'] .ant-typography) {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { TableColumnsType as ColumnsType, Tag } from 'antd';
|
||||
import { TableColumnsType as ColumnsType } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util';
|
||||
@@ -93,9 +94,9 @@ export const getTraceListColumns = (
|
||||
if (primaryKey === 'httpMethod' || primaryKey === 'responseStatusCode') {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(itemData)} openInNewTab>
|
||||
<Tag data-testid={key} color="magenta">
|
||||
<Badge data-testid={key} color="sakura">
|
||||
{getValueForKey(itemData, key)}
|
||||
</Tag>
|
||||
</Badge>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-tag .ant-typography {
|
||||
[data-slot='badge'] .ant-typography {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
@@ -349,7 +349,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-tag .ant-typography {
|
||||
[data-slot='badge'] .ant-typography {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
Table,
|
||||
TablePaginationConfig,
|
||||
TableProps as AntDTableProps,
|
||||
Tag,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
@@ -1055,7 +1054,10 @@ function MultiIngestionSettings(): JSX.Element {
|
||||
<div className="ingestion-key-tags">
|
||||
{APIKey.tags.map((tag, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<Tag key={`${tag}-${index}`}> {tag} </Tag>
|
||||
<Badge key={`${tag}-${index}`} color="vanilla">
|
||||
{' '}
|
||||
{tag}{' '}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -310,9 +310,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
|
||||
return <Typography>-</Typography>;
|
||||
}
|
||||
|
||||
return (
|
||||
<LabelColumn labels={withOutSeverityKeys} value={value} color="magenta" />
|
||||
);
|
||||
return <LabelColumn labels={withOutSeverityKeys} value={value} />;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,26 +1,46 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import type { RuletypesRuleDTO } from 'api/generated/services/sigNoz.schemas';
|
||||
|
||||
function Status({ status }: StatusProps): JSX.Element {
|
||||
switch (status) {
|
||||
case 'inactive': {
|
||||
return <Tag color="green">OK</Tag>;
|
||||
return (
|
||||
<Badge color="forest" variant="outline">
|
||||
OK
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
case 'pending': {
|
||||
return <Tag color="orange">Pending</Tag>;
|
||||
return (
|
||||
<Badge color="amber" variant="outline">
|
||||
Pending
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
case 'firing': {
|
||||
return <Tag color="red">Firing</Tag>;
|
||||
return (
|
||||
<Badge color="cherry" variant="outline">
|
||||
Firing
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
case 'disabled': {
|
||||
return <Tag>Disabled</Tag>;
|
||||
return (
|
||||
<Badge color="vanilla" variant="outline">
|
||||
Disabled
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
default: {
|
||||
return <Tag color="default">Unknown</Tag>;
|
||||
return (
|
||||
<Badge color="vanilla" variant="outline">
|
||||
Unknown
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ import {
|
||||
Popover,
|
||||
Skeleton,
|
||||
Table,
|
||||
Tag,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { TableProps } from 'antd/lib';
|
||||
@@ -420,15 +420,15 @@ function DashboardsList(): JSX.Element {
|
||||
{dashboard?.tags && dashboard.tags.length > 0 && (
|
||||
<div className="dashboard-tags">
|
||||
{dashboard.tags.slice(0, 3).map((tag) => (
|
||||
<Tag className="tag" key={tag}>
|
||||
<Badge className="tag" color="vanilla" key={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
</Badge>
|
||||
))}
|
||||
|
||||
{dashboard.tags.length > 3 && (
|
||||
<Tag className="tag" key={dashboard.tags[3]}>
|
||||
<Badge className="tag" color="vanilla" key={dashboard.tags[3]}>
|
||||
+ <span> {dashboard.tags.length - 3} </span>
|
||||
</Tag>
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const TagContainer = styled(Tag)`
|
||||
export const TagContainer = styled(Badge)`
|
||||
&&& {
|
||||
border-color: var(--bg-slate-400);
|
||||
border-radius: 0.25rem;
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
padding-top: 12px;
|
||||
}
|
||||
|
||||
.ant-tag-borderless {
|
||||
[data-slot='badge'] {
|
||||
border-radius: 2px;
|
||||
background: color-mix(in srgb, var(--bg-robin-400) 8%, transparent);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ import MEditor, { EditorProps, Monaco } from '@monaco-editor/react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button } from '@signozhq/ui/button';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import { Collapse, Divider, Input, Tag } from 'antd';
|
||||
import { Collapse, Divider, Input } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { AddToQueryHOCProps } from 'components/Logs/AddToQueryHOC';
|
||||
import { ChangeViewFunctionType } from 'container/ExplorerOptions/types';
|
||||
@@ -104,11 +105,11 @@ function Overview({
|
||||
{
|
||||
key: '1',
|
||||
label: (
|
||||
<Tag bordered={false}>
|
||||
<Badge color="vanilla">
|
||||
<Typography.Text style={{ color: Color.BG_ROBIN_400 }}>
|
||||
body
|
||||
</Typography.Text>
|
||||
</Tag>
|
||||
</Badge>
|
||||
),
|
||||
children: (
|
||||
<div className="logs-body-content">
|
||||
@@ -142,7 +143,7 @@ function Overview({
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
// extra: <Tag className="tag">JSON</Tag>,
|
||||
// extra: <Badge className="tag" color="vanilla">JSON</Badge>,
|
||||
className: 'collapse-content',
|
||||
},
|
||||
]}
|
||||
@@ -163,11 +164,11 @@ function Overview({
|
||||
className="attribute-tab-header"
|
||||
onClick={toogleAttributePanelOpenState}
|
||||
>
|
||||
<Tag bordered={false}>
|
||||
<Badge color="vanilla">
|
||||
<Typography.Text style={{ color: Color.BG_ROBIN_400 }}>
|
||||
Attributes
|
||||
</Typography.Text>
|
||||
</Tag>
|
||||
</Badge>
|
||||
|
||||
{isAttributesExpanded && (
|
||||
<Button
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-tag .ant-typography {
|
||||
[data-slot='badge'] .ant-typography {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useMutation } from 'react-query';
|
||||
import { Radio, RadioChangeEvent, Tag } from 'antd';
|
||||
import { Radio, RadioChangeEvent } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Switch } from '@signozhq/ui/switch';
|
||||
import setLocalStorageApi from 'api/browser/localstorage/set';
|
||||
import logEvent from 'api/common/logEvent';
|
||||
@@ -64,9 +65,7 @@ function MySettings(): JSX.Element {
|
||||
label: (
|
||||
<div className="theme-option">
|
||||
<Sun size={12} data-testid="light-theme-icon" /> Light{' '}
|
||||
<Tag bordered={false} color="geekblue">
|
||||
Beta
|
||||
</Tag>
|
||||
<Badge color="robin">Beta</Badge>
|
||||
</div>
|
||||
),
|
||||
value: 'light',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tag as AntDTag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Container = styled.div`
|
||||
@@ -20,6 +20,6 @@ export const PanelContainer = styled.div`
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
export const Tag = styled(AntDTag)`
|
||||
export const Tag = styled(Badge)`
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
function Tags({ tags }: TagsProps): JSX.Element {
|
||||
return (
|
||||
<span>
|
||||
{tags?.map((tag) => (
|
||||
<Tag color="magenta" key={tag}>
|
||||
<Badge color="sakura" key={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
</Badge>
|
||||
))}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CircleAlert, CircleX } from '@signozhq/icons';
|
||||
import { Button, Input, InputRef, message, Modal, Tag, Tooltip } from 'antd';
|
||||
import { CircleAlert, CircleX, X } from '@signozhq/icons';
|
||||
import { Button, Input, InputRef, message, Modal, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
import { tagInputStyle } from '../PipelineListsView/config';
|
||||
import { TagInputWrapper } from './styles';
|
||||
@@ -90,12 +91,7 @@ function TagInput({
|
||||
}
|
||||
const isLongTag = tag.length > 20;
|
||||
const tagElem = (
|
||||
<Tag
|
||||
key={tag}
|
||||
closable
|
||||
style={{ userSelect: 'none' }}
|
||||
onClose={handleClose(tag)}
|
||||
>
|
||||
<Badge key={tag} color="vanilla" style={{ userSelect: 'none' }}>
|
||||
<span
|
||||
onDoubleClick={(e): void => {
|
||||
setEditInputIndex(index);
|
||||
@@ -105,7 +101,12 @@ function TagInput({
|
||||
>
|
||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
||||
</span>
|
||||
</Tag>
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={handleClose(tag)}
|
||||
/>
|
||||
</Badge>
|
||||
);
|
||||
return isLongTag ? (
|
||||
<Tooltip title={tag} key={tag}>
|
||||
|
||||
@@ -4,12 +4,20 @@ exports[`PipelinePage container test should render Tags section 1`] = `
|
||||
<DocumentFragment>
|
||||
<span>
|
||||
<span
|
||||
class="ant-tag ant-tag-magenta css-dev-only-do-not-override-2i2tap"
|
||||
class="_badge_1jqif_1"
|
||||
data-capitalize="false"
|
||||
data-color="sakura"
|
||||
data-slot="badge"
|
||||
data-variant="default"
|
||||
>
|
||||
server
|
||||
</span>
|
||||
<span
|
||||
class="ant-tag ant-tag-magenta css-dev-only-do-not-override-2i2tap"
|
||||
class="_badge_1jqif_1"
|
||||
data-capitalize="false"
|
||||
data-color="sakura"
|
||||
data-slot="badge"
|
||||
data-variant="default"
|
||||
>
|
||||
app
|
||||
</span>
|
||||
|
||||
@@ -53,12 +53,6 @@
|
||||
margin-bottom: 8px;
|
||||
overflow: auto;
|
||||
max-height: 100px;
|
||||
.ant-tag {
|
||||
user-select: none;
|
||||
height: 28px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-select {
|
||||
@@ -95,61 +89,8 @@
|
||||
}
|
||||
|
||||
.alert-rule-tags {
|
||||
.ant-tag {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid color-mix(in srgb, var(--bg-robin-400) 20%, transparent);
|
||||
background: color-mix(in srgb, var(--bg-robin-400) 10%, transparent);
|
||||
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
|
||||
padding-right: 0px;
|
||||
border-right: 0;
|
||||
color: var(--bg-robin-400);
|
||||
|
||||
.ant-tag-close-icon {
|
||||
height: 28px;
|
||||
width: 20px !important;
|
||||
justify-content: center;
|
||||
border-left: 1px solid
|
||||
color-mix(in srgb, var(--bg-robin-400) 20%, transparent);
|
||||
border-radius: 0px 2px 2px 0px;
|
||||
background: color-mix(in srgb, var(--bg-robin-400) 30%, transparent);
|
||||
border-right: 1px solid
|
||||
color-mix(in srgb, var(--bg-robin-400) 20%, transparent);
|
||||
margin-right: 0px;
|
||||
|
||||
svg {
|
||||
fill: var(--primary-background);
|
||||
}
|
||||
}
|
||||
}
|
||||
.non-closable-tag {
|
||||
padding-right: 7px;
|
||||
border-right: 1px solid
|
||||
color-mix(in srgb, var(--bg-robin-400) 20%, transparent);
|
||||
}
|
||||
|
||||
.red-tag.non-closable-tag {
|
||||
border-right: 1px solid
|
||||
color-mix(in srgb, var(--bg-sakura-500) 20%, transparent) !important;
|
||||
}
|
||||
|
||||
.red-tag {
|
||||
border: 1px solid color-mix(in srgb, var(--bg-sakura-500) 20%, transparent);
|
||||
background: color-mix(in srgb, var(--bg-sakura-500) 10%, transparent);
|
||||
border-right: 0;
|
||||
color: var(--bg-sakura-400);
|
||||
|
||||
.ant-tag-close-icon {
|
||||
background: color-mix(in srgb, var(--bg-sakura-500) 30%, transparent);
|
||||
border-left: 1px solid
|
||||
color-mix(in srgb, var(--bg-sakura-500) 20%, transparent);
|
||||
border-right: 1px solid
|
||||
color-mix(in srgb, var(--bg-sakura-500) 20%, transparent);
|
||||
|
||||
svg {
|
||||
fill: var(--bg-sakura-500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,9 +198,6 @@
|
||||
line-height: 18px;
|
||||
letter-spacing: -0.07px;
|
||||
}
|
||||
.ant-tag {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
@@ -314,12 +252,6 @@
|
||||
width: 540px;
|
||||
max-height: 100px;
|
||||
overflow: auto;
|
||||
|
||||
.ant-tag {
|
||||
height: 28px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
.ant-collapse-content-active {
|
||||
border-top: 0;
|
||||
|
||||
@@ -311,7 +311,7 @@ export function PlannedDowntimeForm(
|
||||
default:
|
||||
return `Scheduled for ${formattedStartDate} starting at ${formattedStartTime}.`;
|
||||
}
|
||||
}, [formData, recurrenceType, timezone]);
|
||||
}, [formData, recurrenceType]);
|
||||
|
||||
const endTimeText = useMemo((): string => {
|
||||
const endTime = formData.endTime;
|
||||
@@ -322,7 +322,7 @@ export function PlannedDowntimeForm(
|
||||
const formattedEndTime = endTime.format(TIME_FORMAT);
|
||||
const formattedEndDate = endTime.format(DATE_FORMAT);
|
||||
return `Scheduled to end maintenance on ${formattedEndDate} at ${formattedEndTime}.`;
|
||||
}, [formData, recurrenceType, timezone]);
|
||||
}, [formData, recurrenceType]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, { ReactNode, useEffect } from 'react';
|
||||
import { UseQueryResult } from 'react-query';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Collapse, Flex, Space, Table, TableProps, Tag, Tooltip } from 'antd';
|
||||
import { Collapse, Flex, Space, Table, TableProps, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import type { DefaultOptionType } from 'antd/es/select';
|
||||
import type {
|
||||
@@ -15,7 +16,7 @@ import cx from 'classnames';
|
||||
import dayjs from 'dayjs';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { defaultTo } from 'lodash-es';
|
||||
import { CalendarClock, PenLine, Trash2 } from '@signozhq/icons';
|
||||
import { CalendarClock, PenLine, Trash2, X } from '@signozhq/icons';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
|
||||
@@ -48,10 +49,10 @@ export function AlertRuleTags(props: AlertRuleTagsProps): JSX.Element {
|
||||
{selectedTags?.map((tag: DefaultOptionType, index: number) => {
|
||||
const isLongTag = (tag?.label as string)?.length > 20;
|
||||
const tagElem = (
|
||||
<Tag
|
||||
<Badge
|
||||
key={tag.value}
|
||||
onClose={(): void => handleClose?.(tag?.value)}
|
||||
closable={closable}
|
||||
color={index % 2 ? 'sakura' : 'robin'}
|
||||
variant="outline"
|
||||
className={cx(
|
||||
{ 'red-tag': index % 2 },
|
||||
{ 'non-closable-tag': !closable },
|
||||
@@ -62,7 +63,14 @@ export function AlertRuleTags(props: AlertRuleTagsProps): JSX.Element {
|
||||
? `${(tag?.label as string | null)?.slice(0, 20)}...`
|
||||
: tag?.label}
|
||||
</span>
|
||||
</Tag>
|
||||
{closable && (
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={(): void => handleClose?.(tag?.value)}
|
||||
/>
|
||||
)}
|
||||
</Badge>
|
||||
);
|
||||
return isLongTag ? (
|
||||
<Tooltip title={tag?.label} key={tag?.value}>
|
||||
@@ -93,7 +101,7 @@ function HeaderComponent({
|
||||
<Flex className="header-content" justify="space-between">
|
||||
<Flex gap={8}>
|
||||
<Typography>{name}</Typography>
|
||||
<Tag>{duration}</Tag>
|
||||
<Badge color="vanilla">{duration}</Badge>
|
||||
</Flex>
|
||||
|
||||
{isCrudEnabled && (
|
||||
@@ -155,9 +163,7 @@ export function CollapseListContent({
|
||||
created_by_name ? (
|
||||
<Flex gap={8}>
|
||||
<Typography>{created_by_name}</Typography>
|
||||
{created_by_email && (
|
||||
<Tag style={{ borderRadius: 20 }}>{created_by_email}</Tag>
|
||||
)}
|
||||
{created_by_email && <Badge color="vanilla">{created_by_email}</Badge>}
|
||||
</Flex>
|
||||
) : (
|
||||
'-'
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const StyledText = styled.span`
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
export const StyledTag = styled(Tag)`
|
||||
export const StyledTag = styled(Badge)`
|
||||
margin-top: 0.125rem;
|
||||
margin-bottom: 0.125rem;
|
||||
padding-left: 0.5rem;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { X } from '@signozhq/icons';
|
||||
|
||||
import { HavingFilterTagProps } from './HavingFilterTag.interfaces';
|
||||
import { StyledTag, StyledText } from './HavingFilterTag.styled';
|
||||
|
||||
@@ -12,10 +14,17 @@ export function HavingFilterTag({
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledTag closable={closable} onClose={onClose}>
|
||||
<StyledTag color="vanilla">
|
||||
<span role="button" tabIndex={0} onClick={handleClick}>
|
||||
<StyledText>{value}</StyledText>
|
||||
</span>
|
||||
{closable && (
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={onClose}
|
||||
/>
|
||||
)}
|
||||
</StyledTag>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,8 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Button, Select, Spin, Tag, Tooltip } from 'antd';
|
||||
import { Button, Select, Spin, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import cx from 'classnames';
|
||||
import {
|
||||
@@ -37,6 +38,7 @@ import {
|
||||
CornerDownLeft,
|
||||
Filter,
|
||||
Slash,
|
||||
X,
|
||||
} from '@signozhq/icons';
|
||||
import type { BaseSelectRef } from 'rc-select';
|
||||
import {
|
||||
@@ -199,7 +201,7 @@ function QueryBuilderSearch({
|
||||
const isDisabled = !!searchValue;
|
||||
|
||||
return (
|
||||
<Tag closable={!searchValue && closable} onClose={onCloseHandler}>
|
||||
<Badge color="vanilla">
|
||||
<Tooltip title={chipValue}>
|
||||
<TypographyText
|
||||
$isInNin={isInNin}
|
||||
@@ -213,7 +215,14 @@ function QueryBuilderSearch({
|
||||
{chipValue}
|
||||
</TypographyText>
|
||||
</Tooltip>
|
||||
</Tag>
|
||||
{!searchValue && closable && (
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={onCloseHandler}
|
||||
/>
|
||||
)}
|
||||
</Badge>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Check } from '@signozhq/icons';
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const TypographyText = styled.span<{
|
||||
@@ -22,7 +22,7 @@ export const StyledCheckOutlined = styled(Check)`
|
||||
float: right;
|
||||
`;
|
||||
|
||||
export const TagContainer = styled(Tag)`
|
||||
export const TagContainer = styled(Badge)`
|
||||
&&& {
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
|
||||
@@ -225,7 +225,7 @@
|
||||
}
|
||||
|
||||
.qb-search-bar-tokenised-tags {
|
||||
.ant-tag {
|
||||
[data-slot='badge'] {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 2px 0px 0px 2px;
|
||||
@@ -244,7 +244,7 @@
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.ant-tag-close-icon {
|
||||
.close-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -265,7 +265,7 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ant-tag-close-icon {
|
||||
.close-icon {
|
||||
background: color-mix(in srgb, var(--bg-aqua-400) 6%, transparent);
|
||||
}
|
||||
}
|
||||
@@ -278,7 +278,7 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ant-tag-close-icon {
|
||||
.close-icon {
|
||||
background: color-mix(in srgb, var(--bg-sienna-400) 10%, transparent);
|
||||
}
|
||||
}
|
||||
@@ -292,7 +292,7 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.ant-tag-close-icon {
|
||||
.close-icon {
|
||||
background: color-mix(in srgb, var(--bg-robin-400) 10%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Select, Spin, Tag, Tooltip } from 'antd';
|
||||
import { Select, Spin, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import cx from 'classnames';
|
||||
import {
|
||||
DATA_TYPE_VS_ATTRIBUTE_VALUES_KEY,
|
||||
@@ -38,7 +39,7 @@ import {
|
||||
isUndefined,
|
||||
unset,
|
||||
} from 'lodash-es';
|
||||
import { ChevronDown, ChevronUp } from '@signozhq/icons';
|
||||
import { ChevronDown, ChevronUp, X } from '@signozhq/icons';
|
||||
import type { BaseSelectRef } from 'rc-select';
|
||||
import {
|
||||
BaseAutocompleteData,
|
||||
@@ -954,11 +955,7 @@ function QueryBuilderSearchV2(
|
||||
|
||||
return (
|
||||
<span className="qb-search-bar-tokenised-tags">
|
||||
<Tag
|
||||
closable={!searchValue && closable}
|
||||
onClose={onCloseHandler}
|
||||
className={tagDetails?.key?.type || ''}
|
||||
>
|
||||
<Badge color="vanilla" className={tagDetails?.key?.type || ''}>
|
||||
<Tooltip title={chipValue}>
|
||||
<TypographyText
|
||||
$isInNin={isInNin}
|
||||
@@ -972,7 +969,15 @@ function QueryBuilderSearchV2(
|
||||
{chipValue}
|
||||
</TypographyText>
|
||||
</Tooltip>
|
||||
</Tag>
|
||||
{!searchValue && closable && (
|
||||
<X
|
||||
size={12}
|
||||
className="close-icon"
|
||||
style={{ cursor: 'pointer' }}
|
||||
onClick={onCloseHandler}
|
||||
/>
|
||||
)}
|
||||
</Badge>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ant-tag .ant-typography {
|
||||
[data-slot='badge'] .ant-typography {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { X } from '@signozhq/icons';
|
||||
import {
|
||||
convertMetricKeyToTrace,
|
||||
getResourceDeploymentKeys,
|
||||
@@ -20,13 +21,19 @@ function QueryChip({ queryData, onClose }: IQueryChipProps): JSX.Element {
|
||||
|
||||
return (
|
||||
<QueryChipContainer>
|
||||
<QueryChipItem>{convertMetricKeyToTrace(queryData.tagKey)}</QueryChipItem>
|
||||
<QueryChipItem>{queryData.operator}</QueryChipItem>
|
||||
<QueryChipItem
|
||||
closable={queryData.tagKey !== getResourceDeploymentKeys(dotMetricsEnabled)}
|
||||
onClose={onCloseHandler}
|
||||
>
|
||||
<QueryChipItem color="vanilla">
|
||||
{convertMetricKeyToTrace(queryData.tagKey)}
|
||||
</QueryChipItem>
|
||||
<QueryChipItem color="vanilla">{queryData.operator}</QueryChipItem>
|
||||
<QueryChipItem color="vanilla">
|
||||
{queryData.tagValue.join(', ')}
|
||||
{queryData.tagKey !== getResourceDeploymentKeys(dotMetricsEnabled) && (
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={onCloseHandler}
|
||||
/>
|
||||
)}
|
||||
</QueryChipItem>
|
||||
</QueryChipContainer>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { grey } from '@ant-design/colors';
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const SearchContainer = styled.div`
|
||||
@@ -23,6 +23,6 @@ export const QueryChipContainer = styled.span`
|
||||
}
|
||||
`;
|
||||
|
||||
export const QueryChipItem = styled(Tag)`
|
||||
export const QueryChipItem = styled(Badge)`
|
||||
margin-right: 0.1rem;
|
||||
`;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Collapse, Flex, Tag } from 'antd';
|
||||
import { Button, Collapse, Flex } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { PenLine, Trash2 } from '@signozhq/icons';
|
||||
@@ -118,7 +119,9 @@ function PolicyListItemContent({
|
||||
<Typography>Channels</Typography>
|
||||
<div>
|
||||
{routingPolicy.channels.map((channel) => (
|
||||
<Tag key={channel}>{channel}</Tag>
|
||||
<Badge key={channel} color="vanilla">
|
||||
{channel}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Tag, Tooltip } from 'antd';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import cx from 'classnames';
|
||||
import { Pin, PinOff } from '@signozhq/icons';
|
||||
|
||||
@@ -58,17 +59,17 @@ export default function NavItem({
|
||||
|
||||
{isBeta && (
|
||||
<div className="nav-item-beta">
|
||||
<Tag bordered={false} className="sidenav-beta-tag">
|
||||
<Badge color="robin" className="sidenav-beta-tag">
|
||||
Beta
|
||||
</Tag>
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isNew && (
|
||||
<div className="nav-item-new">
|
||||
<Tag bordered={false} className="sidenav-new-tag">
|
||||
<Badge color="robin" className="sidenav-new-tag">
|
||||
New
|
||||
</Tag>
|
||||
</Badge>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { HTMLAttributes } from 'react';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { TableColumnsType as ColumnsType, TableProps, Tag } from 'antd';
|
||||
import { TableColumnsType as ColumnsType, TableProps } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { ResizeTable } from 'components/ResizeTable';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
@@ -70,7 +71,7 @@ function TraceTable(): JSX.Element {
|
||||
if (value.length === 0) {
|
||||
return <Typography>-</Typography>;
|
||||
}
|
||||
return <Tag color="magenta">{value}</Tag>;
|
||||
return <Badge color="sakura">{value}</Badge>;
|
||||
};
|
||||
|
||||
const columns: ColumnsType<TableType> = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { TableColumnsType as ColumnsType } from 'antd';
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { TelemetryFieldKey } from 'api/v5/v5';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
@@ -107,9 +107,9 @@ export const getListColumns = (
|
||||
) {
|
||||
return (
|
||||
<BlockLink to={getTraceLink(item)} openInNewTab={false}>
|
||||
<Tag data-testid={name} color="magenta">
|
||||
<Badge data-testid={name} color="sakura" variant="outline">
|
||||
{value}
|
||||
</Tag>
|
||||
</Badge>
|
||||
</BlockLink>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useCallback, useMemo, useRef } from 'react';
|
||||
import { X } from '@signozhq/icons';
|
||||
import type { SelectProps } from 'antd';
|
||||
import { Tag, Tooltip } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Tooltip } from 'antd';
|
||||
import type { BaseOptionType } from 'antd/es/select';
|
||||
import { Alerts } from 'types/api/alerts/getTriggered';
|
||||
|
||||
@@ -83,14 +85,16 @@ function Filter({
|
||||
const { closable, onClose, label } = props;
|
||||
|
||||
return (
|
||||
<Tag
|
||||
color="magenta"
|
||||
closable={closable}
|
||||
onClose={onClose}
|
||||
style={{ marginRight: 3 }}
|
||||
>
|
||||
<Badge color="sakura" style={{ marginRight: 3 }}>
|
||||
{label}
|
||||
</Tag>
|
||||
{closable && (
|
||||
<X
|
||||
size={12}
|
||||
style={{ cursor: 'pointer', marginInlineStart: 4 }}
|
||||
onClick={(): void => onClose()}
|
||||
/>
|
||||
)}
|
||||
</Badge>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
|
||||
import { useTimezone } from 'providers/Timezone';
|
||||
@@ -51,7 +51,7 @@ function ExapandableRow({ allAlerts }: ExapandableRowProps): JSX.Element {
|
||||
<TableCell minWidth="90px" overflowX="scroll">
|
||||
<div>
|
||||
{tags.map((e) => (
|
||||
<Tag key={e}>{`${e}:${labels[e]}`}</Tag>
|
||||
<Badge color="vanilla" key={e}>{`${e}:${labels[e]}`}</Badge>
|
||||
))}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { SquareMinus, SquarePlus } from '@signozhq/icons';
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { Alerts } from 'types/api/alerts/getTriggered';
|
||||
|
||||
import ExapandableRow from './ExapandableRow';
|
||||
@@ -26,9 +26,9 @@ function TableRowComponent({
|
||||
</IconContainer>
|
||||
<>
|
||||
{tags.map((tag) => (
|
||||
<Tag color="magenta" key={tag}>
|
||||
<Badge color="sakura" key={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
</Badge>
|
||||
))}
|
||||
</>
|
||||
</StatusContainer>
|
||||
|
||||
@@ -59,9 +59,7 @@ function NoFilterTable({
|
||||
return <Typography>-</Typography>;
|
||||
}
|
||||
|
||||
return (
|
||||
<LabelColumn labels={withOutSeverityKeys} value={labels} color="magenta" />
|
||||
);
|
||||
return <LabelColumn labels={withOutSeverityKeys} value={labels} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
function Severity({ severity }: SeverityProps): JSX.Element {
|
||||
switch (severity) {
|
||||
case 'unprocessed': {
|
||||
return <Tag color="green">UnProcessed</Tag>;
|
||||
return <Badge color="forest">UnProcessed</Badge>;
|
||||
}
|
||||
|
||||
case 'active': {
|
||||
return <Tag color="red">Firing</Tag>;
|
||||
return <Badge color="cherry">Firing</Badge>;
|
||||
}
|
||||
|
||||
case 'suppressed': {
|
||||
return <Tag color="red">Suppressed</Tag>;
|
||||
return <Badge color="cherry">Suppressed</Badge>;
|
||||
}
|
||||
|
||||
default: {
|
||||
return <Tag color="default">Unknown Status</Tag>;
|
||||
return <Badge color="vanilla">Unknown Status</Badge>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
import { createBrowserHistory } from 'history';
|
||||
import { getBasePath } from 'utils/basePath';
|
||||
|
||||
export default createBrowserHistory({ basename: getBasePath() });
|
||||
const history = createBrowserHistory({ basename: getBasePath() });
|
||||
|
||||
let inAppPushCount = 0;
|
||||
history.listen((_, action) => {
|
||||
if (action === 'PUSH') {
|
||||
inAppPushCount += 1;
|
||||
}
|
||||
});
|
||||
|
||||
export const hasInAppHistory = (): boolean => inAppPushCount > 0;
|
||||
|
||||
export default history;
|
||||
|
||||
@@ -16,7 +16,7 @@ import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { convertTimeToRelevantUnit } from 'container/TraceDetail/utils';
|
||||
import dayjs from 'dayjs';
|
||||
import history from 'lib/history';
|
||||
import history, { hasInAppHistory } from 'lib/history';
|
||||
import {
|
||||
ArrowLeft,
|
||||
CalendarClock,
|
||||
@@ -96,13 +96,7 @@ function TraceDetailsHeader({
|
||||
}, [traceID]);
|
||||
|
||||
const handlePreviousBtnClick = useCallback((): void => {
|
||||
const isSpaNavigate =
|
||||
document.referrer &&
|
||||
// oxlint-disable-next-line signoz/no-raw-absolute-path
|
||||
new URL(document.referrer).origin === window.location.origin;
|
||||
const hasBackHistory = window.history.length > 1;
|
||||
|
||||
if (isSpaNavigate && hasBackHistory) {
|
||||
if (hasInAppHistory()) {
|
||||
history.goBack();
|
||||
} else {
|
||||
history.push(ROUTES.TRACES_EXPLORER);
|
||||
@@ -130,6 +124,7 @@ function TraceDetailsHeader({
|
||||
size="md"
|
||||
className={styles.backBtn}
|
||||
onClick={handlePreviousBtnClick}
|
||||
aria-label="Back"
|
||||
>
|
||||
<ArrowLeft size={14} />
|
||||
</Button>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
import ROUTES from 'constants/routes';
|
||||
import { render } from 'tests/test-utils';
|
||||
|
||||
import TraceDetailsHeader from '../TraceDetailsHeader';
|
||||
|
||||
const mockGoBack = jest.fn();
|
||||
const mockPush = jest.fn();
|
||||
const mockHasInAppHistory = jest.fn();
|
||||
|
||||
jest.mock('lib/history', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
goBack: (): void => mockGoBack(),
|
||||
push: (path: string): void => mockPush(path),
|
||||
replace: jest.fn(),
|
||||
location: { pathname: '/', search: '' },
|
||||
listen: (): (() => void) => (): void => undefined,
|
||||
},
|
||||
hasInAppHistory: (): boolean => mockHasInAppHistory(),
|
||||
}));
|
||||
|
||||
const baseProps = {
|
||||
filterMetadata: {
|
||||
startTime: 0,
|
||||
endTime: 1,
|
||||
traceId: 'trace-123',
|
||||
},
|
||||
onFilteredSpansChange: jest.fn(),
|
||||
isDataLoaded: false,
|
||||
};
|
||||
|
||||
describe('TraceDetailsHeader – back button', () => {
|
||||
beforeEach(() => {
|
||||
mockGoBack.mockClear();
|
||||
mockPush.mockClear();
|
||||
mockHasInAppHistory.mockReset();
|
||||
});
|
||||
|
||||
it('calls history.goBack() when there is in-app SPA history', () => {
|
||||
mockHasInAppHistory.mockReturnValue(true);
|
||||
render(<TraceDetailsHeader {...baseProps} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /back/i }));
|
||||
|
||||
expect(mockGoBack).toHaveBeenCalledTimes(1);
|
||||
expect(mockPush).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('pushes to the traces explorer route when there is no in-app SPA history', () => {
|
||||
mockHasInAppHistory.mockReturnValue(false);
|
||||
render(<TraceDetailsHeader {...baseProps} />);
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: /back/i }));
|
||||
|
||||
expect(mockPush).toHaveBeenCalledTimes(1);
|
||||
expect(mockPush).toHaveBeenCalledWith(ROUTES.TRACES_EXPLORER);
|
||||
expect(mockGoBack).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,5 @@
|
||||
import { Tag } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
|
||||
export default function BetaTag(): JSX.Element {
|
||||
return (
|
||||
<Tag bordered={false} color="geekblue">
|
||||
Beta
|
||||
</Tag>
|
||||
);
|
||||
return <Badge color="robin">Beta</Badge>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Button, Tag } from 'antd';
|
||||
import { Button } from 'antd';
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { TimelineFilter } from 'container/AlertHistory/types';
|
||||
import { Undo } from '@signozhq/icons';
|
||||
|
||||
@@ -65,11 +66,7 @@ function Tabs2({
|
||||
>
|
||||
{tab.label}
|
||||
|
||||
{tab.isBeta && (
|
||||
<Tag bordered={false} color="geekblue">
|
||||
Beta
|
||||
</Tag>
|
||||
)}
|
||||
{tab.isBeta && <Badge color="robin">Beta</Badge>}
|
||||
</Button>
|
||||
))}
|
||||
</Button.Group>
|
||||
|
||||
@@ -199,16 +199,7 @@ func (q *builderQuery[T]) Execute(ctx context.Context) (*qbtypes.Result, error)
|
||||
return q.executeWindowList(ctx)
|
||||
}
|
||||
|
||||
fromMS, toMS := q.fromMS, q.toMS
|
||||
if q.spec.Signal == telemetrytypes.SignalTraces || q.spec.Signal == telemetrytypes.SignalLogs {
|
||||
var overlap bool
|
||||
fromMS, toMS, overlap = q.narrowWindowByTraceID(ctx, fromMS, toMS)
|
||||
if !overlap {
|
||||
return emptyResultFor(q.kind, q.spec.Name), nil
|
||||
}
|
||||
}
|
||||
|
||||
stmt, err := q.stmtBuilder.Build(ctx, fromMS, toMS, q.kind, q.spec, q.variables)
|
||||
stmt, err := q.stmtBuilder.Build(ctx, q.fromMS, q.toMS, q.kind, q.spec, q.variables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -224,81 +215,6 @@ func (q *builderQuery[T]) Execute(ctx context.Context) (*qbtypes.Result, error)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// narrowWindowByTraceID inspects the filter for trace_id predicates and clamps
|
||||
// [fromMS,toMS] to the time range stored in signoz_traces.distributed_trace_summary.
|
||||
// Returns the (possibly narrowed) window and overlap=false when the trace lies
|
||||
// completely outside the query window — callers should short-circuit in that case.
|
||||
//
|
||||
// When the trace_id is not present in trace_summary the behaviour differs by
|
||||
// signal:
|
||||
// - traces: trace_summary is derived from the spans table, so a missing row
|
||||
// means no spans exist for that trace_id; we short-circuit to empty.
|
||||
// - logs: logs can carry a trace_id even when traces are not ingested at all
|
||||
// (e.g. traces disabled). We must not short-circuit; instead leave the
|
||||
// window untouched and let the query run.
|
||||
func (q *builderQuery[T]) narrowWindowByTraceID(ctx context.Context, fromMS, toMS uint64) (uint64, uint64, bool) {
|
||||
if q.spec.Filter == nil || q.spec.Filter.Expression == "" {
|
||||
return fromMS, toMS, true
|
||||
}
|
||||
|
||||
traceIDs, found := telemetrytraces.ExtractTraceIDsFromFilter(q.spec.Filter.Expression)
|
||||
if !found || len(traceIDs) == 0 {
|
||||
return fromMS, toMS, true
|
||||
}
|
||||
|
||||
finder := telemetrytraces.NewTraceTimeRangeFinder(q.telemetryStore)
|
||||
traceStart, traceEnd, ok := finder.GetTraceTimeRangeMulti(ctx, traceIDs)
|
||||
if !ok {
|
||||
if q.spec.Signal == telemetrytypes.SignalTraces {
|
||||
q.logger.DebugContext(ctx, "trace_id not found in trace_summary; short-circuiting traces query to empty",
|
||||
slog.Any("trace_ids", traceIDs))
|
||||
return fromMS, toMS, false
|
||||
}
|
||||
q.logger.DebugContext(ctx, "trace_id not found in trace_summary; leaving time range untouched for logs",
|
||||
slog.Any("trace_ids", traceIDs))
|
||||
return fromMS, toMS, true
|
||||
}
|
||||
|
||||
traceStartMS := uint64(traceStart) / 1_000_000
|
||||
traceEndMS := uint64(traceEnd) / 1_000_000
|
||||
if traceStartMS == 0 || traceEndMS == 0 {
|
||||
return fromMS, toMS, true
|
||||
}
|
||||
|
||||
if traceStartMS > toMS || traceEndMS < fromMS {
|
||||
return fromMS, toMS, false
|
||||
}
|
||||
if traceStartMS > fromMS {
|
||||
fromMS = traceStartMS
|
||||
}
|
||||
if traceEndMS < toMS {
|
||||
toMS = traceEndMS
|
||||
}
|
||||
q.logger.DebugContext(ctx, "optimized time range using trace_id lookup",
|
||||
slog.String("signal", q.spec.Signal.StringValue()),
|
||||
slog.Any("trace_ids", traceIDs),
|
||||
slog.Uint64("start", fromMS),
|
||||
slog.Uint64("end", toMS))
|
||||
return fromMS, toMS, true
|
||||
}
|
||||
|
||||
// emptyResultFor returns an empty result payload appropriate for the given kind.
|
||||
func emptyResultFor(kind qbtypes.RequestType, queryName string) *qbtypes.Result {
|
||||
var value any
|
||||
switch kind {
|
||||
case qbtypes.RequestTypeTimeSeries:
|
||||
value = &qbtypes.TimeSeriesData{QueryName: queryName}
|
||||
case qbtypes.RequestTypeScalar:
|
||||
value = &qbtypes.ScalarData{QueryName: queryName}
|
||||
default:
|
||||
value = &qbtypes.RawData{QueryName: queryName}
|
||||
}
|
||||
return &qbtypes.Result{
|
||||
Type: kind,
|
||||
Value: value,
|
||||
}
|
||||
}
|
||||
|
||||
// executeWithContext executes the query with query window and step context for partial value detection.
|
||||
func (q *builderQuery[T]) executeWithContext(ctx context.Context, query string, args []any) (*qbtypes.Result, error) {
|
||||
ctx = ctxtypes.NewContextWithCommentVals(ctx, map[string]string{
|
||||
@@ -394,22 +310,42 @@ func (q *builderQuery[T]) executeWindowList(ctx context.Context) (*qbtypes.Resul
|
||||
totalBytes := uint64(0)
|
||||
start := time.Now()
|
||||
|
||||
// Check if filter contains trace_id(s) and optimize time range if needed.
|
||||
// Applies to both traces (the listing this branch was built for) and logs
|
||||
// (which carry trace_id and benefit from the same clamp before bucketing).
|
||||
if q.spec.Signal == telemetrytypes.SignalTraces || q.spec.Signal == telemetrytypes.SignalLogs {
|
||||
var overlap bool
|
||||
fromMS, toMS, overlap = q.narrowWindowByTraceID(ctx, fromMS, toMS)
|
||||
if !overlap {
|
||||
return &qbtypes.Result{
|
||||
Type: qbtypes.RequestTypeRaw,
|
||||
Value: &qbtypes.RawData{
|
||||
QueryName: q.spec.Name,
|
||||
},
|
||||
Stats: qbtypes.ExecStats{
|
||||
DurationMS: uint64(time.Since(start).Milliseconds()),
|
||||
},
|
||||
}, nil
|
||||
// Check if filter contains trace_id(s) and optimize time range if needed
|
||||
if q.spec.Signal == telemetrytypes.SignalTraces &&
|
||||
q.spec.Filter != nil && q.spec.Filter.Expression != "" {
|
||||
|
||||
traceIDs, found := telemetrytraces.ExtractTraceIDsFromFilter(q.spec.Filter.Expression)
|
||||
if found && len(traceIDs) > 0 {
|
||||
finder := telemetrytraces.NewTraceTimeRangeFinder(q.telemetryStore)
|
||||
|
||||
traceStart, traceEnd, ok := finder.GetTraceTimeRangeMulti(ctx, traceIDs)
|
||||
traceStartMS := uint64(traceStart) / 1_000_000
|
||||
traceEndMS := uint64(traceEnd) / 1_000_000
|
||||
if !ok {
|
||||
q.logger.DebugContext(ctx, "failed to get trace time range", slog.Any("trace_ids", traceIDs))
|
||||
} else if traceStartMS > 0 && traceEndMS > 0 {
|
||||
// no overlap — nothing to return
|
||||
if uint64(traceStartMS) > toMS || uint64(traceEndMS) < fromMS {
|
||||
return &qbtypes.Result{
|
||||
Type: qbtypes.RequestTypeRaw,
|
||||
Value: &qbtypes.RawData{
|
||||
QueryName: q.spec.Name,
|
||||
},
|
||||
Stats: qbtypes.ExecStats{
|
||||
DurationMS: uint64(time.Since(start).Milliseconds()),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// clamp window to trace time range before bucketing
|
||||
if uint64(traceStartMS) > fromMS {
|
||||
fromMS = uint64(traceStartMS)
|
||||
}
|
||||
if uint64(traceEndMS) < toMS {
|
||||
toMS = uint64(traceEndMS)
|
||||
}
|
||||
q.logger.DebugContext(ctx, "optimized time range for traces", slog.Any("trace_ids", traceIDs), slog.Uint64("start", fromMS), slog.Uint64("end", toMS))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ from fixtures.querier import (
|
||||
index_series_by_label,
|
||||
make_query_request,
|
||||
)
|
||||
from fixtures.traces import TraceIdGenerator, Traces, TracesKind, TracesStatusCode
|
||||
|
||||
|
||||
def test_logs_list(
|
||||
@@ -2294,331 +2293,3 @@ def test_logs_formula_orderby_and_limit(
|
||||
assert len(f3_services) == 3, f"F3: expected 3 rows after limit, got {len(f3_services)}"
|
||||
assert f3_values == f4_values[:3], f"F3 values {f3_values} do not match F4[:3] values {f4_values[:3]}"
|
||||
assert set(f3_services) == set(f4_services[:3]), f"F3 services {f3_services} do not match F4[:3] services {f4_services[:3]}"
|
||||
|
||||
|
||||
def test_logs_list_filter_by_trace_id(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_logs: Callable[[list[Logs]], None],
|
||||
insert_traces: Callable[[list[Traces]], None],
|
||||
) -> None:
|
||||
"""
|
||||
Tests that filtering logs by trace_id uses the trace_summary lookup to
|
||||
narrow the query window before scanning the logs table:
|
||||
1. Returns the matching log (narrow window, single bucket).
|
||||
2. Does not return duplicate logs when the query window should span multiple
|
||||
exponential buckets (>1 h). But is clamped to the timerange of trace.
|
||||
3. Returns no results when the query window does not contain the trace.
|
||||
4. Logs carrying a trace_id whose trace is NOT in trace_summary (e.g.
|
||||
traces disabled) are still returned — the lookup miss must not
|
||||
short-circuit logs queries.
|
||||
"""
|
||||
target_trace_id = TraceIdGenerator.trace_id()
|
||||
other_trace_id = TraceIdGenerator.trace_id()
|
||||
orphan_trace_id = TraceIdGenerator.trace_id()
|
||||
target_root_span_id = TraceIdGenerator.span_id()
|
||||
target_child_span_id = TraceIdGenerator.span_id()
|
||||
other_span_id = TraceIdGenerator.span_id()
|
||||
orphan_span_id = TraceIdGenerator.span_id()
|
||||
|
||||
now = datetime.now(tz=UTC).replace(second=0, microsecond=0)
|
||||
|
||||
common_resources = {
|
||||
"deployment.environment": "production",
|
||||
"service.name": "logs-trace-filter-service",
|
||||
"cloud.provider": "integration",
|
||||
}
|
||||
|
||||
# Populate signoz_traces.distributed_trace_summary by inserting spans for
|
||||
# the target trace_id. trace_summary records min/max of span timestamps
|
||||
# (it ignores span duration), so two spans are inserted to give the trace
|
||||
# a non-trivial recorded window of [now-10s, now-5s].
|
||||
insert_traces(
|
||||
[
|
||||
Traces(
|
||||
timestamp=now - timedelta(seconds=10),
|
||||
duration=timedelta(seconds=1),
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_root_span_id,
|
||||
parent_span_id="",
|
||||
name="root-span",
|
||||
kind=TracesKind.SPAN_KIND_SERVER,
|
||||
status_code=TracesStatusCode.STATUS_CODE_OK,
|
||||
status_message="",
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
),
|
||||
Traces(
|
||||
timestamp=now - timedelta(seconds=5),
|
||||
duration=timedelta(seconds=1),
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_child_span_id,
|
||||
parent_span_id=target_root_span_id,
|
||||
name="child-span",
|
||||
kind=TracesKind.SPAN_KIND_CLIENT,
|
||||
status_code=TracesStatusCode.STATUS_CODE_OK,
|
||||
status_message="",
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
# Insert logs:
|
||||
# - one with the target trace_id, at a timestamp within the trace's
|
||||
# recorded window (now-10s..now-5s, padded ±1s).
|
||||
# - one with a different trace_id; must never appear in target_trace_id
|
||||
# results.
|
||||
# - one with an orphan trace_id whose trace was never ingested — used to
|
||||
# verify the lookup miss does NOT short-circuit logs queries.
|
||||
insert_logs(
|
||||
[
|
||||
Logs(
|
||||
timestamp=now - timedelta(seconds=7),
|
||||
resources=common_resources,
|
||||
attributes={"http.method": "GET"},
|
||||
body="log inside the target trace window",
|
||||
severity_text="INFO",
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_root_span_id,
|
||||
),
|
||||
Logs(
|
||||
timestamp=now - timedelta(seconds=3),
|
||||
resources=common_resources,
|
||||
attributes={"http.method": "POST"},
|
||||
body="log with a different trace_id",
|
||||
severity_text="INFO",
|
||||
trace_id=other_trace_id,
|
||||
span_id=other_span_id,
|
||||
),
|
||||
Logs(
|
||||
timestamp=now - timedelta(seconds=2),
|
||||
resources=common_resources,
|
||||
attributes={"http.method": "PUT"},
|
||||
body="log with a trace_id absent from trace_summary",
|
||||
severity_text="INFO",
|
||||
trace_id=orphan_trace_id,
|
||||
span_id=orphan_span_id,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
def _query(start_ms: int, end_ms: int, trace_id: str) -> list:
|
||||
response = make_query_request(
|
||||
signoz,
|
||||
token,
|
||||
start_ms=start_ms,
|
||||
end_ms=end_ms,
|
||||
request_type="raw",
|
||||
queries=[
|
||||
{
|
||||
"type": "builder_query",
|
||||
"spec": {
|
||||
"name": "A",
|
||||
"signal": "logs",
|
||||
"disabled": False,
|
||||
"limit": 100,
|
||||
"offset": 0,
|
||||
"filter": {"expression": f"trace_id = '{trace_id}'"},
|
||||
"order": [
|
||||
{"key": {"name": "timestamp"}, "direction": "desc"},
|
||||
{"key": {"name": "id"}, "direction": "desc"},
|
||||
],
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
return response.json()["data"]["data"]["results"][0]["rows"] or []
|
||||
|
||||
now_ms = int(now.timestamp() * 1000)
|
||||
|
||||
# --- Test 1: narrow window (single bucket, <1 h) ---
|
||||
narrow_start_ms = int((now - timedelta(minutes=5)).timestamp() * 1000)
|
||||
narrow_rows = _query(narrow_start_ms, now_ms, target_trace_id)
|
||||
|
||||
assert len(narrow_rows) == 1, f"Expected 1 log for trace_id filter (narrow window), got {len(narrow_rows)}"
|
||||
assert narrow_rows[0]["data"]["trace_id"] == target_trace_id
|
||||
assert narrow_rows[0]["data"]["span_id"] == target_root_span_id
|
||||
|
||||
# --- Test 2: wide window (>1 h, camp to the timerange from trace_summary) ---
|
||||
# Should still return exactly one log — no duplicates from multi-bucket scan.
|
||||
wide_start_ms = int((now - timedelta(hours=12)).timestamp() * 1000)
|
||||
wide_rows = _query(wide_start_ms, now_ms, target_trace_id)
|
||||
|
||||
assert len(wide_rows) == 1, f"Expected 1 log for trace_id filter (wide window, multi-bucket), got {len(wide_rows)} — possible duplicate-log regression"
|
||||
assert wide_rows[0]["data"]["trace_id"] == target_trace_id
|
||||
assert wide_rows[0]["data"]["span_id"] == target_root_span_id
|
||||
|
||||
# --- Test 3: window that does not contain the trace returns no results ---
|
||||
past_start_ms = int((now - timedelta(hours=6)).timestamp() * 1000)
|
||||
past_end_ms = int((now - timedelta(hours=2)).timestamp() * 1000)
|
||||
past_rows = _query(past_start_ms, past_end_ms, target_trace_id)
|
||||
|
||||
assert len(past_rows) == 0, f"Expected 0 logs for trace_id filter outside time window, got {len(past_rows)}"
|
||||
|
||||
# --- Test 4: trace_id not present in trace_summary still returns logs ---
|
||||
orphan_rows = _query(narrow_start_ms, now_ms, orphan_trace_id)
|
||||
|
||||
assert len(orphan_rows) == 1, f"Expected 1 log for orphan trace_id (no trace_summary entry), got {len(orphan_rows)} — logs query may have been incorrectly short-circuited"
|
||||
assert orphan_rows[0]["data"]["trace_id"] == orphan_trace_id
|
||||
|
||||
|
||||
def test_logs_aggregation_filter_by_trace_id(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_logs: Callable[[list[Logs]], None],
|
||||
insert_traces: Callable[[list[Traces]], None],
|
||||
) -> None:
|
||||
"""
|
||||
Tests that the trace_id time-range optimization also applies to
|
||||
non-window-list (time_series / aggregation) logs queries:
|
||||
1. Wide query window containing the trace returns the correct count.
|
||||
2. Query window outside the trace's time range short-circuits to an
|
||||
empty result.
|
||||
3. A trace_id with no row in trace_summary (e.g. traces disabled) still
|
||||
returns the matching logs — the lookup miss must not short-circuit
|
||||
logs aggregation queries.
|
||||
"""
|
||||
target_trace_id = TraceIdGenerator.trace_id()
|
||||
orphan_trace_id = TraceIdGenerator.trace_id()
|
||||
target_root_span_id = TraceIdGenerator.span_id()
|
||||
target_child_span_id = TraceIdGenerator.span_id()
|
||||
orphan_span_id = TraceIdGenerator.span_id()
|
||||
|
||||
now = datetime.now(tz=UTC).replace(second=0, microsecond=0)
|
||||
|
||||
common_resources = {
|
||||
"deployment.environment": "production",
|
||||
"service.name": "logs-trace-agg-service",
|
||||
"cloud.provider": "integration",
|
||||
}
|
||||
|
||||
# trace_summary records min/max of span timestamps (it ignores duration),
|
||||
# so insert two spans to give the trace a recorded window wide enough to
|
||||
# comfortably contain the log timestamps below.
|
||||
insert_traces(
|
||||
[
|
||||
Traces(
|
||||
timestamp=now - timedelta(seconds=10),
|
||||
duration=timedelta(seconds=1),
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_root_span_id,
|
||||
parent_span_id="",
|
||||
name="root-span",
|
||||
kind=TracesKind.SPAN_KIND_SERVER,
|
||||
status_code=TracesStatusCode.STATUS_CODE_OK,
|
||||
status_message="",
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
),
|
||||
Traces(
|
||||
timestamp=now - timedelta(seconds=5),
|
||||
duration=timedelta(seconds=1),
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_child_span_id,
|
||||
parent_span_id=target_root_span_id,
|
||||
name="child-span",
|
||||
kind=TracesKind.SPAN_KIND_CLIENT,
|
||||
status_code=TracesStatusCode.STATUS_CODE_OK,
|
||||
status_message="",
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
# Two logs for the target trace_id, both inside the recorded trace window.
|
||||
# One additional log carries an orphan trace_id with no row in
|
||||
# trace_summary — used to verify that the lookup miss does not
|
||||
# short-circuit logs aggregations.
|
||||
insert_logs(
|
||||
[
|
||||
Logs(
|
||||
timestamp=now - timedelta(seconds=9),
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
body="log A inside trace window",
|
||||
severity_text="INFO",
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_root_span_id,
|
||||
),
|
||||
Logs(
|
||||
timestamp=now - timedelta(seconds=6),
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
body="log B inside trace window",
|
||||
severity_text="INFO",
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_root_span_id,
|
||||
),
|
||||
Logs(
|
||||
timestamp=now - timedelta(seconds=2),
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
body="log with a trace_id absent from trace_summary",
|
||||
severity_text="INFO",
|
||||
trace_id=orphan_trace_id,
|
||||
span_id=orphan_span_id,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
def _count(start_ms: int, end_ms: int, trace_id: str) -> float:
|
||||
response = make_query_request(
|
||||
signoz,
|
||||
token,
|
||||
start_ms=start_ms,
|
||||
end_ms=end_ms,
|
||||
request_type="time_series",
|
||||
queries=[
|
||||
{
|
||||
"type": "builder_query",
|
||||
"spec": {
|
||||
"name": "A",
|
||||
"signal": "logs",
|
||||
"stepInterval": 60,
|
||||
"disabled": False,
|
||||
"filter": {"expression": f"trace_id = '{trace_id}'"},
|
||||
"having": {"expression": ""},
|
||||
"aggregations": [{"expression": "count()"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
results = response.json()["data"]["data"]["results"]
|
||||
assert len(results) == 1
|
||||
aggregations = results[0].get("aggregations") or []
|
||||
if not aggregations:
|
||||
return 0
|
||||
series = aggregations[0].get("series") or []
|
||||
if not series:
|
||||
return 0
|
||||
return sum(v["value"] for v in series[0]["values"])
|
||||
|
||||
now_ms = int(now.timestamp() * 1000)
|
||||
narrow_start_ms = int((now - timedelta(minutes=5)).timestamp() * 1000)
|
||||
|
||||
# --- Test 1: wide window (>1 h) containing the trace returns 2 logs ---
|
||||
wide_start_ms = int((now - timedelta(hours=12)).timestamp() * 1000)
|
||||
wide_count = _count(wide_start_ms, now_ms, target_trace_id)
|
||||
assert wide_count == 2, f"Expected count=2 for trace_id aggregation (wide window), got {wide_count}"
|
||||
|
||||
# --- Test 2: window outside the trace short-circuits to empty ---
|
||||
past_start_ms = int((now - timedelta(hours=6)).timestamp() * 1000)
|
||||
past_end_ms = int((now - timedelta(hours=2)).timestamp() * 1000)
|
||||
past_count = _count(past_start_ms, past_end_ms, target_trace_id)
|
||||
assert past_count == 0, f"Expected count=0 for trace_id aggregation outside time window, got {past_count}"
|
||||
|
||||
# --- Test 3: trace_id not present in trace_summary still returns logs ---
|
||||
orphan_count = _count(narrow_start_ms, now_ms, orphan_trace_id)
|
||||
assert orphan_count == 1, f"Expected count=1 for orphan trace_id aggregation, got {orphan_count} — query may have been incorrectly short-circuited"
|
||||
|
||||
@@ -2123,115 +2123,3 @@ def test_traces_list_filter_by_trace_id(
|
||||
past_rows = _query(past_start_ms, past_end_ms)
|
||||
|
||||
assert len(past_rows) == 0, f"Expected 0 spans for trace_id filter outside time window, got {len(past_rows)}"
|
||||
|
||||
|
||||
def test_traces_aggregation_filter_by_trace_id(
|
||||
signoz: types.SigNoz,
|
||||
create_user_admin: None, # pylint: disable=unused-argument
|
||||
get_token: Callable[[str, str], str],
|
||||
insert_traces: Callable[[list[Traces]], None],
|
||||
) -> None:
|
||||
"""
|
||||
Tests that the trace_id time-range optimization also applies to
|
||||
non-window-list (time_series / aggregation) traces queries:
|
||||
1. Wide query window containing the trace returns the correct count.
|
||||
2. Query window outside the trace's time range short-circuits to empty.
|
||||
3. Filter referencing a trace_id with no row in trace_summary
|
||||
short-circuits to empty (trace_summary is authoritative for traces).
|
||||
"""
|
||||
target_trace_id = TraceIdGenerator.trace_id()
|
||||
target_root_span_id = TraceIdGenerator.span_id()
|
||||
target_child_span_id = TraceIdGenerator.span_id()
|
||||
missing_trace_id = TraceIdGenerator.trace_id()
|
||||
|
||||
now = datetime.now(tz=UTC).replace(second=0, microsecond=0)
|
||||
|
||||
common_resources = {
|
||||
"deployment.environment": "production",
|
||||
"service.name": "traces-agg-filter-service",
|
||||
"cloud.provider": "integration",
|
||||
}
|
||||
|
||||
insert_traces(
|
||||
[
|
||||
Traces(
|
||||
timestamp=now - timedelta(seconds=10),
|
||||
duration=timedelta(seconds=5),
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_root_span_id,
|
||||
parent_span_id="",
|
||||
name="root-span",
|
||||
kind=TracesKind.SPAN_KIND_SERVER,
|
||||
status_code=TracesStatusCode.STATUS_CODE_OK,
|
||||
status_message="",
|
||||
resources=common_resources,
|
||||
attributes={"http.request.method": "GET"},
|
||||
),
|
||||
Traces(
|
||||
timestamp=now - timedelta(seconds=9),
|
||||
duration=timedelta(seconds=1),
|
||||
trace_id=target_trace_id,
|
||||
span_id=target_child_span_id,
|
||||
parent_span_id=target_root_span_id,
|
||||
name="child-span",
|
||||
kind=TracesKind.SPAN_KIND_CLIENT,
|
||||
status_code=TracesStatusCode.STATUS_CODE_OK,
|
||||
status_message="",
|
||||
resources=common_resources,
|
||||
attributes={},
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
token = get_token(USER_ADMIN_EMAIL, USER_ADMIN_PASSWORD)
|
||||
|
||||
def _count(start_ms: int, end_ms: int, trace_id: str) -> float:
|
||||
response = make_query_request(
|
||||
signoz,
|
||||
token,
|
||||
start_ms=start_ms,
|
||||
end_ms=end_ms,
|
||||
request_type="time_series",
|
||||
queries=[
|
||||
{
|
||||
"type": "builder_query",
|
||||
"spec": {
|
||||
"name": "A",
|
||||
"signal": "traces",
|
||||
"stepInterval": 60,
|
||||
"disabled": False,
|
||||
"filter": {"expression": f"trace_id = '{trace_id}'"},
|
||||
"aggregations": [{"expression": "count()"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
)
|
||||
assert response.status_code == HTTPStatus.OK
|
||||
assert response.json()["status"] == "success"
|
||||
results = response.json()["data"]["data"]["results"]
|
||||
assert len(results) == 1
|
||||
aggregations = results[0].get("aggregations") or []
|
||||
if not aggregations:
|
||||
return 0
|
||||
series = aggregations[0].get("series") or []
|
||||
if not series:
|
||||
return 0
|
||||
return sum(v["value"] for v in series[0]["values"])
|
||||
|
||||
now_ms = int(now.timestamp() * 1000)
|
||||
|
||||
# --- Test 1: wide window (>1 h) containing the trace returns both spans ---
|
||||
wide_start_ms = int((now - timedelta(hours=12)).timestamp() * 1000)
|
||||
wide_count = _count(wide_start_ms, now_ms, target_trace_id)
|
||||
assert wide_count == 2, f"Expected count=2 for trace_id aggregation (wide window), got {wide_count}"
|
||||
|
||||
# --- Test 2: window outside the trace short-circuits to empty ---
|
||||
past_start_ms = int((now - timedelta(hours=6)).timestamp() * 1000)
|
||||
past_end_ms = int((now - timedelta(hours=2)).timestamp() * 1000)
|
||||
past_count = _count(past_start_ms, past_end_ms, target_trace_id)
|
||||
assert past_count == 0, f"Expected count=0 for trace_id aggregation outside time window, got {past_count}"
|
||||
|
||||
# --- Test 3: trace_id with no entry in trace_summary short-circuits ---
|
||||
missing_start_ms = int((now - timedelta(minutes=5)).timestamp() * 1000)
|
||||
missing_count = _count(missing_start_ms, now_ms, missing_trace_id)
|
||||
assert missing_count == 0, f"Expected count=0 for trace_id absent from trace_summary, got {missing_count}"
|
||||
|
||||
Reference in New Issue
Block a user