feat: added worker count and other misc changes (#6951)

* feat: added worker count - via autocomplete API

* feat: added worker count and code fix

* feat: added lightMode styles for all celery feat

* feat: changed routes to have redirects, subroute etc

* feat: feedback changes

* feat: removed console.log
This commit is contained in:
SagarRajput-7 2025-01-29 17:32:01 +05:30 committed by GitHub
parent 36f91d1993
commit fb3b70b729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 470 additions and 268 deletions

View File

@ -28,7 +28,6 @@ import {
LogsExplorer, LogsExplorer,
LogsIndexToFields, LogsIndexToFields,
LogsSaveViews, LogsSaveViews,
MQDetailPage,
MySettings, MySettings,
NewDashboardPage, NewDashboardPage,
OldLogsExplorer, OldLogsExplorer,
@ -395,10 +394,10 @@ const routes: AppRoutes[] = [
key: 'INTEGRATIONS', key: 'INTEGRATIONS',
}, },
{ {
path: ROUTES.MESSAGING_QUEUES, path: ROUTES.MESSAGING_QUEUES_KAFKA,
exact: true, exact: true,
component: MessagingQueues, component: MessagingQueues,
key: 'MESSAGING_QUEUES', key: 'MESSAGING_QUEUES_KAFKA',
isPrivate: true, isPrivate: true,
}, },
{ {
@ -416,10 +415,10 @@ const routes: AppRoutes[] = [
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.MESSAGING_QUEUES_DETAIL, path: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
exact: true, exact: true,
component: MQDetailPage, component: MessagingQueues,
key: 'MESSAGING_QUEUES_DETAIL', key: 'MESSAGING_QUEUES_KAFKA_DETAIL',
isPrivate: true, isPrivate: true,
}, },
{ {
@ -461,6 +460,7 @@ export const oldRoutes = [
'/logs-save-views', '/logs-save-views',
'/traces-save-views', '/traces-save-views',
'/settings/access-tokens', '/settings/access-tokens',
'/messaging-queues',
]; ];
export const oldNewRoutesMapping: Record<string, string> = { export const oldNewRoutesMapping: Record<string, string> = {
@ -470,6 +470,7 @@ export const oldNewRoutesMapping: Record<string, string> = {
'/logs-save-views': '/logs/saved-views', '/logs-save-views': '/logs/saved-views',
'/traces-save-views': '/traces/saved-views', '/traces-save-views': '/traces/saved-views',
'/settings/access-tokens': '/settings/api-keys', '/settings/access-tokens': '/settings/api-keys',
'/messaging-queues': '/messaging-queues/overview',
}; };
export const ROUTES_NOT_TO_BE_OVERRIDEN: string[] = [ export const ROUTES_NOT_TO_BE_OVERRIDEN: string[] = [

View File

@ -12,93 +12,138 @@
cursor: pointer; cursor: pointer;
} }
.celery-overview-table { .celery-overview-table-container {
.ant-table { width: 100%;
.ant-table-thead > tr > th {
padding: 12px;
font-weight: 500;
font-size: 12px;
line-height: 18px;
background: var(--bg-ink-500); > .ant-input-search {
border-bottom: none; margin-bottom: 8px;
color: var(--Vanilla-400, #c0c1c3);
font-family: Inter;
font-size: 11px;
font-style: normal;
font-weight: 600;
line-height: 18px; /* 163.636% */
letter-spacing: 0.44px;
text-transform: uppercase;
&::before {
background-color: transparent;
}
}
.ant-table-cell {
padding: 12px;
font-size: 13px;
line-height: 20px;
color: var(--bg-vanilla-100);
background: var(--bg-ink-500);
}
.progress-container {
.ant-progress-bg {
height: 8px !important;
border-radius: 4px;
}
}
.ant-table-tbody > tr:hover > td {
background: rgba(255, 255, 255, 0.04);
}
.ant-table-cell:first-child {
text-align: justify;
}
.ant-table-cell:nth-child(2) {
padding-left: 16px;
padding-right: 16px;
}
.ant-table-cell:nth-child(n + 3) {
padding-right: 24px;
}
.column-header-right {
text-align: right;
}
.column-header-left {
text-align: left;
}
.ant-table-tbody > tr > td {
border-bottom: none;
}
} }
.ant-pagination { .celery-overview-table {
position: relative; .ant-table {
bottom: 0; .ant-table-thead > tr > th {
width: 100%; padding: 12px;
background: var(--bg-ink-500); font-weight: 500;
padding: 4px; font-size: 12px;
margin: 0; line-height: 18px;
// this is to offset intercom icon background: var(--bg-ink-500);
padding-right: 72px; border-bottom: none;
.ant-pagination-item { color: var(--Vanilla-400, #c0c1c3);
border-radius: 4px; font-family: Inter;
font-size: 11px;
font-style: normal;
font-weight: 600;
line-height: 18px; /* 163.636% */
letter-spacing: 0.44px;
text-transform: uppercase;
&-active { &::before {
background: var(--bg-robin-500); background-color: transparent;
border-color: var(--bg-robin-500); }
}
a { .ant-table-cell {
color: var(--bg-ink-500) !important; padding: 12px;
font-size: 13px;
line-height: 20px;
color: var(--bg-vanilla-100);
background: var(--bg-ink-500);
}
.progress-container {
.ant-progress-bg {
height: 8px !important;
border-radius: 4px;
}
}
.ant-table-tbody > tr:hover > td {
background: rgba(255, 255, 255, 0.04);
}
.ant-table-cell:first-child {
text-align: justify;
}
.ant-table-cell:nth-child(2) {
padding-left: 16px;
padding-right: 16px;
}
.ant-table-cell:nth-child(n + 3) {
padding-right: 24px;
}
.column-header-right {
text-align: right;
}
.column-header-left {
text-align: left;
}
.ant-table-tbody > tr > td {
border-bottom: none;
}
}
.ant-pagination {
position: relative;
bottom: 0;
width: 100%;
background: var(--bg-ink-500);
padding: 4px;
margin: 0;
// this is to offset intercom icon
padding-right: 72px;
.ant-pagination-item {
border-radius: 4px;
&-active {
background: var(--bg-robin-500);
border-color: var(--bg-robin-500);
a {
color: var(--bg-ink-500) !important;
}
}
}
}
}
}
.lightMode {
.celery-overview-table-container {
.celery-overview-table {
.ant-table {
.ant-table-thead > tr > th {
background: var(--bg-vanilla-100);
color: var(--text-ink-300);
}
.ant-table-cell {
background: var(--bg-vanilla-100);
color: var(--bg-ink-500);
}
.ant-table-tbody > tr:hover > td {
background: rgba(0, 0, 0, 0.04);
}
}
.ant-pagination {
background: var(--bg-vanilla-100);
.ant-pagination-item {
&-active {
background: var(--bg-robin-500);
border-color: var(--bg-robin-500);
a {
color: var(--bg-vanilla-100) !important;
}
}
} }
} }
} }

View File

@ -400,6 +400,15 @@ export default function CeleryOverviewTable({
confirm(); confirm();
}; };
// Add defaultSorting state
const [sortedInfo, setSortedInfo] = useState<{
columnKey: string;
order: 'ascend' | 'descend';
}>({
columnKey: 'error_percentage',
order: 'descend',
});
const columns = useMemo( const columns = useMemo(
() => () =>
getDraggedColumns<RowData>( getDraggedColumns<RowData>(
@ -411,10 +420,15 @@ export default function CeleryOverviewTable({
handleSearch, handleSearch,
item.key?.toString(), item.key?.toString(),
), ),
// Only set defaultSortOrder for error_percentage, but allow sorting for all columns
...(item.key === 'error_percentage' && {
defaultSortOrder: 'descend',
}),
sortOrder: sortedInfo.columnKey === item.key ? sortedInfo.order : null,
})), })),
draggedColumns, draggedColumns,
), ),
[tableData, draggedColumns], [tableData, draggedColumns, sortedInfo],
); );
const handleDragColumn = useCallback( const handleDragColumn = useCallback(
(fromIndex: number, toIndex: number) => (fromIndex: number, toIndex: number) =>
@ -459,7 +473,7 @@ export default function CeleryOverviewTable({
]); ]);
return ( return (
<div style={{ width: '100%' }}> <div className="celery-overview-table-container">
<Input.Search <Input.Search
placeholder="Search across all columns" placeholder="Search across all columns"
onChange={(e): void => setSearchText(e.target.value)} onChange={(e): void => setSearchText(e.target.value)}
@ -488,6 +502,12 @@ export default function CeleryOverviewTable({
className: 'clickable-row', className: 'clickable-row',
})} })}
tableLayout="fixed" tableLayout="fixed"
onChange={(_pagination, _filters, sorter): void => {
setSortedInfo({
columnKey: (sorter as { columnKey: string }).columnKey,
order: (sorter as { order: 'ascend' | 'descend' }).order,
});
}}
/> />
</div> </div>
); );

