Skip to content

Commit

Permalink
feat(Diagnostics): display db feature flags (#1229)
Browse files Browse the repository at this point in the history
Co-authored-by: Valerii Sidorenko <[email protected]>
  • Loading branch information
sareyu and ValeraS authored Sep 9, 2024
1 parent bb647f5 commit 182d803
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/containers/Tenant/Diagnostics/Configs/Configs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.ydb-diagnostics-configs {
&__icon-touched {
line-height: 1;
cursor: default !important;

color: var(--g-color-text-secondary);
}
}
125 changes: 125 additions & 0 deletions src/containers/Tenant/Diagnostics/Configs/Configs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {PersonPencil} from '@gravity-ui/icons';
import type {Column} from '@gravity-ui/react-data-table';
import {Icon, Popover, Switch} from '@gravity-ui/uikit';
import {StringParam, useQueryParam} from 'use-query-params';

import {ResponseError} from '../../../../components/Errors/ResponseError';
import {ResizeableDataTable} from '../../../../components/ResizeableDataTable/ResizeableDataTable';
import {Search} from '../../../../components/Search';
import {TableWithControlsLayout} from '../../../../components/TableWithControlsLayout/TableWithControlsLayout';
import {tenantApi} from '../../../../store/reducers/tenant/tenant';
import type {FeatureFlagConfig} from '../../../../types/api/featureFlags';
import {cn} from '../../../../utils/cn';
import {DEFAULT_TABLE_SETTINGS} from '../../../../utils/constants';

import i18n from './i18n';

import './Configs.scss';

const FEATURE_FLAGS_COLUMNS_WIDTH_LS_KEY = 'featureFlagsColumnsWidth';

const b = cn('ydb-diagnostics-configs');

const columns: Column<FeatureFlagConfig>[] = [
{
name: 'Touched',
header: '',
render: ({row}) =>
row.Current ? (
<Popover
content={i18n('flag-touched')}
className={b('icon-touched')}
placement="left"
>
<Icon data={PersonPencil} />
</Popover>
) : null,
width: 36,
sortable: false,
resizeable: false,
},
{
name: 'Name',
get header() {
return i18n('td-feature-flag');
},
render: ({row}) => (row.Current ? <b>{row.Name}</b> : row.Name),
width: 400,
sortable: true,
sortAccessor: ({Current, Name}) => {
return Number(!Current) + Name.toLowerCase();
},
},
{
name: 'Default',
get header() {
return i18n('td-default');
},
render: ({row}) => {
switch (row.Default) {
case true:
return i18n('enabled');
case false:
return i18n('disabled');
default:
return '-';
}
},
width: 100,
sortable: false,
resizeable: false,
},
{
name: 'Current',
get header() {
return i18n('td-current');
},
render: ({row}) => <Switch disabled checked={(row.Current ?? row.Default) || false} />,
width: 100,
sortable: false,
resizeable: false,
},
];

interface ConfigsProps {
database: string;
}

export const Configs = ({database}: ConfigsProps) => {
const [search, setSearch] = useQueryParam('search', StringParam);
const {currentData = [], isFetching, error} = tenantApi.useGetClusterConfigQuery({database});

const onChange = (value: string) => {
setSearch(value || undefined, 'replaceIn');
};

const featureFlagsFilter = search?.toLocaleLowerCase();
const featureFlags = featureFlagsFilter
? currentData.filter((item) => item.Name.toLocaleLowerCase().includes(featureFlagsFilter))
: currentData;

return (
<TableWithControlsLayout>
<TableWithControlsLayout.Controls>
<Search
value={featureFlagsFilter}
onChange={onChange}
placeholder={i18n('search-placeholder')}
/>
</TableWithControlsLayout.Controls>
<TableWithControlsLayout.Table loading={isFetching}>
{error ? (
<ResponseError error={error} />
) : (
<ResizeableDataTable
emptyDataMessage={i18n(featureFlagsFilter ? 'search-empty' : 'no-data')}
columnsWidthLSKey={FEATURE_FLAGS_COLUMNS_WIDTH_LS_KEY}
columns={columns}
data={featureFlags}
settings={DEFAULT_TABLE_SETTINGS}
/>
)}
</TableWithControlsLayout.Table>
</TableWithControlsLayout>
);
};
13 changes: 13 additions & 0 deletions src/containers/Tenant/Diagnostics/Configs/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"td-feature-flag": "Feature flag",
"td-default": "Default",
"td-current": "Current",

"enabled": "Enabled",
"disabled": "Disabled",
"flag-touched": "Flag is changed",

"search-placeholder": "Search by feature flag",
"search-empty": "Empty search result",
"no-data": "No data"
}
7 changes: 7 additions & 0 deletions src/containers/Tenant/Diagnostics/Configs/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-diagnostics-configs';

