From 999ccf64ad910fa8e0f6548e4698a86b9fc3360f Mon Sep 17 00:00:00 2001 From: TsMask <340112800@qq.com> Date: Tue, 20 Aug 2024 15:49:03 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=8A=93=E5=8C=85=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/traceManage/pcap.ts | 13 +- src/i18n/locales/en-US.ts | 16 +- src/i18n/locales/zh-CN.ts | 16 +- src/views/traceManage/pcap/index.vue | 382 ++++++++++++++++++--------- 4 files changed, 285 insertions(+), 142 deletions(-) diff --git a/src/api/traceManage/pcap.ts b/src/api/traceManage/pcap.ts index 1090ebbd..6942e455 100644 --- a/src/api/traceManage/pcap.ts +++ b/src/api/traceManage/pcap.ts @@ -18,10 +18,21 @@ export function dumpStop(data: Record) { }); } +// 网元抓包PACP 下载 +export function dumpDownload(data: Record) { + return request({ + url: '/trace/tcpdump/download', + method: 'get', + params: data, + responseType: 'blob', + timeout: 60_000, + }); +} + // UPF标准版内部抓包 export function traceUPF(data: Record) { return request({ - url: '/trace/tcpdump/traceUPF', + url: '/trace/tcpdump/upf', method: 'post', data: data, }); diff --git a/src/i18n/locales/en-US.ts b/src/i18n/locales/en-US.ts index 7708d546..258b565d 100644 --- a/src/i18n/locales/en-US.ts +++ b/src/i18n/locales/en-US.ts @@ -1086,18 +1086,20 @@ export default { pcap: { capArgPlease: 'Please enter tcpdump -i any support parameter', cmd: 'Command', - execCmd: "Generic tcpdump packet capture command", - execCmdsSctp: "Generic tcpdump filter sctp and port commands", - execUPFCmdA: 'Suitable for anomalous packet capture of other NE', - execUPFCmdB: 'Suitable for UPF anomaly packet capture analysis', + execCmd: "Common Command Options", + execCmd2: "Filter Protocol Port Command", + execCmd3: "File Split By Time, Number Of Retained File (-G 10 -W 7)", + execUPFCmdA: 'Standard Edition - UPF with other NE anomalous packet capture analysis', + execUPFCmdB: 'Standard Edition - UPF anomalies requiring packet capture analysis', + batchOper: 'Batch Operations', + batchStartText: 'Batch Start', + batchStopText: 'Batch Stop', + batchDownText: 'Batch Download', textStart: "Start", - textStartBatch: "Batch Start", textStop: "Stop", - textStopBatch: "Batch Stop", textLog: "Log", textLogMsg: "Log Info", textDown: "Download", - textDownBatch: "Batch Download", downTip: "Are you sure you want to download the {title} capture data file?", downOk: "{title} file download complete", downErr: "{title} file download exception", diff --git a/src/i18n/locales/zh-CN.ts b/src/i18n/locales/zh-CN.ts index 71718b90..92996b74 100644 --- a/src/i18n/locales/zh-CN.ts +++ b/src/i18n/locales/zh-CN.ts @@ -1086,18 +1086,20 @@ export default { pcap: { capArgPlease: '请输入tcpdump -i any支持参数', cmd: '命令', - execCmd: "通用tcpdump抓包命令", - execCmdsSctp: "过滤sctp和port命令", - execUPFCmdA: '适合其他网元异常,UPF配合抓包的情况', - execUPFCmdB: '适合UPF异常需要抓包分析的情况', + execCmd: "通用命令选项", + execCmd2: "过滤协议端口命令", + execCmd3: "按时间分割的文件,保留的文件数量 (-G 10 -W 7)", + execUPFCmdA: '标准版-UPF配合其他网元异常抓包分析', + execUPFCmdB: '标准版-UPF异常需要抓包分析', + batchOper: '批量操作', + batchStartText: '批量开始', + batchStopText: '批量停止', + batchDownText: '批量下载', textStart: "开始", - textStartBatch: "批量开始", textStop: "停止", - textStopBatch: "批量停止", textLog: "日志", textLogMsg: "日志信息", textDown: "下载", - textDownBatch: "批量下载", downTip: "确认要下载 {title} 抓包数据文件吗?", downOk: "{title} 文件下载完成", downErr: "{title} 文件下载异常", diff --git a/src/views/traceManage/pcap/index.vue b/src/views/traceManage/pcap/index.vue index d5ecd361..05619e91 100644 --- a/src/views/traceManage/pcap/index.vue +++ b/src/views/traceManage/pcap/index.vue @@ -3,7 +3,12 @@ import { onMounted, reactive } from 'vue'; import { message, Modal } from 'ant-design-vue/lib'; import { ColumnsType } from 'ant-design-vue/lib/table'; import { PageContainer } from 'antdv-pro-layout'; -import { dumpStart, dumpStop, traceUPF } from '@/api/traceManage/pcap'; +import { + dumpStart, + dumpStop, + dumpDownload, + traceUPF, +} from '@/api/traceManage/pcap'; import { listAllNeInfo } from '@/api/ne/neInfo'; import { getNeFile } from '@/api/tool/neFile'; import saveAs from 'file-saver'; @@ -14,11 +19,50 @@ const { t } = useI18n(); /**对话框对象信息状态类型 */ type ModalStateType = { /**表单数据 */ - from: Record; + from: Record< + string, + { + loading: boolean; + /**网元名 */ + title: string; + /**命令 */ + cmdStart: string; + /**upf标准版需要停止命令,一般空字符 */ + cmdStop: string; + /**任务编号 */ + taskCode: string; + /**任务日志,upf标准版为空字符串 */ + logMsg: string; + /**提交表单参数 */ + data: { + neType: string; + neId: string; + cmd?: string; + }; + } + >; /**tcpdump命令组 */ - cmdOptions: Record[]; + cmdOptions: { + /**命令名称 */ + label: string; + /**命令选中值 */ + value: string; + /**开始命令 */ + start: string; + /**停止命令 */ + stop: string; + }[]; /**UPF命令组 */ - cmdOptionsUPF: Record[]; + cmdOptionsUPF: { + /**命令名称 */ + label: string; + /**命令选中值 */ + value: string; + /**开始命令 */ + start: string; + /**停止命令 */ + stop: string; + }[]; /**详情框是否显示 */ visibleByView: boolean; /**详情框内容 */ @@ -31,29 +75,35 @@ let modalState: ModalStateType = reactive({ cmdOptions: [ { label: t('views.traceManage.pcap.execCmd'), - start: '-n -s 0 -v -w', - stop: '', value: 'any', + start: '-n -v -s 0', + stop: '', }, { - label: t('views.traceManage.pcap.execCmdsSctp'), + label: t('views.traceManage.pcap.execCmd2'), + value: 'any2', start: 'sctp or tcp port 3030 or 8088', stop: '', - value: 'any2', + }, + { + label: t('views.traceManage.pcap.execCmd3'), + value: 'any3', + start: '-n -s 0 -v -G 10 -W 7', + stop: '', }, ], cmdOptionsUPF: [ { label: t('views.traceManage.pcap.execUPFCmdA'), + value: 'pcap trace', start: 'pcap trace rx tx max 100000 intfc any', stop: 'pcap trace rx tx off', - value: 'pcap trace', }, { label: t('views.traceManage.pcap.execUPFCmdB'), + value: 'pcap dispatch', start: 'pcap dispatch trace on max 100000', stop: 'pcap dispatch trace off', - value: 'pcap dispatch', }, ], visibleByView: false, @@ -80,25 +130,25 @@ let tableState: TabeStateType = reactive({ /**表格字段列 */ let tableColumns: ColumnsType = [ { - title: t('views.configManage.neManage.neType'), + title: t('views.ne.common.neType'), dataIndex: 'neType', align: 'left', width: 100, }, { - title: t('views.configManage.neManage.neId'), + title: t('views.ne.common.neId'), dataIndex: 'neId', align: 'left', width: 100, }, { - title: t('views.configManage.neManage.neName'), + title: t('views.ne.common.neName'), dataIndex: 'neName', align: 'left', width: 100, }, { - title: t('views.configManage.neManage.ip'), + title: t('views.ne.common.ipAddr'), dataIndex: 'ip', align: 'left', width: 150, @@ -108,13 +158,12 @@ let tableColumns: ColumnsType = [ key: 'cmd', dataIndex: 'serverState', align: 'left', - width: 300, + width: 350, }, { title: t('common.operate'), key: 'id', align: 'left', - fixed: 'right', }, ]; @@ -137,20 +186,22 @@ function fnGetList() { ) { tableState.data = res.data; // 初始网元参数表单 - const { start, stop } = modalState.cmdOptions[0]; - for (const item of res.data) { - modalState.from[item.id] = { - loading: false, - title: item.neName, // 网元名 - cmdStart: start, - cmdStop: stop, // upf需要停止命令 - out: '', - log: '', - data: { - neType: item.neType, - neId: item.neId, - }, - }; + if (tableState.data.length > 0) { + const { start, stop } = modalState.cmdOptions[0]; + for (const item of res.data) { + modalState.from[item.id] = { + loading: false, + title: item.neName, + cmdStart: start, + cmdStop: stop, + taskCode: '', + logMsg: '', + data: { + neType: item.neType, + neId: item.neId, + }, + }; + } } } else { message.warning({ @@ -166,6 +217,9 @@ function fnGetList() { function fnSelectCmd(id: any, option: any) { modalState.from[id].cmdStart = option.start; modalState.from[id].cmdStop = option.stop; + // 重置任务 + modalState.from[id].taskCode = ''; + modalState.from[id].logMsg = ''; } /** @@ -203,8 +257,9 @@ function fnRecordStart(row?: Record) { if (res.status === 'fulfilled') { const resV = res.value; if (resV.code === RESULT_CODE_SUCCESS) { - fromArr[idx].out = resV.data.out; - fromArr[idx].log = resV.data.log; + if (!fromArr[idx].cmdStop) { + fromArr[idx].taskCode = resV.data; + } fromArr[idx].loading = true; message.success({ content: t('views.traceManage.pcap.startOk', { title }), @@ -250,24 +305,51 @@ function fnRecordStop(row?: Record) { title: t('common.tipTitle'), content: t('views.traceManage.pcap.stopTip', { title: row.neName }), onOk() { - const hide = message.loading(t('common.loading'), 0); const fromArr = neIDs.map(id => modalState.from[id]); - const reqArr = fromArr.map(from => { + const reqArr: any = []; + for (const from of fromArr) { if (from.data.neType === 'UPF' && from.cmdStart.startsWith('pcap')) { - return traceUPF(Object.assign({ cmd: from.cmdStop }, from.data)); + reqArr.push( + traceUPF(Object.assign({ cmd: from.cmdStop }, from.data)) + ); + } else { + const taskCode = from.taskCode; + if (!taskCode) { + message.warning({ + content: t('views.traceManage.pcap.stopNotRun', { + title: from.title, + }), + duration: 3, + }); + continue; + } + reqArr.push( + dumpStop(Object.assign({ taskCode: from.taskCode }, from.data)) + ); } - return dumpStop(Object.assign({ fileName: from.out }, from.data)); - }); + } + if (reqArr.length === 0) return; + + const hide = message.loading(t('common.loading'), 0); Promise.allSettled(reqArr) .then(resArr => { resArr.forEach((res, idx) => { const title = fromArr[idx].title; + if (res.status === 'fulfilled') { const resV = res.value; + fromArr[idx].loading = false; + fromArr[idx].logMsg = ''; + if (fromArr[idx].cmdStop) { + fromArr[idx].taskCode = ''; + } + if (resV.code === RESULT_CODE_SUCCESS) { - fromArr[idx].out = resV.data.out; - fromArr[idx].log = resV.data.log; - fromArr[idx].loading = false; + if (fromArr[idx].cmdStop) { + fromArr[idx].taskCode = resV.data; + } else { + fromArr[idx].logMsg = resV.msg; + } message.success({ content: t('views.traceManage.pcap.stopOk', { title }), duration: 3, @@ -314,11 +396,11 @@ function fnDownPCAP(row?: Record) { title: t('common.tipTitle'), content: t('views.traceManage.pcap.downTip', { title: row.neName }), onOk() { - const hide = message.loading(t('common.loading'), 0); const fromArr = neIDs.map(id => modalState.from[id]); - const reqArr = []; + const reqArr: any = []; for (const from of fromArr) { - if (!from.out) { + const taskCode = from.taskCode; + if (!taskCode) { message.warning({ content: t('views.traceManage.pcap.stopNotRun', { title: from.title, @@ -327,24 +409,25 @@ function fnDownPCAP(row?: Record) { }); continue; } - - reqArr.push( - getNeFile( - Object.assign( - { - path: '/tmp', - fileName: `${from.out}.pcap`, - }, - from.data - ) - ) - ); + if (from.data.neType === 'UPF' && taskCode.startsWith('/tmp')) { + const fileName = taskCode.substring(taskCode.lastIndexOf('/') + 1); + reqArr.push( + getNeFile(Object.assign({ path: '/tmp', fileName }, from.data)) + ); + } else { + reqArr.push( + dumpDownload(Object.assign({ taskCode: taskCode }, from.data)) + ); + } } + if (reqArr.length === 0) return; + const hide = message.loading(t('common.loading'), 0); Promise.allSettled(reqArr) .then(resArr => { resArr.forEach((res, idx) => { const title = fromArr[idx].title; + const taskCode = fromArr[idx].taskCode; if (res.status === 'fulfilled') { const resV = res.value; @@ -354,9 +437,10 @@ function fnDownPCAP(row?: Record) { duration: 3, }); // 文件名 - const fileName = `${fromArr[idx].out}.pcap`; - if (fileName.length > 6) { - saveAs(resV.data, fileName); + if (taskCode.startsWith('/tmp')) { + saveAs(resV.data, `${title}_${Date.now()}.pcap`); + } else { + saveAs(resV.data, `${title}_${Date.now()}.zip`); } } else { message.warning({ @@ -379,6 +463,24 @@ function fnDownPCAP(row?: Record) { }); } +/**批量操作 */ +function fnBatchOper(key: string) { + switch (key) { + case 'start': + fnRecordStart(); + break; + case 'stop': + fnRecordStop(); + break; + case 'down': + fnDownPCAP(); + break; + default: + console.warn('undefined batch oper', key); + break; + } +} + /** * 对话框弹出显示为 查看 * @param dictId 字典编号id @@ -387,7 +489,7 @@ function fnModalVisibleByVive(id: string | number) { const from = modalState.from[id]; if (!from) return; modalState.visibleByView = true; - modalState.logMsg = from.log; + modalState.logMsg = from.logMsg; } /** @@ -411,30 +513,28 @@ onMounted(() => { @@ -454,12 +554,12 @@ onMounted(() => { - - - {{ t('views.traceManage.pcap.textStart') }} - - - - - {{ t('views.traceManage.pcap.textStop') }} - - - - - {{ t('views.traceManage.pcap.textLog') }} - - - + + + + + + - - {{ t('views.traceManage.pcap.textDown') }} - + + + + + + + + + + + + + + + + + + @@ -542,12 +669,13 @@ onMounted(() => { :footer="false" :maskClosable="false" :keyboard="false" + :body-style="{ padding: '12px' }" :title="t('views.traceManage.pcap.textLogMsg')" @cancel="fnModalCancel" >