import React from 'react' import {amisRender, commonInfo, crudCommonOptions, readOnlyDialogOptions} from '../../util/amis.tsx' const color = (number: number) => { let color = 'text-success' if (number > 30) { color = 'text-primary' } if (number > 90) { color = 'text-danger' } return color } const versionDetailDialog = (variable: string, target: string) => { return { disabledOn: `${variable} === 0`, type: 'action', label: '详情', level: 'link', size: 'sm', actionType: 'dialog', dialog: { title: '详情', actions: [], size: 'md', closeOnEsc: false, closeOnOutside: false, body: [ { type: 'service', api: { method: 'get', url: `${commonInfo.baseUrl}/overview/version_detail`, data: { target: target, version: '${version}', }, }, body: [ { type: 'table', source: '${items}', affixHeader: false, columns: [ { label: 'Flink job id', fixed: 'left', type: 'wrapper', size: 'none', body: [ { type: 'tpl', tpl: '${id}', }, { type: 'action', level: 'link', label: '', icon: 'fa fa-copy', size: 'xs', actionType: 'copy', content: '${id}', tooltip: '复制 ID', }, ], }, { label: '别名', type: 'wrapper', fixed: 'left', size: 'none', className: 'nowrap', body: [ { type: 'tpl', tpl: '${alias}', }, { type: 'action', level: 'link', label: '', icon: 'fa fa-copy', size: 'xs', actionType: 'copy', content: '${alias}', tooltip: '复制别名', }, ], }, ], }, ], }, ], }, } } const tableDetailDialog = (variable: string, targetList: any) => { return { disabledOn: `${variable} === 0`, type: 'action', label: '详情', level: 'link', size: 'sm', actionType: 'dialog', dialog: { title: '详情', size: 'md', ...readOnlyDialogOptions(), body: [ { type: 'table', source: `\${${targetList}}`, affixHeader: false, columns: [ { label: 'Flink job id', fixed: 'left', type: 'wrapper', size: 'none', body: [ { type: 'tpl', tpl: '${id}', }, { type: 'action', level: 'link', label: '', icon: 'fa fa-copy', size: 'xs', actionType: 'copy', content: '${id}', tooltip: '复制 ID', }, ], }, { label: '别名', type: 'wrapper', fixed: 'left', size: 'none', className: 'nowrap', body: [ { type: 'tpl', tpl: '${alias}', }, { type: 'action', level: 'link', label: '', icon: 'fa fa-copy', size: 'xs', actionType: 'copy', content: '${alias}', tooltip: '复制别名', }, ], }, ], }, ], }, } } const overviewYarnJob = (cluster: string, search: string, queue: string | undefined, yarnQueue: string) => { return { className: 'text-base leading-none', type: 'table-view', border: false, padding: '0 10px 0 15px', trs: [ { tds: [ { body: `${cluster}`, }, { padding: '0px', body: queue === undefined ? {} : { type: 'service', api: `${commonInfo.baseUrl}/overview/queue?queue=${queue}`, interval: 10000, silentPolling: true, body: [ { type: 'tpl', tpl: '${size}', }, ], }, width: 100, align: 'center', }, { padding: '0px', width: 200, body: { type: 'service', api: { method: 'get', url: `${commonInfo.baseUrl}/overview/yarn-cluster`, data: { cluster: cluster, queue: yarnQueue, }, // @ts-ignore adaptor: function (payload, response) { let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity']) let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity']) return { ...payload, data: { ...payload.data, rootUsed: rootUsed, rootUsedColor: color(rootUsed), targetUsed: targetUsed, targetUsedColor: color(targetUsed), }, } }, }, interval: 10000, silentPolling: true, body: { type: 'table-view', border: false, trs: [ { tds: [ { body: { type: 'tpl', tpl: '${ROUND(rootUsed, 0)}%', }, width: 100, align: 'center', }, { body: { type: 'tpl', tpl: '${ROUND(targetUsed, 0)}%', }, width: 100, align: 'center', }, ], }, ], }, }, }, { padding: '0px', width: 200, body: { type: 'service', api: { url: `${commonInfo.baseUrl}/overview/yarn-job`, data: { cluster: cluster, search: search, }, }, interval: 10000, silentPolling: true, body: { type: 'table-view', border: false, trs: [ { tds: [ { body: { type: 'tpl', tpl: '${scheduling}', }, width: 100, align: 'center', }, { body: { type: 'tpl', tpl: '${running}', }, width: 100, align: 'center', }, ], }, ], }, }, }, ], }, ], } } const Overview: React.FC = () => { return (
{amisRender( { type: 'wrapper', body: [ { type: 'service', // language=JavaScript dataProvider: 'const timer = setInterval(() => {\n setData({date: new Date().toLocaleString()})\n}, 1000)\nreturn () => {\n clearInterval(timer)\n}', body: [ '当前时间:', { type: 'tpl', className: 'font-bold', tpl: '${date}', }, ], }, {type: 'divider'}, { type: 'crud', title: '同步表数量', api: `${commonInfo.baseUrl}/overview`, ...crudCommonOptions(), interval: 60000, columns: [ { name: 'type', label: '表类型', }, { name: 'total', label: '总表数', width: 100, align: 'center', }, { name: 'focus', label: '重点表', className: 'text-danger font-bold', width: 100, align: 'center', }, { label: '普通表', type: 'tpl', tpl: '${total - focus}', width: 100, align: 'center', }, ], }, { type: 'crud', title: '同步表数量', api: `${commonInfo.baseUrl}/overview/sync_running_status`, ...crudCommonOptions(), interval: 10000, columns: [ { name: 'type', label: '类型', }, { name: 'total', label: '任务数', width: 100, align: 'center', }, { name: 'running', label: '运行中', width: 100, align: 'center', }, { name: 'stopped', label: '已停止', className: 'text-danger font-bold', width: 100, align: 'center', }, { type: 'operation', label: '操作', width: 100, align: 'center', buttons: [ tableDetailDialog('stopped', 'list'), ], }, ], }, { className: 'pl-2 my-5', type: 'wrapper', size: 'none', body: { type: 'tpl', tpl: '同步集群资源用量情况', }, }, { type: 'table-view', border: false, trs: [ { background: '#F9F9F9', tds: [ { bold: true, body: '集群', }, { bold: true, body: '集群资源', width: 100, align: 'center', }, { bold: true, body: '队列资源', width: 100, align: 'center', }, { bold: true, body: '调度中', width: 100, align: 'center', }, { bold: true, body: '运行中', width: 100, align: 'center', }, ], }, ], }, overviewYarnJob(commonInfo.clusters.sync_names(), 'Sync', undefined, 'default'), {type: 'divider'}, { className: 'pl-2 my-5', type: 'wrapper', size: 'none', body: [ { type: 'tpl', tpl: '压缩集群资源用量情况', }, { className: 'mt-2', type: 'service', api: `${commonInfo.baseUrl}/overview/queue?queue=compaction-queue-pre`, interval: 10000, silentPolling: true, body: [ { type: 'tpl', tpl: '预调度队列:${size}', }, ], }, ], }, { type: 'table-view', border: false, bold: true, trs: [ { background: '#F9F9F9', tds: [ { bold: true, body: '集群', }, { bold: true, body: '队列', width: 100, align: 'center', }, { bold: true, body: '集群资源', width: 100, align: 'center', }, { bold: true, body: '队列资源', width: 100, align: 'center', }, { bold: true, body: '调度中', width: 100, align: 'center', }, { bold: true, body: '运行中', width: 100, align: 'center', }, ], }, ], }, // @ts-ignore ...Object.keys(commonInfo.clusters.compaction).map(name => overviewYarnJob(name, 'Compaction', `compaction-queue-${name}`, commonInfo.clusters.compaction[name])), {type: 'divider'}, { type: 'service', api: `${commonInfo.baseUrl}/overview/version`, interval: 10000, silentPolling: true, body: [ { type: 'table', title: '跨天情况 (${version})', source: '${items}', ...crudCommonOptions(), headerToolbar: [ '${version}', ], columns: [ { name: 'type', label: '类型', }, { name: 'unReceive', label: '未接收', width: 100, align: 'center', }, { type: 'operation', label: '操作', width: 100, align: 'center', buttons: [ versionDetailDialog('unReceive', 'unReceive_${key}'), ], }, { name: 'unScheduled', label: '未跨天', className: 'text-danger font-bold', width: 100, align: 'center', }, { type: 'operation', label: '操作', width: 100, align: 'center', buttons: [ versionDetailDialog('unScheduled', 'unScheduled_${key}'), ], }, ], }, ], }, { type: 'crud', title: '调度策略', api: `${commonInfo.baseUrl}/overview/schedule_jobs`, ...crudCommonOptions(), interval: 60000, loadDataOnce: true, columns: [ { name: 'job', label: '策略描述', }, { name: 'trigger', label: 'Cron表达式', className: 'font-mono', width: 250, }, ], }, { type: 'crud', title: '监控指标运行进度', api: `${commonInfo.baseUrl}/overview/monitor_progress`, ...crudCommonOptions(), interval: 2000, loadDataOnce: true, columns: [ { name: 'name', label: '名称', width: 150, }, { name: 'running', label: '状态', type: 'mapping', width: 70, map: { 'true': '运行中', 'false': '未运行', }, }, { label: '进度', type: 'progress', value: '${ROUND(progress * 100)}', map: 'bg-primary', }, ], }, ], }, )}
) } export default Overview