View File

@ -8,6 +8,11 @@ import { DataSource } from 'types/common/queryBuilder';
export interface Filters { export interface Filters {
searchText: string; searchText: string;
attributeKey: string | string[]; attributeKey: string | string[];
aggregateOperator?: string;
dataSource?: DataSource;
aggregateAttribute?: string;
filterAttributeKeyDataType?: DataTypes;
tagType?: string;
} }
export interface GetAllFiltersResponse { export interface GetAllFiltersResponse {
@ -16,7 +21,15 @@ export interface GetAllFiltersResponse {
} }
export function useGetAllFilters(props: Filters): GetAllFiltersResponse { export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const { searchText, attributeKey } = props; const {
searchText,
attributeKey,
aggregateOperator,
dataSource,
aggregateAttribute,
filterAttributeKeyDataType,
tagType,
} = props;
const { data, isLoading } = useQuery( const { data, isLoading } = useQuery(
['attributesValues', attributeKey, searchText], ['attributesValues', attributeKey, searchText],
@ -26,13 +39,14 @@ export function useGetAllFilters(props: Filters): GetAllFiltersResponse {
const responses = await Promise.all( const responses = await Promise.all(
keys.map((key) => keys.map((key) =>
getAttributesValues({ getAttributesValues({
aggregateOperator: 'noop', aggregateOperator: aggregateOperator || 'noop',
dataSource: DataSource.TRACES, dataSource: dataSource || DataSource.TRACES,
aggregateAttribute: '', aggregateAttribute: aggregateAttribute || '',
attributeKey: key, attributeKey: key,
searchText: searchText ?? '', searchText: searchText ?? '',
filterAttributeKeyDataType: DataTypes.String, filterAttributeKeyDataType:
tagType: 'tag', filterAttributeKeyDataType || DataTypes.String,
tagType: tagType || 'tag',
}), }),
), ),
); );

View File

@ -72,3 +72,51 @@
} }
} }
} }
.lightMode {
.celery-task-detail-drawer {
.ant-drawer-wrapper-body {
background: var(--bg-vanilla-100);
border: 1px solid var(--bg-vanilla-300);
}
.ant-drawer-body {
.ant-card {
.ant-card-body {
background: var(--bg-vanilla-100);
.ant-table {
background: var(--bg-vanilla-100);
}
}
}
}
.ant-drawer-header {
border-bottom: 1px solid var(--bg-vanilla-300);
.ant-drawer-header-title {
button > svg {
color: var(--bg-ink-500);
}
.ant-drawer-title {
.title {
color: var(--bg-ink-400);
}
.subtitle {
color: var(--bg-ink-300);
}
}
}
}
.ant-drawer-footer {
border-top: 1px solid var(--bg-vanilla-300);
.footer-text {
color: var(--bg-ink-400);
}
}
}
}

