Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add documentation link for logs explorer quick filters #6854

Merged
merged 11 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions frontend/src/assets/CustomIcons/EmptyQuickFilterIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
interface EmptyQuickFilterIconProps {
width?: number;
height?: number;
className?: string;
}

function EmptyQuickFilterIcon({
width = 32,
height = 32,
className,
}: EmptyQuickFilterIconProps): JSX.Element {
return (
<svg
width={width}
height={height}
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path
d="M17.948 6.906h-6.62V6.24h6.62v.667ZM17.948 10.293h-6.62v-.667h6.62v.667Z"
fill="#616161"
ahmadshaheer marked this conversation as resolved.
Show resolved Hide resolved
ahmadshaheer marked this conversation as resolved.
Show resolved Hide resolved
/>
<path
d="M16.175 29.403H13.62V3.442s.238-.554 1.278-.554 1.278.554 1.278.554v25.96h-.002Z"
fill="#9E9E9E"
/>
<path
d="M15.52 2.971v20.974H13.62v1.91c.323.001.614.04.876.097a1.3 1.3 0 0 1 1.024 1.269v2.182h.656V3.442c-.002 0-.14-.318-.658-.471Z"
fill="#757575"
/>
<path
d="M22.363 2.737a5.382 5.382 0 0 0-5.382 5.402 5.365 5.365 0 0 0 5.382 5.382 5.378 5.378 0 0 0 5.382-5.382c0-2.975-2.407-5.402-5.382-5.402Z"
fill="#2196F3"
/>
<path
d="M24.714 4.749c-.338-.085-1.01-.174-2.349-.174-1.337 0-2.01.087-2.348.174-.2.05-.87.328-.87 1.077v4.618c0 .253.205.46.46.46h.17v.51c0 .15.12.27.268.27h.545c.149 0 .269-.12.269-.27v-.51h3.008v.51c0 .15.12.27.27.27h.544c.149 0 .269-.12.269-.27v-.51h.173a.46.46 0 0 0 .46-.46V5.826c0-.717-.669-1.029-.869-1.077Zm-3.802.366c0-.113.091-.204.205-.204h2.493c.113 0 .204.09.204.204v.362a.204.204 0 0 1-.204.205h-2.493a.204.204 0 0 1-.205-.205v-.362Zm.042 4.864a.138.138 0 0 1-.137.138h-.55a.469.469 0 0 1-.468-.469v-.246c0-.076.062-.138.138-.138h.548c.258 0 .47.209.47.469v.246Zm3.973-.33a.469.469 0 0 1-.468.468h-.55a.138.138 0 0 1-.137-.138v-.246c0-.258.209-.47.469-.47h.549c.075 0 .137.063.137.139v.246Zm.125-2.007c0 .297-.645.817-2.689.817-2.046 0-2.689-.482-2.689-.817V6.277c0-.089.09-.31.311-.31h4.791c.223 0 .276.224.276.31v1.365Z"
fill="#fff"
/>
<path
d="M18.861 24.652h-7.926a.506.506 0 0 1-.507-.507V14.99c0-.28.227-.507.507-.507h7.924c.28 0 .507.227.507.507v9.155c0 .28-.227.507-.505.507Z"
fill="#F5F5F5"
/>
<path
opacity=".8"
d="M18.006 23.139H11.79l-.017-7.236h6.217l.016 7.236Z"
fill="#82AEC0"
/>
<path d="M14.66 23.234v-7.33h.444v7.33h-.445Z" fill="#F5F5F5" />
<path d="M14.66 15.903h-2.887v.605h2.886v-.605Z" fill="#616161" />
<path
d="M18.03 21.878h-6.264v-.222h6.264v.223ZM18.03 20.412h-6.264v-.222h6.264v.222ZM17.99 18.945h-6.217v-.222h6.217v.222ZM17.99 17.481h-6.224v-.222h6.224v.222Z"
fill="#F5F5F5"
/>
<path
d="M17.988 18.534H15.1v.605h2.887v-.605ZM14.672 19.999h-2.877v.604h2.877V20Z"
fill="#616161"
/>
<path
d="M10.935 14.817a.173.173 0 0 0-.173.173v9.155c0 .096.077.174.173.174h7.926a.173.173 0 0 0 .171-.174V14.99a.173.173 0 0 0-.173-.173h-7.924Zm-.84.173a.84.84 0 0 1 .84-.84h7.924a.84.84 0 0 1 .84.84v9.155a.84.84 0 0 1-.838.84h-7.926a.84.84 0 0 1-.84-.84V14.99Z"
fill="#9E9E9E"
/>
<path
d="M10.968 24.323c-.344.031-.344-.195-.344-.258V15.1c0-.251.204-.455.455-.455h7.693c.21 0 .305.126.262.384 0 0-.026-.165-.226-.165h-7.726a.237.237 0 0 0-.236.236v8.968c0 .21.122.256.122.256Z"
fill="#757575"
/>
<path d="M12.268 4.933H4.695v6.577h7.573V4.933Z" fill="#FFCA28" />
<path
d="M11.846 4.933c.233 0 .422.189.422.422v5.733a.422.422 0 0 1-.422.422H5.12a.422.422 0 0 1-.423-.422V5.355c0-.233.19-.422.423-.422h6.726Zm0-.445H5.12a.868.868 0 0 0-.867.867v5.733c0 .478.389.867.867.867h6.726a.868.868 0 0 0 .867-.867V5.355a.866.866 0 0 0-.867-.867Z"
fill="#9E9E9E"
/>
<path
d="M12.27 7.308H4.696v-.444h7.575v.444ZM12.27 9.579H4.696v-.444h7.575v.444Z"
fill="#FFFDE7"
/>
<path
d="M7.066 5.664H5.162v.502h1.904v-.502ZM6.597 10.27H5.162v.503h1.435v-.502ZM11.648 10.27h-1.435v.503h1.435v-.502ZM11.648 5.664h-1.435v.502h1.435v-.502ZM10.302 7.968h-.827v.502h.827v-.502ZM11.648 7.968h-.826v.502h.826v-.502ZM7.802 7.968h-2.64v.502h2.64v-.502Z"
fill="#757575"
/>
</svg>
);
}

