/
githubmirror
/
ydb-embedded-ui
Обзор
Документация
Войти
/
githubmirror
/
ydb-embedded-ui
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/services/api/viewer.ts
691 строка
22 KB
Hellen
feat(Database): show healthcheck in list (#4225)
11 авг 2026, 14:59
Не верифицирован
11 авг 2026, 14:59
d39b5b5
Код
Авторство
О чём код?
import type {CommitOffsetParams} from '../../store/reducers/partitions/types'; import type {PlanToSvgQueryParams} from '../../store/reducers/planToSvg'; import type {VDiskBlobIndexStatParams} from '../../store/reducers/vdisk/vdisk'; import type { AccessRightsUpdateRequest, AvailablePermissionsResponse, TMetaInfo, } from '../../types/api/acl'; import type {TQueryAutocomplete} from '../../types/api/autocomplete'; import type {CapabilitiesResponse} from '../../types/api/capabilities'; import type {TClusterInfo} from '../../types/api/cluster'; import type {SchemaPathParam} from '../../types/api/common'; 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 {TNetInfo} from '../../types/api/netInfo'; import type {NodesRequestParams, TNodesInfo} from '../../types/api/nodes'; import type {TEvNodesInfo} from '../../types/api/nodesList'; import type {TEvPDiskStateResponse} from '../../types/api/pdisk'; import type {PeersRequestParams, TPeersResponse} from '../../types/api/peers'; import type { Actions, ErrorResponse, QueryAPIResponse, SendQueryParams, } from '../../types/api/query'; import type {JsonRenderRequestParams, JsonRenderResponse} from '../../types/api/render'; import type {DescribeReplicationResult} from '../../types/api/replication'; import type {TEvDescribeSchemeResult} from '../../types/api/schema'; import type { StorageRequestParams, StorageStatsRequestParams, StorageStatsResponse, TStorageInfo, } from '../../types/api/storage'; import type {TEvSystemStateResponse} from '../../types/api/systemState'; import type { TDomainKey, TEvTabletStateResponse, UnmergedTEvTabletStateResponse, } from '../../types/api/tablet'; import type {TTenantInfo, TTenants} from '../../types/api/tenant'; import type {DescribeTopicResult, TopicDataRequest, TopicDataResponse} from '../../types/api/topic'; import type {VDiskBlobIndexResponse} from '../../types/api/vdiskBlobIndex'; import type {TUserToken} from '../../types/api/whoami'; import type {TabletsApiRequestParams} from '../../types/store/tablets'; import type {Nullable} from '../../utils/typecheckers'; import type {AxiosOptions} from './base'; import {BaseYdbAPI} from './base'; export class ViewerAPI extends BaseYdbAPI { getClusterCapabilities({database}: {database?: string}) { return this.get<CapabilitiesResponse>(this.getPath('/viewer/capabilities'), {database}, {}); } getClusterInfo(clusterName?: string, {concurrentId, signal}: AxiosOptions = {}) { return this.get<TClusterInfo>( this.getPath('/viewer/json/cluster'), { name: clusterName, tablets: true, }, {concurrentId: concurrentId || `getClusterInfo`, requestConfig: {signal}}, ); } /** id=. returns data about node that fullfills request */ getNodeInfo( {nodeId, database}: {nodeId?: string | number; database?: string}, {concurrentId, timeout, signal}: AxiosOptions = {}, ) { return this.get<TEvSystemStateResponse>( this.getPath('/viewer/json/sysinfo?enums=true'), { node_id: nodeId, database, fields_required: -1, }, {concurrentId, requestConfig: {signal}, timeout}, ); } getTenants({clusterName}: {clusterName?: string}, {concurrentId, signal}: AxiosOptions = {}) { return this.get<TTenantInfo>( this.getPath('/viewer/json/tenantinfo'), { tablets: false, storage: true, cluster_name: clusterName, }, {concurrentId, requestConfig: {signal}}, ); } getTenantInfo({database}: {database: string}, {concurrentId, signal}: AxiosOptions = {}) { return this.get<TTenantInfo>( this.getPath('/viewer/json/tenantinfo'), { database, path: database, tablets: false, storage: true, memory: true, }, {concurrentId, requestConfig: {signal}}, ); } getNodes( { type = 'any', tablets, database, tenant, fieldsRequired, filter, path, storage, ...params }: NodesRequestParams, {concurrentId, signal}: AxiosOptions = {}, ) { // This param determines whether we need VDisks to be returned // We need them only together with PDisks const isStorage = storage ?? fieldsRequired?.includes('PDisks'); const preparedFieldsRequired = Array.isArray(fieldsRequired) ? this.prepareArrayRequestParam(fieldsRequired) : fieldsRequired; return this.get<TNodesInfo>( this.getPath('/viewer/json/nodes?enums=true'), { type, // Use tablets for backward compatibility even if fieldsRequired is passed tablets: tablets ?? fieldsRequired?.includes('Tablets'), // Do not send empty string filter: filter || undefined, // TODO: remove after remove tenant param database: database || tenant, fields_required: preparedFieldsRequired, path: this.getSchemaPath(path), storage: isStorage, ...params, }, {concurrentId, requestConfig: {signal}}, ); } getNodePeers( {nodeId, filter, ...params}: PeersRequestParams, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TPeersResponse>( this.getPath('/viewer/json/peers'), { enums: true, node_id: nodeId, filter: filter || undefined, ...params, }, {concurrentId, requestConfig: {signal}}, ); } getTabletsInfo( {nodeId, path, database, filter}: TabletsApiRequestParams, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TEvTabletStateResponse>( this.getPath('/viewer/json/tabletinfo'), { database, node_id: nodeId, path: this.getSchemaPath(path), enums: true, filter, }, {concurrentId, requestConfig: {signal}}, ); } getSchema( {path, database}: {path: SchemaPathParam; database: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<Nullable<TEvDescribeSchemeResult>>( this.getPath('/viewer/json/describe'), { database, path: this.getSchemaPath(path), enums: true, backup: false, private: true, partition_config: false, partition_stats: false, partitioning_info: false, subs: 1, }, {concurrentId, requestConfig: {signal}}, ); } getDescribe( {path, database, timeout}: {path: SchemaPathParam; database: string; timeout?: number}, {concurrentId, signal}: AxiosOptions = {}, ) { const schemaPath = this.getSchemaPath(path); return this.get<Nullable<TEvDescribeSchemeResult>>( this.getPath('/viewer/json/describe'), { database, path: schemaPath, enums: true, partition_stats: false, subs: 0, }, { concurrentId: concurrentId || `getDescribe|${database}|${schemaPath}`, requestConfig: {signal}, timeout, }, ); } getSchemaAcl( {path, database, dialect}: {path: SchemaPathParam; database: string; dialect: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TMetaInfo>( this.getPath('/viewer/json/acl'), { database, path: this.getSchemaPath(path), merge_rules: true, dialect, }, {concurrentId, requestConfig: {signal}}, ); } getAvailablePermissions( {path, database, dialect}: {path: SchemaPathParam; database: string; dialect: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<AvailablePermissionsResponse>( this.getPath('/viewer/json/acl'), { database, path: this.getSchemaPath(path), merge_rules: true, dialect, list_permissions: true, }, {concurrentId, requestConfig: {signal}}, ); } updateAccessRights( { path, database, rights, dialect, }: { path: SchemaPathParam; database: string; rights: AccessRightsUpdateRequest; dialect: string; }, {concurrentId, signal}: AxiosOptions = {}, ) { return this.post<AccessRightsUpdateRequest>( this.getPath('/viewer/json/acl'), rights, { database, path: this.getSchemaPath(path), merge_rules: true, dialect, }, {concurrentId, requestConfig: {signal}}, ); } getHeatmapData( {path, database}: {path: SchemaPathParam; database: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<Nullable<TEvDescribeSchemeResult>>( this.getPath('/viewer/json/describe'), { database, path: this.getSchemaPath(path), enums: true, backup: false, children: false, partition_config: false, partition_stats: true, }, {concurrentId, requestConfig: {signal}}, ); } getNetwork( {path, database}: {path: SchemaPathParam; database: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TNetInfo>( this.getPath('/viewer/json/netinfo'), { enums: true, database, path: this.getSchemaPath(path), }, {concurrentId, requestConfig: {signal}}, ); } getReplication( {path, database}: {path: SchemaPathParam; database: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<DescribeReplicationResult>( this.getPath('/viewer/json/describe_replication'), { enums: true, include_stats: true, database, path: this.getSchemaPath(path), }, {concurrentId, requestConfig: {signal}}, ); } getTopic( {path, database}: {path: SchemaPathParam; database: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<DescribeTopicResult>( this.getPath('/viewer/json/describe_topic'), { enums: true, include_stats: true, database, path: this.getSchemaPath(path), }, {concurrentId, requestConfig: {signal}}, ); } getTopicData(params: TopicDataRequest, {concurrentId, signal}: AxiosOptions = {}) { return this.get<TopicDataResponse>(this.getPath('/viewer/json/topic_data'), params, { concurrentId, requestConfig: {signal}, }); } getConsumer( {path, consumer, database}: {path: SchemaPathParam; consumer: string; database: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<DescribeConsumerResult>( this.getPath('/viewer/json/describe_consumer'), { enums: true, include_stats: true, database, path: this.getSchemaPath(path), consumer, }, {concurrentId: concurrentId || 'getConsumer', requestConfig: {signal}}, ); } getTablet( {id, database, followerId}: {id: string; database?: string; followerId?: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TEvTabletStateResponse>( this.getPath('/viewer/json/tabletinfo'), { enums: true, database, filter: `(TabletId=${id};FollowerId=${followerId || 0})`, }, { concurrentId, requestConfig: {signal}, }, ); } getTabletHistory( {id, database}: {id: string; database?: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<UnmergedTEvTabletStateResponse>( this.getPath('/viewer/json/tabletinfo'), { enums: true, merge: false, database, filter: `(TabletId=${id};State!=Dead)`, }, { concurrentId, requestConfig: {signal}, }, ); } getNodesList({database}: {database?: string}, {concurrentId, signal}: AxiosOptions = {}) { return this.get<TEvNodesInfo>( this.getPath('/viewer/json/nodelist'), { enums: true, database, }, { concurrentId, requestConfig: {signal}, }, ); } getTenantsList({concurrentId, signal}: AxiosOptions = {}) { return this.get<TTenants>( this.getPath('/viewer/json/tenants'), { enums: true, state: 0, }, { concurrentId, requestConfig: {signal}, }, ); } sendQuery<Action extends Actions>( params: SendQueryParams<Action>, {concurrentId, signal, withRetries}: AxiosOptions = {}, ) { const base64 = params.base64; return this.post<QueryAPIResponse<Action> | ErrorResponse | null>( this.getPath('/viewer/json/query'), {...params, base64}, {database: params.database, schema: 'multi', base64, timeout: params.timeout}, { concurrentId, timeout: params.timeout, requestConfig: { signal, 'axios-retry': {retries: withRetries ? this.DEFAULT_RETRIES_COUNT : 0}, }, headers: params.tracingLevel ? { 'X-Trace-Verbosity': params.tracingLevel, } : undefined, }, ); } getHotKeys( { path, database, enableSampling, }: {path: SchemaPathParam; database: string; enableSampling: boolean}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<JsonHotKeysResponse>( this.getPath('/viewer/json/hotkeys'), { database, path: this.getSchemaPath(path), enable_sampling: enableSampling, }, {concurrentId: concurrentId || 'getHotKeys', requestConfig: {signal}}, ); } getTabletDescribe( tenantId: TDomainKey, database?: string, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<Nullable<TEvDescribeSchemeResult>>( this.getPath('/viewer/json/describe'), { schemeshard_id: tenantId?.SchemeShard, path_id: tenantId?.PathId, database, }, {concurrentId, requestConfig: {signal}}, ); } getStorageInfo( {database, nodeId, groupId, pDiskId, filter, ...params}: StorageRequestParams, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TStorageInfo>( this.getPath(`/viewer/json/storage?enums=true`), { database, node_id: nodeId, group_id: groupId, pdisk_id: pDiskId, // Do not send empty string filter: filter || undefined, ...params, }, {concurrentId, requestConfig: {signal}}, ); } getStorageStats( { database, path, groupBy = 'path', everything, groups, tablets, media, }: StorageStatsRequestParams, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<StorageStatsResponse>( this.getPath('/viewer/storage_stats'), { database, path: this.getSchemaPath(path), group_by: groupBy, everything, groups, tablets, media, }, {concurrentId, requestConfig: {signal}}, ); } getChartData( {target, from, until, maxDataPoints, database}: JsonRenderRequestParams, {concurrentId, signal}: AxiosOptions = {}, ) { const requestString = `${target}&from=${from}&until=${until}&maxDataPoints=${maxDataPoints}&format=json`; return this.post<JsonRenderResponse>( this.getPath(`/viewer/json/render?database=${database}`), requestString, {}, { concurrentId, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, requestConfig: {signal}, }, ); } whoami({database}: {database?: string}) { return this.get<TUserToken>(this.getPath('/viewer/json/whoami'), {database}); } autocomplete(params: {database: string; prefix?: string; limit?: number; table?: string[]}) { const {table, ...rest} = params; const tablesParam = table?.join(','); return this.get<TQueryAutocomplete>( this.getPath('/viewer/json/autocomplete'), {...rest, table: tablesParam}, {concurrentId: 'sql-autocomplete'}, ); } getFeatureFlags(database?: string, {concurrentId, signal}: AxiosOptions = {}) { return this.get<FeatureFlagConfigs>( this.getPath('/viewer/feature_flags'), { database, }, {concurrentId, requestConfig: {signal}}, ); } getConfig(database?: string, {concurrentId, signal}: AxiosOptions = {}) { return this.get<Record<string, unknown>>( this.getPath('/viewer/config'), { database, }, {concurrentId, requestConfig: {signal}}, ); } getVDiskBlobIndexStat( {database, ...rest}: VDiskBlobIndexStatParams, {concurrentId, signal}: AxiosOptions = {}, ) { const params = 'vDiskId' in rest ? {vdisk_id: rest.vDiskId} : { node_id: rest.nodeId, pdisk_id: rest.pDiskId, vslot_id: rest.vDiskSlotId, }; return this.get<VDiskBlobIndexResponse>( this.getPath('/vdisk/blobindexstat'), { ...params, database, }, {concurrentId, requestConfig: {signal}}, ); } getNodeWhiteboardPDiskInfo( { nodeId, pDiskId, database, }: {nodeId: string | number; pDiskId: string | number; database?: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<TEvPDiskStateResponse>( this.getPath('/viewer/json/pdiskinfo?enums=true'), { filter: `(NodeId=${nodeId}${pDiskId ? `;PDiskId=${pDiskId}` : ''})`, database, }, {concurrentId, requestConfig: {signal}}, ); } planToSvg({database, plan}: PlanToSvgQueryParams, {signal}: {signal?: AbortSignal} = {}) { return this.post<string>( this.getPath('/viewer/plan2svg'), plan, {database}, { requestConfig: { signal, responseType: 'text', headers: { Accept: 'image/svg+xml', }, }, }, ); } getHealthcheckInfo( { database, maxLevel, clusterName, }: {database: string; maxLevel?: number; clusterName?: string}, {concurrentId, signal}: AxiosOptions = {}, ) { return this.get<HealthCheckAPIResponse>( this.getPath('/viewer/json/healthcheck?merge_records=true', clusterName), {database, max_level: maxLevel}, {concurrentId, requestConfig: {signal}}, ); } commitOffset( {database, path, consumer, partitionId, offset}: CommitOffsetParams, {concurrentId, signal}: AxiosOptions = {}, ) { return this.post( this.getPath('/viewer/commit_offset'), { database, path: this.getSchemaPath(path), consumer, partition_id: partitionId, offset, }, {database}, {concurrentId, requestConfig: {signal}}, ); } }