View File

@ -24,12 +24,53 @@
.widget-graph-container { .widget-graph-container {
&.bar { &.bar {
height: calc(100% - 105px); height: calc(100% - 110px);
} }
} }
} }
} }
.celery-task-graph-worker-count {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid var(--bg-slate-500);
background: linear-gradient(
0deg,
rgba(171, 189, 255, 0) 0%,
rgba(171, 189, 255, 0) 100%
),
#0b0c0e;
.ant-card-body {
height: 100%;
width: 100%;
}
.worker-count-text-container {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
.celery-task-graph-worker-count-text {
font-size: 2.5vw;
text-align: center;
}
}
.worker-count-header {
display: flex;
justify-content: start;
align-items: start;
position: absolute;
height: 100%;
width: 100%;
}
}
.celery-task-graph-bar, .celery-task-graph-bar,
.celery-task-graph-task-latency { .celery-task-graph-task-latency {
height: 380px !important; height: 380px !important;
@ -46,7 +87,7 @@
.widget-graph-container { .widget-graph-container {
&.bar { &.bar {
height: calc(100% - 105px); height: calc(100% - 110px);
} }
&.graph { &.graph {
@ -126,3 +167,40 @@
background-color: var(--bg-vanilla-100); background-color: var(--bg-vanilla-100);
} }
} }
.lightMode {
.celery-task-graph-grid-container {
.celery-task-graph-grid {
.celery-task-graph-worker-count {
border: 1px solid var(--bg-vanilla-300);
background: unset;
}
}
}
.celery-task-states {
border-bottom: 1px solid var(--bg-vanilla-300);
&__tab {
&:not([data-last-tab='true']) {
border-right: 1px solid var(--bg-vanilla-300);
}
&--selected {
background-color: var(--bg-vanilla-200);
}
}
&__label {
color: var(--bg-ink-500);
}
&__value {
color: var(--bg-slate-100);
}
&__indicator {
background-color: var(--bg-ink-400);
}
}
}

View File

@ -1,11 +1,15 @@
import './CeleryTaskGraph.style.scss'; import './CeleryTaskGraph.style.scss';
import { Card, Typography } from 'antd';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { CaptureDataProps } from '../CeleryTaskDetail/CeleryTaskDetail'; import { CaptureDataProps } from '../CeleryTaskDetail/CeleryTaskDetail';
import { useCeleryFilterOptions } from '../useCeleryFilterOptions';
import CeleryTaskBar from './CeleryTaskBar'; import CeleryTaskBar from './CeleryTaskBar';
import CeleryTaskGraph from './CeleryTaskGraph'; import CeleryTaskGraph from './CeleryTaskGraph';
import { import {
@ -13,7 +17,6 @@ import {
celeryErrorByWorkerWidgetData, celeryErrorByWorkerWidgetData,
celeryLatencyByWorkerWidgetData, celeryLatencyByWorkerWidgetData,
celeryTasksByWorkerWidgetData, celeryTasksByWorkerWidgetData,
celeryWorkerOnlineWidgetData,
} from './CeleryTaskGraphUtils'; } from './CeleryTaskGraphUtils';
import CeleryTaskLatencyGraph from './CeleryTaskLatencyGraph'; import CeleryTaskLatencyGraph from './CeleryTaskLatencyGraph';
@ -28,11 +31,6 @@ export default function CeleryTaskGraphGrid({
(state) => state.globalTime, (state) => state.globalTime,
); );
const celeryWorkerOnlineData = useMemo(
() => celeryWorkerOnlineWidgetData(minTime, maxTime),
[minTime, maxTime],
);
const celeryActiveTasksData = useMemo( const celeryActiveTasksData = useMemo(
() => celeryActiveTasksWidgetData(minTime, maxTime), () => celeryActiveTasksWidgetData(minTime, maxTime),
[minTime, maxTime], [minTime, maxTime],
@ -65,15 +63,31 @@ export default function CeleryTaskGraphGrid({
'Latency by worker', 'Latency by worker',
]; ];
const { options } = useCeleryFilterOptions(
'worker',
'rate',
DataSource.METRICS,
'flower_task_runtime_seconds_sum',
DataTypes.String,
'tag',
);
return ( return (
<div className="celery-task-graph-grid-container"> <div className="celery-task-graph-grid-container">
<div className="celery-task-graph-grid"> <div className="celery-task-graph-grid">
<CeleryTaskBar queryEnabled={queryEnabled} onClick={onClick} /> <CeleryTaskBar queryEnabled={queryEnabled} onClick={onClick} />
<CeleryTaskGraph <Card className="celery-task-graph-worker-count">
key={celeryWorkerOnlineData.id} <div className="worker-count-header">
widgetData={celeryWorkerOnlineData} <Typography.Text className="worker-count-header-text">
queryEnabled={queryEnabled} Worker Count
/> </Typography.Text>
</div>
<div className="worker-count-text-container">
<Typography.Text className="celery-task-graph-worker-count-text">
{options.filter((option) => option.value).length}
</Typography.Text>
</div>
</Card>
</div> </div>
<div className="celery-task-graph-grid"> <div className="celery-task-graph-grid">
<CeleryTaskLatencyGraph onClick={onClick} queryEnabled={queryEnabled} /> <CeleryTaskLatencyGraph onClick={onClick} queryEnabled={queryEnabled} />

View File

@ -490,49 +490,6 @@ export const celeryActiveTasksWidgetData = (
}), }),
); );
export const celeryWorkerOnlineWidgetData = (
startTime: number,
endTime: number,
): Widgets =>
getWidgetQueryBuilder(
getWidgetQuery({
title: 'Worker Online',
description: 'Represents the number of workers online.',
panelTypes: PANEL_TYPES.VALUE,
queryData: [
{
aggregateAttribute: {
dataType: DataTypes.Float64,
id: 'flower_task_runtime_seconds_sum--float64--Sum--true',
isColumn: true,
isJSON: false,
key: 'flower_task_runtime_seconds_sum',
type: 'Sum',
},
aggregateOperator: 'rate',
dataSource: DataSource.METRICS,
disabled: false,
expression: 'A',
filters: {
items: [],
op: 'AND',
},
functions: [],
groupBy: [],
having: [],
legend: '',
limit: null,
orderBy: [],
queryName: 'A',
reduceTo: 'avg',
spaceAggregation: 'sum',
stepInterval: getStepInterval(startTime, endTime),
timeAggregation: 'rate',
},
],
}),
);
export const celeryTaskLatencyWidgetData = ( export const celeryTaskLatencyWidgetData = (
type: string, type: string,
startTime: number, startTime: number,

View File

@ -1,11 +1,18 @@
import { DefaultOptionType } from 'antd/es/select'; import { DefaultOptionType } from 'antd/es/select';
import useDebouncedFn from 'hooks/useDebouncedFunction'; import useDebouncedFn from 'hooks/useDebouncedFunction';
import { useState } from 'react'; import { useState } from 'react';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { DataSource } from 'types/common/queryBuilder';
import { useGetAllFilters } from './CeleryTaskConfigOptions/useGetCeleryFilters'; import { useGetAllFilters } from './CeleryTaskConfigOptions/useGetCeleryFilters';
export const useCeleryFilterOptions = ( export const useCeleryFilterOptions = (
type: string | string[], type: string | string[],
aggregateOperator?: string,
dataSource?: DataSource,
aggregateAttribute?: string,
filterAttributeKeyDataType?: DataTypes,
tagType?: string,
): { ): {
searchText: string; searchText: string;
handleSearch: (value: string) => void; handleSearch: (value: string) => void;
@ -16,6 +23,11 @@ export const useCeleryFilterOptions = (
const { isFetching, options } = useGetAllFilters({ const { isFetching, options } = useGetAllFilters({
attributeKey: type, attributeKey: type,
searchText, searchText,
aggregateOperator,
dataSource,
aggregateAttribute,
filterAttributeKeyDataType,
tagType,
}); });
const handleDebouncedSearch = useDebouncedFn((searchText): void => { const handleDebouncedSearch = useDebouncedFn((searchText): void => {
setSearchText(searchText as string); setSearchText(searchText as string);

View File

@ -59,8 +59,8 @@ const ROUTES = {
WORKSPACE_SUSPENDED: '/workspace-suspended', WORKSPACE_SUSPENDED: '/workspace-suspended',
SHORTCUTS: '/shortcuts', SHORTCUTS: '/shortcuts',
INTEGRATIONS: '/integrations', INTEGRATIONS: '/integrations',
MESSAGING_QUEUES: '/messaging-queues', MESSAGING_QUEUES_KAFKA: '/messaging-queues/kafka',
MESSAGING_QUEUES_DETAIL: '/messaging-queues/detail', MESSAGING_QUEUES_KAFKA_DETAIL: '/messaging-queues/kafka/detail',
INFRASTRUCTURE_MONITORING_HOSTS: '/infrastructure-monitoring/hosts', INFRASTRUCTURE_MONITORING_HOSTS: '/infrastructure-monitoring/hosts',
INFRASTRUCTURE_MONITORING_KUBERNETES: '/infrastructure-monitoring/kubernetes', INFRASTRUCTURE_MONITORING_KUBERNETES: '/infrastructure-monitoring/kubernetes',
MESSAGING_QUEUES_CELERY_TASK: '/messaging-queues/celery-task', MESSAGING_QUEUES_CELERY_TASK: '/messaging-queues/celery-task',

View File

@ -287,8 +287,8 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
routeKey === 'TRACES_EXPLORER' || routeKey === 'TRACES_SAVE_VIEWS'; routeKey === 'TRACES_EXPLORER' || routeKey === 'TRACES_SAVE_VIEWS';
const isMessagingQueues = (): boolean => const isMessagingQueues = (): boolean =>
routeKey === 'MESSAGING_QUEUES' || routeKey === 'MESSAGING_QUEUES_KAFKA' ||
routeKey === 'MESSAGING_QUEUES_DETAIL' || routeKey === 'MESSAGING_QUEUES_KAFKA_DETAIL' ||
routeKey === 'MESSAGING_QUEUES_CELERY_TASK' || routeKey === 'MESSAGING_QUEUES_CELERY_TASK' ||
routeKey === 'MESSAGING_QUEUES_OVERVIEW'; routeKey === 'MESSAGING_QUEUES_OVERVIEW';

View File

@ -23,21 +23,15 @@ import {
TableData, TableData,
} from './utils'; } from './utils';
export const HoverButtonWrapper = styled.div` const ButtonWrapper = styled.div`
position: absolute; position: absolute;
right: 0; right: 0;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
opacity: 0;
transition: opacity 0.2s;
`; `;
const RelativeWrapper = styled.div` const RelativeWrapper = styled.div`
position: relative; position: relative;
&:hover ${HoverButtonWrapper} {
opacity: 1;
}
`; `;
function GridTableComponent({ function GridTableComponent({
@ -206,12 +200,12 @@ function GridTableComponent({
return ( return (
<RelativeWrapper> <RelativeWrapper>
{LineClampedTextComponent} {LineClampedTextComponent}
<HoverButtonWrapper className="hover-button"> <ButtonWrapper className="hover-button">
<button type="button" className="open-traces-button"> <button type="button" className="open-traces-button">
<Compass size={12} /> <Compass size={12} />
Open Trace Open Trace
</button> </button>
</HoverButtonWrapper> </ButtonWrapper>
</RelativeWrapper> </RelativeWrapper>
); );
}, },

View File

@ -239,7 +239,7 @@ function SideNav(): JSX.Element {
); );
registerShortcut(GlobalShortcuts.NavigateToMessagingQueues, () => registerShortcut(GlobalShortcuts.NavigateToMessagingQueues, () =>
onClickHandler(ROUTES.MESSAGING_QUEUES, null), onClickHandler(ROUTES.MESSAGING_QUEUES_OVERVIEW, null),
); );
registerShortcut(GlobalShortcuts.NavigateToAlerts, () => registerShortcut(GlobalShortcuts.NavigateToAlerts, () =>

View File

@ -49,8 +49,8 @@ export const routeConfig: Record<string, QueryParams[]> = {
[ROUTES.TRACE_EXPLORER]: [QueryParams.resourceAttributes], [ROUTES.TRACE_EXPLORER]: [QueryParams.resourceAttributes],
[ROUTES.LOGS_PIPELINES]: [QueryParams.resourceAttributes], [ROUTES.LOGS_PIPELINES]: [QueryParams.resourceAttributes],
[ROUTES.WORKSPACE_LOCKED]: [QueryParams.resourceAttributes], [ROUTES.WORKSPACE_LOCKED]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES]: [QueryParams.resourceAttributes], [ROUTES.MESSAGING_QUEUES_KAFKA]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_DETAIL]: [QueryParams.resourceAttributes], [ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_CELERY_TASK]: [QueryParams.resourceAttributes], [ROUTES.MESSAGING_QUEUES_CELERY_TASK]: [QueryParams.resourceAttributes],
[ROUTES.MESSAGING_QUEUES_OVERVIEW]: [QueryParams.resourceAttributes], [ROUTES.MESSAGING_QUEUES_OVERVIEW]: [QueryParams.resourceAttributes],
[ROUTES.INFRASTRUCTURE_MONITORING_HOSTS]: [QueryParams.resourceAttributes], [ROUTES.INFRASTRUCTURE_MONITORING_HOSTS]: [QueryParams.resourceAttributes],

View File

@ -94,7 +94,7 @@ const menuItems: SidebarItem[] = [
icon: <LayoutGrid size={16} />, icon: <LayoutGrid size={16} />,
}, },
{ {
key: ROUTES.MESSAGING_QUEUES, key: ROUTES.MESSAGING_QUEUES_OVERVIEW,
label: 'Messaging Queues', label: 'Messaging Queues',
icon: <ListMinus size={16} />, icon: <ListMinus size={16} />,
}, },

View File

@ -29,7 +29,7 @@ const breadcrumbNameMap: Record<string, string> = {
[ROUTES.SUPPORT]: 'Support', [ROUTES.SUPPORT]: 'Support',
[ROUTES.WORKSPACE_LOCKED]: 'Workspace Locked', [ROUTES.WORKSPACE_LOCKED]: 'Workspace Locked',
[ROUTES.WORKSPACE_SUSPENDED]: 'Workspace Suspended', [ROUTES.WORKSPACE_SUSPENDED]: 'Workspace Suspended',
[ROUTES.MESSAGING_QUEUES]: 'Messaging Queues', [ROUTES.MESSAGING_QUEUES_OVERVIEW]: 'Messaging Queues',
}; };
function ShowBreadcrumbs(props: RouteComponentProps): JSX.Element { function ShowBreadcrumbs(props: RouteComponentProps): JSX.Element {

View File

@ -212,8 +212,8 @@ export const routesToSkip = [
ROUTES.SERVICE_TOP_LEVEL_OPERATIONS, ROUTES.SERVICE_TOP_LEVEL_OPERATIONS,
ROUTES.ALERT_HISTORY, ROUTES.ALERT_HISTORY,
ROUTES.ALERT_OVERVIEW, ROUTES.ALERT_OVERVIEW,
ROUTES.MESSAGING_QUEUES, ROUTES.MESSAGING_QUEUES_KAFKA,
ROUTES.MESSAGING_QUEUES_DETAIL, ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
ROUTES.MESSAGING_QUEUES_CELERY_TASK, ROUTES.MESSAGING_QUEUES_CELERY_TASK,
ROUTES.MESSAGING_QUEUES_OVERVIEW, ROUTES.MESSAGING_QUEUES_OVERVIEW,
ROUTES.INFRASTRUCTURE_MONITORING_HOSTS, ROUTES.INFRASTRUCTURE_MONITORING_HOSTS,

View File

@ -1,22 +1,4 @@
.celery-overview-container { .celery-overview-container {
.celery-overview-breadcrumb {
display: flex;
padding: 0px 16px;
align-items: center;
gap: 8px;
padding-top: 10px;
padding-bottom: 8px;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
border-bottom: 1px solid var(--bg-slate-400);
}
.celery-overview-content { .celery-overview-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -42,3 +24,15 @@
} }
} }
} }
.lightMode {
.celery-overview-container {
.celery-overview-content {
.celery-overview-content-header {
.celery-overview-content-header-title {
color: var(--bg-slate-200);
}
}
}
}
}

View File

@ -28,3 +28,16 @@
} }
} }
} }
.lightMode {
.overview-right-panel-graph-card {
border: 1px solid var(--bg-vanilla-300) !important;
background: var(--bg-vanilla-100);
.request-rate-card,
.error-rate-card,
.avg-latency-card {
border-bottom: 0.75px solid var(--bg-vanilla-300);
}
}
}

View File

@ -29,7 +29,9 @@ export default function CeleryOverviewDetails({
case 'span_name': case 'span_name':
return getFiltersFromKeyValue('name', value, ''); return getFiltersFromKeyValue('name', value, '');
case 'messaging_system': case 'messaging_system':
return getFiltersFromKeyValue('messaging.system', value, 'tag'); return value === 'celery'
? undefined
: getFiltersFromKeyValue('messaging.system', value, 'tag');
case 'destination': case 'destination':
return getFiltersFromKeyValue( return getFiltersFromKeyValue(
details.messaging_system === 'celery' details.messaging_system === 'celery'
@ -48,12 +50,6 @@ export default function CeleryOverviewDetails({
return keyValues.filter((item) => item !== undefined) as TagFilterItem[]; return keyValues.filter((item) => item !== undefined) as TagFilterItem[];
}, [details]); }, [details]);
const groupByFilter = useMemo(
() =>
getFiltersFromKeyValue('messaging.destination.partition.id', '', 'tag').key,
[],
);
return ( return (
<Drawer <Drawer
width="60%" width="60%"
@ -92,7 +88,7 @@ export default function CeleryOverviewDetails({
> >
<div className="celery-overview-detail-container"> <div className="celery-overview-detail-container">
<ValueInfo filters={filters} /> <ValueInfo filters={filters} />
<OverviewRightPanelGraph filters={filters} groupByFilter={groupByFilter} /> <OverviewRightPanelGraph filters={filters} />
</div> </div>
</Drawer> </Drawer>
); );

View File

@ -49,6 +49,8 @@
margin-top: 8px; margin-top: 8px;
background: #262626; background: #262626;
border: none; border: none;
box-shadow: none;
border-radius: 4px;
&:hover { &:hover {
background: #404040; background: #404040;
@ -61,3 +63,32 @@
} }
} }
} }
.lightMode {
.value-info-card {
border: 1px solid var(--bg-vanilla-300) !important;
background: var(--bg-vanilla-100);
.metric-column {
.metric-title {
color: var(--bg-slate-100);
}
.metric-unit {
color: var(--bg-ink-500);
}
.metric-reference {
color: var(--bg-ink-500);
}
.trace-button {
background: var(--bg-slate-200);
&:hover {
background: var(--bg-slate-100);
}
}
}
}
}

View File

@ -1,22 +1,4 @@
.celery-task-container { .celery-task-container {
.celery-task-breadcrumb {
display: flex;
padding: 0px 16px;
align-items: center;
gap: 8px;
padding-top: 10px;
padding-bottom: 8px;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
border-bottom: 1px solid var(--bg-slate-400);
}
.celery-content { .celery-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -42,3 +24,15 @@
} }
} }
} }
.lightMode {
.celery-task-container {
.celery-content {
.celery-content-header {
.celery-content-header-title {
color: var(--bg-slate-200);
}
}
}
}
}

View File

@ -1,13 +1,12 @@
/* eslint-disable no-nested-ternary */ /* eslint-disable no-nested-ternary */
import '../MessagingQueues.styles.scss'; import '../MessagingQueues.styles.scss';
import { Select, Typography } from 'antd'; import { Select } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2'; import DateTimeSelectionV2 from 'container/TopNav/DateTimeSelectionV2';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { ListMinus } from 'lucide-react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
@ -65,20 +64,27 @@ function MQDetailPage(): JSX.Element {
selectedView !== MessagingQueuesViewType.dropRate.value && selectedView !== MessagingQueuesViewType.dropRate.value &&
selectedView !== MessagingQueuesViewType.metricPage.value; selectedView !== MessagingQueuesViewType.metricPage.value;
const handleBackClick = (): void => {
history.push(ROUTES.MESSAGING_QUEUES_KAFKA);
};
return ( return (
<div className="messaging-queue-container"> <div className="messaging-queue-container">
<div className="messaging-breadcrumb">
<ListMinus size={16} />
<Typography.Text
onClick={(): void => history.push(ROUTES.MESSAGING_QUEUES)}
className="message-queue-text"
>
Messaging Queues
</Typography.Text>
</div>
<div className="messaging-header"> <div className="messaging-header">
<div className="header-config"> <div className="header-config">
Kafka / views / <div
onClick={handleBackClick}
className="message-queue-text"
onKeyDown={(e): void => {
if (e.key === 'Enter' || e.key === ' ') {
handleBackClick();
}
}}
role="button"
tabIndex={0}
>
Kafka / views /
</div>
<Select <Select
className="messaging-queue-options" className="messaging-queue-options"
defaultValue={MessagingQueuesViewType.consumerLag.value} defaultValue={MessagingQueuesViewType.consumerLag.value}

View File

@ -1,31 +1,6 @@
.messaging-queue-container { .messaging-queue-container {
.messaging-breadcrumb { .message-queue-text {
display: flex; cursor: pointer;
padding: 0px 16px;
align-items: center;
gap: 8px;
padding-top: 10px;
padding-bottom: 8px;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
border-bottom: 1px solid var(--bg-slate-400);
.message-queue-text {
cursor: pointer;
color: var(--bg-vanilla-400);
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 20px;
letter-spacing: -0.07px;
}
} }
.messaging-header { .messaging-header {
@ -334,14 +309,6 @@
.lightMode { .lightMode {
.messaging-queue-container { .messaging-queue-container {
.messaging-breadcrumb {
color: var(--bg-ink-400);
border-bottom: 1px solid var(--bg-vanilla-300);
.message-queue-text {
color: var(--bg-ink-400);
}
}
.messaging-header { .messaging-header {
color: var(--bg-ink-400); color: var(--bg-ink-400);
border-bottom: 1px solid var(--bg-vanilla-300); border-bottom: 1px solid var(--bg-vanilla-300);

View File

@ -30,7 +30,7 @@ function MessagingQueues(): JSX.Element {
}); });
history.push( history.push(
`${ROUTES.MESSAGING_QUEUES_DETAIL}?${QueryParams.mqServiceView}=${callerView}`, `${ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL}?${QueryParams.mqServiceView}=${callerView}`,
); );
}; };

View File

@ -6,10 +6,11 @@ import ROUTES from 'constants/routes';
import history from 'lib/history'; import history from 'lib/history';
import { ListMinus, Rows3 } from 'lucide-react'; import { ListMinus, Rows3 } from 'lucide-react';
import CeleryOverview from 'pages/Celery/CeleryOverview/CeleryOverview'; import CeleryOverview from 'pages/Celery/CeleryOverview/CeleryOverview';
import { useLocation } from 'react-use'; import { useLocation } from 'react-router-dom';
import CeleryTask from '../Celery/CeleryTask/CeleryTask'; import CeleryTask from '../Celery/CeleryTask/CeleryTask';
import MessagingQueues from './MessagingQueues'; import MessagingQueues from './MessagingQueues';
import MQDetailPage from './MQDetailPage/MQDetailPage';
export const Kafka: TabRoutes = { export const Kafka: TabRoutes = {
Component: MessagingQueues, Component: MessagingQueues,
@ -18,8 +19,19 @@ export const Kafka: TabRoutes = {
<ListMinus size={16} /> Kafka <ListMinus size={16} /> Kafka
</div> </div>
), ),
route: ROUTES.MESSAGING_QUEUES, route: ROUTES.MESSAGING_QUEUES_KAFKA,
key: ROUTES.MESSAGING_QUEUES, key: ROUTES.MESSAGING_QUEUES_KAFKA,
};
export const KafkaDetail: TabRoutes = {
Component: MQDetailPage,
name: (
<div className="tab-item">
<ListMinus size={16} /> Kafka
</div>
),
route: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
key: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
}; };
export const Celery: TabRoutes = { export const Celery: TabRoutes = {
@ -47,7 +59,13 @@ export const Overview: TabRoutes = {
export default function MessagingQueuesMainPage(): JSX.Element { export default function MessagingQueuesMainPage(): JSX.Element {
const { pathname } = useLocation(); const { pathname } = useLocation();
const routes: TabRoutes[] = [Kafka, Celery, Overview]; const isKafkaDetail = pathname === ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL;
const routes: TabRoutes[] = [
Overview,
isKafkaDetail ? KafkaDetail : Kafka,
Celery,
];
return ( return (
<div className="messaging-queues-module-container"> <div className="messaging-queues-module-container">

View File

@ -52,8 +52,8 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
ALL_CHANNELS: ['ADMIN', 'EDITOR', 'VIEWER'], ALL_CHANNELS: ['ADMIN', 'EDITOR', 'VIEWER'],
INGESTION_SETTINGS: ['ADMIN', 'EDITOR', 'VIEWER'], INGESTION_SETTINGS: ['ADMIN', 'EDITOR', 'VIEWER'],
ALL_DASHBOARD: ['ADMIN', 'EDITOR', 'VIEWER'], ALL_DASHBOARD: ['ADMIN', 'EDITOR', 'VIEWER'],
MESSAGING_QUEUES: ['ADMIN', 'EDITOR', 'VIEWER'], MESSAGING_QUEUES_KAFKA: ['ADMIN', 'EDITOR', 'VIEWER'],
MESSAGING_QUEUES_DETAIL: ['ADMIN', 'EDITOR', 'VIEWER'], MESSAGING_QUEUES_KAFKA_DETAIL: ['ADMIN', 'EDITOR', 'VIEWER'],
ALL_ERROR: ['ADMIN', 'EDITOR', 'VIEWER'], ALL_ERROR: ['ADMIN', 'EDITOR', 'VIEWER'],
APPLICATION: ['ADMIN', 'EDITOR', 'VIEWER'], APPLICATION: ['ADMIN', 'EDITOR', 'VIEWER'],
CHANNELS_EDIT: ['ADMIN'], CHANNELS_EDIT: ['ADMIN'],