function color(number) { let color = 'text-success' if (number > 30) { color = 'text-primary' } if (number > 90) { color = 'text-danger' } return color } function versionDetailDialog(variable, target) { 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: '${base}/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: '复制别名', }, ], }, ] } ] } ] } } } function overviewYarnJob(cluster, search, queue, yarnQueue) { return { className: 'font-mono', type: 'service', api: `\${base}/overview/yarn-job?cluster=${cluster}&search=${search}`, interval: 10000, silentPolling: true, body: [ { type: 'tpl', className: 'mr-1 font-bold', tpl: `${cluster}`, }, queue === undefined ? {} : { type: 'service', className: 'inline ml-2', api: `\${base}/overview/queue?queue=compaction-queue-${cluster}`, interval: 10000, silentPolling: true, body: [ { type: 'tpl', tpl: "${PADSTART(size, 2)}", } ] }, ' ', { type: 'service', className: 'inline', api: { method: 'get', url: `\${base}/overview/yarn-cluster`, data: { cluster: cluster, queue: yarnQueue, }, adaptor: function (payload, response) { let rootUsed = (payload['data']['root']['usedCapacity'] * 100 / payload['data']['root']['capacity']).toFixed(0) let targetUsed = (payload['data']['target']['absoluteUsedCapacity'] * 100 / payload['data']['target']['absoluteMaxCapacity']).toFixed(0) return { ...payload, data: { ...payload.data, rootUsed: rootUsed, rootUsedColor: color(rootUsed), targetUsed: targetUsed, targetUsedColor: color(targetUsed), } } } }, interval: 10000, silentPolling: true, body: [ '(', { type: 'tpl', tpl: '${PADSTART(ROUND(rootUsed), 3)}%', }, ',', { type: 'tpl', tpl: '${PADSTART(ROUND(targetUsed), 3)}%', }, ')' ], }, '(', { type: 'tpl', tpl: "${PADSTART(total, 4)}", }, ',', { type: 'tpl', tpl: "${PADSTART(scheduling, 2)}", }, ',', { type: 'tpl', tpl: '${PADSTART(running, 3)}', }, ',', { type: 'tpl', tpl: '${PADSTART(failure, 3)}', }, ')', ] } } function overviewTab() { return { className: 'white-space-pre', title: '概览', tab: [ { 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: 'service', api: '${base}/overview', interval: 60000, silentPolling: true, body: [ { type: 'tpl', tpl: '逻辑表:${PADSTART(table_count, 4)} (${PADSTART(table_focus_count, 4)}, ${PADSTART(table_count - table_focus_count, 4)})', }, '
', { type: 'tpl', tpl: '湖底表:${PADSTART(hudi_count, 4)} (${PADSTART(hudi_focus_count, 4)}, ${PADSTART(hudi_count - hudi_focus_count, 4)})', }, '
', { type: 'tpl', tpl: '嗨福表:${PADSTART(hive_count, 4)} (${PADSTART(hive_focus_count, 4)}, ${PADSTART(hive_count - hive_focus_count, 4)})', }, ] }, {type: 'divider'}, '集群 (集群总资源使用,队列资源使用)(总压缩任务数,调度中任务数,运行中任务数,失败任务数)', overviewYarnJob('b5-sync', 'Sync', undefined, 'default'), {type: 'divider'}, { className: 'my-2', type: 'service', api: `\${base}/overview/queue?queue=compaction-queue-pre`, interval: 10000, silentPolling: true, body: [ { type: 'tpl', tpl: '预调度队列:${size}', } ] }, '集群 压缩队列任务数(集群总资源使用,队列资源使用)(总压缩任务数,调度中任务数,运行中任务数,失败任务数)', overviewYarnJob('b1', 'Compaction', 'compaction-queue-b1', 'datalake'), overviewYarnJob('b5', 'Compaction', 'compaction-queue-b5', 'ten_iap.datalake'), overviewYarnJob('a4', 'Compaction', 'compaction-queue-a4', 'ten_iap.datalake'), {type: 'divider'}, { type: 'service', api: '${base}/overview/version', interval: 10000, silentPolling: true, body: [ '版本:', { type: 'tpl', className: 'font-bold', tpl: '${version}', }, '
', '未接收, 未跨天', '
', '重点表:', { type: 'tpl', tpl: '${PADSTART(unReceive.focus, 3)}', }, versionDetailDialog('unReceive.focus', 'unReceive_focus'), ',', { type: 'tpl', tpl: '${PADSTART(unSchedule.focus, 3)}', }, versionDetailDialog('unSchedule.focus', 'unScheduled_focus'), '
', '普通表:', { type: 'tpl', tpl: '${PADSTART(unReceive.normal, 3)}', }, versionDetailDialog('unReceive.normal', 'unReceive_normal'), ',', { type: 'tpl', tpl: '${PADSTART(unSchedule.normal, 3)}', }, versionDetailDialog('unSchedule.normal', 'unScheduled_normal'), ] }, {type: 'divider'}, { type: 'service', api: '${base}/overview/schedule_jobs', interval: 60000, silentPolling: true, body: [ '调度策略', { type: 'each', name: 'items', items: { type: 'tpl', tpl: '
${trigger} (${job})
' } } ] } ] } }