Skip to content
Closed
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
4 changes: 4 additions & 0 deletions src/containers/Tenant/Diagnostics/Diagnostics.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@
// This prevents inheritance issues with percentage-based calculations
container-type: size;
}

&__new-label {
margin-left: 8px;
}
}
30 changes: 29 additions & 1 deletion src/containers/Tenant/Diagnostics/Diagnostics.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';

import {Tab, TabList, TabProvider} from '@gravity-ui/uikit';
import {Label, Tab, TabList, TabProvider} from '@gravity-ui/uikit';
import {Helmet} from 'react-helmet-async';

import {AutoRefreshControl} from '../../../components/AutoRefreshControl/AutoRefreshControl';
Expand Down Expand Up @@ -33,6 +33,7 @@ import Describe from './Describe/Describe';
import DetailedOverview from './DetailedOverview/DetailedOverview';
import {getPagesByType, useDiagnosticsPageLinkGetter} from './DiagnosticsPages';
import {HotKeys} from './HotKeys/HotKeys';
import {Monitoring} from './Monitoring/Monitoring';
import {NetworkWrapper} from './Network/NetworkWrapper';
import {Partitions} from './Partitions/Partitions';
import {TopQueries} from './TopQueries';
Expand Down Expand Up @@ -98,6 +99,15 @@ function Diagnostics({additionalTenantProps}: DiagnosticsProps) {
/>
);
}
case TENANT_DIAGNOSTICS_TABS_IDS.monitoring: {
const monitoringUrl = additionalTenantProps?.getMonitoringLink?.(
database,
databaseType,
);
return (
<Monitoring database={database} monitoringUrl={monitoringUrl || undefined} />
);
}
case TENANT_DIAGNOSTICS_TABS_IDS.schema: {
return (
<SchemaViewer
Expand Down Expand Up @@ -220,17 +230,35 @@ function Diagnostics({additionalTenantProps}: DiagnosticsProps) {
}
};
const renderTabs = () => {
// Date when the Monitoring tab was added (Oct 22, 2025)
const MONITORING_TAB_LAUNCH_DATE = new Date('2025-10-22');
const FOURTEEN_DAYS_MS = 14 * 24 * 60 * 60 * 1000;
const now = new Date();
const showNewLabel =
now.getTime() - MONITORING_TAB_LAUNCH_DATE.getTime() < FOURTEEN_DAYS_MS;

return (
<div className={b('header-wrapper')}>
<div className={b('tabs')}>
<TabProvider value={activeTab?.id}>
<TabList size="l">
{pages.map(({id, title}) => {
const linkPath = getDiagnosticsPageLink(id);
const isMonitoringTab =
id === TENANT_DIAGNOSTICS_TABS_IDS.monitoring;
return (
<Tab key={id} value={id}>
<InternalLink to={linkPath} as="tab">
{title}
{isMonitoringTab && showNewLabel && (
<Label
theme="info"
size="xs"
className={b('new-label')}
>
New
</Label>
)}
</InternalLink>
</Tab>
);
Expand Down
7 changes: 7 additions & 0 deletions src/containers/Tenant/Diagnostics/DiagnosticsPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ const overview = {
title: 'Info',
};

const monitoring = {
id: TENANT_DIAGNOSTICS_TABS_IDS.monitoring,
title: 'Monitoring',
};

const schema = {
id: TENANT_DIAGNOSTICS_TABS_IDS.schema,
title: 'Schema',
Expand Down Expand Up @@ -115,6 +120,7 @@ const TRANSFER_PAGES = [overview, tablets, describe, access];

const DATABASE_PAGES = [
overview,
monitoring,
topQueries,
topShards,
nodes,
Expand All @@ -130,6 +136,7 @@ const DATABASE_PAGES = [

const SERVERLESS_DATABASE_PAGES = [
overview,
monitoring,
topQueries,
topShards,
tablets,
Expand Down
28 changes: 28 additions & 0 deletions src/containers/Tenant/Diagnostics/Monitoring/Monitoring.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@use '../../../../styles/mixins';

.ydb-monitoring {
width: 100%;
height: 100%;

&__iframe {
width: 100%;
height: 100%;

border: none;
}

&__empty {
display: flex;
justify-content: center;
align-items: center;

width: 100%;
height: 100%;
}

&__empty-text {
font-size: 16px;

color: var(--g-color-text-secondary);
}
}
33 changes: 33 additions & 0 deletions src/containers/Tenant/Diagnostics/Monitoring/Monitoring.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {cn} from '../../../../utils/cn';

import i18n from './i18n';

import './Monitoring.scss';

const b = cn('ydb-monitoring');

interface MonitoringProps {
database: string;
monitoringUrl?: string;
}

export function Monitoring({monitoringUrl}: MonitoringProps) {
if (!monitoringUrl) {
return (
<div className={b('empty')}>
<div className={b('empty-text')}>{i18n('message_not-available')}</div>
</div>
);
}

return (
<div className={b()}>
<iframe
className={b('iframe')}
src={monitoringUrl}
title="YDB Monitoring Dashboard"
frameBorder="0"
/>
</div>
);
}
3 changes: 3 additions & 0 deletions src/containers/Tenant/Diagnostics/Monitoring/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"message_not-available": "Monitoring is not available"
}
7 changes: 7 additions & 0 deletions src/containers/Tenant/Diagnostics/Monitoring/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {registerKeysets} from '../../../../../utils/i18n';

import en from './en.json';

const COMPONENT = 'ydb-monitoring';

export default registerKeysets(COMPONENT, {en});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Button, Flex, HelpMark, Icon, Label} from '@gravity-ui/uikit';
import {Button, Flex, HelpMark, Icon, Label, Tooltip} from '@gravity-ui/uikit';

import {EntityStatus} from '../../../../components/EntityStatus/EntityStatus';
import {LoaderWrapper} from '../../../../components/LoaderWrapper/LoaderWrapper';
Expand Down Expand Up @@ -186,17 +186,37 @@ export function TenantOverview({
<Flex alignItems="center" gap="1" className={b('top')}>
{renderName()}
<Flex gap="2">
{links.map(({title, url, icon}) => (
<Button
key={title}
href={url}
target="_blank"
size="xs"
title={title}
>
{links.map(({title, url, icon}) => {
const isMonitoring = title === i18n('field_monitoring-link');
const buttonContent = isMonitoring ? (
<>
<Icon data={icon} />
Monium
</>
) : (
<Icon data={icon} />
</Button>
))}
);

const button = (
<Button
key={title}
href={url}
target="_blank"
size="xs"
title={isMonitoring ? undefined : title}
>
{buttonContent}
</Button>
);

return isMonitoring ? (
<Tooltip key={title} content={i18n('tooltip_monium')}>
{button}
</Tooltip>
) : (
button
);
})}
</Flex>
</Flex>
<Flex direction="column" gap={4}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,7 @@
"value_serverless": "Serverless",
"context_serverless-tooltip": "Some metrics are hidden in Serverless mode — resources scale automatically based on workload",
"context_serverless-autoscaled": "Auto-Scaled Resources",
"context_serverless-storage-subtitle": "{{legend}} | {{groups}} groups"
"context_serverless-storage-subtitle": "{{legend}} | {{groups}} groups",
"field_monitoring-link": "Monitoring",
"tooltip_monium": "Full monitoring in Monium"
}
1 change: 1 addition & 0 deletions src/containers/Tenant/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"actions.notCopied": "Couldn’t copy the path",
"actions.copyPath": "Copy path",
"actions.connectToDB": "Connect to DB",
"actions.monitoring": "Monitoring",
"actions.dropIndex": "Drop index",
"actions.openPreview": "Open preview",
"actions.createTable": "Create table...",
Expand Down
22 changes: 18 additions & 4 deletions src/containers/Tenant/utils/schemaActions.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import {CirclePlus, Copy, PlugConnection} from '@gravity-ui/icons';
import {CirclePlus, Copy, PlugConnection, Pulse} from '@gravity-ui/icons';
import {Flex, Spin} from '@gravity-ui/uikit';
import copy from 'copy-to-clipboard';
import type {NavigationTreeNodeType} from 'ydb-ui-components';

import type {SnippetParams} from '../../../components/ConnectToDB/types';
import type {AppDispatch} from '../../../store';
import {TENANT_PAGES_IDS, TENANT_QUERY_TABS_ID} from '../../../store/reducers/tenant/constants';
import {setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
import {
TENANT_DIAGNOSTICS_TABS_IDS,
TENANT_PAGES_IDS,
TENANT_QUERY_TABS_ID,
} from '../../../store/reducers/tenant/constants';
import {setDiagnosticsTab, setQueryTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
import createToast from '../../../utils/createToast';
import {insertSnippetToEditor} from '../../../utils/monaco/insertSnippet';
import {transformPath} from '../ObjectSummary/transformPath';
Expand Down Expand Up @@ -98,6 +102,11 @@ const bindActions = (
}
: undefined,
getConnectToDBDialog: () => getConnectToDBDialog?.({database: params.database}),
goToMonitoring: () => {
dispatch(setTenantPage(TENANT_PAGES_IDS.diagnostics));
dispatch(setDiagnosticsTab(TENANT_DIAGNOSTICS_TABS_IDS.monitoring));
setActivePath(params.path);
},
createTable: inputQuery(createTableTemplate),
createColumnTable: inputQuery(createColumnTableTemplate),
createAsyncReplication: inputQuery(createAsyncReplicationTemplate),
Expand Down Expand Up @@ -190,6 +199,11 @@ export const getActions =
action: actions.getConnectToDBDialog,
iconStart: <PlugConnection />,
};
const monitoringItem = {
text: i18n('actions.monitoring'),
action: actions.goToMonitoring,
iconStart: <Pulse />,
};

const createEntitiesSet = [
{text: i18n('actions.createTable'), action: actions.createTable},
Expand All @@ -216,7 +230,7 @@ export const getActions =
},
],
};
const DB_SET: ActionsSet = [[copyItem, connectToDBItem], createEntitiesSet];
const DB_SET: ActionsSet = [[copyItem, connectToDBItem, monitoringItem], createEntitiesSet];

const DIR_SET: ActionsSet = [[copyItem], createEntitiesSet];

Expand Down
1 change: 1 addition & 0 deletions src/store/reducers/tenant/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const TENANT_QUERY_TABS_ID = {

export const TENANT_DIAGNOSTICS_TABS_IDS = {
overview: 'overview',
monitoring: 'monitoring',
schema: 'schema',
topQueries: 'topQueries',
topShards: 'topShards',
Expand Down