Browse Source

(*)采集日志功能完善

master
peng.peng 2 years ago
parent
commit
ca08e62ea0
  1. 2
      api/app/lib/controllers/metadataAcquisition/initJob.js
  2. 12
      api/app/lib/controllers/metadataAcquisition/log.js
  3. 2
      api/app/lib/controllers/metadataAcquisition/taskHandle.js
  4. 2
      api/app/lib/routes/metadataAcquisition/log.js
  5. 5
      web/client/src/sections/metadataAcquisition/components/steps/postgre/stepThree.js
  6. 132
      web/client/src/sections/metadataAcquisition/containers/acquisitionLog.js

2
api/app/lib/controllers/metadataAcquisition/initJob.js

@ -26,7 +26,7 @@ module.exports = async function (app, task) {
const endTime = moment() const endTime = moment()
const logBody = { const logBody = {
task: task.id, task: task.id,
success: true, success: false,
details: '采集失败' + JSON.stringify(error).substring(0, 248), details: '采集失败' + JSON.stringify(error).substring(0, 248),
startTime: startTime, startTime: startTime,
endTime: endTime endTime: endTime

12
api/app/lib/controllers/metadataAcquisition/log.js

@ -1,10 +1,10 @@
'use strict'; 'use strict';
function getAcquisitionTask(opts) { function getAcquisitionLog(opts) {
return async function (ctx, next) { return async function (ctx, next) {
const models = ctx.fs.dc.models; const models = ctx.fs.dc.models;
const { page, limit, taskName } = ctx.query; const { page, limit, taskName, logState } = ctx.query;
let errMsg = { message: '获取采集任务失败' } let errMsg = { message: '获取采集任务失败' }
const Op = ctx.fs.dc.ORM.Op; const Op = ctx.fs.dc.ORM.Op;
try { try {
@ -28,6 +28,10 @@ function getAcquisitionTask(opts) {
] ]
} }
if (logState && logState != '全部') {
searchWhere.success = logState == 'true' ? true : false
}
option.where = searchWhere option.where = searchWhere
let limit_ = limit || 10; let limit_ = limit || 10;
@ -50,7 +54,5 @@ function getAcquisitionTask(opts) {
} }
module.exports = { module.exports = {
getAcquisitionLog,
getAcquisitionTask,
} }

2
api/app/lib/controllers/metadataAcquisition/taskHandle.js

@ -170,7 +170,7 @@ async function handleTask(app, task) {
const endTime = moment() const endTime = moment()
const logBody = { const logBody = {
task: task.id, task: task.id,
success: true, success: false,
details: '采集失败' + JSON.stringify(error).substring(0, 248), details: '采集失败' + JSON.stringify(error).substring(0, 248),
startTime: startTime, startTime: startTime,
endTime: endTime endTime: endTime

2
api/app/lib/routes/metadataAcquisition/log.js

@ -6,6 +6,6 @@ module.exports = function (app, router, opts, AuthCode) {
//获取采集任务列表 //获取采集任务列表
app.fs.api.logAttr['GET/meta/acq/logs'] = { content: '获取采集任务列表', visible: true }; app.fs.api.logAttr['GET/meta/acq/logs'] = { content: '获取采集任务列表', visible: true };
router.get('/meta/acq/logs', log.getAcquisitionTask(opts)); router.get('/meta/acq/logs', log.getAcquisitionLog(opts));
}; };

5
web/client/src/sections/metadataAcquisition/components/steps/postgre/stepThree.js

@ -28,6 +28,9 @@ function StepThree(props) {
const checkCron = async (rule, value) => { const checkCron = async (rule, value) => {
try { try {
var interval = parser.parseExpression(value); var interval = parser.parseExpression(value);
if (interval?.fields?.second.length == 60) {
return Promise.reject(new Error('cron最小间隔不能小于一分钟!'));
}
console.log('Date: ', moment(interval.next().toString()).format('YYYY-MM-DD HH:mm:ss')); console.log('Date: ', moment(interval.next().toString()).format('YYYY-MM-DD HH:mm:ss'));
return Promise.resolve(); return Promise.resolve();
} catch (err) { } catch (err) {
@ -61,7 +64,7 @@ function StepThree(props) {
}} }}
> >
{dataSourceFilter && < ProFormSelect {dataSourceFilter && <ProFormSelect
width={'md'} width={'md'}
rules={[{ required: true, message: '请选择数据源' }]} rules={[{ required: true, message: '请选择数据源' }]}
options={dataSourceFilter?.map(s => { options={dataSourceFilter?.map(s => {

132
web/client/src/sections/metadataAcquisition/containers/acquisitionLog.js

@ -1,23 +1,37 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { Spin, Popconfirm, Tree, Row, Col, Button, Input, Table } from 'antd'; import { Spin, Popconfirm, Tree, Row, Col, Button, Input, Table, Select } from 'antd';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import moment from 'moment'; import moment from 'moment';
import { useFsRequest, ApiTable } from '$utils';
const { Option } = Select;
import xlsx from 'xlsx';
import './style.less'; import './style.less';
function AcquisitionLog(props) { function AcquisitionLog(props) {
const { loading, clientHeight, actions, dispatch, acqlogs } = props; const { loading, clientHeight, actions, dispatch, acqlogs } = props;
const [pageSize, setPageSize] = useState(10); const [pageSize, setPageSize] = useState(10);
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [searchValue, setSearchValue] = useState('') const [searchValue, setSearchValue] = useState('')
const [logState, setLogState] = useState('全部')
const queryData = (search) => { const queryData = (search) => {
const query = { const query = {
limit: search ? 10 : pageSize || 10, limit: search ? 10 : pageSize || 10,
page: search ? 1 : currentPage || 1, page: search ? 1 : currentPage || 1,
logState: logState,
taskName: searchValue taskName: searchValue
} }
dispatch(actions.metadataAcquisition.getLogs(query)); dispatch(actions.metadataAcquisition.getLogs(query));
} }
const { data: allLogs = {} } = useFsRequest({
url: ApiTable.getLogs,
query: {
logState: logState,
taskName: searchValue
},
refreshDeps: [logState, searchValue]
});
useEffect(() => { useEffect(() => {
queryData(); queryData();
@ -31,6 +45,13 @@ function AcquisitionLog(props) {
return record?.acquisitionTask?.taskName; return record?.acquisitionTask?.taskName;
} }
}, },
// {
// title: '任务描述',
// dataIndex: 'taskDescription',
// render: (text, record) => {
// return record?.acquisitionTask?.description;
// }
// },
{ {
title: '数据源名称', title: '数据源名称',
dataIndex: 'dataSourceName', dataIndex: 'dataSourceName',
@ -39,36 +60,111 @@ function AcquisitionLog(props) {
} }
}, },
{ {
title: '适配器类型', title: '任务状态',
dataIndex: 'adapter', dataIndex: 'success',
render: (text, record) => {
return record?.success ? '采集成功' : "采集失败";
}, },
{
title: '采集方式',
dataIndex: 'control',
}, },
{ {
title: '执行周期', title: '开始时间',
dataIndex: 'cron', dataIndex: 'startTime',
// render: (text, record) => { render: (text, record) => {
// return transCron(record?.cron); return moment(record?.startTime).format('YYYY-MM-DD HH:mm:ss');
// } },
sorter: {
compare: (a, b) => moment(b?.startTime).valueOf() - moment(a?.startTime).valueOf(),
multiple: 2,
},
}, },
{ {
title: '重复次数', title: '耗时',
dataIndex: 'retryCount', dataIndex: 'endTime',
render: (text, record) => {
return moment(record?.endTime).valueOf() - moment(record?.startTime).valueOf() + '毫秒';
},
sorter: {
compare: (a, b) => (moment(b?.endTime).valueOf() - moment(b?.startTime).valueOf()) - (moment(a?.endTime).valueOf() - moment(a?.startTime).valueOf()),
multiple: 2,
},
}, },
{ {
title: '时间间隔(分钟)', title: '详情',
dataIndex: 'retryTime', dataIndex: 'details',
ellipsis: true,
}, },
]; ];
const handleTableExport = () => {
let rows = allLogs?.rows;
if (rows.length == 0) {
message.info('当前无采集日志信息!')
}
let excelTitle = columns.map(s => {
return { k: s.dataIndex, v: s.title }
});
let workBook = {
SheetNames: [], //sheet名称
Sheets: {} //根据SheetNames名称顺序依次添加每个sheet数据
};
if (rows && rows.length > 0) {
let sheetName = '日志信息';
let sheetDataMap = new Map();
let sheetData = [excelTitle];
let index = 1;
rows.map(record => {
sheetData.push([
{ k: 'taskName', v: record?.acquisitionTask?.taskName },
// { k: 'taskDescription', v: record?.acquisitionTask?.description || '' },
{ k: 'dataSourceName', v: record?.acquisitionTask?.dataSource?.name },
{ k: 'success', v: record?.success ? '采集成功' : "采集失败" },
{ k: 'startTime', v: moment(record?.startTime).format('YYYY-MM-DD HH:mm:ss') },
{ k: 'endTime', v: moment(record?.endTime).valueOf() - moment(record?.startTime).valueOf() + '毫秒' },
{ k: 'details', v: record?.details },
]);
index = index + 1;
})
sheetDataMap.set(sheetName, sheetData);
sheetDataMap.forEach((values, key) => {
// 写入excel
workBook.Sheets[key] = xlsx.utils.aoa_to_sheet(values);
workBook.Sheets[key]['!cols'] = [{ wpx: 50 }, { wpx: 150 }, { wpx: 180 }, { wpx: 230 }, { wpx: 230 }, { wpx: 230 }]
})
workBook.SheetNames = [sheetName];
}
// 将workBook写入文件
xlsx.writeFile(workBook, `采集日志-${moment().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
}
return <Spin spinning={loading}> return <Spin spinning={loading}>
<Row className='protable-title'> <Row className='protable-title' style={{ alignItems: 'center' }}>
<span style={{ marginRight: 8 }}>关键字搜索:</span>
<Input <Input
value={searchValue} onChange={e => { setSearchValue(e.target.value) }} value={searchValue} onChange={e => { setSearchValue(e.target.value) }}
style={{ width: 220, marginRight: 15 }} placeholder="数据源或任务名称" /> style={{ width: 220, marginRight: 15 }} placeholder="任务名称或数据源" />
<Button onClick={() => { queryData() }} type='primary'>查询</Button> <span style={{ marginRight: 8 }}> 任务状态:</span>
<Select
style={{ width: 160, marginRight: 15 }}
defaultValue='全部'
onChange={(e) => {
setLogState(e)
}}
>
<Option value={'全部'} key={'全部'}>全部</Option>
<Option value={true} key={'采集成功'}>采集成功</Option>
<Option value={false} key={'采集失败'}>采集失败</Option>
</Select>
<Button
onClick={() => {
setCurrentPage(1);
setPageSize(10);
queryData()
}} type='primary'>查询</Button>
<Button style={{ marginLeft: 15 }} onClick={() => { handleTableExport() }} type='primary'>导出</Button>
</Row> </Row>
<ProTable <ProTable

Loading…
Cancel
Save