EmptyQuickFilterIcon.defaultProps = {
width: 32,
height: 32,
className: '',
};

export default EmptyQuickFilterIcon;
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,39 @@
cursor: pointer;
}
}
.go-to-docs {
display: flex;
flex-direction: column;
gap: 64px;
&__container {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 4px;

&-message {
color: var(--bg-vanilla-400);
font-size: 14px;
line-height: 20px; /* 142.857% */
letter-spacing: -0.07px;
}
}
&__button {
display: flex;
align-items: center;
gap: 4px;
cursor: pointer;
margin: 0 0 4px;
padding: 0;
&-text {
color: var(--bg-robin-400);
font-family: Inter;
font-size: 14px;
line-height: 20px; /* 142.857% */
letter-spacing: -0.07px;
}
}
}
}

.lightMode {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import './Checkbox.styles.scss';

import { Button, Checkbox, Input, Skeleton, Typography } from 'antd';
import cx from 'classnames';
import { IQuickFiltersConfig } from 'components/QuickFilters/QuickFilters';
import {
IQuickFiltersConfig,
QuickFiltersSource,
} from 'components/QuickFilters/types';
import { OPERATORS } from 'constants/queryBuilder';
import { DEBOUNCE_DELAY } from 'constants/queryBuilderFilterConfig';
import { getOperatorValue } from 'container/QueryBuilder/filters/QueryBuilderSearch/utils';
Expand All @@ -21,9 +24,13 @@ import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';
import { v4 as uuid } from 'uuid';

import LogsQuickFilterEmptyState from './LogsQuickFilterEmptyState';

const SELECTED_OPERATORS = [OPERATORS['='], 'in'];
const NON_SELECTED_OPERATORS = [OPERATORS['!='], 'nin'];

const SOURCES_WITH_EMPTY_STATE_ENABLED = [QuickFiltersSource.LOGS_EXPLORER];

function setDefaultValues(
values: string[],
trueOrFalse: boolean,
Expand All @@ -36,11 +43,13 @@ function setDefaultValues(
}
interface ICheckboxProps {
filter: IQuickFiltersConfig;
source: QuickFiltersSource;
onFilterChange?: (query: Query) => void;
}

// eslint-disable-next-line sonarjs/cognitive-complexity
export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
const { filter, onFilterChange } = props;
const { source, filter, onFilterChange } = props;
const [searchText, setSearchText] = useState<string>('');
const [isOpen, setIsOpen] = useState<boolean>(filter.defaultOpen);
const [visibleItemsCount, setVisibleItemsCount] = useState<number>(10);
Expand Down Expand Up @@ -410,6 +419,11 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
}
};

const isEmptyStateWithDocsEnabled =
SOURCES_WITH_EMPTY_STATE_ENABLED.includes(source) &&
!searchText &&
!attributeValues.length;