export default registerKeysets(COMPONENT, {en});
4 changes: 4 additions & 0 deletions src/containers/Tenant/Diagnostics/Diagnostics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {SchemaViewer} from '../Schema/SchemaViewer/SchemaViewer';
import {TenantTabsGroups} from '../TenantPages';
import {isDatabaseEntityType} from '../utils/schema';

import {Configs} from './Configs/Configs';
import {Consumers} from './Consumers';
import Describe from './Describe/Describe';
import DetailedOverview from './DetailedOverview/DetailedOverview';
Expand Down Expand Up @@ -131,6 +132,9 @@ function Diagnostics(props: DiagnosticsProps) {
case TENANT_DIAGNOSTICS_TABS_IDS.partitions: {
return <Partitions path={path} database={tenantName} />;
}
case TENANT_DIAGNOSTICS_TABS_IDS.configs: {
return <Configs database={tenantName} />;
}
default: {
return <div>No data...</div>;
}
Expand Down
6 changes: 6 additions & 0 deletions src/containers/Tenant/Diagnostics/DiagnosticsPages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ const partitions = {
title: 'Partitions',
};

const configs = {
id: TENANT_DIAGNOSTICS_TABS_IDS.configs,
title: 'Configs',
};

export const ASYNC_REPLICATION_PAGES = [overview, tablets, describe];

export const DATABASE_PAGES = [
Expand All @@ -81,6 +86,7 @@ export const DATABASE_PAGES = [
storage,
network,
describe,
configs,
];

export const TABLE_PAGES = [overview, schema, topShards, nodes, graph, tablets, hotKeys, describe];
Expand Down
10 changes: 10 additions & 0 deletions src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {CapabilitiesResponse} from '../types/api/capabilities';
import type {TClusterInfo} from '../types/api/cluster';
import type {TComputeInfo} from '../types/api/compute';
import type {DescribeConsumerResult} from '../types/api/consumer';
import type {FeatureFlagConfigs} from '../types/api/featureFlags';
import type {HealthCheckAPIResponse} from '../types/api/healthcheck';
import type {JsonHotKeysResponse} from '../types/api/hotkeys';
import type {
Expand Down Expand Up @@ -147,6 +148,15 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
{concurrentId: concurrentId || `getClusterInfo`, requestConfig: {signal}},
);
}
getClusterConfig(database?: string, {concurrentId, signal}: AxiosOptions = {}) {
return this.get<FeatureFlagConfigs>(
this.getPath('/viewer/feature_flags'),
{
database,
},
{concurrentId, requestConfig: {signal}},
);
}
getNodeInfo(id?: string | number, {concurrentId, signal}: AxiosOptions = {}) {
return this.get<TEvSystemStateResponse>(
this.getPath('/viewer/json/sysinfo?enums=true'),
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 @@ -25,6 +25,7 @@ export const TENANT_DIAGNOSTICS_TABS_IDS = {
graph: 'graph',
consumers: 'consumers',
partitions: 'partitions',
configs: 'configs',
} as const;

export const TENANT_SUMMARY_TABS_IDS = {
Expand Down
12 changes: 12 additions & 0 deletions src/store/reducers/tenant/tenant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ export const tenantApi = api.injectEndpoints({
},
providesTags: ['All'],
}),
getClusterConfig: builder.query({
queryFn: async ({database}: {database: string}, {signal}) => {
try {
const res = await window.api.getClusterConfig(database, {signal});
const db = res.Databases[0];

return {data: db.FeatureFlags};
} catch (error) {
return {error};
}
},
}),
}),
overrideExisting: 'throw',
});
14 changes: 14 additions & 0 deletions src/types/api/featureFlags.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface FeatureFlagConfig {
Name: string;
Current?: boolean;
Default?: boolean;
}

interface ConfigDb {
Name: string;
FeatureFlags: FeatureFlagConfig[];
}

export interface FeatureFlagConfigs {
Databases: ConfigDb[];
}

0 comments on commit 182d803

Please sign in to comment.