setup()

in seatunnel-engine/seatunnel-engine-ui/src/views/jobs/detail.tsx [42:268]


  setup() {
    const { t } = useI18n()
    const route = useRoute()

    const jobId = route.params.jobId as string
    const job = reactive({} as Job)
    const duration = ref('')
    let timer: NodeJS.Timeout
    const fetch = async () => {
      const res = await getJobInfo(jobId)
      Object.assign(job, res)
      clearInterval(timer)
      const d = parse(res.createTime, 'yyyy-MM-dd HH:mm:ss', new Date())
      duration.value = getRemainTime(Math.abs(Date.now() - d.getTime()))
      setTimeout(fetch, 5000)
      if (job.jobStatus !== 'RUNNING') {
        return
      }
      timer = setInterval(() => {
        duration.value = getRemainTime(Math.abs(Date.now() - d.getTime()))
      }, 1000)
    }

    fetch()

    const select = ref('Overview')
    const change = () => {
      console.log(select.value)
    }
    watch(() => select.value, change)

    const tableData = computed(() => {
      return job.jobDag?.vertexInfoMap?.filter((v) => v.type !== 'transform') || []
    })
    const sourceCell = (
      row: Vertex,
      key:
        | 'TableSourceReceivedBytes'
        | 'TableSourceReceivedCount'
        | 'TableSourceReceivedQPS'
        | 'TableSourceReceivedBytesPerSeconds'
    ) => {
      if (row.type === 'source') {
        return row.tablePaths.reduce((s, path) => s + Number(job.metrics?.[key][path]), 0)
      }
      return 0
    }
    const sinkCell = (
      row: Vertex,
      key:
        | 'TableSinkWriteBytes'
        | 'TableSinkWriteCount'
        | 'TableSinkWriteQPS'
        | 'TableSinkWriteBytesPerSeconds'
    ) => {
      if (row.type === 'sink') {
        return row.tablePaths.reduce((s, path) => s + Number(job.metrics?.[key][path]), 0)
      }
      return 0
    }
    const columns: DataTableColumns<Vertex> = [
      {
        title: 'Name',
        key: 'vertexName'
      },
      {
        title: 'Received Bytes',
        key: 'key',
        render: (row) => sourceCell(row, 'TableSourceReceivedBytes')
      },
      {
        title: 'Write Bytes',
        key: 'key',
        render: (row) => sinkCell(row, 'TableSinkWriteBytes')
      },
      {
        title: 'Received Count',
        key: 'key',
        render: (row) => sourceCell(row, 'TableSourceReceivedCount')
      },
      {
        title: 'Write Count',
        key: 'key',
        render: (row) => sinkCell(row, 'TableSinkWriteCount')
      },
      {
        title: 'Received QPS',
        key: 'key',
        render: (row) => sourceCell(row, 'TableSourceReceivedQPS')
      },
      {
        title: 'Write QPS',
        key: 'key',
        render: (row) => sinkCell(row, 'TableSinkWriteQPS')
      },
      {
        title: 'Received Bytes PerSecond',
        key: 'key',
        render: (row) => sourceCell(row, 'TableSourceReceivedBytesPerSeconds')
      },
      {
        title: 'Write Bytes PerSecond',
        key: 'key',
        render: (row) => sinkCell(row, 'TableSinkWriteBytesPerSeconds')
      }
    ]

    const focusedId = ref(0)
    const drawerShow = ref(false)
    const onFocus = (vertex?: Vertex) => {
      if (vertex && vertex.type !== 'transform') {
        drawerShow.value = true
        focusedId.value = vertex.vertexId
      } else {
        drawerShow.value = false
        focusedId.value = 0
      }
    }
    const onDrawerClose = () => {
      drawerShow.value = false
    }
    const focusedVertex = computed(() => {
      const vertex = job.jobDag?.vertexInfoMap?.find((v) => v.vertexId === focusedId.value)
      const metrics = {} as any
      if (vertex?.type === 'source') {
        Object.keys(job.metrics?.TableSourceReceivedBytes || {}).forEach((key) => {
          metrics[`TableSourceReceivedBytes.${key}`] = job.metrics?.TableSourceReceivedBytes[key]
        })
        Object.keys(job.metrics?.TableSourceReceivedCount || {}).forEach((key) => {
          metrics[`TableSourceReceivedCount.${key}`] = job.metrics?.TableSourceReceivedCount[key]
        })
        Object.keys(job.metrics?.TableSourceReceivedQPS || {}).forEach((key) => {
          metrics[`TableSourceReceivedQPS.${key}`] = job.metrics?.TableSourceReceivedQPS[key]
        })
        Object.keys(job.metrics?.TableSourceReceivedBytesPerSeconds || {}).forEach((key) => {
          metrics[`TableSourceReceivedBytesPerSeconds.${key}`] =
            job.metrics?.TableSourceReceivedBytesPerSeconds[key]
        })
      }
      if (vertex?.type === 'sink') {
        Object.keys(job.metrics?.TableSinkWriteBytes || {}).forEach((key) => {
          metrics[`TableSinkWriteBytes.${key}`] = job.metrics?.TableSinkWriteBytes[key]
        })
        Object.keys(job.metrics?.TableSinkWriteCount || {}).forEach((key) => {
          metrics[`TableSinkWriteCount.${key}`] = job.metrics?.TableSinkWriteCount[key]
        })
        Object.keys(job.metrics?.TableSinkWriteQPS || {}).forEach((key) => {
          metrics[`TableSinkWriteQPS.${key}`] = job.metrics?.TableSinkWriteQPS[key]
        })
        Object.keys(job.metrics?.TableSinkWriteBytesPerSeconds || {}).forEach((key) => {
          metrics[`TableSinkWriteBytesPerSeconds.${key}`] =
            job.metrics?.TableSinkWriteBytesPerSeconds[key]
        })
      }
      return Object.assign({}, vertex, metrics)
    })
    const rowClassName = (row: Vertex) => {
      if (row.vertexId === focusedId.value) {
        return 'focused-row'
      }
      return ''
    }
    const rowProps = (row: Vertex) => {
      return { onClick: () => onFocus(row) }
    }
    return () => (
      <div class="w-full bg-white px-12 pt-6 pb-12 border border-gray-100 rounded-xl">
        <div class="font-bold text-xl">
          {job.jobName}
          <NTag bordered={false} color={getColorFromStatus(job.jobStatus)} class="ml-3">
            {job.jobStatus}
          </NTag>
        </div>
        <div class="mt-3 flex items-center gap-3">
          <span>{t('detail.id')}:</span>
          <span class="font-bold">{job.jobId}</span>
          <NDivider vertical />
          <span>{t('detail.createTime')}:</span>
          <span class="font-bold">{job.createTime}</span>
          <NDivider vertical />
          <span>{t('detail.duration')}:</span>
          <span class="font-bold">{duration.value}</span>
        </div>
        <div class="tab-wrap relative">
          <NTabs v-model:value={select.value} type="line" animated>
            <NTabPane name="Overview" tab="Overview">
              <DAG job={job} focusedId={focusedId.value} onNodeClick={onFocus} />
              <NDataTable
                columns={columns}
                data={tableData.value}
                pagination={false}
                scrollX="auto"
                bordered
                rowClassName={rowClassName}
                rowProps={rowProps}
              />
            </NTabPane>
            <NTabPane name="Exception" tab="Exception">
              <pre style="white-space: pre-wrap; word-wrap: break-word; background-color: #f5f5f5; padding: 12px; border-radius: 4px; overflow: auto; max-height: 600px; font-family: monospace; line-height: 1.5;">
                {job.errorMsg}
              </pre>
            </NTabPane>
            <NTabPane name="Configuration" tab="Configuration">
              <Configuration data={job.envOptions || job.jobDag.envOptions}></Configuration>
            </NTabPane>
            <NTabPane name="Log" tab="Log">
              <JobLog jobId={job.jobId}></JobLog>
            </NTabPane>
          </NTabs>
          <NDrawer
            show={select.value === 'Overview' && !!focusedId.value && drawerShow.value}
            showMask={false}
            width={'40%'}
            to=".tab-wrap"
            style="top:42px"
            closeOnEsc={false}
            mask-closable={false}
            onUpdateShow={onDrawerClose}
          >
            <NDrawerContent title={focusedVertex.value?.vertexName} closable>
              <Configuration data={focusedVertex.value}></Configuration>
            </NDrawerContent>
          </NDrawer>
        </div>
      </div>
    )
  }