return (
<div className="checkbox-filter">
<section
Expand All @@ -432,7 +446,7 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
<Typography.Text className="title">{filter.title}</Typography.Text>
</section>
<section className="right-action">
{isOpen && (
{isOpen && !!attributeValues.length && (
<Typography.Text
className="clear-all"
onClick={(e): void => {
Expand All @@ -453,13 +467,15 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
)}
{isOpen && !isLoading && (
<>
<section className="search">
<Input
placeholder="Filter values"
onChange={(e): void => setSearchTextDebounced(e.target.value)}
disabled={isFilterDisabled}
/>
</section>
{!isEmptyStateWithDocsEnabled && (
<section className="search">
<Input
placeholder="Filter values"
onChange={(e): void => setSearchTextDebounced(e.target.value)}
disabled={isFilterDisabled}
/>
</section>
)}
{attributeValues.length > 0 ? (
<section className="values">
{currentAttributeKeys.map((value: string) => (
Expand Down Expand Up @@ -507,6 +523,8 @@ export default function CheckboxFilter(props: ICheckboxProps): JSX.Element {
</div>
))}
</section>
) : isEmptyStateWithDocsEnabled ? (
<LogsQuickFilterEmptyState attributeKey={filter.attributeKey.key} />
) : (
<section className="no-data">
<Typography.Text>No values found</Typography.Text>{' '}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Color } from '@signozhq/design-tokens';
import { Button } from 'antd';
import EmptyQuickFilterIcon from 'assets/CustomIcons/EmptyQuickFilterIcon';
import { ArrowUpRight } from 'lucide-react';

const QUICK_FILTER_DOC_PATHS: Record<string, string> = {
severity_text: 'severity-text',
'deployment.environment': 'environment',
'service.name': 'service-name',
'host.name': 'hostname',
'k8s.cluster.name': 'k8s-cluster-name',
'k8s.deployment.name': 'k8s-deployment-name',
'k8s.namespace.name': 'k8s-namespace-name',
'k8s.pod.name': 'k8s-pod-name',
};

function LogsQuickFilterEmptyState({
attributeKey,
}: {
attributeKey: string;
}): JSX.Element {
const handleLearnMoreClick = (): void => {
const section = QUICK_FILTER_DOC_PATHS[attributeKey];

window.open(
`https://signoz.io/docs/logs-management/features/logs-quick-filters#${section}`,
'_blank',
);
};
return (
<section className="go-to-docs">
<div className="go-to-docs__container">
<div className="go-to-docs__container-icon">
<EmptyQuickFilterIcon />
</div>
<div className="go-to-docs__container-message">
{`You'd need to parse out this attribute to start getting them as a fast
filter.`}
</div>
</div>
<Button
type="link"
className="go-to-docs__button"
onClick={handleLearnMoreClick}
>
<div className="go-to-docs__button-text">Learn more</div>
<ArrowUpRight size={14} color={Color.BG_ROBIN_400} />
</Button>
</section>
);
}

export default LogsQuickFilterEmptyState;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './Slider.styles.scss';

import { IQuickFiltersConfig } from 'components/QuickFilters/QuickFilters';
import { IQuickFiltersConfig } from 'components/QuickFilters/types';

interface ISliderProps {
filter: IQuickFiltersConfig;
Expand Down
58 changes: 17 additions & 41 deletions frontend/src/components/QuickFilters/QuickFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,11 @@ import {
import { Tooltip, Typography } from 'antd';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { cloneDeep, isFunction } from 'lodash-es';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query } from 'types/api/queryBuilder/queryBuilderData';
import { DataSource } from 'types/common/queryBuilder';

import Checkbox from './FilterRenderers/Checkbox/Checkbox';
import Slider from './FilterRenderers/Slider/Slider';

export enum FiltersType {
SLIDER = 'SLIDER',
CHECKBOX = 'CHECKBOX',
}

export enum MinMax {
MIN = 'MIN',
MAX = 'MAX',
}

export enum SpecficFilterOperations {
ALL = 'ALL',
ONLY = 'ONLY',
}

export interface IQuickFiltersConfig {
type: FiltersType;
title: string;
attributeKey: BaseAutocompleteData;
aggregateOperator?: string;
aggregateAttribute?: string;
dataSource?: DataSource;
customRendererForValue?: (value: string) => JSX.Element;
defaultOpen: boolean;
}

interface IQuickFiltersProps {
config: IQuickFiltersConfig[];
handleFilterVisibilityChange: () => void;
source?: string | null;
onFilterChange?: (query: Query) => void;
}
import { FiltersType, IQuickFiltersProps, QuickFiltersSource } from './types';

export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
const { config, handleFilterVisibilityChange, source, onFilterChange } = props;
Expand Down Expand Up @@ -95,11 +61,9 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
const lastQueryName =
currentQuery.builder.queryData?.[lastUsedQuery || 0]?.queryName;

const isInfraMonitoring = source === 'infra-monitoring';
ahmadshaheer marked this conversation as resolved.
Show resolved Hide resolved

return (
<div className="quick-filters">
{!isInfraMonitoring && (
{source !== QuickFiltersSource.INFRA_MONITORING && (
<section className="header">
<section className="left-actions">
<FilterOutlined />
Expand Down Expand Up @@ -128,11 +92,24 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
{config.map((filter) => {
switch (filter.type) {
case FiltersType.CHECKBOX:
return <Checkbox filter={filter} onFilterChange={onFilterChange} />;
return (
<Checkbox
source={source}
filter={filter}
onFilterChange={onFilterChange}
/>
);
case FiltersType.SLIDER:
return <Slider filter={filter} />;
// eslint-disable-next-line sonarjs/no-duplicated-branches
default:
return <Checkbox filter={filter} onFilterChange={onFilterChange} />;
ahmadshaheer marked this conversation as resolved.
Show resolved Hide resolved
return (
<Checkbox
source={source}
filter={filter}
onFilterChange={onFilterChange}
/>
);
}
})}
</section>
Expand All @@ -141,6 +118,5 @@ export default function QuickFilters(props: IQuickFiltersProps): JSX.Element {
}

QuickFilters.defaultProps = {
source: null,
onFilterChange: null,
};
Loading
Loading