diff --git a/database/install/sys_dict_data0.sql b/database/install/sys_dict_data0.sql index ebdcb834..e5afe451 100644 --- a/database/install/sys_dict_data0.sql +++ b/database/install/sys_dict_data0.sql @@ -168,5 +168,24 @@ INSERT INTO `sys_dict_data` VALUES (140, 21, 'dictData.cdr_cause_code.41', '41', INSERT INTO `sys_dict_data` VALUES (141, 22, 'dictData.cdr_cause_code.42', '42', 'cdr_cause_code', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (142, 23, 'dictData.cdr_cause_code.47', '47', 'cdr_cause_code', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (143, 30, 'dictData.cdr_cause_code.50', '50', 'cdr_cause_code', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (144, 1, 'dictData.trace_msg_type.0', '0', 'trace_msg_type', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (145, 2, 'dictData.trace_msg_type.1', '1', 'trace_msg_type', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (146, 1, 'dictData.trace_msg_direct.0', '0', 'trace_msg_direct', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (147, 2, 'dictData.trace_msg_direct.1', '1', 'trace_msg_direct', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (148, 1, 'dictData.trace_interfaces.1', 'N1', 'trace_interfaces', '', '', '0', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (149, 2, 'dictData.trace_interfaces.2', 'N2', 'trace_interfaces', '', '', '0', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (150, 3, 'dictData.trace_interfaces.3', 'N1/N2', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (151, 4, 'dictData.trace_interfaces.4', 'N4', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (152, 8, 'dictData.trace_interfaces.8', 'N8', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (153, 10, 'dictData.trace_interfaces.10', 'N10', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (154, 11, 'dictData.trace_interfaces.11', 'N11', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (155, 12, 'dictData.trace_interfaces.12', 'N12', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (156, 13, 'dictData.trace_interfaces.13', 'N13', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (157, 7, 'dictData.trace_interfaces.7', 'N7', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (158, 15, 'dictData.trace_interfaces.15', 'N15', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (159, 17, 'dictData.trace_interfaces.17', 'N17', 'trace_interfaces', '', '', '0', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (160, 20, 'dictData.trace_interfaces.20', 'N20', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (161, 22, 'dictData.trace_interfaces.22', 'N22', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (162, 40, 'dictData.trace_interfaces.40', 'N40', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_dict_data1_i18n_zh.sql b/database/install/sys_dict_data1_i18n_zh.sql index 9d83e25e..3649d3e0 100644 --- a/database/install/sys_dict_data1_i18n_zh.sql +++ b/database/install/sys_dict_data1_i18n_zh.sql @@ -79,7 +79,7 @@ INSERT INTO `sys_dict_data` VALUES (1071, 1071, 'menu.ueUser.onlineUE', 'UE在 INSERT INTO `sys_dict_data` VALUES (1072, 1072, 'menu.ueUser.base5G', '基站信息', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1073, 1073, 'menu.trace', '跟踪', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1074, 1074, 'menu.trace.task', '网元跟踪任务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); -INSERT INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.analysis', '网元跟踪数据', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); +INSERT INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.taskData', '网元跟踪任务数据', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1076, 1076, 'menu.trace.pcap', '信令抓包', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1077, 1077, 'menu.fault', '监控', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1078, 1078, 'config.sys.exportTable', '备份文件FTP服务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -89,7 +89,7 @@ INSERT INTO `sys_dict_data` VALUES (1081, 1081, 'menu.ueUser.onlineUERemark', 'U INSERT INTO `sys_dict_data` VALUES (1082, 1082, 'menu.ueUser.base5GRemark', '5G基站信息菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1083, 1083, 'menu.traceRemark', '跟踪管理目录', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1084, 1084, 'menu.trace.taskRemark', '跟踪任务菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); -INSERT INTO `sys_dict_data` VALUES (1085, 1085, 'menu.trace.analysisRemark', '信令分析菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); +-- INSERT INTO `sys_dict_data` VALUES (1085, 1085, 'menu.trace.analysisRemark', '信令分析菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1086, 1086, 'menu.trace.pcapRemark', '信令抓包菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1087, 1087, 'menu.faultRemark', '故障管理目录', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (1088, 1088, 'menu.fault.active', '活动告警', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -656,7 +656,7 @@ INSERT INTO `sys_dict_data` VALUES (2145, 2145, 'menu.system.user.editPost', ' INSERT INTO `sys_dict_data` VALUES (2146, 2146, 'menu.dashboard.smscCDR', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1717051745866, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2147, 2147, 'log.operate.title.smscCDR', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2148, 2148, 'menu.trace.pcapFile', '信令抓包文件', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); -INSERT INTO `sys_dict_data` VALUES (2149, 2149, 'menu.trace.taskAnalyze', '跟踪数据分析', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2149, 2149, 'menu.trace.taskAnalyze', '网元跟踪任务分析', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2150, 2150, 'job.ne_data_udm', '网元数据-UDM数据刷新同步', 'i18n_zh', '', '', '1', 'supervisor', 1730173767412, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2151, 2151, 'menu.system.setting.doc', '系统使用文档', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2152, 2152, 'menu.system.setting.official', '官网链接', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); @@ -701,5 +701,37 @@ INSERT INTO `sys_dict_data` VALUES (2190, 2190, 'menu.dashboard.overview.smfUeNu INSERT INTO `sys_dict_data` VALUES (2191, 2191, 'menu.dashboard.overview.imsUeNum', '展示语音会话数', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2192, 2192, 'menu.dashboard.overview.gnbBase', '展示5G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (2193, 2193, 'menu.dashboard.overview.enbBase', '展示4G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2194, 2194, 'menu.ueUser.imsUDM', 'IMS签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2195, 2195, 'menu.ueUser.imsUDMRemark', 'IMS签约用户菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2196, 2196, 'menu.ueUser.voipUDM', 'VoIP鉴权数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2197, 2197, 'menu.ueUser.voipUDMRemark', 'VoIP鉴权数据菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2198, 2198, 'menu.ueUser.exportFile', '文件管理', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2199, 2199, 'menu.ueUser.exportFileRemark', '文件管理菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2200, 2200, 'job.backup.ue.data', '定期备份UE用户和数据表', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2201, 2201, 'table.u_auth_user', 'UDM鉴权用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2202, 2202, 'table.u_sub_user', 'UDM签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2203, 2203, 'table.u_voip_auth', 'VoIP鉴权数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2204, 2204, 'table.u_ims_user', 'IMS签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2205, 2205, 'dictType.trace_msg_type', '跟踪消息类型', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2206, 2206, 'dictData.trace_msg_type.0', '请求', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2207, 2207, 'dictData.trace_msg_type.1', '响应', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2208, 2208, 'dictType.trace_msg_direct', '跟踪消息方向', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2209, 2209, 'dictData.trace_msg_direct.0', '接收', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2210, 2210, 'dictData.trace_msg_direct.1', '发送', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2211, 2211, 'dictData.trace_interfaces.1', 'N1', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2212, 2212, 'dictData.trace_interfaces.2', 'N2', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2213, 2213, 'dictData.trace_interfaces.3', 'N1/N2', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2214, 2214, 'dictData.trace_interfaces.4', 'N4', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2215, 2215, 'dictData.trace_interfaces.8', 'N8', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2216, 2216, 'dictData.trace_interfaces.10', 'N10', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2217, 2217, 'dictData.trace_interfaces.11', 'N11', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2218, 2218, 'dictData.trace_interfaces.12', 'N12', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2219, 2219, 'dictData.trace_interfaces.13', 'N13', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2220, 2220, 'dictData.trace_interfaces.7', 'N7', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2221, 2221, 'dictData.trace_interfaces.15', 'N15', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2222, 2222, 'dictData.trace_interfaces.17', 'N17', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2223, 2223, 'dictData.trace_interfaces.20', 'N20', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2224, 2224, 'dictData.trace_interfaces.22', 'N22', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (2225, 2225, 'dictData.trace_interfaces.40', 'N40', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_dict_data2_i18n_en.sql b/database/install/sys_dict_data2_i18n_en.sql index 689882e1..2a355ae0 100644 --- a/database/install/sys_dict_data2_i18n_en.sql +++ b/database/install/sys_dict_data2_i18n_en.sql @@ -79,7 +79,7 @@ INSERT INTO `sys_dict_data` VALUES (3071, 3071, 'menu.ueUser.onlineUE', 'UE Onli INSERT INTO `sys_dict_data` VALUES (3072, 3072, 'menu.ueUser.base5G', 'Radio Information', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3073, 3073, 'menu.trace', 'Trace', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3074, 3074, 'menu.trace.task', 'NE Trace Task', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, ''); -INSERT INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.analysis', 'NE Trace Task Data', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, ''); +INSERT INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.taskData', 'NE Trace Task Data', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3076, 3076, 'menu.trace.pcap', 'Signaling Capture', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3077, 3077, 'menu.fault', 'Monitor', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3078, 3078, 'config.sys.exportTable', 'Backup file FTP service', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -89,7 +89,7 @@ INSERT INTO `sys_dict_data` VALUES (3081, 3081, 'menu.ueUser.onlineUERemark', 'U INSERT INTO `sys_dict_data` VALUES (3082, 3082, 'menu.ueUser.base5GRemark', '5G Base Station Information Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3083, 3083, 'menu.traceRemark', 'Tracking Management Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3084, 3084, 'menu.trace.taskRemark', 'Tracking Task Menu', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, ''); -INSERT INTO `sys_dict_data` VALUES (3085, 3085, 'menu.trace.analysisRemark', 'Signaling Analysis Menu', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, ''); +-- INSERT INTO `sys_dict_data` VALUES (3085, 3085, 'menu.trace.analysisRemark', 'Signaling Analysis Menu', 'i18n_en', '', '', '1', 'supervisor', 1700000000000, NULL, 0, ''); INSERT INTO `sys_dict_data` VALUES (3086, 3086, 'menu.trace.pcapRemark', 'Signaling Capture Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3087, 3087, 'menu.faultRemark', 'Fault Management Catalog', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); INSERT INTO `sys_dict_data` VALUES (3088, 3088, 'menu.fault.active', 'Active Alarms', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -656,7 +656,7 @@ INSERT INTO `sys_dict_data` VALUES (4145, 4145, 'menu.system.user.editPost', 'Mo INSERT INTO `sys_dict_data` VALUES (4146, 4146, 'menu.dashboard.smscCDR', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4147, 4147, 'log.operate.title.smscCDR', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4148, 4148, 'menu.trace.pcapFile', 'Signaling Capture File', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, ''); -INSERT INTO `sys_dict_data` VALUES (4149, 4149, 'menu.trace.taskAnalyze', 'Tracking Data Analysis', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4149, 4149, 'menu.trace.taskAnalyze', 'NE Trace Task Analysis', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4150, 4150, 'job.ne_data_udm', 'NE Data Sync UDM', 'i18n_en', '', '', '1', 'supervisor', 1730173767412, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4151, 4151, 'menu.system.setting.doc', 'System User Documentation', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4152, 4152, 'menu.system.setting.official', 'Official Website', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); @@ -701,5 +701,37 @@ INSERT INTO `sys_dict_data` VALUES (4190, 4190, 'menu.dashboard.overview.smfUeNu INSERT INTO `sys_dict_data` VALUES (4191, 4191, 'menu.dashboard.overview.imsUeNum', 'Display the number of voice sessions', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4192, 4192, 'menu.dashboard.overview.gnbBase', 'Display 5G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); INSERT INTO `sys_dict_data` VALUES (4193, 4193, 'menu.dashboard.overview.enbBase', 'Display 4G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4194, 4194, 'menu.ueUser.imsUDM', 'IMS Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4195, 4195, 'menu.ueUser.imsUDMRemark', 'IMS Subscribers Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4196, 4196, 'menu.ueUser.voipUDM', 'VoIP Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4197, 4197, 'menu.ueUser.voipUDMRemark', 'VoIP Authentication Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4198, 4198, 'menu.ueUser.exportFile', 'File Management', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4199, 4199, 'menu.ueUser.exportFileRemark', 'File Management Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4200, 4200, 'job.backup.ue.data', 'Backup regularly UE users and data tables', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4201, 4201, 'table.u_auth_user', 'UDM Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4202, 4202, 'table.u_sub_user', 'UDM Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4203, 4203, 'table.u_voip_auth', 'VoIP Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4204, 4204, 'table.u_ims_user', 'IMS Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4205, 4205, 'dictType.trace_msg_type', 'Trace Message Type', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4206, 4206, 'dictData.trace_msg_type.0', 'Request', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4207, 4207, 'dictData.trace_msg_type.1', 'Response', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4208, 4208, 'dictType.trace_msg_direct', 'Track Message Directio', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4209, 4209, 'dictData.trace_msg_direct.0', 'Receive', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4210, 4210, 'dictData.trace_msg_direct.1', 'Send', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4211, 4211, 'dictData.trace_interfaces.1', 'N1', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4212, 4212, 'dictData.trace_interfaces.2', 'N2', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4213, 4213, 'dictData.trace_interfaces.3', 'N1/N2', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4214, 4214, 'dictData.trace_interfaces.4', 'N4', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4215, 4215, 'dictData.trace_interfaces.8', 'N8', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4216, 4216, 'dictData.trace_interfaces.10', 'N10', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4217, 4217, 'dictData.trace_interfaces.11', 'N11', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4218, 4218, 'dictData.trace_interfaces.12', 'N12', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4219, 4219, 'dictData.trace_interfaces.13', 'N13', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4220, 4220, 'dictData.trace_interfaces.7', 'N7', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4221, 4221, 'dictData.trace_interfaces.15', 'N15', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4222, 4222, 'dictData.trace_interfaces.17', 'N17', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4223, 4223, 'dictData.trace_interfaces.20', 'N20', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4224, 4224, 'dictData.trace_interfaces.22', 'N22', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +INSERT INTO `sys_dict_data` VALUES (4225, 4225, 'dictData.trace_interfaces.40', 'N40', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/install/sys_dict_type.sql b/database/install/sys_dict_type.sql index bd46756b..060f91cf 100644 --- a/database/install/sys_dict_type.sql +++ b/database/install/sys_dict_type.sql @@ -56,6 +56,9 @@ INSERT INTO `sys_dict_type` VALUES (121, 'dictType.ne_host_cmd_groupId', 'ne_hos INSERT INTO `sys_dict_type` VALUES (122, 'dictType.ne_info_status', 'ne_info_status', '1', 'supervisor', 1702020000000, '', 0, ''); INSERT INTO `sys_dict_type` VALUES (123, 'dictType.ne_license_status', 'ne_license_status', '1', 'supervisor', 1702020000000, '', 0, ''); INSERT INTO `sys_dict_type` VALUES (124, 'dictType.cdr_cause_code', 'cdr_cause_code', '1', 'supervisor', 1725877564156, '', 0, ''); +INSERT INTO `sys_dict_type` VALUES (125, 'dictType.trace_msg_type', 'trace_msg_type', '1', 'system', 1699348237468, 'system', 1699348237468, ''); +INSERT INTO `sys_dict_type` VALUES (126, 'dictType.trace_msg_direct', 'trace_msg_direct', '1', 'system', 1699348237468, 'system', 1699348237468, ''); +INSERT INTO `sys_dict_type` VALUES (127, 'dictType.trace_interfaces', 'trace_interfaces', '1', 'system', 1699348237468, 'system', 1699348237468, ''); UNLOCK TABLES; diff --git a/database/install/sys_menu.sql b/database/install/sys_menu.sql index ca09cf93..f7b7d4d9 100644 --- a/database/install/sys_menu.sql +++ b/database/install/sys_menu.sql @@ -136,8 +136,8 @@ INSERT INTO `sys_menu` VALUES (2080, 'menu.ueUser.onlineIMS', 5, 4, 'ims', 'neUs INSERT INTO `sys_menu` VALUES (2081, 'menu.ueUser.onlineUE', 5, 6, 'ue', 'neUser/ue/index', '1', '0', 'M', '1', '1', 'neUser:ue:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.onlineUERemark'); INSERT INTO `sys_menu` VALUES (2082, 'menu.ueUser.base5G', 5, 7, 'base5G', 'neUser/base5G/index', '1', '0', 'M', '0', '1', 'neUser:base5G:index', 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.base5GRemark'); INSERT INTO `sys_menu` VALUES (2083, 'menu.trace', 2087, 30, 'traceManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.traceRemark'); -INSERT INTO `sys_menu` VALUES (2084, 'menu.trace.task', 2083, 1, 'task', 'traceManage/task/index', '1', '0', 'M', '0', '1', 'traceManage:task:index', 'icon-chexiao', 'supervisor', 1700000000000, 'admin', 1713176976458, 'menu.trace.taskRemark'); -INSERT INTO `sys_menu` VALUES (2085, 'menu.trace.analysis', 2083, 4, 'analysis', 'traceManage/analysis/index', '1', '0', 'M', '0', '1', 'traceManage:analysis:index', 'icon-gongnengjieshao', 'supervisor', 1700000000000, 'admin', 1713176987835, 'menu.trace.analysisRemark'); +INSERT INTO `sys_menu` VALUES (2084, 'menu.trace.task', 2083, 1, 'task', 'traceManage/task/index', '1', '0', 'M', '1', '1', 'traceManage:task:index', 'icon-chexiao', 'supervisor', 1700000000000, 'admin', 1744453890548, 'menu.trace.taskRemark'); +INSERT INTO `sys_menu` VALUES (2085, 'menu.trace.taskData', 2083, 4, 'task/inline/data', 'traceManage/task/data', '1', '0', 'M', '0', '1', 'traceManage:task:data', '#', 'supervisor', 1700000000000, 'admin', 1744453921381, ''); INSERT INTO `sys_menu` VALUES (2086, 'menu.trace.pcap', 2083, 11, 'pcap', 'traceManage/pcap/index', '1', '1', 'M', '1', '1', 'traceManage:pcap:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.trace.pcapRemark'); INSERT INTO `sys_menu` VALUES (2087, 'menu.fault', 0, 2, 'faultManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-jinggao', 'supervisor', 1700000000000, NULL, 0, 'menu.faultRemark'); INSERT INTO `sys_menu` VALUES (2088, 'menu.fault.active', 2129, 1, 'active-alarm', 'faultManage/active-alarm/index', '1', '1', 'M', '1', '1', 'faultManage:active-alarm:index', 'icon-wenjian', 'supervisor', 1700000000000, NULL, 0, 'menu.fault.activemRemark'); @@ -210,7 +210,7 @@ INSERT INTO `sys_menu` VALUES (2158, 'menu.trace.pcapFile', 2083, 12, 'pcap/inli INSERT INTO `sys_menu` VALUES (2159, 'menu.log.exportFile', 2089, 100, 'exportFile', 'logManage/exportFile/index', '1', '1', 'M', '1', '1', 'logManage:exportFile:index', 'icon-wenjian', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2160, 'menu.perf.kpiCReport', 2099, 100, 'kpiCReport', 'perfManage/kpiCReport/index', '1', '0', 'M', '1', '1', 'perfManage:kpiCReport:index', 'icon-tubiaoku', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2161, 'menu.trace.taskHLR', 2083, 6, 'taskHLR', 'traceManage/task-hlr/index', '1', '0', 'M', '0', '1', 'traceManage:taskHLR:index', 'icon-chexiao', 'supervisor', 1724144595914, '', 0, ''); -INSERT INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/inline/analyze', 'traceManage/task/analyze', '1', '0', 'M', '0', '1', 'traceManage:taskAnalyze:index', '#', 'supervisor', 1724144595914, '', 0, ''); +INSERT INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/inline/analyze', 'traceManage/task/analyze', '1', '0', 'M', '0', '1', 'traceManage:task:analyze', '#', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2163, 'menu.trace.tshark', 2083, 14, 'tshark', 'traceManage/tshark/index', '1', '0', 'M', '1', '1', 'traceManage:tshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2164, 'menu.trace.wireshark', 2083, 16, 'wireshark', 'traceManage/wireshark/index', '1', '0', 'M', '1', '1', 'traceManage:wireshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); INSERT INTO `sys_menu` VALUES (2165, 'menu.config.neOverview', 4, 1, 'neOverview', 'configManage/neOverview/index', '1', '0', 'M', '1', '1', 'configManage:neOverview:index', 'icon-tubiaoku', 'supervisor', 1700000000000, NULL, 0, 'menu.config.neOverviewRemark'); diff --git a/database/install/sys_role_menu.sql b/database/install/sys_role_menu.sql index b6d0f8e7..2860cdae 100644 --- a/database/install/sys_role_menu.sql +++ b/database/install/sys_role_menu.sql @@ -81,6 +81,7 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2010); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2080); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2081); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2083); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2084); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2086); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2087); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2088); @@ -138,6 +139,7 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2158); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2159); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2160); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2163); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2164); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2165); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2166); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2167); diff --git a/database/install/trace_data.sql b/database/install/trace_data.sql index 4b1d8c22..299cf01b 100644 --- a/database/install/trace_data.sql +++ b/database/install/trace_data.sql @@ -5,19 +5,21 @@ DROP TABLE IF EXISTS `trace_data`; CREATE TABLE `trace_data` ( `id` int NOT NULL AUTO_INCREMENT, - `task_id` int NOT NULL COMMENT '跟踪任务ID', - `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', - `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '', - `src_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '源地址带端口', - `dst_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '目标地址带端口', - `if_type` int DEFAULT NULL COMMENT '接口类型,未分类', - `msg_type` int DEFAULT NULL, - `msg_direct` int DEFAULT NULL, - `length` int DEFAULT NULL COMMENT '去除头后的原始数据byte长度', - `timestamp` bigint DEFAULT '0' COMMENT '毫秒', - `raw_msg` text COLLATE utf8mb4_general_ci COMMENT '去除头后的原始数据byteBase64', - `dec_msg` text COLLATE utf8mb4_general_ci COMMENT 'TCP内容消息', - PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='跟踪_任务数据'; + `trace_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '跟踪任务ID', + `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'UE类型 IMSI', + `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'UE类型 可能存在', + `src_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '源地址', + `dst_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '目标地址', + `if_type` varchar(16) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '接口类型,未分类', + `msg_type` int DEFAULT NULL COMMENT '消息类型,0-req, 1-rsp', + `msg_direct` int DEFAULT NULL COMMENT '消息方向,0-recv,1-send', + `msg_ne` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '消息网元', + `msg_event` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '消息事件,e.g: CreateContextReq', + `length` int DEFAULT NULL COMMENT '原始数据byte长度', + `timestamp` bigint DEFAULT '0' COMMENT '纳秒时间戳', + `raw_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '原始数据byteBase64', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_task_id_time` (`trace_id`,`timestamp`) COMMENT '任务DI时间' +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='跟踪_任务数据'; --- Dump completed on 2024-09-19 14:26:59 +-- Dump completed on 2025-04-14 14:26:59 diff --git a/database/install/trace_task.sql b/database/install/trace_task.sql index 6f4c4668..ea5ca574 100644 --- a/database/install/trace_task.sql +++ b/database/install/trace_task.sql @@ -6,26 +6,20 @@ DROP TABLE IF EXISTS `trace_task`; CREATE TABLE `trace_task` ( `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID', `trace_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '任务编号', - `trace_type` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '1-Interface,2-Device,3-User', + `trace_type` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '1-Interface,2-Device,3-UE', `start_time` bigint DEFAULT '0' COMMENT '开始时间 毫秒', `end_time` bigint DEFAULT '0' COMMENT '结束时间 毫秒', `interfaces` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '接口跟踪必须 例如 N8,N10', `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户跟踪必须', `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户跟踪可选', - `ue_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '设备跟踪必须 IP', `src_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '源地址IP', `dst_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '目标地址IP', - `signal_port` int DEFAULT '0' COMMENT '地址IP端口', `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者', `create_time` bigint DEFAULT '0' COMMENT '创建时间', - `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '更新者', - `update_time` bigint DEFAULT '0' COMMENT '更新时间', `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '备注', - `ne_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '网元类型', - `ne_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '网元ID', - `notify_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '信息数据通知回调地址UDP 例如udp:192.168.5.58:29500', - `fetch_msg` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '任务下发请求响应消息', + `ne_list` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '网元列表 neType_neId 例如 UDM_001,AMF_001', + `notify_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '信息数据通知回调地址UDP 例如udp:192.168.5.58:33033', PRIMARY KEY (`id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='跟踪_任务'; +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='跟踪_任务'; --- Dump completed on 2024-09-19 14:26:59 +-- Dump completed on 2025-04-14 14:26:59 diff --git a/database/upgrade/upg_sys_dict_data0.sql b/database/upgrade/upg_sys_dict_data0.sql index a0d48a59..0d2f5916 100644 --- a/database/upgrade/upg_sys_dict_data0.sql +++ b/database/upgrade/upg_sys_dict_data0.sql @@ -168,6 +168,25 @@ REPLACE INTO `sys_dict_data` VALUES (140, 21, 'dictData.cdr_cause_code.41', '41' REPLACE INTO `sys_dict_data` VALUES (141, 22, 'dictData.cdr_cause_code.42', '42', 'cdr_cause_code', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (142, 23, 'dictData.cdr_cause_code.47', '47', 'cdr_cause_code', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (143, 30, 'dictData.cdr_cause_code.50', '50', 'cdr_cause_code', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (144, 1, 'dictData.trace_msg_type.0', '0', 'trace_msg_type', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (145, 2, 'dictData.trace_msg_type.1', '1', 'trace_msg_type', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (146, 1, 'dictData.trace_msg_direct.0', '0', 'trace_msg_direct', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (147, 2, 'dictData.trace_msg_direct.1', '1', 'trace_msg_direct', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (148, 1, 'dictData.trace_interfaces.1', 'N1', 'trace_interfaces', '', '', '0', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (149, 2, 'dictData.trace_interfaces.2', 'N2', 'trace_interfaces', '', '', '0', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (150, 3, 'dictData.trace_interfaces.3', 'N1/N2', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (151, 4, 'dictData.trace_interfaces.4', 'N4', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (152, 8, 'dictData.trace_interfaces.8', 'N8', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (153, 10, 'dictData.trace_interfaces.10', 'N10', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (154, 11, 'dictData.trace_interfaces.11', 'N11', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (155, 12, 'dictData.trace_interfaces.12', 'N12', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (156, 13, 'dictData.trace_interfaces.13', 'N13', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (157, 7, 'dictData.trace_interfaces.7', 'N7', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (158, 15, 'dictData.trace_interfaces.15', 'N15', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (159, 17, 'dictData.trace_interfaces.17', 'N17', 'trace_interfaces', '', '', '0', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (160, 20, 'dictData.trace_interfaces.20', 'N20', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (161, 22, 'dictData.trace_interfaces.22', 'N22', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (162, 40, 'dictData.trace_interfaces.40', 'N40', 'trace_interfaces', '', '', '1', 'supervisor', 1712720201349, '', 0, ''); -- 指定记录条件更新 diff --git a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql index a10f69f3..12d26152 100644 --- a/database/upgrade/upg_sys_dict_data1_i18n_zh.sql +++ b/database/upgrade/upg_sys_dict_data1_i18n_zh.sql @@ -92,7 +92,7 @@ REPLACE INTO `sys_dict_data` VALUES (1071, 1071, 'menu.ueUser.onlineUE', 'UE在 REPLACE INTO `sys_dict_data` VALUES (1072, 1072, 'menu.ueUser.base5G', '基站信息', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1073, 1073, 'menu.trace', '跟踪', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1074, 1074, 'menu.trace.task', '网元跟踪任务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); -REPLACE INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.analysis', '网元跟踪数据', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); +REPLACE INTO `sys_dict_data` VALUES (1075, 1075, 'menu.trace.taskData', '网元跟踪任务数据', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1076, 1076, 'menu.trace.pcap', '信令抓包', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1077, 1077, 'menu.fault', '监控', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1078, 1078, 'config.sys.exportTable', '备份文件FTP服务', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -102,7 +102,7 @@ REPLACE INTO `sys_dict_data` VALUES (1081, 1081, 'menu.ueUser.onlineUERemark', ' REPLACE INTO `sys_dict_data` VALUES (1082, 1082, 'menu.ueUser.base5GRemark', '5G基站信息菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1083, 1083, 'menu.traceRemark', '跟踪管理目录', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1084, 1084, 'menu.trace.taskRemark', '跟踪任务菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); -REPLACE INTO `sys_dict_data` VALUES (1085, 1085, 'menu.trace.analysisRemark', '信令分析菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); +-- REPLACE INTO `sys_dict_data` VALUES (1085, 1085, 'menu.trace.analysisRemark', '信令分析菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1086, 1086, 'menu.trace.pcapRemark', '信令抓包菜单', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1087, 1087, 'menu.faultRemark', '故障管理目录', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (1088, 1088, 'menu.fault.active', '活动告警', 'i18n_zh', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -663,7 +663,7 @@ REPLACE INTO `sys_dict_data` VALUES (2145, 2145, 'menu.system.user.editPost', ' REPLACE INTO `sys_dict_data` VALUES (2146, 2146, 'menu.dashboard.smscCDR', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1717051745866, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2147, 2147, 'log.operate.title.smscCDR', '短信话单', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2148, 2148, 'menu.trace.pcapFile', '信令抓包文件', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); -REPLACE INTO `sys_dict_data` VALUES (2149, 2149, 'menu.trace.taskAnalyze', '跟踪数据分析', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2149, 2149, 'menu.trace.taskAnalyze', '网元跟踪任务分析', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2150, 2150, 'job.ne_data_udm', '网元数据-UDM数据刷新同步', 'i18n_zh', '', '', '1', 'supervisor', 1730173767412, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2151, 2151, 'menu.system.setting.doc', '系统使用文档', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2152, 2152, 'menu.system.setting.official', '官网链接', 'i18n_zh', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); @@ -708,5 +708,37 @@ REPLACE INTO `sys_dict_data` VALUES (2190, 2190, 'menu.dashboard.overview.smfUeN REPLACE INTO `sys_dict_data` VALUES (2191, 2191, 'menu.dashboard.overview.imsUeNum', '展示语音会话数', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2192, 2192, 'menu.dashboard.overview.gnbBase', '展示5G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (2193, 2193, 'menu.dashboard.overview.enbBase', '展示4G基站在线信息', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2194, 2194, 'menu.ueUser.imsUDM', 'IMS签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2195, 2195, 'menu.ueUser.imsUDMRemark', 'IMS签约用户菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2196, 2196, 'menu.ueUser.voipUDM', 'VoIP鉴权数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2197, 2197, 'menu.ueUser.voipUDMRemark', 'VoIP鉴权数据菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2198, 2198, 'menu.ueUser.exportFile', '文件管理', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2199, 2199, 'menu.ueUser.exportFileRemark', '文件管理菜单', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2200, 2200, 'job.backup.ue.data', '定期备份UE用户和数据表', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2201, 2201, 'table.u_auth_user', 'UDM鉴权用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2202, 2202, 'table.u_sub_user', 'UDM签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2203, 2203, 'table.u_voip_auth', 'VoIP鉴权数据', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2204, 2204, 'table.u_ims_user', 'IMS签约用户', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2205, 2205, 'dictType.trace_msg_type', '跟踪消息类型', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2206, 2206, 'dictData.trace_msg_type.0', '请求', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2207, 2207, 'dictData.trace_msg_type.1', '响应', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2208, 2208, 'dictType.trace_msg_direct', '跟踪消息方向', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2209, 2209, 'dictData.trace_msg_direct.0', '接收', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2210, 2210, 'dictData.trace_msg_direct.1', '发送', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2211, 2211, 'dictData.trace_interfaces.1', 'N1', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2212, 2212, 'dictData.trace_interfaces.2', 'N2', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2213, 2213, 'dictData.trace_interfaces.3', 'N1/N2', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2214, 2214, 'dictData.trace_interfaces.4', 'N4', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2215, 2215, 'dictData.trace_interfaces.8', 'N8', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2216, 2216, 'dictData.trace_interfaces.10', 'N10', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2217, 2217, 'dictData.trace_interfaces.11', 'N11', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2218, 2218, 'dictData.trace_interfaces.12', 'N12', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2219, 2219, 'dictData.trace_interfaces.13', 'N13', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2220, 2220, 'dictData.trace_interfaces.7', 'N7', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2221, 2221, 'dictData.trace_interfaces.15', 'N15', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2222, 2222, 'dictData.trace_interfaces.17', 'N17', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2223, 2223, 'dictData.trace_interfaces.20', 'N20', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2224, 2224, 'dictData.trace_interfaces.22', 'N22', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (2225, 2225, 'dictData.trace_interfaces.40', 'N40', 'i18n_zh', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_dict_data2_i18n_en.sql b/database/upgrade/upg_sys_dict_data2_i18n_en.sql index ae5a4b98..632a3553 100644 --- a/database/upgrade/upg_sys_dict_data2_i18n_en.sql +++ b/database/upgrade/upg_sys_dict_data2_i18n_en.sql @@ -90,7 +90,7 @@ REPLACE INTO `sys_dict_data` VALUES (3071, 3071, 'menu.ueUser.onlineUE', 'UE Onl REPLACE INTO `sys_dict_data` VALUES (3072, 3072, 'menu.ueUser.base5G', 'Radio Information', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3073, 3073, 'menu.trace', 'Trace', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3074, 3074, 'menu.trace.task', 'NE Trace Task', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); -REPLACE INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.analysis', 'NE Trace Task Data', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); +REPLACE INTO `sys_dict_data` VALUES (3075, 3075, 'menu.trace.taskData', 'NE Trace Task Data', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3076, 3076, 'menu.trace.pcap', 'Signaling Capture', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3077, 3077, 'menu.fault', 'Monitor', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3078, 3078, 'config.sys.exportTable', 'Backup file FTP service', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -100,7 +100,7 @@ REPLACE INTO `sys_dict_data` VALUES (3081, 3081, 'menu.ueUser.onlineUERemark', ' REPLACE INTO `sys_dict_data` VALUES (3082, 3082, 'menu.ueUser.base5GRemark', '5G Base Station Information Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3083, 3083, 'menu.traceRemark', 'Tracking Management Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3084, 3084, 'menu.trace.taskRemark', 'Tracking Task Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); -REPLACE INTO `sys_dict_data` VALUES (3085, 3085, 'menu.trace.analysisRemark', 'Signaling Analysis Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); +-- REPLACE INTO `sys_dict_data` VALUES (3085, 3085, 'menu.trace.analysisRemark', 'Signaling Analysis Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3086, 3086, 'menu.trace.pcapRemark', 'Signaling Capture Menu', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3087, 3087, 'menu.faultRemark', 'Fault Management Catalog', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); REPLACE INTO `sys_dict_data` VALUES (3088, 3088, 'menu.fault.active', 'Active Alarms', 'i18n_en', NULL, NULL, '1', 'supervisor', 1700000000000, NULL, 0, NULL); @@ -662,7 +662,7 @@ REPLACE INTO `sys_dict_data` VALUES (4145, 4145, 'menu.system.user.editPost', 'M REPLACE INTO `sys_dict_data` VALUES (4146, 4146, 'menu.dashboard.smscCDR', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4147, 4147, 'log.operate.title.smscCDR', 'SMS CDR', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4148, 4148, 'menu.trace.pcapFile', 'Signaling Capture File', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, ''); -REPLACE INTO `sys_dict_data` VALUES (4149, 4149, 'menu.trace.taskAnalyze', 'Tracking Data Analysis', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4149, 4149, 'menu.trace.taskAnalyze', 'NE Trace Task Analysis', 'i18n_en', '', '', '1', 'supervisor', 1718441035866, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4150, 4150, 'job.ne_data_udm', 'NE Data Sync UDM', 'i18n_en', '', '', '1', 'supervisor', 1730173767412, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4151, 4151, 'menu.system.setting.doc', 'System User Documentation', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4152, 4152, 'menu.system.setting.official', 'Official Website', 'i18n_en', '', '', '1', 'supervisor', 1705550000000, '', 0, ''); @@ -707,5 +707,37 @@ REPLACE INTO `sys_dict_data` VALUES (4190, 4190, 'menu.dashboard.overview.smfUeN REPLACE INTO `sys_dict_data` VALUES (4191, 4191, 'menu.dashboard.overview.imsUeNum', 'Display the number of voice sessions', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4192, 4192, 'menu.dashboard.overview.gnbBase', 'Display 5G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); REPLACE INTO `sys_dict_data` VALUES (4193, 4193, 'menu.dashboard.overview.enbBase', 'Display 4G base station online information', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4194, 4194, 'menu.ueUser.imsUDM', 'IMS Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4195, 4195, 'menu.ueUser.imsUDMRemark', 'IMS Subscribers Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4196, 4196, 'menu.ueUser.voipUDM', 'VoIP Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4197, 4197, 'menu.ueUser.voipUDMRemark', 'VoIP Authentication Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4198, 4198, 'menu.ueUser.exportFile', 'File Management', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4199, 4199, 'menu.ueUser.exportFileRemark', 'File Management Menu', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4200, 4200, 'job.backup.ue.data', 'Backup regularly UE users and data', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4201, 4201, 'table.u_auth_user', 'UDM Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4202, 4202, 'table.u_sub_user', 'UDM Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4203, 4203, 'table.u_voip_auth', 'VoIP Authentication', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4204, 4204, 'table.u_ims_user', 'IMS Subscribers', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4205, 4205, 'dictType.trace_msg_type', 'Trace Message Type', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4206, 4206, 'dictData.trace_msg_type.0', 'Request', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4207, 4207, 'dictData.trace_msg_type.1', 'Response', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4208, 4208, 'dictType.trace_msg_direct', 'Track Message Directio', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4209, 4209, 'dictData.trace_msg_direct.0', 'Receive', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4210, 4210, 'dictData.trace_msg_direct.1', 'Send', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4211, 4211, 'dictData.trace_interfaces.1', 'N1', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4212, 4212, 'dictData.trace_interfaces.2', 'N2', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4213, 4213, 'dictData.trace_interfaces.3', 'N1/N2', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4214, 4214, 'dictData.trace_interfaces.4', 'N4', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4215, 4215, 'dictData.trace_interfaces.8', 'N8', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4216, 4216, 'dictData.trace_interfaces.10', 'N10', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4217, 4217, 'dictData.trace_interfaces.11', 'N11', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4218, 4218, 'dictData.trace_interfaces.12', 'N12', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4219, 4219, 'dictData.trace_interfaces.13', 'N13', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4220, 4220, 'dictData.trace_interfaces.7', 'N7', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4221, 4221, 'dictData.trace_interfaces.15', 'N15', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4222, 4222, 'dictData.trace_interfaces.17', 'N17', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4223, 4223, 'dictData.trace_interfaces.20', 'N20', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4224, 4224, 'dictData.trace_interfaces.22', 'N22', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); +REPLACE INTO `sys_dict_data` VALUES (4225, 4225, 'dictData.trace_interfaces.40', 'N40', 'i18n_en', '', '', '1', 'supervisor', 1721902269805, '', 0, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_dict_type.sql b/database/upgrade/upg_sys_dict_type.sql index 6c2c5b38..1079f6bf 100644 --- a/database/upgrade/upg_sys_dict_type.sql +++ b/database/upgrade/upg_sys_dict_type.sql @@ -54,5 +54,8 @@ INSERT IGNORE INTO `sys_dict_type` VALUES (121, 'dictType.ne_host_cmd_groupId', INSERT IGNORE INTO `sys_dict_type` VALUES (122, 'dictType.ne_info_status', 'ne_info_status', '1', 'supervisor', 1702020000000, '', 0, ''); INSERT IGNORE INTO `sys_dict_type` VALUES (123, 'dictType.ne_license_status', 'ne_license_status', '1', 'supervisor', 1702020000000, '', 0, ''); INSERT IGNORE INTO `sys_dict_type` VALUES (124, 'dictType.cdr_cause_code', 'cdr_cause_code', '1', 'supervisor', 1725877564156, '', 0, ''); +INSERT IGNORE INTO `sys_dict_type` VALUES (125, 'dictType.trace_msg_type', 'trace_msg_type', '1', 'system', 1699348237468, 'system', 1699348237468, ''); +INSERT IGNORE INTO `sys_dict_type` VALUES (126, 'dictType.trace_msg_direct', 'trace_msg_direct', '1', 'system', 1699348237468, 'system', 1699348237468, ''); +INSERT IGNORE INTO `sys_dict_type` VALUES (127, 'dictType.trace_interfaces', 'trace_interfaces', '1', 'system', 1699348237468, 'system', 1699348237468, ''); SET FOREIGN_KEY_CHECKS = 1; diff --git a/database/upgrade/upg_sys_menu.sql b/database/upgrade/upg_sys_menu.sql index 0a5ea6c1..44859166 100644 --- a/database/upgrade/upg_sys_menu.sql +++ b/database/upgrade/upg_sys_menu.sql @@ -119,8 +119,8 @@ REPLACE INTO `sys_menu` VALUES (2080, 'menu.ueUser.onlineIMS', 5, 4, 'ims', 'neU REPLACE INTO `sys_menu` VALUES (2081, 'menu.ueUser.onlineUE', 5, 6, 'ue', 'neUser/ue/index', '1', '0', 'M', '1', '1', 'neUser:ue:index', 'icon-xiangmuchengyuan', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.onlineUERemark'); REPLACE INTO `sys_menu` VALUES (2082, 'menu.ueUser.base5G', 5, 7, 'base5G', 'neUser/base5G/index', '1', '0', 'M', '0', '1', 'neUser:base5G:index', 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.ueUser.base5GRemark'); REPLACE INTO `sys_menu` VALUES (2083, 'menu.trace', 2087, 30, 'traceManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-paixu', 'supervisor', 1700000000000, NULL, 0, 'menu.traceRemark'); -REPLACE INTO `sys_menu` VALUES (2084, 'menu.trace.task', 2083, 1, 'task', 'traceManage/task/index', '1', '0', 'M', '0', '1', 'traceManage:task:index', 'icon-chexiao', 'supervisor', 1700000000000, 'admin', 1713176976458, 'menu.trace.taskRemark'); -REPLACE INTO `sys_menu` VALUES (2085, 'menu.trace.analysis', 2083, 4, 'analysis', 'traceManage/analysis/index', '1', '0', 'M', '0', '1', 'traceManage:analysis:index', 'icon-gongnengjieshao', 'supervisor', 1700000000000, 'admin', 1713176987835, 'menu.trace.analysisRemark'); +REPLACE INTO `sys_menu` VALUES (2084, 'menu.trace.task', 2083, 1, 'task', 'traceManage/task/index', '1', '0', 'M', '1', '1', 'traceManage:task:index', 'icon-chexiao', 'supervisor', 1700000000000, 'admin', 1744453890548, 'menu.trace.taskRemark'); +REPLACE INTO `sys_menu` VALUES (2085, 'menu.trace.taskData', 2083, 4, 'task/inline/data', 'traceManage/task/data', '1', '0', 'M', '0', '1', 'traceManage:task:data', '#', 'supervisor', 1700000000000, 'admin', 1744453921381, ''); REPLACE INTO `sys_menu` VALUES (2086, 'menu.trace.pcap', 2083, 11, 'pcap', 'traceManage/pcap/index', '1', '1', 'M', '1', '1', 'traceManage:pcap:index', 'icon-soutubiao', 'supervisor', 1700000000000, NULL, 0, 'menu.trace.pcapRemark'); REPLACE INTO `sys_menu` VALUES (2087, 'menu.fault', 0, 2, 'faultManage', NULL, '1', '0', 'D', '1', '1', NULL, 'icon-jinggao', 'supervisor', 1700000000000, NULL, 0, 'menu.faultRemark'); REPLACE INTO `sys_menu` VALUES (2088, 'menu.fault.active', 2129, 1, 'active-alarm', 'faultManage/active-alarm/index', '1', '1', 'M', '1', '1', 'faultManage:active-alarm:index', 'icon-wenjian', 'supervisor', 1700000000000, NULL, 0, 'menu.fault.activemRemark'); @@ -191,9 +191,9 @@ REPLACE INTO `sys_menu` VALUES (2156, 'menu.common.edit', 2154, 2, '#', '', '1', REPLACE INTO `sys_menu` VALUES (2157, 'menu.dashboard.smscCDR', 2140, 9, 'smscCDR', 'dashboard/smscCDR/index', '1', '0', 'M', '1', '1', 'dashboard:cdr:index', 'icon-paixu', 'supervisor', 1723107637982, 'supervisor', 1723107637982, ''); REPLACE INTO `sys_menu` VALUES (2158, 'menu.trace.pcapFile', 2083, 12, 'pcap/inline/file', 'traceManage/pcap/file', '1', '1', 'M', '0', '1', 'traceManage:pcap:index', '#', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2159, 'menu.log.exportFile', 2089, 100, 'exportFile', 'logManage/exportFile/index', '1', '1', 'M', '1', '1', 'logManage:exportFile:index', 'icon-wenjian', 'supervisor', 1724144595914, '', 0, ''); -REPLACE INTO `sys_menu` VALUES (2160, 'menu.perf.kpiCReport', 2099, 100, 'kpiCReport', 'perfManage/kpiCReport/index', '1', '0', 'M', '1', '1', 'perfManage:kpiCReport:index', 'icon-tubiaoku', 'supervisor', 1724144595914, '', 0, ''); +REPLACE INTO `sys_menu` VALUES (2160, 'menu.perf.kpiCReport', 2099, 100, 'kpiCReport', 'perfManage/kpiCReport/index', '1', '1', 'M', '1', '1', 'perfManage:kpiCReport:index', 'icon-tubiaoku', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2161, 'menu.trace.taskHLR', 2083, 6, 'taskHLR', 'traceManage/task-hlr/index', '1', '0', 'M', '0', '1', 'traceManage:taskHLR:index', 'icon-chexiao', 'supervisor', 1724144595914, '', 0, ''); -REPLACE INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/inline/analyze', 'traceManage/task/analyze', '1', '0', 'M', '0', '1', 'traceManage:taskAnalyze:index', '#', 'supervisor', 1724144595914, '', 0, ''); +REPLACE INTO `sys_menu` VALUES (2162, 'menu.trace.taskAnalyze', 2083, 2, 'task/inline/analyze', 'traceManage/task/analyze', '1', '0', 'M', '0', '1', 'traceManage:task:analyze', '#', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2163, 'menu.trace.tshark', 2083, 14, 'tshark', 'traceManage/tshark/index', '1', '0', 'M', '1', '1', 'traceManage:tshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2164, 'menu.trace.wireshark', 2083, 16, 'wireshark', 'traceManage/wireshark/index', '1', '0', 'M', '1', '1', 'traceManage:wireshark:index', 'icon-gengduo', 'supervisor', 1724144595914, '', 0, ''); REPLACE INTO `sys_menu` VALUES (2165, 'menu.config.neOverview', 4, 1, 'neOverview', 'configManage/neOverview/index', '1', '0', 'M', '1', '1', 'configManage:neOverview:index', 'icon-tubiaoku', 'supervisor', 1700000000000, NULL, 0, 'menu.config.neOverviewRemark'); diff --git a/database/upgrade/upg_sys_role_menu.sql b/database/upgrade/upg_sys_role_menu.sql index 33a39600..f8ebb134 100644 --- a/database/upgrade/upg_sys_role_menu.sql +++ b/database/upgrade/upg_sys_role_menu.sql @@ -1,7 +1,6 @@ -- ---------------------------- -- Table structure for sys_role_menu -- ---------------------------- -DROP TABLE IF EXISTS `sys_role_menu`; CREATE TABLE IF NOT EXISTS `sys_role_menu` ( `role_id` bigint(20) NOT NULL COMMENT '角色ID', `menu_id` bigint(20) NOT NULL COMMENT '菜单ID', @@ -78,6 +77,7 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2010); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2080); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2081); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2083); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2084); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2086); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2087); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2088); @@ -135,6 +135,7 @@ INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2158); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2159); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2160); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2163); +INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2164); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2165); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2166); INSERT IGNORE INTO `sys_role_menu` VALUES (2, 2167); diff --git a/database/upgrade/upg_trace_data.sql b/database/upgrade/upg_trace_data.sql new file mode 100644 index 00000000..a3016e14 --- /dev/null +++ b/database/upgrade/upg_trace_data.sql @@ -0,0 +1,44 @@ +-- +-- Table structure for table `trace_data` +-- + +CREATE TABLE IF NOT EXISTS `trace_data` ( + `id` int NOT NULL AUTO_INCREMENT, + `trace_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '跟踪任务ID', + `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'UE类型 IMSI', + `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT 'UE类型 可能存在', + `src_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '源地址', + `dst_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '目标地址', + `if_type` varchar(16) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '接口类型,未分类', + `msg_type` int DEFAULT NULL COMMENT '消息类型,0-req, 1-rsp', + `msg_direct` int DEFAULT NULL COMMENT '消息方向,0-recv,1-send', + `msg_ne` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '消息网元', + `msg_event` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '消息事件,e.g: CreateContextReq', + `length` int DEFAULT NULL COMMENT '原始数据byte长度', + `timestamp` bigint DEFAULT '0' COMMENT '纳秒时间戳', + `raw_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci COMMENT '原始数据byteBase64', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_task_id_time` (`trace_id`,`timestamp`) COMMENT '任务DI时间' +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='跟踪_任务数据'; + +-- Dump completed on 2025-04-14 14:26:59 + +ALTER TABLE `trace_data` COMMENT = '跟踪_任务数据'; +ALTER TABLE `trace_data` ADD COLUMN IF NOT EXISTS `trace_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '跟踪任务ID' AFTER `id`; +ALTER TABLE `trace_data` ADD COLUMN IF NOT EXISTS `msg_ne` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '消息网元' AFTER `msg_direct`; +ALTER TABLE `trace_data` ADD COLUMN IF NOT EXISTS `msg_event` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '消息事件,e.g: CreateContextReq' AFTER `msg_ne`; +ALTER TABLE `trace_data` MODIFY COLUMN `id` int NOT NULL FIRST; +ALTER TABLE `trace_data` MODIFY COLUMN `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'UE类型 IMSI' AFTER `trace_id`; +ALTER TABLE `trace_data` MODIFY COLUMN `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT 'UE类型 可能存在' AFTER `imsi`; +ALTER TABLE `trace_data` MODIFY COLUMN `src_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '源地址' AFTER `msisdn`; +ALTER TABLE `trace_data` MODIFY COLUMN `dst_addr` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '目标地址' AFTER `src_addr`; +ALTER TABLE `trace_data` MODIFY COLUMN `if_type` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '接口类型,未分类' AFTER `dst_addr`; +ALTER TABLE `trace_data` MODIFY COLUMN `msg_type` int NULL DEFAULT NULL COMMENT '消息类型,0-req, 1-rsp' AFTER `if_type`; +ALTER TABLE `trace_data` MODIFY COLUMN `msg_direct` int NULL DEFAULT NULL COMMENT '消息方向,0-recv,1-send' AFTER `msg_type`; +ALTER TABLE `trace_data` MODIFY COLUMN `length` int NULL DEFAULT NULL COMMENT '原始数据byte长度' AFTER `msg_event`; +ALTER TABLE `trace_data` MODIFY COLUMN `timestamp` bigint NULL DEFAULT 0 COMMENT '纳秒时间戳' AFTER `length`; +ALTER TABLE `trace_data` MODIFY COLUMN `raw_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '原始数据byteBase64' AFTER `timestamp`; +ALTER TABLE `trace_data` MODIFY COLUMN `id` int NOT NULL AUTO_INCREMENT; +ALTER TABLE `trace_data` DROP COLUMN IF EXISTS `task_id`; +ALTER TABLE `trace_data` DROP COLUMN IF EXISTS `dec_msg`; +ALTER TABLE `trace_data` ADD INDEX IF NOT EXISTS `idx_task_id_time`(`trace_id`, `timestamp`) USING BTREE COMMENT '任务DI时间'; diff --git a/database/upgrade/upg_trace_task.sql b/database/upgrade/upg_trace_task.sql new file mode 100644 index 00000000..7984c88d --- /dev/null +++ b/database/upgrade/upg_trace_task.sql @@ -0,0 +1,49 @@ +-- +-- Table structure for table `trace_task` +-- + +CREATE TABLE IF NOT EXISTS `trace_task` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID', + `trace_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '任务编号', + `trace_type` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '1-Interface,2-Device,3-UE', + `start_time` bigint DEFAULT '0' COMMENT '开始时间 毫秒', + `end_time` bigint DEFAULT '0' COMMENT '结束时间 毫秒', + `interfaces` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '接口跟踪必须 例如 N8,N10', + `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户跟踪必须', + `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户跟踪可选', + `src_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '源地址IP', + `dst_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '目标地址IP', + `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '创建者', + `create_time` bigint DEFAULT '0' COMMENT '创建时间', + `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '' COMMENT '备注', + `ne_list` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '网元列表 neType_neId 例如 UDM_001,AMF_001', + `notify_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '信息数据通知回调地址UDP 例如udp:192.168.5.58:33033', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='跟踪_任务'; + +-- Dump completed on 2025-04-14 14:26:59 + +ALTER TABLE `trace_task` COMMENT = '跟踪_任务'; +ALTER TABLE `trace_task` ADD COLUMN IF NOT EXISTS `ne_list` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '网元列表 neType_neId 例如 UDM_001,AMF_001' AFTER `remark`; +ALTER TABLE `trace_task` MODIFY COLUMN `id` int NOT NULL COMMENT 'ID' FIRST; +ALTER TABLE `trace_task` MODIFY COLUMN `trace_id` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '任务编号' AFTER `id`; +ALTER TABLE `trace_task` MODIFY COLUMN `trace_type` varchar(2) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '1-Interface,2-Device,3-UE' AFTER `trace_id`; +ALTER TABLE `trace_task` MODIFY COLUMN `start_time` bigint NULL DEFAULT 0 COMMENT '开始时间 毫秒' AFTER `trace_type`; +ALTER TABLE `trace_task` MODIFY COLUMN `end_time` bigint NULL DEFAULT 0 COMMENT '结束时间 毫秒' AFTER `start_time`; +ALTER TABLE `trace_task` MODIFY COLUMN `interfaces` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '接口跟踪必须 例如 N8,N10' AFTER `end_time`; +ALTER TABLE `trace_task` MODIFY COLUMN `imsi` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户跟踪必须' AFTER `interfaces`; +ALTER TABLE `trace_task` MODIFY COLUMN `msisdn` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '用户跟踪可选' AFTER `imsi`; +ALTER TABLE `trace_task` MODIFY COLUMN `src_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '源地址IP' AFTER `msisdn`; +ALTER TABLE `trace_task` MODIFY COLUMN `dst_ip` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '目标地址IP' AFTER `src_ip`; +ALTER TABLE `trace_task` MODIFY COLUMN `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '创建者' AFTER `dst_ip`; +ALTER TABLE `trace_task` MODIFY COLUMN `create_time` bigint NULL DEFAULT 0 COMMENT '创建时间' AFTER `create_by`; +ALTER TABLE `trace_task` MODIFY COLUMN `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT '' COMMENT '备注' AFTER `create_time`; +ALTER TABLE `trace_task` MODIFY COLUMN `notify_url` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '信息数据通知回调地址UDP 例如udp:192.168.5.58:33033' AFTER `ne_list`; +ALTER TABLE `trace_task` MODIFY COLUMN `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID'; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `ue_ip`; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `signal_port`; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `update_by`; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `update_time`; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `ne_type`; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `ne_id`; +ALTER TABLE `trace_task` DROP COLUMN IF EXISTS `fetch_msg`; diff --git a/src/modules/trace/controller/packet.go b/src/modules/trace/controller/packet.go index ac54aa2b..2fb07ee9 100644 --- a/src/modules/trace/controller/packet.go +++ b/src/modules/trace/controller/packet.go @@ -1,12 +1,16 @@ package controller import ( + "fmt" + "path/filepath" + "runtime" + "be.ems/src/framework/i18n" - "be.ems/src/framework/utils/ctx" - "be.ems/src/framework/vo/result" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" traceService "be.ems/src/modules/trace/service" + "github.com/gin-gonic/gin" - "github.com/gin-gonic/gin/binding" ) // 实例化控制层 PacketController 结构体 @@ -26,85 +30,89 @@ type PacketController struct { // GET /devices func (s *PacketController) Devices(c *gin.Context) { data := s.packetService.NetworkDevices() - c.JSON(200, result.OkData(data)) + c.JSON(200, resp.OkData(data)) } // 信令跟踪开始 // // POST /start func (s *PacketController) Start(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { TaskNo string `json:"taskNo" binding:"required"` // 任务编号 Device string `json:"device" binding:"required"` // 网卡设备 Filter string `json:"filter" ` // 过滤表达式(port 33030 or 33040) OutputPCAP bool `json:"outputPCAP" ` // 输出PCAP文件 (默认false) } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } msg, err := s.packetService.LiveStart(body.TaskNo, body.Device, body.Filter, body.OutputPCAP) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.OkData(msg)) + c.JSON(200, resp.OkData(msg)) } // 信令跟踪结束 // // POST /stop func (s *PacketController) Stop(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { TaskNo string `json:"taskNo" binding:"required"` // 任务编号 } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } if err := s.packetService.LiveStop(body.TaskNo); err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.Ok(nil)) + c.JSON(200, resp.Ok(nil)) } // 信令跟踪过滤 // // PUT /filter func (s *PacketController) Filter(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { TaskNo string `json:"taskNo" binding:"required"` // 任务编号 Expr string `json:"expr" ` // 过滤表达式(port 33030 or 33040) } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } if err := s.packetService.LiveFilter(body.TaskNo, body.Expr); err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.Ok(nil)) + c.JSON(200, resp.Ok(nil)) } // 信令跟踪续期保活 // // PUT /keep-alive func (s *PacketController) KeepAlive(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { TaskNo string `json:"taskNo" binding:"required"` // 任务编号 Duration int `json:"duration" ` // 服务失效的时间,默认设置为120秒 } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } @@ -114,8 +122,28 @@ func (s *PacketController) KeepAlive(c *gin.Context) { } if err := s.packetService.LiveTimeout(body.TaskNo, body.Duration); err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.Ok(nil)) + c.JSON(200, resp.Ok(nil)) +} + +// 信令跟踪文件 +// +// GET /filePull +func (s *PacketController) FilePull(c *gin.Context) { + var querys struct { + TaskNo string `json:"taskNo" form:"taskNo" binding:"required"` // 任务编号 + } + if err := c.ShouldBindQuery(&querys); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) + return + } + fileName := fmt.Sprintf("%s.pcap", querys.TaskNo) + localFilePath := filepath.Join("/tmp/omc/packet", fileName) + if runtime.GOOS == "windows" { + localFilePath = fmt.Sprintf("C:%s", localFilePath) + } + c.FileAttachment(localFilePath, fileName) } diff --git a/src/modules/trace/controller/tcpdump.go b/src/modules/trace/controller/tcpdump.go index dd1efbf2..c2920e08 100644 --- a/src/modules/trace/controller/tcpdump.go +++ b/src/modules/trace/controller/tcpdump.go @@ -1,9 +1,11 @@ package controller import ( + "fmt" + "be.ems/src/framework/i18n" - "be.ems/src/framework/utils/ctx" - "be.ems/src/framework/vo/result" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" traceService "be.ems/src/modules/trace/service" "github.com/gin-gonic/gin" @@ -35,7 +37,7 @@ type TCPdumpController struct { // @Description Network Element Capture Packet PACP Start // @Router /trace/tcpdump/start [post] func (s *TCPdumpController) DumpStart(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` // 网元类型 NeId string `json:"neId" binding:"required"` // 网元ID @@ -43,16 +45,17 @@ func (s *TCPdumpController) DumpStart(c *gin.Context) { } err := c.ShouldBindBodyWithJSON(&body) if err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } taskCode, err := s.tcpdumpService.DumpStart(body.NeType, body.NeId, body.Cmd) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.OkData(taskCode)) + c.JSON(200, resp.OkData(taskCode)) } // 网元抓包PACP 结束 @@ -69,7 +72,7 @@ func (s *TCPdumpController) DumpStart(c *gin.Context) { // @Description Network Element Capture Packet PACP Stop // @Router /trace/tcpdump/stop [post] func (s *TCPdumpController) DumpStop(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` // 网元类型 NeId string `json:"neId" binding:"required"` // 网元ID @@ -77,16 +80,17 @@ func (s *TCPdumpController) DumpStop(c *gin.Context) { } err := c.ShouldBindBodyWithJSON(&body) if err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } logFiles, err := s.tcpdumpService.DumpStop(body.NeType, body.NeId, body.TaskCode) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.OkData(logFiles)) + c.JSON(200, resp.OkData(logFiles)) } // UPF标准版内部抓包 @@ -103,7 +107,7 @@ func (s *TCPdumpController) DumpStop(c *gin.Context) { // @Description UPF Standard Edition Internal Grab Bag // @Router /trace/tcpdump/upf [post] func (s *TCPdumpController) UPFTrace(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { NeType string `json:"neType" binding:"required"` // 网元类型 NeId string `json:"neId" binding:"required"` // 网元ID @@ -111,14 +115,15 @@ func (s *TCPdumpController) UPFTrace(c *gin.Context) { } err := c.ShouldBindBodyWithJSON(&body) if err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } msg, err := s.tcpdumpService.UPFTrace(body.NeType, body.NeId, body.Cmd) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.OkData(msg)) + c.JSON(200, resp.OkData(msg)) } diff --git a/src/modules/trace/controller/trace_data.go b/src/modules/trace/controller/trace_data.go index 2d8222b9..cc011ffa 100644 --- a/src/modules/trace/controller/trace_data.go +++ b/src/modules/trace/controller/trace_data.go @@ -1,13 +1,12 @@ package controller import ( - "strings" - "be.ems/src/framework/i18n" - "be.ems/src/framework/utils/ctx" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" "be.ems/src/framework/utils/parse" - "be.ems/src/framework/vo/result" traceService "be.ems/src/modules/trace/service" + "github.com/gin-gonic/gin" ) @@ -20,43 +19,60 @@ var NewTraceData = &TraceDataController{ // // PATH /data type TraceDataController struct { - // 跟踪_数据信息服务 - traceDataService *traceService.TraceData + traceDataService *traceService.TraceData // 跟踪_数据信息服务 } // 跟踪任务数据列表 // // GET /list func (s *TraceDataController) List(c *gin.Context) { - query := ctx.QueryMap(c) + query := reqctx.QueryMap(c) + rows, total := s.traceDataService.FindByPage(query) + c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) +} - // 查询数据 - data := s.traceDataService.SelectPage(query) - c.JSON(200, result.Ok(data)) +// 跟踪任务数据信息 +// +// GET /:id +func (s *TraceDataController) Info(c *gin.Context) { + id := parse.Number(c.Param("id")) + if id <= 0 { + c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty")) + return + } + + data := s.traceDataService.FindById(id) + if data.ID == id { + c.JSON(200, resp.OkData(data)) + return + } + c.JSON(200, resp.Err(nil)) } // 跟踪任务数据删除 // -// DELETE /:ids +// DELETE /:id func (s *TraceDataController) Remove(c *gin.Context) { - language := ctx.AcceptLanguage(c) - rowIds := c.Param("ids") - if rowIds == "" { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + language := reqctx.AcceptLanguage(c) + id := c.Param("id") + if id == "" { + c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty")) return } + // 处理字符转id数组后去重 - ids := strings.Split(rowIds, ",") - uniqueIDs := parse.RemoveDuplicates(ids) - if len(uniqueIDs) <= 0 { - c.JSON(200, result.Err(nil)) - return + uniqueIDs := parse.RemoveDuplicatesToArray(id, ",") + // 转换成int64数组类型 + ids := make([]int64, 0) + for _, v := range uniqueIDs { + ids = append(ids, parse.Number(v)) } - rows, err := s.traceDataService.DeleteByIds(uniqueIDs) + + rows, err := s.traceDataService.DeleteByIds(ids) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) - c.JSON(200, result.OkMsg(msg)) + c.JSON(200, resp.OkMsg(msg)) } diff --git a/src/modules/trace/controller/trace_task.go b/src/modules/trace/controller/trace_task.go index fc912eab..abb5dfd6 100644 --- a/src/modules/trace/controller/trace_task.go +++ b/src/modules/trace/controller/trace_task.go @@ -4,16 +4,15 @@ import ( "fmt" "path/filepath" "runtime" - "strings" "be.ems/src/framework/i18n" - "be.ems/src/framework/utils/ctx" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" "be.ems/src/framework/utils/parse" - "be.ems/src/framework/vo/result" "be.ems/src/modules/trace/model" traceService "be.ems/src/modules/trace/service" + "github.com/gin-gonic/gin" - "github.com/gin-gonic/gin/binding" ) // 实例化控制层 TraceTaskController 结构体 @@ -33,116 +32,92 @@ type TraceTaskController struct { // // GET /list func (s *TraceTaskController) List(c *gin.Context) { - query := ctx.QueryMap(c) - - // 查询数据 - data := s.traceTaskService.SelectPage(query) - c.JSON(200, result.Ok(data)) + query := reqctx.QueryMap(c) + rows, total := s.traceTaskService.FindByPage(query) + c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) } // 跟踪任务信息 // // GET /:id func (s *TraceTaskController) Info(c *gin.Context) { - language := ctx.AcceptLanguage(c) - id := c.Param("id") - if id == "" { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + id := parse.Number(c.Param("id")) + if id <= 0 { + c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty")) return } - data := s.traceTaskService.SelectById(id) + data := s.traceTaskService.FindById(id) if data.ID == id { - c.JSON(200, result.OkData(data)) + c.JSON(200, resp.OkData(data)) return } - c.JSON(200, result.Err(nil)) + c.JSON(200, resp.Err(nil)) } // 跟踪任务新增 // // POST / func (s *TraceTaskController) Add(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body model.TraceTask - err := c.ShouldBindBodyWith(&body, binding.JSON) - if err != nil || body.ID != "" { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + err := c.ShouldBindBodyWithJSON(&body) + if err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) + return + } + if body.ID > 0 { + c.JSON(400, resp.CodeMsg(40010, "bind err: id not is empty")) return } - body.CreateBy = ctx.LoginUserToUserName(c) + body.CreateBy = reqctx.LoginUserToUserName(c) if err = s.traceTaskService.Insert(body); err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } - c.JSON(200, result.Ok(nil)) -} - -// 跟踪任务修改 -// -// PUT / -func (s *TraceTaskController) Edit(c *gin.Context) { - language := ctx.AcceptLanguage(c) - var body model.TraceTask - err := c.ShouldBindBodyWith(&body, binding.JSON) - if err != nil || body.ID == "" { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) - return - } - - // 检查是否存在 - taskInfo := s.traceTaskService.SelectById(body.ID) - if taskInfo.ID != body.ID { - // 没有可访问任务信息数据! - c.JSON(200, result.ErrMsg(i18n.TKey(language, "task.noData"))) - return - } - - body.UpdateBy = ctx.LoginUserToUserName(c) - if err = s.traceTaskService.Update(body); err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) - return - } - c.JSON(200, result.Ok(nil)) + c.JSON(200, resp.Ok(nil)) } // 跟踪任务删除 // -// DELETE /:ids +// DELETE /:id func (s *TraceTaskController) Remove(c *gin.Context) { - language := ctx.AcceptLanguage(c) - rowIds := c.Param("ids") - if rowIds == "" { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + language := reqctx.AcceptLanguage(c) + id := c.Param("id") + if id == "" { + c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty")) return } + // 处理字符转id数组后去重 - ids := strings.Split(rowIds, ",") - uniqueIDs := parse.RemoveDuplicates(ids) - if len(uniqueIDs) <= 0 { - c.JSON(200, result.Err(nil)) - return + uniqueIDs := parse.RemoveDuplicatesToArray(id, ",") + // 转换成int64数组类型 + ids := make([]int64, 0) + for _, v := range uniqueIDs { + ids = append(ids, parse.Number(v)) } - rows, err := s.traceTaskService.DeleteByIds(uniqueIDs) + + rows, err := s.traceTaskService.DeleteByIds(ids) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) - c.JSON(200, result.OkMsg(msg)) + c.JSON(200, resp.OkMsg(msg)) } // 跟踪任务文件 // // GET /filePull func (s *TraceTaskController) FilePull(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var querys struct { TraceId string `form:"traceId" binding:"required"` } if err := c.ShouldBindQuery(&querys); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } diff --git a/src/modules/trace/controller/trace_task_hlr.go b/src/modules/trace/controller/trace_task_hlr.go index 07acc5ba..53b5e33a 100644 --- a/src/modules/trace/controller/trace_task_hlr.go +++ b/src/modules/trace/controller/trace_task_hlr.go @@ -5,18 +5,17 @@ import ( "os" "path/filepath" "runtime" - "strings" "be.ems/src/framework/i18n" - "be.ems/src/framework/utils/ctx" + "be.ems/src/framework/reqctx" + "be.ems/src/framework/resp" "be.ems/src/framework/utils/generate" "be.ems/src/framework/utils/parse" - "be.ems/src/framework/vo/result" neService "be.ems/src/modules/network_element/service" "be.ems/src/modules/trace/model" traceService "be.ems/src/modules/trace/service" + "github.com/gin-gonic/gin" - "github.com/gin-gonic/gin/binding" ) // 实例化控制层 TraceTaskHlrController 结构体 @@ -37,49 +36,50 @@ type TraceTaskHlrController struct { // // GET /list func (s *TraceTaskHlrController) List(c *gin.Context) { - language := ctx.AcceptLanguage(c) - var querys model.TraceTaskHlrQuery - if err := c.ShouldBindQuery(&querys); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + language := reqctx.AcceptLanguage(c) + var query model.TraceTaskHlrQuery + if err := c.ShouldBindQuery(&query); err != nil { + c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } - // 查询数据 - data := s.traceTaskHlrService.SelectPage(querys) - c.JSON(200, result.Ok(data)) + rows, total := s.traceTaskHlrService.FindByPage(query) + c.JSON(200, resp.OkData(map[string]any{"rows": rows, "total": total})) } // 跟踪任务删除 // -// DELETE /:ids +// DELETE /:id func (s *TraceTaskHlrController) Remove(c *gin.Context) { - language := ctx.AcceptLanguage(c) - rowIds := c.Param("ids") - if rowIds == "" { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + language := reqctx.AcceptLanguage(c) + id := c.Param("id") + if id == "" { + c.JSON(400, resp.CodeMsg(40010, "bind err: id is empty")) return } + // 处理字符转id数组后去重 - ids := strings.Split(rowIds, ",") - uniqueIDs := parse.RemoveDuplicates(ids) - if len(uniqueIDs) <= 0 { - c.JSON(200, result.Err(nil)) - return + uniqueIDs := parse.RemoveDuplicatesToArray(id, ",") + // 转换成int64数组类型 + ids := make([]int64, 0) + for _, v := range uniqueIDs { + ids = append(ids, parse.Number(v)) } - rows, err := s.traceTaskHlrService.DeleteByIds(uniqueIDs) + + rows, err := s.traceTaskHlrService.DeleteByIds(ids) if err != nil { - c.JSON(200, result.ErrMsg(i18n.TKey(language, err.Error()))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, err.Error()))) return } msg := i18n.TTemplate(language, "app.common.deleteSuccess", map[string]any{"num": rows}) - c.JSON(200, result.OkMsg(msg)) + c.JSON(200, resp.OkMsg(msg)) } // 跟踪任务创建 // // POST /start func (s *TraceTaskHlrController) Start(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { IMSI string `json:"imsi"` // IMSI MSISDN string `json:"msisdn"` // MSISDN @@ -87,13 +87,13 @@ func (s *TraceTaskHlrController) Start(c *gin.Context) { EndTime int64 `json:"endTime"` // 结束时间 Remark string `json:"remark"` // 备注说明 } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } if body.IMSI == "" && body.MSISDN == "" { - c.JSON(400, result.CodeMsg(400, "imsi amd msisdn is empty")) + c.JSON(400, resp.CodeMsg(400, "imsi amd msisdn is empty")) return } @@ -103,88 +103,88 @@ func (s *TraceTaskHlrController) Start(c *gin.Context) { StartTime: body.StartTime, EndTime: body.EndTime, Remark: body.Remark, - CreateBy: ctx.LoginUserToUserName(c), + CreateBy: reqctx.LoginUserToUserName(c), } id, err := s.traceTaskHlrService.Start(task) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } - c.JSON(200, result.OkData(id)) + c.JSON(200, resp.OkData(id)) } // 跟踪任务停止 // // POST /stop func (s *TraceTaskHlrController) Stop(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var body struct { ID string `json:"id" binding:"required"` // 任务ID } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + c.JSON(400, resp.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) return } // 处理字符转id数组后去重 - ids := strings.Split(body.ID, ",") - uniqueIDs := parse.RemoveDuplicates(ids) - if len(uniqueIDs) <= 0 { - c.JSON(200, result.Err(nil)) - return + uniqueIDs := parse.RemoveDuplicatesToArray(body.ID, ",") + // 转换成int64数组类型 + ids := make([]int64, 0) + for _, v := range uniqueIDs { + ids = append(ids, parse.Number(v)) } errArr := []map[string]any{} - for _, id := range uniqueIDs { - task := s.traceTaskHlrService.SelectById(id) - if task.ID != id || task.ID == "" { + for _, id := range ids { + task := s.traceTaskHlrService.FindById(id) + if task.ID == 0 || task.ID != id { errArr = append(errArr, map[string]any{"id": id, "err": "task not found"}) continue } - task.UpdateBy = ctx.LoginUserToUserName(c) + task.UpdateBy = reqctx.LoginUserToUserName(c) err := s.traceTaskHlrService.Stop(task) if err != nil { errArr = append(errArr, map[string]any{"id": id, "err": err.Error()}) continue } } - c.JSON(200, result.OkData(errArr)) + c.JSON(200, resp.OkData(errArr)) } // 跟踪任务文件 // // POST /file func (s *TraceTaskHlrController) File(c *gin.Context) { - language := ctx.AcceptLanguage(c) var body struct { - ID string `json:"id" binding:"required"` // 任务ID + ID int64 `json:"id" binding:"required"` // 任务ID Dir string `json:"dir" binding:"required"` // 网元文件目录 } - if err := c.ShouldBindBodyWith(&body, binding.JSON); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + if err := c.ShouldBindBodyWithJSON(&body); err != nil { + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } - task := s.traceTaskHlrService.SelectById(body.ID) - if task.ID != body.ID || task.ID == "" { - c.JSON(200, result.CodeMsg(400, "task not found")) + task := s.traceTaskHlrService.FindById(body.ID) + if task.ID == 0 || task.ID != body.ID { + c.JSON(200, resp.CodeMsg(400, "task not found")) return } list, err := s.traceTaskHlrService.File(task.TraceId, body.Dir) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } - c.JSON(200, result.OkData(list)) + c.JSON(200, resp.OkData(list)) } // 跟踪任务文件从网元到本地 // // GET /filePull func (s *TraceTaskHlrController) FilePull(c *gin.Context) { - language := ctx.AcceptLanguage(c) + language := reqctx.AcceptLanguage(c) var querys struct { NeType string `form:"neType" binding:"required"` NeID string `form:"neId" binding:"required"` @@ -193,28 +193,29 @@ func (s *TraceTaskHlrController) FilePull(c *gin.Context) { DelTemp bool `form:"delTemp"` // 删除本地临时文件 } if err := c.ShouldBindQuery(&querys); err != nil { - c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400"))) + errMsgs := fmt.Sprintf("bind err: %s", resp.FormatBindError(err)) + c.JSON(422, resp.CodeMsg(40422, errMsgs)) return } // 查询网元获取IP neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID(querys.NeType, querys.NeID) if neInfo.NeId != querys.NeID || neInfo.IP == "" { - c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) + c.JSON(200, resp.ErrMsg(i18n.TKey(language, "app.common.noNEInfo"))) return } // 网元主机的SSH客户端 sshClient, err := s.neInfoService.NeRunSSHClient(neInfo.NeType, neInfo.NeId) if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } defer sshClient.Close() // 网元主机的SSH客户端进行文件传输 sftpClient, err := sshClient.NewClientSFTP() if err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } defer sftpClient.Close() @@ -227,7 +228,7 @@ func (s *TraceTaskHlrController) FilePull(c *gin.Context) { } // 复制到本地 if err = sftpClient.CopyFileRemoteToLocal(nePath, localFilePath); err != nil { - c.JSON(200, result.ErrMsg(err.Error())) + c.JSON(200, resp.ErrMsg(err.Error())) return } diff --git a/src/modules/trace/model/trace_data.go b/src/modules/trace/model/trace_data.go index 368d16e7..3669199d 100644 --- a/src/modules/trace/model/trace_data.go +++ b/src/modules/trace/model/trace_data.go @@ -2,19 +2,20 @@ package model // TraceData 跟踪_数据 trace_data type TraceData struct { - ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` - TaskId int64 `json:"taskId" gorm:"task_id"` // 任务ID - IMSI string `json:"imsi" gorm:"imsi"` - MSISDN string `json:"msisdn" gorm:"msisdn"` // 可能存在 - SrcAddr string `json:"srcAddr" gorm:"src_addr"` // 源地址带端口 - DstAddr string `json:"dstAddr" gorm:"dst_addr"` // 目标地址带端口 - IfType int64 `json:"ifType" gorm:"if_type"` // 接口类型,未分类 - MsgType int64 `json:"msgType" gorm:"msg_type"` - MsgDirect int64 `json:"msgDirect" gorm:"msg_direct"` - Length int64 `json:"length" gorm:"length"` // 去除头后的原始数据byte长度 - Timestamp int64 `json:"timestamp" gorm:"timestamp"` // 毫秒 - RawMsg string `json:"rawMsg" gorm:"raw_msg"` // 去除头后的原始数据byteBase64 - DecMsg string `json:"decMsg" gorm:"dec_msg"` // TCP内容消息 + ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` + TraceId int64 `json:"traceId" gorm:"column:trace_id"` // 跟踪任务ID + IMSI string `json:"imsi" gorm:"column:imsi"` // UE类型 IMSI + MSISDN string `json:"msisdn" gorm:"column:msisdn"` // UE类型 可能存在 + SrcAddr string `json:"srcAddr" gorm:"column:src_addr"` // 源地址 + DstAddr string `json:"dstAddr" gorm:"column:dst_addr"` // 目标地址 + IfType string `json:"ifType" gorm:"column:if_type"` // 接口类型,未分类 + MsgType int64 `json:"msgType" gorm:"column:msg_type"` // 消息类型,0-req, 1-rsp + MsgDirect int64 `json:"msgDirect" gorm:"column:msg_direct"` // 消息方向,0-recv,1-send + MsgNe string `json:"msgNe" gorm:"column:msg_ne"` // 消息网元 + MsgEvent string `json:"msgEvent" gorm:"column:msg_event"` // 消息事件,e.g: CreateContextReq + Length int64 `json:"length" gorm:"column:length"` // 原始数据byte长度 + Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 纳秒时间戳 + RawMsg string `json:"rawMsg" gorm:"column:raw_msg"` // 原始数据byteBase64 } // TableName 表名称 diff --git a/src/modules/trace/model/trace_task.go b/src/modules/trace/model/trace_task.go index 752d4f70..29f2ce20 100644 --- a/src/modules/trace/model/trace_task.go +++ b/src/modules/trace/model/trace_task.go @@ -2,27 +2,21 @@ package model // TraceTask 跟踪_任务 type TraceTask struct { - ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 跟踪任务ID - TraceId string `json:"traceId" gorm:"trace_id"` // 任务编号 - TraceType string `json:"traceType" gorm:"trace_type"` // 1-Interface,2-Device,3-User - StartTime int64 `json:"startTime" gorm:"start_time"` // 开始时间 毫秒 - EndTime int64 `json:"endTime" gorm:"end_time"` // 结束时间 毫秒 - Interfaces string `json:"interfaces" gorm:"interfaces"` // 接口跟踪必须 例如 N8,N10 - IMSI string `json:"imsi" gorm:"imsi"` // 用户跟踪必须 - MSISDN string `json:"msisdn" gorm:"msisdn"` // 用户跟踪可选 - UeIp string `json:"ueIp" gorm:"ue_ip"` // 设备跟踪必须 IP - SrcIp string `json:"srcIp" gorm:"src_ip"` // 源地址IP - DstIp string `json:"dstIp" gorm:"dst_ip"` // 目标地址IP - SignalPort int64 `json:"signalPort" gorm:"signal_port"` // 地址IP端口 - CreateBy string `json:"createBy" gorm:"create_by"` // 创建者 - CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间 - UpdateBy string `json:"updateBy" gorm:"update_by"` // 更新者 - UpdateTime int64 `json:"updateTime" gorm:"update_time"` // 更新时间 - Remark string `json:"remark" gorm:"remark"` // 备注 - NeType string `json:"neType" gorm:"ne_type"` // 网元类型 - NeId string `json:"neId" gorm:"ne_id"` // 网元ID - NotifyUrl string `json:"notifyUrl" gorm:"notify_url"` // 信息数据通知回调地址UDP 例如udp:192.168.5.58:29500 - FetchMsg string `json:"fetchMsg" gorm:"fetch_msg"` // 任务下发请求响应消息 + ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` // 跟踪任务ID + TraceId string `json:"traceId" gorm:"column:trace_id"` // 任务编号 + TraceType string `json:"traceType" gorm:"column:trace_type" binding:"required"` // 1-Interface,2-Device,3-UE + StartTime int64 `json:"startTime" gorm:"column:start_time"` // 开始时间 毫秒 + EndTime int64 `json:"endTime" gorm:"column:end_time" binding:"required"` // 结束时间 毫秒 + Interfaces string `json:"interfaces" gorm:"column:interfaces"` // 接口跟踪必须 例如 N8,N10 + IMSI string `json:"imsi" gorm:"column:imsi"` // 用户跟踪必须 + MSISDN string `json:"msisdn" gorm:"column:msisdn"` // 用户跟踪可选 + SrcIp string `json:"srcIp" gorm:"column:src_ip"` // 源地址IP + DstIp string `json:"dstIp" gorm:"column:dst_ip"` // 目标地址IP + CreateBy string `json:"createBy" gorm:"column:create_by"` // 创建者 + CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间 + Remark string `json:"remark" gorm:"column:remark"` // 备注 + NeList string `json:"neList" gorm:"column:ne_list" binding:"required"` // 网元列表 neType_neId 例如 UDM_001,AMF_001 + NotifyUrl string `json:"notifyUrl" gorm:"column:notify_url"` // 信息数据通知回调地址UDP 例如udp:192.168.5.58:33033 } // TableName 表名称 diff --git a/src/modules/trace/model/trace_task_hlr.go b/src/modules/trace/model/trace_task_hlr.go index 2d306c4d..9658a017 100644 --- a/src/modules/trace/model/trace_task_hlr.go +++ b/src/modules/trace/model/trace_task_hlr.go @@ -2,19 +2,19 @@ package model // TraceTaskHlr 跟踪_任务给HRL网元 trace_task_hlr type TraceTaskHlr struct { - ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"` - TraceId string `json:"traceId" gorm:"trace_id"` // 任务编号 - IMSI string `json:"imsi" gorm:"imsi"` // IMSI - MSISDN string `json:"msisdn" gorm:"msisdn"` // MSISDN - StartTime int64 `json:"startTime" gorm:"start_time"` // 开始时间 - EndTime int64 `json:"endTime" gorm:"end_time"` // 结束时间 - Status string `json:"status" gorm:"status"` // 任务状态(0停止 1进行) - Msg string `json:"msg" gorm:"msg"` // 任务信息 - Remark string `json:"remark" gorm:"remark"` // 备注说明 - CreateBy string `json:"createBy" gorm:"create_by"` // 创建者 - CreateTime int64 `json:"createTime" gorm:"create_time"` // 创建时间 - UpdateBy string `json:"updateBy" gorm:"update_by"` // 更新者 - UpdateTime int64 `json:"updateTime" gorm:"update_time"` // 更新时间 + ID int64 `json:"id" gorm:"column:id;primaryKey;autoIncrement"` + TraceId string `json:"traceId" gorm:"column:trace_id"` // 任务编号 + IMSI string `json:"imsi" gorm:"column:imsi"` // IMSI + MSISDN string `json:"msisdn" gorm:"column:msisdn"` // MSISDN + StartTime int64 `json:"startTime" gorm:"column:start_time"` // 开始时间 + EndTime int64 `json:"endTime" gorm:"column:end_time"` // 结束时间 + Status string `json:"status" gorm:"column:status"` // 任务状态(0停止 1进行) + Msg string `json:"msg" gorm:"column:msg"` // 任务信息 + Remark string `json:"remark" gorm:"column:remark"` // 备注说明 + CreateBy string `json:"createBy" gorm:"column:create_by"` // 创建者 + CreateTime int64 `json:"createTime" gorm:"column:create_time"` // 创建时间 + UpdateBy string `json:"updateBy" gorm:"column:update_by"` // 更新者 + UpdateTime int64 `json:"updateTime" gorm:"column:update_time"` // 更新时间 } // TableName 表名称 diff --git a/src/modules/trace/model/trace_task_udp_msg.go b/src/modules/trace/model/trace_task_udp_msg.go new file mode 100644 index 00000000..99019c77 --- /dev/null +++ b/src/modules/trace/model/trace_task_udp_msg.go @@ -0,0 +1,42 @@ +package model + +type TraceDefType = int64 + +const ( + MSG_TYPE_REQ TraceDefType = 0 + MSG_TYPE_RSP TraceDefType = 1 + MSG_DIRECT_RECV TraceDefType = 0 + MSG_DIRECT_SEND TraceDefType = 1 + // NF_TYPE_AMF = "AMF" + // NF_TYPE_SMF = "SMF" + // NF_TYPE_AUSF = "AUSF" + // NF_TYPE_UDM = "UDM" + // NF_TYPE_PCF = "PCF" +) + +// TraceMsg 跟踪_消息 +type TraceMsg struct { + TraceId int + MsgType TraceDefType //0-req, 1-rsp + MsgDirect TraceDefType //0-recv,1-send + NfName string + MsgEvent string //e.g: CreateContextReq + IMSI string + IfType string //interface type: N2,N8... + SrcIpStr string + DstIpStr string + Timestamp int64 +} + +// TraceReq 跟踪_请求 +type TraceReq struct { + TraceId int64 `json:"traceId"` // Unique identifier for trace operations:delete... + TraceType string `json:"traceType"` // Type of trace: Interface;UE; Device + StartTime string `json:"startTime"` // Start time of the trace: e.g., "2025-04-12 11:24:59" + EndTime string `json:"endTime"` // End time of the trace: e.g., "2025-04-12 14:24:59" + Interfaces []string `json:"interfaces,omitempty"` // List of interfaces: e.g., ["N8", "N10", "N1/N2"] + IMSI string `json:"imsi,omitempty"` // International Mobile Subscriber Identity + SrcIp string `json:"srcIp,omitempty"` // Source IP address (used for device-level filtering) + DstIp string `json:"dstIp,omitempty"` // Destination IP address (used for device-level filtering) + NotifyUrl string `json:"notifyUrl,omitempty"` // Notification URL: e.g., "udp:192.168.5.58:33033" +} diff --git a/src/modules/trace/packet_task/packet.go b/src/modules/trace/packet_task/packet.go deleted file mode 100644 index 5df723b3..00000000 --- a/src/modules/trace/packet_task/packet.go +++ /dev/null @@ -1,245 +0,0 @@ -package packet_task - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - "sync" - "time" - - "be.ems/src/framework/logger" - wsService "be.ems/src/modules/ws/service" - "github.com/gopacket/gopacket" - "github.com/gopacket/gopacket/layers" - "github.com/gopacket/gopacket/pcap" - "github.com/gopacket/gopacket/pcapgo" -) - -// 捕获任务 -var taskMap sync.Map - -// task 任务信息 -type task struct { - TaskNo string // 任务编号 - Handle *pcap.Handle // 捕获句柄 - File *os.File // 捕获信息输出文件句柄 - Writer *pcapgo.Writer // 捕获信息输出句柄 - Filter string // 过滤表达式 - Ticker *time.Ticker // 任务失效定时器 -} - -// NetworkDevices 获取网卡设备信息 -func NetworkDevices() ([]pcap.Interface, error) { - devices, err := pcap.FindAllDevs() - if err != nil { - logger.Errorf("interfaces find all devices err: %s", err.Error()) - return nil, err - } - return devices, nil -} - -// verifyDevice 检查网卡设备是否存在 -func verifyDevice(str string) (string, bool) { - devices, err := pcap.FindAllDevs() - if err != nil { - logger.Errorf("interfaces find all devices err: %s", err.Error()) - return "", false - } - for _, device := range devices { - if len(device.Addresses) == 0 { - continue - } - if device.Name == str { - return device.Name, true - } - for _, address := range device.Addresses { - if address.IP.String() == str { - return device.Name, true - } - } - } - return "", false -} - -// outputPCAP 输出 pcap 文件 -// 新文件时需要 snaplen 最大长度 linktype 链路类型 -func outputPCAP(snaplen uint32, linktype layers.LinkType, outputFile string) (*os.File, *pcapgo.Writer, error) { - var err error - var f *os.File - if err := os.MkdirAll(filepath.Dir(outputFile), 0775); err != nil { - return nil, nil, err - } - - // 检查文件是否存在 - if _, err = os.Stat(outputFile); os.IsNotExist(err) { - f, err = os.Create(outputFile) - if err != nil { - return nil, nil, err - } - w := pcapgo.NewWriter(f) - w.WriteFileHeader(snaplen, linktype) // new file, must do this. - return f, w, nil - } - - f, err = os.OpenFile(outputFile, os.O_APPEND, 0700) - if err != nil { - return nil, nil, err - } - w := pcapgo.NewWriter(f) - return f, w, nil -} - -// capturePacketSource 捕获数据 -func capturePacketSource(taskInfo *task) { - // capture packets - packetSource := gopacket.NewPacketSource(taskInfo.Handle, taskInfo.Handle.LinkType()) - packetSource.Lazy = false - packetSource.NoCopy = true - packetSource.DecodeStreamsAsDatagrams = true - - // 协程停止后关闭句柄并移除任务信息 - defer func() { - taskInfo.Ticker.Stop() - taskInfo.Handle.Close() - if taskInfo.File != nil { - taskInfo.File.Close() - } - taskMap.Delete(taskInfo.TaskNo) - }() - - frameNumber := 0 // 帧编号 - frameTime := 0.000000 // 时间 - var startTimestamp time.Time // 开始时间 - - for { - select { - case <-taskInfo.Ticker.C: - return - case packet := <-packetSource.Packets(): - if packet == nil { - continue - } - // if packet.Metadata().Timestamp.Before(time.Now()) { - // continue - // } - if taskInfo.Writer != nil { - taskInfo.Writer.WritePacket(packet.Metadata().CaptureInfo, packet.Data()) - } - fmt.Println("---------- packet.Layers() ", len(packet.Layers())) - frameNumber++ // 帧编号 - currentTimestamp := packet.Metadata().Timestamp - if !startTimestamp.IsZero() { - // 计算时间差转换为秒 - frameTime = currentTimestamp.Sub(startTimestamp).Seconds() - } else { - startTimestamp = currentTimestamp - } - - // 数据 - frameMeta := parsePacketFrame(frameNumber, frameTime, packet) - - // 推送到ws订阅组 - wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%s", wsService.GROUP_TRACE_PACKET, taskInfo.TaskNo), frameMeta) - } - } -} - -// LiveStart 开始捕获数据 -func LiveStart(taskNo, deviceName, filterBPF string, outputFile bool) (string, error) { - if _, ok := taskMap.Load(taskNo); ok { - return "", fmt.Errorf("task no. %s already exist", taskNo) - } - - // Verify the specified network interface exists - device, deviceOk := verifyDevice(deviceName) - if !deviceOk { - return "", fmt.Errorf("network device not exist: %s", deviceName) - } - - snapshotLength := 262144 - - // open device - handle, err := pcap.OpenLive(device, int32(snapshotLength), true, pcap.BlockForever) - if err != nil { - logger.Errorf("open live err: %s", err.Error()) - if strings.Contains(err.Error(), "operation not permitted") { - return "", fmt.Errorf("you don't have permission to capture on that/these device(s)") - } - return "", err - } - - // write a new file - var w *pcapgo.Writer - var f *os.File - if outputFile { - // 网管本地路径 - localFilePath := fmt.Sprintf("/tmp/omc/packet/%s.pcap", taskNo) - if runtime.GOOS == "windows" { - localFilePath = fmt.Sprintf("C:%s", localFilePath) - } - f, w, err = outputPCAP(uint32(snapshotLength), handle.LinkType(), localFilePath) - if err != nil { - return "", err - } - } - - // set filter - if filterBPF != "" { - if err = handle.SetBPFFilter(filterBPF); err != nil { - logger.Errorf("packet BPF Filter %s => %s", filterBPF, err.Error()) - filterBPF = "" - } - } - - // save tasks - taskInfo := &task{ - TaskNo: taskNo, - Handle: handle, - File: f, - Writer: w, - Filter: filterBPF, - Ticker: time.NewTicker(time.Second * 120), - } - - go capturePacketSource(taskInfo) - taskMap.Store(taskNo, taskInfo) - return fmt.Sprintf("task no. %s initiated", taskNo), nil -} - -// LiveFilter 捕获过滤 -func LiveFilter(taskNo, expr string) error { - info, ok := taskMap.Load(taskNo) - if !ok { - return fmt.Errorf("task no. %s not exist", taskNo) - } - task := info.(*task) - task.Filter = expr - err := task.Handle.SetBPFFilter(expr) - if err != nil { - logger.Errorf("packet BPF Filter %s => %s", expr, err.Error()) - return fmt.Errorf("can't parse filter expression") - } - return nil -} - -// LiveTimeout 更新捕获失效时间 -func LiveTimeout(taskNo string, seconds int) error { - info, ok := taskMap.Load(taskNo) - if !ok { - return fmt.Errorf("task no. %s not exist", taskNo) - } - info.(*task).Ticker.Reset(time.Duration(seconds) * time.Second) - return nil -} - -// LiveStop 停止捕获数据 -func LiveStop(taskNo string) error { - info, ok := taskMap.Load(taskNo) - if !ok { - return fmt.Errorf("task no. %s not exist", taskNo) - } - info.(*task).Ticker.Reset(time.Millisecond) - return nil -} diff --git a/src/modules/trace/packet_task/packet_frame.go b/src/modules/trace/packet_task/packet_frame.go deleted file mode 100644 index d060149d..00000000 --- a/src/modules/trace/packet_task/packet_frame.go +++ /dev/null @@ -1,843 +0,0 @@ -package packet_task - -import ( - "encoding/base64" - "fmt" - "strings" - - "be.ems/src/framework/logger" - "github.com/gopacket/gopacket" - "github.com/gopacket/gopacket/layers" -) - -// FrameMeta 数据帧元信息 -type FrameMeta struct { - Number int `json:"number"` - Comments bool `json:"comments"` - Ignored bool `json:"ignored"` - Marked bool `json:"marked"` - Bg int `json:"bg"` // 背景色 数值转字符串16进制 15007687->e4ffc7 - Fg int `json:"fg"` // 前景色 文字 - Columns [7]string `json:"columns"` // 长度对应字段 ['No.', 'Time', 'Source', 'Destination', 'Protocol', 'Length', 'Info'] - Frame Frame `json:"frame"` -} - -// Frame 数据帧信息 -type Frame struct { - Number int `json:"number"` - Comments []string `json:"comments"` - DataSource []map[string]string `json:"data_sources"` - Tree []ProtoTree `json:"tree"` - Follow [][]string `json:"follow"` -} - -// ProtoTree 数据帧协议树 -type ProtoTree struct { - Label string `json:"label"` // 显示的文本 - Filter string `json:"filter"` // 过滤条件 - Severity string `json:"severity"` - Type string `json:"type"` - URL string `json:"url"` - Fnum int `json:"fnum"` - Start int `json:"start"` // 开始位置 - Length int `json:"length"` // 长度 - DataSourceIdx int `json:"data_source_idx"` - Tree []ProtoTree `json:"tree"` // 子节点 -} - -// parsePacketFrame 解析数据包帧信息 -// frameNumber 帧编号 i++ -// frameTime 时间秒 0.000000 -func parsePacketFrame(frameNumber int, frameTime float64, packet gopacket.Packet) FrameMeta { - frameSrcHost := "" // 源主机IP - frameDstHost := "" // 目的主机IP - frameProtocol := "" // 协议 - frameLength := fmt.Sprintf("%d", packet.Metadata().Length) // 长度 - frameInfo := "" // 信息 - fg, bg := colorRuleFB(packet) // 背景色 数值转字符串16进制 15007687->e4ffc7 - - frame := Frame{ - Number: frameNumber, - Comments: []string{}, - DataSource: []map[string]string{ - { - "name": fmt.Sprintf("Frame (%d bytes)", packet.Metadata().Length), - "data": base64.StdEncoding.EncodeToString(packet.Data()), - }, - }, - Tree: []ProtoTree{}, // 各层的数据 - Follow: [][]string{}, // {"TCP", "tcp.stream eq 0"} - } - - // 连接层 - // fmt.Println(packet.LinkLayer()) - if linkLayer := packet.LinkLayer(); linkLayer != nil { - linkTree := linkLayerTree(linkLayer) - frame.Tree = append(frame.Tree, linkTree) - } - - // 网络层 - // fmt.Println(packet.NetworkLayer()) - if networkLayer := packet.NetworkLayer(); networkLayer != nil { - networkTree := networkLayerTree(networkLayer) - frame.Tree = append(frame.Tree, networkTree) - - src, dst := networkLayer.NetworkFlow().Endpoints() - frameSrcHost = src.String() - frameDstHost = dst.String() - if frameDstHost == "ff:ff:ff:ff" { - frameDstHost = "Broadcast" - } - } - - // 传输层 - // fmt.Println(packet.TransportLayer()) - if transportLayer := packet.TransportLayer(); transportLayer != nil { - info, transportTree := transportLayerTree(transportLayer) - frame.Tree = append(frame.Tree, transportTree) - - frameProtocol = transportLayer.LayerType().String() - frameInfo += info - frame.Follow = append(frame.Follow, []string{ - frameProtocol, - fmt.Sprintf("%s.stream eq 0", strings.ToLower(frameProtocol)), - }) - } - - // 应用层 - // fmt.Println(packet.ApplicationLayer()) - if applicationLayer := packet.ApplicationLayer(); applicationLayer != nil { - applicationTree := applicationLayerTree(applicationLayer) - frame.Tree = append(frame.Tree, applicationTree) - } - - return FrameMeta{ - Number: frameNumber, - Comments: false, - Ignored: false, - Marked: false, - Bg: fg, - Fg: bg, - Columns: [7]string{ - fmt.Sprintf("%d", frameNumber), - fmt.Sprintf("%.6f", frameTime), // 格式化为 0.000000 - frameSrcHost, - frameDstHost, - frameProtocol, - frameLength, - frameInfo, - }, - Frame: frame, - } -} - -// linkLayerTree 连接层 -func linkLayerTree(linkLayer gopacket.LinkLayer) ProtoTree { - var protoTree ProtoTree - switch layer := linkLayer.(type) { - case *layers.Ethernet: // 最常见的链路层协议,用于局域网(LAN)中。 - srcMAC := layer.SrcMAC - dstMAC := layer.DstMAC - ethernetLayerLen := len(layer.Contents) - protoTree = ProtoTree{ - Label: fmt.Sprintf("%s II, Src: %s, Dst: %s", layer.LayerType(), srcMAC, dstMAC), - Filter: "eth", - Start: 0, - Length: ethernetLayerLen, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("Destination: %s", dstMAC.String()), - Filter: fmt.Sprintf("eth.dst == %s", dstMAC.String()), - Start: 0, - Length: ethernetLayerLen, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("Address: %s", dstMAC.String()), - Filter: fmt.Sprintf("eth.addr == %s", dstMAC.String()), - Start: 0, - Length: 6, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: ".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)", - Filter: "eth.dst.lg == 0", - Start: 0, - Length: 3, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: ".... ...0 .... .... .... .... = IG bit: Individual address (unicast)", - Filter: "eth.dst.ig == 0", - Start: 0, - Length: 3, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - }, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Source: %s", srcMAC.String()), - Filter: fmt.Sprintf("eth.src == %s", srcMAC.String()), - Start: ethernetLayerLen, - Length: ethernetLayerLen, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("Address: %s", srcMAC.String()), - Filter: fmt.Sprintf("eth.addr == %s", dstMAC.String()), - Start: ethernetLayerLen, - Length: ethernetLayerLen, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: ".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)", - Filter: "eth.src.lg == 0", - Start: len(srcMAC), - Length: len(srcMAC) / 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: ".... ...0 .... .... .... .... = IG bit: Individual address (unicast)", - Filter: "eth.src.ig == 0", - Start: len(srcMAC), - Length: len(srcMAC) / 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - }, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: "Type: IPv4 (0x0800)", - Filter: "eth.type == 0x0800", - Start: len(dstMAC) + len(srcMAC), - Length: len(layer.LayerContents()) - (len(dstMAC) + len(srcMAC)), - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - }, - Severity: "", - Type: "proto", - Fnum: 1052, - URL: "", - } - case *layers.PPP: // 点对点协议,通常用于拨号连接。 - protoTree = ProtoTree{ - Label: fmt.Sprintf("%s ", layer.LayerType()), - Filter: "ppp", - Start: 0, - Length: len(layer.LayerContents()), - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "proto", - Fnum: 1052, - URL: "", - } - } - return protoTree -} - -// networkLayerTree 网络层 -func networkLayerTree(networkLayer gopacket.NetworkLayer) ProtoTree { - var protoTree ProtoTree - switch layer := networkLayer.(type) { - case *layers.IPv4: // 第四版因特网协议,广泛使用。 - // 偏移量取连接层的长度Length - linkLayerLen := 14 - networkLayerLen := len(layer.Contents) - - version := layer.Version - length := layer.Length - srcIP := layer.SrcIP - dstIP := layer.DstIP - ihl := layer.IHL - headerLength := ihl * 4 // 提取头部长度 - tos := layer.TOS - dscp, ecn := networkDSCPAndECN(tos) - identification := layer.Id - flags := layer.Flags // 提取标志位 - // 生成标志描述 - flagsDesc := networkFlagsDesc(flags) - rb, rbDesc := networkFlagsEvil(flags) - df, dfDesc := networkFlagsDF(flags) - mf, mfDesc := networkFlagsMF(flags) - fragOffset := layer.FragOffset - fragOffsetDesc := networkOffset(fragOffset) - ttl := layer.TTL - proto := layer.Protocol - checksum := layer.Checksum - - protoTree = ProtoTree{ - Label: fmt.Sprintf("Internet Protocol Version %d, Src: %s, Dst: %s", version, srcIP, dstIP), - Filter: "ip", - Start: linkLayerLen, - Length: networkLayerLen, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("%04b .... = Version: %d", version, version), - Filter: fmt.Sprintf("ip.version == %d", version), - Start: linkLayerLen, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf(".... 0101 = Header Length: %d bytes (%d)", headerLength, ihl), - Filter: fmt.Sprintf("ip.hdr_len == %d", headerLength), - Start: linkLayerLen, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Differentiated Services Field: 0x%02x (DSCP: %s, ECN: %s)", tos, dscp, ecn), - Filter: fmt.Sprintf("ip.dsfield == 0x%02x", tos), - Start: linkLayerLen + 1, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("0000 00.. = Differentiated Services Codepoint: %s (%d)", dscp, tos), - Filter: fmt.Sprintf("ip.dsfield.dscp == %d", tos>>2), - Start: linkLayerLen + 1, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: fmt.Sprintf(".... ..00 = Explicit Congestion Notification: %s Capable Transport (%d)", ecn, tos), - Filter: fmt.Sprintf("ip.dsfield.ecn == %d", tos&0x03), - Start: linkLayerLen + 1, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - }, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Total Length: %d", length), - Filter: fmt.Sprintf("ip.len == %d", length), - Start: linkLayerLen + 2, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Identification: 0x%X (%d)", identification, identification), - Filter: fmt.Sprintf("ip.id == 0x%X", identification), - Start: linkLayerLen + 4, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("%03b. .... = Flags: %s", flags, flagsDesc), - Filter: fmt.Sprintf("ip.flags == 0x%X", flags), - Start: linkLayerLen + 6, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("0... .... = Reserved bit: %s", rbDesc), - Filter: fmt.Sprintf("ip.flags.rb == %d", rb), - Start: linkLayerLen + 6, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: fmt.Sprintf(".1.. .... = Don't fragment: %s", dfDesc), - Filter: fmt.Sprintf("ip.flags.df == %d", df), - Start: linkLayerLen + 6, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: fmt.Sprintf("..0. .... = More fragments: %s", mfDesc), - Filter: fmt.Sprintf("ip.flags.mf == %d", mf), - Start: linkLayerLen + 6, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - }, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("%s = Fragment Offset: %d", fragOffsetDesc, fragOffset), - Filter: fmt.Sprintf("ip.frag_offset == %d", fragOffset), - Start: linkLayerLen + 6, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Time to Live: %d", ttl), - Filter: fmt.Sprintf("ip.ttl == %d", ttl), - Start: linkLayerLen + 8, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Protocol: TCP (%d)", proto), - Filter: fmt.Sprintf("ip.proto == %d", proto), - Start: linkLayerLen + 9, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Header Checksum: 0x%x [validation disabled]", checksum), - Filter: fmt.Sprintf("ip.checksum == 0x%x", checksum), - Start: linkLayerLen + 10, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: "Header checksum status: Unverified", - Filter: "ip.checksum.status == \"Unverified\"", - Start: 0, - Length: 0, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Source Address: %s", srcIP), - Filter: fmt.Sprintf("ip.src == %s", srcIP), - Start: linkLayerLen + 12, - Length: 4, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Destination Address: %s", dstIP), - Filter: fmt.Sprintf("ip.dst == %s", dstIP), - Start: linkLayerLen + 16, - Length: 4, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - }, - Severity: "", - Type: "proto", - Fnum: 1052, - URL: "", - } - - logger.Infof("-> (tos 0x%x, ttl %d, id %d, offset %d, flags [%s], proto %s (%d), length %d)\n", tos, ttl, identification, fragOffset, flags, proto, proto, len(layer.Contents)+len(layer.Payload)) - case *layers.IPv6: // 第六版因特网协议,逐渐取代 IPv4。 - logger.Infof("-> (flowlabel 0x%x, hlim %d, next-header %s (%d), payload length: %d)\n", layer.FlowLabel, layer.HopLimit, layer.NextHeader, layer.NextHeader, len(layer.Payload)) - } - return protoTree -} - -// transportLayerTree 传输层 -func transportLayerTree(transportLayer gopacket.TransportLayer) (string, ProtoTree) { - var info string - var tree ProtoTree - switch layer := transportLayer.(type) { - case *layers.TCP: // 传输控制协议,提供可靠的数据传输。 - // 偏移量取连接层加网络层的长度Length - linkLayerAndNetworkLayerLen := 14 + 20 - transportLayerLen := len(layer.Contents) - payloadrLen := len(layer.Payload) - seq := layer.Seq - ack := layer.Ack - srcPort := layer.SrcPort - dstPort := layer.DstPort - dataOffset := layer.DataOffset - hdrLen := dataOffset * 4 - flags, flagsDesc := transportFlagsDesc(layer) - flagsACK, flagsACKDesc := transportFlagsStatus(layer.ACK) - flagsPSH, flagsPSHDesc := transportFlagsStatus(layer.PSH) - window := layer.Window - checksum := layer.Checksum - urgent := layer.Urgent - optionsLen, optionsDesc := transportOptions(layer.Options) - payloadStr := bytesToHexString(layer.Payload) - - tree = ProtoTree{ - Label: fmt.Sprintf("Transmission Control Protocol, Src Port: %s, Dst Port: %s, Seq: %d, Ack: %d, Len: %d", srcPort, dstPort, seq, ack, payloadrLen), - Filter: "tcp", - Start: linkLayerAndNetworkLayerLen, - Length: transportLayerLen, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf("Source Port: %s", srcPort), - Filter: fmt.Sprintf("tcp.srcport == %d", srcPort), - Start: linkLayerAndNetworkLayerLen, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Destination Port: %s", dstPort), - Filter: fmt.Sprintf("tcp.dstport == %d", dstPort), - Start: linkLayerAndNetworkLayerLen + 2, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("TCP Segment Len: %d", payloadrLen), - Filter: fmt.Sprintf("tcp.len == %d", payloadrLen), - Start: linkLayerAndNetworkLayerLen + 12, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Sequence Number: %d (relative sequence number)", seq), - Filter: fmt.Sprintf("tcp.seq == %d", seq), - Start: linkLayerAndNetworkLayerLen + 4, - Length: 4, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Acknowledgment Number: %d (relative ack number)", ack), - Filter: fmt.Sprintf("tcp.ack == %d", ack), - Start: linkLayerAndNetworkLayerLen + 8, - Length: 4, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("%04b .... = Header Length: %d bytes (%d)", dataOffset, hdrLen, dataOffset), - Filter: fmt.Sprintf("tcp.hdr_len == %d", hdrLen), - Start: linkLayerAndNetworkLayerLen + 12, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Flags: 0x%03X (%s)", flags, flagsDesc), - Filter: fmt.Sprintf("ip.frag_offset == 0x%03X", flags), - Start: linkLayerAndNetworkLayerLen + 12, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{ - { - Label: fmt.Sprintf(".... ...%d .... = Acknowledgment: %s", flagsACK, flagsACKDesc), - Filter: fmt.Sprintf("tcp.flags.ack == %d", flagsACK), - Start: linkLayerAndNetworkLayerLen + 13, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - { - Label: fmt.Sprintf(".... .... %d... = Push: %s", flagsPSH, flagsPSHDesc), - Filter: fmt.Sprintf("tcp.flags.push == %d", flagsPSH), - Start: linkLayerAndNetworkLayerLen + 13, - Length: 1, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 926233912, - URL: "", - }, - }, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Window: %d", window), - Filter: fmt.Sprintf("tcp.window_size_value == %d", window), - Start: linkLayerAndNetworkLayerLen + 14, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Calculated window size: %d", window), - Filter: fmt.Sprintf("tcp.window_size == %d", window), - Start: linkLayerAndNetworkLayerLen + 14, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Checksum: 0x%04x [unverified]", checksum), - Filter: fmt.Sprintf("tcp.checksum == 0x%04x", checksum), - Start: linkLayerAndNetworkLayerLen + 16, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: "Checksum Status: Unverified", - Filter: "tcp.checksum.status == \"Unverified\"", - Start: 0, - Length: 0, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Urgent Pointer: %d", urgent), - Filter: fmt.Sprintf("tcp.urgent_pointer == %d", urgent), - Start: linkLayerAndNetworkLayerLen + 18, - Length: 2, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("Options: (%d bytes), %s", optionsLen, optionsDesc), - Filter: fmt.Sprintf("tcp.options == %d", optionsLen), - Start: linkLayerAndNetworkLayerLen + 20, - Length: int(optionsLen), - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - { - Label: fmt.Sprintf("TCP payload (%d bytes)", payloadrLen), - Filter: fmt.Sprintf("tcp.payload == %s", payloadStr), - Start: linkLayerAndNetworkLayerLen + 32, - Length: payloadrLen, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "", - Fnum: 0, - URL: "", - }, - }, - Severity: "", - Type: "proto", - Fnum: 1052, - URL: "", - } - - info = fmt.Sprintf("%v -> %v [%s], Seq=%d Ack=%d Win=%d Len=1%d ", srcPort, dstPort, flagsDesc, seq, ack, window, payloadrLen) - logger.Infof("-> TCP, %s", info) - case *layers.UDP: // 用户数据报协议,提供无连接的快速数据传输。 - logger.Infof("-> UDP, length %d", len(layer.Payload)) - case *layers.UDPLite: - logger.Infof("-> UDPLite, length %d", len(layer.Payload)) - case *layers.SCTP: // 流控制传输协议,支持多流和多宿主机。 - logger.Infof("-> SCTP, length %d", len(layer.Payload)) - } - return info, tree -} - -// applicationLayerTree 应用层 -func applicationLayerTree(applicationLayer gopacket.ApplicationLayer) ProtoTree { - var protoTree ProtoTree - switch layer := applicationLayer.(type) { - case *layers.DNS: - logger.Infof("-> DNS, %d", layer.ID) - case *layers.SIP: - logger.Infof("-> SIP, %s", layer.RequestURI) - default: - logger.Infof("-> %s, length %d", layer.LayerType(), layer.Payload()) - if applicationHTTP(layer.LayerContents()) { - logger.Infof("-> HTTP, %s", layer.LayerContents()) - // 偏移量取连接层加网络层加协议层的长度Length - linkLayerAndNetworkLayerAndTransportLayerLen := 14 + 20 + 32 - length := len(layer.LayerContents()) - - protoTree = ProtoTree{ - Label: "Hypertext Transfer Protocol", - Filter: "http", - Start: linkLayerAndNetworkLayerAndTransportLayerLen, - Length: length, - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "Chat", - Fnum: 1052, - URL: "", - } - - result := applicationHTTPProcess(string(layer.LayerContents())) - for _, v := range result { - protoTree.Tree = append(protoTree.Tree, ProtoTree{ - Label: v["label"].(string), - Filter: fmt.Sprintf("http.%s == %s", v["key"].(string), v["value"].(string)), - Start: linkLayerAndNetworkLayerAndTransportLayerLen + v["length"].(int), - Length: v["length"].(int), - DataSourceIdx: 0, - Tree: []ProtoTree{}, - Severity: "", - Type: "Chat", - Fnum: 1052, - URL: "", - }) - } - - } - } - return protoTree -} diff --git a/src/modules/trace/packet_task/packet_frame_util.go b/src/modules/trace/packet_task/packet_frame_util.go deleted file mode 100644 index 77d86a9f..00000000 --- a/src/modules/trace/packet_task/packet_frame_util.go +++ /dev/null @@ -1,346 +0,0 @@ -package packet_task - -import ( - "encoding/binary" - "fmt" - "net" - "strings" - - "github.com/gopacket/gopacket" - "github.com/gopacket/gopacket/layers" -) - -// networkDSCPAndECN 提取 TOS 字段并获取 DSCP 和 ECN -func networkDSCPAndECN(tos uint8) (string, string) { - // 提取 DSCP 和 ECN - dscp := tos >> 2 // 高 6 位 - ecn := tos & 0x03 // 低 2 位 - - // 定义 DSCP 映射 - dscpMapping := map[uint8]string{ - 0: "Default CS0", // Default Forwarding (DF) - 8: "CS1", // Class Selector 1 - 16: "CS2", // Class Selector 2 - 24: "CS3", // Class Selector 3 - 32: "CS4", // Class Selector 4 - 40: "CS5", // Class Selector 5 - 48: "CS6", // Class Selector 6 - 56: "CS7", // Class Selector 7 - } - - // 定义 ECN 映射 - ecnMapping := map[uint8]string{ - 0: "Not-ECT", // Not ECN-Capable Transport - 1: "ECT(1)", // ECN-Capable Transport - 2: "ECT(0)", // ECN-Capable Transport - 3: "CE", // Congestion Experienced - } - - // 返回可读的 DSCP 和 ECN 字符串 - return dscpMapping[dscp], ecnMapping[ecn] -} - -// networkFlagsDesc 生成标志描述 -func networkFlagsDesc(flags layers.IPv4Flag) string { - f := fmt.Sprintf("Flags: 0x%X", flags) - if flags&layers.IPv4DontFragment != 0 { - f += ", Don't fragment" - } - if flags&layers.IPv4MoreFragments != 0 { - f += ", More fragments" - } - return f -} - -// networkFlagsEvil 生成标志描述 Evil -func networkFlagsEvil(flags layers.IPv4Flag) (int, string) { - if flags&layers.IPv4EvilBit != 0 { - return 1, "Set" - } - return 0, "Not set" -} - -// networkFlagsDF 生成标志描述 DF -func networkFlagsDF(flags layers.IPv4Flag) (int, string) { - if flags&layers.IPv4DontFragment != 0 { - return 1, " Set" - } - return 0, "Not set" -} - -// networkFlagsMF 生成标志描述 MF -func networkFlagsMF(flags layers.IPv4Flag) (int, string) { - if flags&layers.IPv4MoreFragments != 0 { - return 1, " Set" - } - return 0, "Not set" -} - -// networkOffset 二进制Fragment Offset表示 ...0 0000 0000 0000 -func networkOffset(offset uint16) string { - return fmt.Sprintf("...0 %04b %04b %04b %04b", - (offset>>12)&0xF, // 高四位 - (offset>>8)&0xF, // 次四位 - (offset>>4)&0xF, // 再次四位 - offset&0xF, // 低四位 - ) -} - -// transportFlagsDesc 生成标志描述 -func transportFlagsDesc(layer *layers.TCP) (byte, string) { - var flags byte - var flagsDesc []string - if layer.FIN { - flags |= 1 << 0 // 0b00000001 - flagsDesc = append(flagsDesc, "FIN") - } - if layer.SYN { - flags |= 1 << 1 // 0b00000010 - flagsDesc = append(flagsDesc, "SYN") - } - if layer.RST { - flags |= 1 << 2 // 0b00000100 - flagsDesc = append(flagsDesc, "RST") - } - if layer.PSH { - flags |= 1 << 3 // 0b00001000 - flagsDesc = append(flagsDesc, "PSH") - } - if layer.ACK { - flags |= 1 << 4 // 0b00010000 - flagsDesc = append(flagsDesc, "ACK") - } - if layer.URG { - flags |= 1 << 5 // 0b00100000 - flagsDesc = append(flagsDesc, "URG") - } - if layer.ECE { - flags |= 1 << 6 // 0b01000000 - flagsDesc = append(flagsDesc, "ECE") - } - if layer.CWR { - flags |= 1 << 7 // 0b10000000 - flagsDesc = append(flagsDesc, "CWR") - } - if layer.NS { - flagsDesc = append(flagsDesc, "NS") - } - - return flags, strings.Join(flagsDesc, ", ") -} - -// transportFlagsStatus 生成标志描述状态 -func transportFlagsStatus(flag bool) (int, string) { - if flag { - return 1, " Set" - } - return 0, "Not set" -} - -// bytesToHexString 转换为十六进制字符串格式 -func bytesToHexString(data []byte) string { - var sb strings.Builder - for i, b := range data { - if i > 0 { - sb.WriteString(":") - } - sb.WriteString(fmt.Sprintf("%02x", b)) - } - return sb.String() -} - -// transportOptions 生成头部选项描述 -func transportOptions(options []layers.TCPOption) (uint8, string) { - var opts []string - var optLen uint8 - for _, opt := range options { - if opt.OptionType == layers.TCPOptionKindMSS && len(opt.OptionData) == 2 { - optLen += opt.OptionLength - opts = append(opts, fmt.Sprintf("%s val %v", - opt.OptionType.String(), - binary.BigEndian.Uint16(opt.OptionData), - )) - } else if opt.OptionType == layers.TCPOptionKindTimestamps && len(opt.OptionData) == 8 { - optLen += opt.OptionLength - opts = append(opts, fmt.Sprintf("%s val %v echo %v", - opt.OptionType.String(), - binary.BigEndian.Uint32(opt.OptionData[:4]), - binary.BigEndian.Uint32(opt.OptionData[4:8]), - )) - } else { - optLen += opt.OptionLength - opts = append(opts, opt.OptionType.String()) - } - } - return optLen, strings.Join(opts, ", ") -} - -// applicationHTTP 辨别 HTTP 数据 -func applicationHTTP(data []byte) bool { - if len(data) == 0 { - return false - } - prefixStr := string(data) - return strings.HasPrefix(prefixStr, "GET ") || strings.HasPrefix(prefixStr, "POST ") || - strings.HasPrefix(prefixStr, "PUT ") || strings.HasPrefix(prefixStr, "DELETE ") || - strings.HasPrefix(prefixStr, "HEAD ") || strings.HasPrefix(prefixStr, "OPTIONS ") || - strings.HasPrefix(prefixStr, "HTTP/") -} - -// applicationHTTP 处理 HTTP 请求 -func applicationHTTPProcess(data string) map[string]map[string]any { - p := make(map[string]map[string]any, 0) - // 按行分割 - lines := strings.Split(data, "\r\n") - for i, line := range lines { - if i == 0 { - label := line + "\r\n" - p[label] = map[string]any{ - "label": label, - "length": len([]byte(label)), - "key": "", - "value": "", - } - continue - } - - // 空行表示头部结束,Body开始 - if line == "" { - break - } - - label := line + "\r\n" - p[label] = map[string]any{ - "label": label, - "length": len([]byte(label)), - "key": "", - "value": "", - } - - // 分割键值对 - parts := strings.SplitN(line, ":", 2) - if len(parts) == 2 { - key := strings.TrimSpace(parts[0]) - value := strings.TrimSpace(parts[1]) - p[label]["key"] = key - p[label]["value"] = value - } - } - return p -} - -// colorRuleFB 着色规则-F前景,B背景 -// -// This file was created by Wireshark. Edit with care. -func colorRuleFB(packet gopacket.Packet) (int, int) { - // Ethernet - if ethernetLayer := packet.Layer(layers.LayerTypeEthernet); ethernetLayer != nil { - eth := ethernetLayer.(*layers.Ethernet) - ethData := eth.Contents - // Broadcast 检查第一个字节的最低位 - // #babdb6, #ffffff - if len(ethData) > 0 && (ethData[0]&1) == 1 { - return 12238262, 16777215 - } - // Routing CDP (Cisco Discovery Protocol) 检查前三个字节 - // #12272e, #fff3d6 - if ethernetLayer.LayerPayload()[0] == 0x01 && ethernetLayer.LayerPayload()[1] == 0x00 && ethernetLayer.LayerPayload()[2] == 0x0c { - return 1189678, 16774102 - } - // Routing CARP (Common Address Redundancy Protocol) uses a specific Ethernet type (0x0800) - // #12272e, #fff3d6 - if ethernetLayer.LayerType() == 0x0800 { - return 1189678, 16774102 - } - } - // ARP - if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil { - // #12272e, #faf0d7 - return 1189678, 16445655 - } - // ICMP - if icmpLayer := packet.Layer(layers.LayerTypeICMPv4); icmpLayer != nil { - // #12272e, #fce0ff - return 1189678, 16572671 - } - if icmpLayer := packet.Layer(layers.LayerTypeICMPv6); icmpLayer != nil { - // #12272e, #fce0ff - return 1189678, 16572671 - } - // SCTP - if sctpLayer := packet.Layer(layers.LayerTypeSCTP); sctpLayer != nil { - sctp := sctpLayer.(*layers.SCTP) - // SCTP ABORT - // #fffc9c, #a40000 - if sctp.Checksum == 6 { - return 16776348, 10747904 - } - } - // TCP - if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil { - tcp := tcpLayer.(*layers.TCP) - // TCP SYN/FIN - // #12272e, #a0a0a0 - if tcp.SYN && tcp.FIN { - return 1189678, 10526880 - } - // TCP RST - // #fffc9c, #a40000 - if tcp.RST { - return 16776348, 10747904 - } - // HTTP - // #12272e, #e4ffc7 - if tcp.SrcPort == 80 || tcp.DstPort == 80 || tcp.SrcPort == 443 || tcp.DstPort == 443 { - return 1189678, 15007687 - } - // 检查 SMB - 通常基于 TCP 445 或 139 - // #12272e, #feffd0 - if tcp.SrcPort == 445 || tcp.DstPort == 445 || tcp.SrcPort == 139 || tcp.DstPort == 139 { - return 1189678, 16711632 - } - // Routing BGP usually runs on TCP port 179 - // #12272e, #fff3d6 - if tcp.DstPort == 179 || tcp.SrcPort == 179 { - return 1189678, 16774102 - } - } - // UDP - if udpLayer := packet.Layer(layers.LayerTypeUDP); udpLayer != nil { - udp := udpLayer.(*layers.UDP) - // 检查 SMB NetBIOS 名称服务 (NBNS) - 端口 53 - // 检查 SMB NetBIOS 数据报服务 (NBDS) - 端口 138 - if udp.SrcPort == 53 || udp.DstPort == 53 || udp.SrcPort == 138 || udp.DstPort == 138 { - return 1189678, 16711632 - } - } - // IPv4 - if ipv4Layer := packet.Layer(layers.LayerTypeIPv4); ipv4Layer != nil { - ipv4 := ipv4Layer.(*layers.IPv4) - // TCP(6) - // #12272e, #e7e6ff - if ipv4.Protocol == layers.IPProtocolTCP { - return 1189678, 15197951 - } - // UDP(17) - // #12272e, #daeeff - if ipv4.Protocol == layers.IPProtocolUDP || ipv4.Protocol == layers.IPProtocolUDPLite { - return 1189678, 14348031 - } - // Routing EIGRP(0x2f) OSPF(89) - // #12272e, #fff3d6 - if ipv4.Protocol == 0x2f || ipv4.Protocol == layers.IPProtocolOSPF { - return 1189678, 16774102 - } - // Routing - // GVRP (GARP VLAN Registration Protocol) - // GVRP typically utilizes the same multicast address as GARP - // HSRP (Hot Standby Router Protocol) uses multicast IP 224.0.0.2 - // VRRP (Virtual Router Redundancy Protocol) uses multicast IP 224.0.0.18 - // #12272e, #fff3d6 - if ipv4.DstIP.Equal(net.IPv4(224, 0, 0, 2)) || ipv4.DstIP.Equal(net.IPv4(224, 0, 0, 100)) { - return 1189678, 16774102 - } - } - return 16222087, 1189678 // 默认颜色值 #f78787, #12272e -} diff --git a/src/modules/trace/repository/trace_data.go b/src/modules/trace/repository/trace_data.go index c1e791b4..bd65b76f 100644 --- a/src/modules/trace/repository/trace_data.go +++ b/src/modules/trace/repository/trace_data.go @@ -1,246 +1,139 @@ package repository import ( + "fmt" "strings" - "be.ems/src/framework/datasource" + "be.ems/src/framework/database/db" "be.ems/src/framework/logger" - "be.ems/src/framework/utils/parse" - "be.ems/src/framework/utils/repo" "be.ems/src/modules/trace/model" ) // 实例化数据层 TraceData 结构体 -var NewTraceData = &TraceData{ - selectSql: `select id, task_id, imsi, msisdn, src_addr, dst_addr, if_type, msg_type, msg_direct, length, timestamp, raw_msg, dec_msg from trace_data`, - - resultMap: map[string]string{ - "id": "ID", - "task_id": "TaskId", - "imsi": "IMSI", - "msisdn": "MSISDN", - "src_addr": "SrcAddr", - "dst_addr": "DstAddr", - "if_type": "IfType", - "msg_type": "MsgType", - "msg_direct": "MsgDirect", - "length": "Length", - "timestamp": "Timestamp", - "raw_msg": "RawMsg", - "dec_msg": "DecMsg", - }, -} +var NewTraceData = &TraceData{} // CDREventIMSImpl 跟踪_任务给HRL网元 数据层处理 -type TraceData struct { - // 查询视图对象SQL - selectSql string - // 结果字段与实体映射 - resultMap map[string]string -} +type TraceData struct{} -// convertResultRows 将结果记录转实体结果组 -func (r *TraceData) convertResultRows(rows []map[string]any) []model.TraceData { - arr := make([]model.TraceData, 0) - for _, row := range rows { - item := model.TraceData{} - for key, value := range row { - if keyMapper, ok := r.resultMap[key]; ok { - repo.SetFieldValue(&item, keyMapper, value) - } - } - arr = append(arr, item) - } - return arr -} - -// SelectPage 根据条件分页查询 -func (r *TraceData) SelectPage(query map[string]any) map[string]any { +// SelectByPage 分页查询集合 +func (r TraceData) SelectByPage(query map[string]string) ([]model.TraceData, int64) { + tx := db.DB("").Model(&model.TraceData{}) // 查询条件拼接 - var conditions []string - var params []any - if v, ok := query["imsi"]; ok && v != "" { - conditions = append(conditions, "imsi like concat(?, '%')") - params = append(params, v) - } - if v, ok := query["msisdn"]; ok && v != "" { - conditions = append(conditions, "msisdn like concat(?, '%')") - params = append(params, v) + if v, ok := query["traceId"]; ok && v != "" { + tx = tx.Where("trace_id = ?", v) } if v, ok := query["startTime"]; ok && v != "" { - conditions = append(conditions, "timestamp >= ?") - params = append(params, v) + if len(v) == 10 { + v = fmt.Sprintf("%s000", v) + tx = tx.Where("timestamp >= ?", v) + } else if len(v) == 13 { + tx = tx.Where("timestamp >= ?", v) + } } if v, ok := query["endTime"]; ok && v != "" { - conditions = append(conditions, "timestamp <= ?") - params = append(params, v) + if len(v) == 10 { + v = fmt.Sprintf("%s999", v) + tx = tx.Where("timestamp <= ?", v) + } else if len(v) == 13 { + tx = tx.Where("timestamp <= ?", v) + } } - // 构建查询条件语句 - whereSql := "" - if len(conditions) > 0 { - whereSql += " where " + strings.Join(conditions, " and ") + // 查询结果 + var total int64 = 0 + rows := []model.TraceData{} + + // 查询数量为0直接返回 + if err := tx.Count(&total).Error; err != nil || total <= 0 { + return rows, total } - result := map[string]any{ - "total": 0, - "rows": []model.TraceData{}, - } - - // 查询数量 长度为0直接返回 - totalSql := "select count(1) as 'total' from trace_data" - totalRows, err := datasource.RawDB("", totalSql+whereSql, params) - if err != nil { - logger.Errorf("total err => %v", err) - return result - } - total := parse.Number(totalRows[0]["total"]) - if total == 0 { - return result + // 查询数据分页 + pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"]) + tx = tx.Limit(pageSize).Offset(pageSize * pageNum) + // 排序 + sortByStr, sortOk := query["sortBy"] + sortOrderStr, orderOk := query["sortOrder"] + if sortOk && sortByStr != "" && orderOk && sortOrderStr != "" { + sortByArr := strings.Split(sortByStr, ",") + sortOrderArr := strings.Split(sortOrderStr, ",") + for i := range sortByArr { + sortBy := sortByArr[i] + sortOrder := sortOrderArr[i] + // 排序字段 + sort := "id" + if sortBy == "timestamp" { + sort = "timestamp" + } + // 排序方式 + order := "ASC" + if strings.HasPrefix(sortOrder, "asc") { + order = "ASC" + } else if strings.HasPrefix(sortOrder, "desc") { + order = "DESC" + } + tx = tx.Order(fmt.Sprintf("%s %s", sort, order)) + } } else { - result["total"] = total + tx = tx.Order("id desc") } + err := tx.Omit("raw_msg").Find(&rows).Error + if err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows, total + } + return rows, total +} - // 分页 - pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"]) - pageSql := " limit ?,? " - params = append(params, pageNum*pageSize) - params = append(params, pageSize) - +// SelectByIds 通过ID查询信息 +func (r TraceData) SelectByIds(ids []int64) []model.TraceData { + rows := []model.TraceData{} + if len(ids) <= 0 { + return rows + } + tx := db.DB("").Model(&model.TraceData{}) + // 构建查询条件 + tx = tx.Where("id in ?", ids) // 查询数据 - querySql := r.selectSql + whereSql + pageSql - results, err := datasource.RawDB("", querySql, params) - if err != nil { - logger.Errorf("query err => %v", err) + if err := tx.Find(&rows).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows } - - // 转换实体 - result["rows"] = r.convertResultRows(results) - return result + return rows } -// SelectList 根据实体查询 -func (r *TraceData) SelectList(data model.TraceData) []model.TraceData { - // 查询条件拼接 - var conditions []string - var params []any - if data.IMSI != "" { - conditions = append(conditions, "imsi = ?") - params = append(params, data.IMSI) - } - if data.MSISDN != "" { - conditions = append(conditions, "msisdn = ?") - params = append(params, data.MSISDN) - } - - // 构建查询条件语句 - whereSql := "" - if len(conditions) > 0 { - whereSql += " where " + strings.Join(conditions, " and ") - } - - // 查询数据 - querySql := r.selectSql + whereSql + " order by id desc " - results, err := datasource.RawDB("", querySql, params) - if err != nil { - logger.Errorf("query err => %v", err) - } - - // 转换实体 - return r.convertResultRows(results) -} - -// SelectByIds 通过ID查询 -func (r *TraceData) SelectByIds(ids []string) []model.TraceData { - placeholder := repo.KeyPlaceholderByQuery(len(ids)) - querySql := r.selectSql + " where id in (" + placeholder + ")" - parameters := repo.ConvertIdsSlice(ids) - results, err := datasource.RawDB("", querySql, parameters) - if err != nil { - logger.Errorf("query err => %v", err) - return []model.TraceData{} - } - // 转换实体 - return r.convertResultRows(results) -} - -// Insert 新增信息 -func (r *TraceData) Insert(data model.TraceData) string { - // 参数拼接 - params := make(map[string]any) - if data.TaskId > 0 { - params["task_id"] = data.TaskId - } - if data.IMSI != "" { - params["imsi"] = data.IMSI - } - if data.MSISDN != "" { - params["msisdn"] = data.MSISDN - } - if data.SrcAddr != "" { - params["src_addr"] = data.SrcAddr - } - if data.DstAddr != "" { - params["dst_addr"] = data.DstAddr - } - if data.IfType > -1 { - params["if_type"] = data.IfType - } - if data.MsgType > -1 { - params["msg_type"] = data.MsgType - } - if data.MsgDirect > -1 { - params["msg_direct"] = data.MsgDirect - } - if data.Length > 0 { - params["length"] = data.Length - } - if data.Timestamp > 0 { - params["timestamp"] = data.Timestamp - } - if data.RawMsg != "" { - params["raw_msg"] = data.RawMsg - } - if data.DecMsg != "" { - params["dec_msg"] = data.DecMsg - } - - // 构建执行语句 - keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params) - sql := "insert into trace_data (" + strings.Join(keys, ",") + ")values(" + placeholder + ")" - - db := datasource.DefaultDB() - // 开启事务 - tx := db.Begin() +// Insert 新增信息 返回新增数据ID +func (r TraceData) Insert(param model.TraceData) int64 { // 执行插入 - err := tx.Exec(sql, values...).Error - if err != nil { - logger.Errorf("insert row : %v", err.Error()) - tx.Rollback() - return "" - } - // 获取生成的自增 ID - var insertedID string - err = tx.Raw("select last_insert_id()").Row().Scan(&insertedID) - if err != nil { - logger.Errorf("insert last id : %v", err.Error()) - tx.Rollback() - return "" - } - // 提交事务 - tx.Commit() - return insertedID -} - -// DeleteByIds 批量删除信息 -func (r *TraceData) DeleteByIds(ids []string) int64 { - placeholder := repo.KeyPlaceholderByQuery(len(ids)) - sql := "delete from trace_data where id in (" + placeholder + ")" - parameters := repo.ConvertIdsSlice(ids) - results, err := datasource.ExecDB("", sql, parameters) - if err != nil { - logger.Errorf("delete err => %v", err) + if err := db.DB("").Create(¶m).Error; err != nil { + logger.Errorf("insert err => %v", err.Error()) return 0 } - return results + return param.ID +} + +// DeleteByIds 批量删除信息 返回受影响行数 +func (r TraceData) DeleteByIds(ids []int64) int64 { + if len(ids) <= 0 { + return 0 + } + tx := db.DB("").Where("id in ?", ids) + if err := tx.Delete(&model.TraceData{}).Error; err != nil { + logger.Errorf("delete err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} + +// DeleteByTraceId 删除跟踪任务数据 返回受影响行数 +func (r TraceData) DeleteByTraceId(traceId string) int64 { + if traceId == "" || traceId == "" { + return 0 + } + tx := db.DB("").Where("trace_id = ?", traceId) + if err := tx.Delete(&model.TraceData{}).Error; err != nil { + logger.Errorf("delete err => %v", err.Error()) + return 0 + } + return tx.RowsAffected } diff --git a/src/modules/trace/repository/trace_task.go b/src/modules/trace/repository/trace_task.go index 39f3aa30..2233420e 100644 --- a/src/modules/trace/repository/trace_task.go +++ b/src/modules/trace/repository/trace_task.go @@ -5,354 +5,148 @@ import ( "strings" "time" - "be.ems/src/framework/datasource" + "be.ems/src/framework/database/db" "be.ems/src/framework/logger" - "be.ems/src/framework/utils/parse" - "be.ems/src/framework/utils/repo" "be.ems/src/modules/trace/model" ) // 实例化数据层 TraceTask 结构体 -var NewTraceTask = &TraceTask{ - selectSql: `select id, trace_id, trace_type, start_time, end_time, - interfaces, imsi, msisdn, - ue_ip, src_ip, dst_ip, signal_port, - create_by, create_time, update_by, update_time, remark, - ne_type, ne_id, notify_url, fetch_msg - from trace_task`, - - resultMap: map[string]string{ - "id": "ID", - "trace_id": "TraceId", - "trace_type": "TraceType", - "start_time": "StartTime", - "end_time": "EndTime", - "interfaces": "Interfaces", - "imsi": "IMSI", - "msisdn": "MSISDN", - "ue_ip": "UeIp", - "src_ip": "SrcIp", - "dst_ip": "DstIp", - "signal_port": "SignalPort", - "create_by": "CreateBy", - "create_time": "CreateTime", - "update_by": "UpdateBy", - "update_time": "UpdateTime", - "remark": "Remark", - "ne_type": "NeType", - "ne_id": "NeId", - "notify_url": "NotifyUrl", - "fetch_msg": "FetchMsg", - }, -} +var NewTraceTask = &TraceTask{} // TraceTask 跟踪_任务 数据层处理 -type TraceTask struct { - // 查询视图对象SQL - selectSql string - // 结果字段与实体映射 - resultMap map[string]string -} +type TraceTask struct{} -// convertResultRows 将结果记录转实体结果组 -func (r *TraceTask) convertResultRows(rows []map[string]any) []model.TraceTask { - arr := make([]model.TraceTask, 0) - for _, row := range rows { - item := model.TraceTask{} - for key, value := range row { - if keyMapper, ok := r.resultMap[key]; ok { - repo.SetFieldValue(&item, keyMapper, value) - } - } - arr = append(arr, item) - } - return arr -} - -// SelectPage 根据条件分页查询 -func (r *TraceTask) SelectPage(query map[string]any) map[string]any { +// SelectByPage 分页查询集合 +func (r TraceTask) SelectByPage(query map[string]string) ([]model.TraceTask, int64) { + tx := db.DB("").Model(&model.TraceTask{}) // 查询条件拼接 - var conditions []string - var params []any - if v, ok := query["neType"]; ok && v != "" { - conditions = append(conditions, "ne_type = ?") - params = append(params, v) + if v, ok := query["traceType"]; ok && v != "" { + tx = tx.Where("trace_type = ?", v) } if v, ok := query["imsi"]; ok && v != "" { - conditions = append(conditions, "imsi like concat(?, '%')") - params = append(params, v) + tx = tx.Where("imsi like ?", fmt.Sprintf("%s%%", v)) } if v, ok := query["msisdn"]; ok && v != "" { - conditions = append(conditions, "msisdn like concat(?, '%')") - params = append(params, v) + tx = tx.Where("msisdn like ?", fmt.Sprintf("%s%%", v)) } if v, ok := query["startTime"]; ok && v != "" { - conditions = append(conditions, "start_time >= ?") - params = append(params, v) + if len(v) == 10 { + v = fmt.Sprintf("%s000", v) + tx = tx.Where("start_time >= ?", v) + } else if len(v) == 13 { + tx = tx.Where("start_time >= ?", v) + } } if v, ok := query["endTime"]; ok && v != "" { - conditions = append(conditions, "end_time <= ?") - params = append(params, v) - } - - // 构建查询条件语句 - whereSql := "" - if len(conditions) > 0 { - whereSql += " where " + strings.Join(conditions, " and ") - } - - result := map[string]any{ - "total": 0, - "rows": []model.TraceTask{}, - } - - // 查询数量 长度为0直接返回 - totalSql := "select count(1) as 'total' from trace_task" - totalRows, err := datasource.RawDB("", totalSql+whereSql, params) - if err != nil { - logger.Errorf("total err => %v", err) - return result - } - total := parse.Number(totalRows[0]["total"]) - if total == 0 { - return result - } else { - result["total"] = total - } - - // 分页 - pageNum, pageSize := repo.PageNumSize(query["pageNum"], query["pageSize"]) - pageSql := " limit ?,? " - params = append(params, pageNum*pageSize) - params = append(params, pageSize) - - // 排序 - orderSql := "" - if v, ok := query["sortField"]; ok && v != "" { - sortSql := v.(string) - if v, ok := query["sortOrder"]; ok && v != "" { - if v.(string) == "desc" { - sortSql += " desc " - } else { - sortSql += " asc " - } + if len(v) == 10 { + v = fmt.Sprintf("%s999", v) + tx = tx.Where("end_time <= ?", v) + } else if len(v) == 13 { + tx = tx.Where("end_time <= ?", v) } - orderSql = fmt.Sprintf(" order by %s ", sortSql) } + // 查询结果 + var total int64 = 0 + rows := []model.TraceTask{} + + // 查询数量为0直接返回 + if err := tx.Count(&total).Error; err != nil || total <= 0 { + return rows, total + } + + // 查询数据分页 + pageNum, pageSize := db.PageNumSize(query["pageNum"], query["pageSize"]) + tx = tx.Limit(pageSize).Offset(pageSize * pageNum) + // 排序 + sortByStr, sortOk := query["sortBy"] + sortOrderStr, orderOk := query["sortOrder"] + if sortOk && sortByStr != "" && orderOk && sortOrderStr != "" { + sortByArr := strings.Split(sortByStr, ",") + sortOrderArr := strings.Split(sortOrderStr, ",") + for i := range sortByArr { + sortBy := sortByArr[i] + sortOrder := sortOrderArr[i] + // 排序字段 + sort := "id" + if sortBy == "operaBy" { + sort = "opera_by" + } else if sortBy == "endTime" { + sort = "end_time" + } + // 排序方式 + order := "ASC" + if strings.HasPrefix(sortOrder, "asc") { + order = "ASC" + } else if strings.HasPrefix(sortOrder, "desc") { + order = "DESC" + } + tx = tx.Order(fmt.Sprintf("%s %s", sort, order)) + } + } else { + tx = tx.Order("id desc") + } + + err := tx.Find(&rows).Error + if err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows, total + } + return rows, total +} + +// SelectByIds 通过ID查询信息 +func (r TraceTask) SelectByIds(ids []int64) []model.TraceTask { + rows := []model.TraceTask{} + if len(ids) <= 0 { + return rows + } + tx := db.DB("").Model(&model.TraceTask{}) + // 构建查询条件 + tx = tx.Where("id in ?", ids) // 查询数据 - querySql := r.selectSql + whereSql + orderSql + pageSql - results, err := datasource.RawDB("", querySql, params) - if err != nil { - logger.Errorf("query err => %v", err) - } - - // 转换实体 - result["rows"] = r.convertResultRows(results) - return result -} - -// SelectList 根据实体查询 -func (r *TraceTask) SelectList(task model.TraceTask) []model.TraceTask { - // 查询条件拼接 - var conditions []string - var params []any - if task.IMSI != "" { - conditions = append(conditions, "imsi = ?") - params = append(params, task.IMSI) - } - if task.SrcIp != "" { - conditions = append(conditions, "src_ip = ?") - params = append(params, task.SrcIp) - } - if task.DstIp != "" { - conditions = append(conditions, "dst_ip = ?") - params = append(params, task.DstIp) - } - - // 构建查询条件语句 - whereSql := "" - if len(conditions) > 0 { - whereSql += " where " + strings.Join(conditions, " and ") - } - - // 查询数据 - querySql := r.selectSql + whereSql + " order by id desc " - results, err := datasource.RawDB("", querySql, params) - if err != nil { - logger.Errorf("query err => %v", err) - } - - // 转换实体 - return r.convertResultRows(results) -} - -// SelectByIds 通过ID查询 -func (r *TraceTask) SelectByIds(ids []string) []model.TraceTask { - placeholder := repo.KeyPlaceholderByQuery(len(ids)) - querySql := r.selectSql + " where id in (" + placeholder + ")" - parameters := repo.ConvertIdsSlice(ids) - results, err := datasource.RawDB("", querySql, parameters) - if err != nil { - logger.Errorf("query err => %v", err) - return []model.TraceTask{} - } - // 转换实体 - return r.convertResultRows(results) -} - -// Insert 新增信息 -func (r *TraceTask) Insert(task model.TraceTask) string { - // 参数拼接 - params := make(map[string]any) - if task.TraceId != "" { - params["trace_id"] = task.TraceId - } - if task.TraceType != "" { - params["trace_type"] = task.TraceType - } - if task.StartTime > 0 { - params["start_time"] = task.StartTime - } - if task.EndTime > 0 { - params["end_time"] = task.EndTime - } - if task.Interfaces != "" { - params["interfaces"] = task.Interfaces - } - if task.IMSI != "" { - params["imsi"] = task.IMSI - } - if task.MSISDN != "" { - params["msisdn"] = task.MSISDN - } - if task.UeIp != "" { - params["ue_ip"] = task.UeIp - } - if task.SrcIp != "" { - params["src_ip"] = task.SrcIp - } - if task.DstIp != "" { - params["dst_ip"] = task.DstIp - } - if task.SignalPort != 0 { - params["signal_port"] = task.SignalPort - } - if task.NeType != "" { - params["ne_type"] = task.NeType - } - if task.NeId != "" { - params["ne_id"] = task.NeId - } - if task.NotifyUrl != "" { - params["notify_url"] = task.NotifyUrl - } - if task.FetchMsg != "" { - params["fetch_msg"] = task.FetchMsg - } - if task.Remark != "" { - params["remark"] = task.Remark - } - if task.CreateBy != "" { - params["create_by"] = task.CreateBy - params["create_time"] = time.Now().UnixMilli() - } - - // 构建执行语句 - keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params) - sql := "insert into trace_task (" + strings.Join(keys, ",") + ")values(" + placeholder + ")" - - db := datasource.DefaultDB() - // 开启事务 - tx := db.Begin() - // 执行插入 - err := tx.Exec(sql, values...).Error - if err != nil { - logger.Errorf("insert row : %v", err.Error()) - tx.Rollback() - return "" - } - // 获取生成的自增 ID - var insertedID string - err = tx.Raw("select last_insert_id()").Row().Scan(&insertedID) - if err != nil { - logger.Errorf("insert last id : %v", err.Error()) - tx.Rollback() - return "" - } - // 提交事务 - tx.Commit() - return insertedID -} - -// Update 修改信息 -func (r *TraceTask) Update(task model.TraceTask) int64 { - // 参数拼接 - params := make(map[string]any) - params["trace_id"] = task.TraceId - params["trace_type"] = task.TraceType - params["ne_type"] = task.NeType - params["ne_id"] = task.NeId - params["notify_url"] = task.NotifyUrl - - params["start_time"] = task.StartTime - params["end_time"] = task.EndTime - params["fetch_msg"] = task.FetchMsg - params["remark"] = task.Remark - - params["interfaces"] = task.Interfaces - - params["imsi"] = task.IMSI - params["msisdn"] = task.MSISDN - - params["ue_ip"] = task.UeIp - params["src_ip"] = task.SrcIp - params["dst_ip"] = task.DstIp - params["signal_port"] = task.SignalPort - - if task.UpdateBy != "" { - params["update_by"] = task.UpdateBy - params["update_time"] = time.Now().UnixMilli() - } - - // 构建执行语句 - keys, values := repo.KeyValueByUpdate(params) - sql := "update trace_task set " + strings.Join(keys, ",") + " where id = ?" - - // 执行更新 - values = append(values, task.ID) - rows, err := datasource.ExecDB("", sql, values) - if err != nil { - logger.Errorf("update row : %v", err.Error()) - return 0 + if err := tx.Find(&rows).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows } return rows } -// DeleteByIds 批量删除信息 -func (r *TraceTask) DeleteByIds(ids []string) int64 { - placeholder := repo.KeyPlaceholderByQuery(len(ids)) - sql := "delete from trace_task where id in (" + placeholder + ")" - parameters := repo.ConvertIdsSlice(ids) - results, err := datasource.ExecDB("", sql, parameters) - if err != nil { - logger.Errorf("delete err => %v", err) +// Insert 新增信息 返回新增数据ID +func (r TraceTask) Insert(param model.TraceTask) int64 { + if param.CreateBy != "" { + ms := time.Now().UnixMilli() + param.CreateTime = ms + } + // 执行插入 + if err := db.DB("").Create(¶m).Error; err != nil { + logger.Errorf("insert err => %v", err.Error()) return 0 } - return results + return param.ID +} + +// DeleteByIds 批量删除信息 返回受影响行数 +func (r TraceTask) DeleteByIds(ids []int64) int64 { + if len(ids) <= 0 { + return 0 + } + tx := db.DB("").Where("id in ?", ids) + if err := tx.Delete(&model.TraceTask{}).Error; err != nil { + logger.Errorf("delete err => %v", err.Error()) + return 0 + } + return tx.RowsAffected } // LastID 最后一条ID -func (r *TraceTask) LastID() int64 { +func (r TraceTask) LastID() int64 { + tx := db.DB("").Model(&model.TraceTask{}) // 查询数据 - querySql := "SELECT id as 'str' FROM trace_task ORDER BY id DESC LIMIT 1" - results, err := datasource.RawDB("", querySql, nil) - if err != nil { - logger.Errorf("query err %v", err) - return 0 + var id int64 = 0 + if err := tx.Select("id").Order("id DESC").Limit(1).Find(&id).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return id } - if len(results) > 0 { - return parse.Number(results[0]["str"]) - } - return 0 + return id } diff --git a/src/modules/trace/repository/trace_task_hlr.go b/src/modules/trace/repository/trace_task_hlr.go index 15b6cbf5..ed721a35 100644 --- a/src/modules/trace/repository/trace_task_hlr.go +++ b/src/modules/trace/repository/trace_task_hlr.go @@ -2,315 +2,144 @@ package repository import ( "fmt" - "strings" "time" - "be.ems/src/framework/datasource" + "be.ems/src/framework/database/db" "be.ems/src/framework/logger" - "be.ems/src/framework/utils/parse" - "be.ems/src/framework/utils/repo" "be.ems/src/modules/trace/model" ) // 实例化数据层 TraceTaskHlr 结构体 -var NewTraceTaskHlr = &TraceTaskHlr{ - selectSql: `select id, trace_id, imsi, msisdn, start_time, end_time, status, msg, remark, create_by, create_time, update_by, update_time from trace_task_hlr`, - - resultMap: map[string]string{ - "id": "ID", - "trace_id": "TraceId", - "imsi": "IMSI", - "msisdn": "MSISDN", - "start_time": "StartTime", - "end_time": "EndTime", - "status": "Status", - "msg": "Msg", - "remark": "Remark", - "create_by": "CreateBy", - "create_time": "CreateTime", - "update_by": "UpdateBy", - "update_time": "UpdateTime", - }, -} +var NewTraceTaskHlr = &TraceTaskHlr{} // TraceTaskHlr 跟踪_任务给HRL网元 数据层处理 -type TraceTaskHlr struct { - // 查询视图对象SQL - selectSql string - // 结果字段与实体映射 - resultMap map[string]string -} +type TraceTaskHlr struct{} -// convertResultRows 将结果记录转实体结果组 -func (r *TraceTaskHlr) convertResultRows(rows []map[string]any) []model.TraceTaskHlr { - arr := make([]model.TraceTaskHlr, 0) - for _, row := range rows { - item := model.TraceTaskHlr{} - for key, value := range row { - if keyMapper, ok := r.resultMap[key]; ok { - repo.SetFieldValue(&item, keyMapper, value) - } - } - arr = append(arr, item) - } - return arr -} - -// SelectPage 根据条件分页查询 -func (r *TraceTaskHlr) SelectPage(querys model.TraceTaskHlrQuery) map[string]any { +// SelectByPage 分页查询集合 +func (r TraceTaskHlr) SelectByPage(query model.TraceTaskHlrQuery) ([]model.TraceTaskHlr, int64) { + tx := db.DB("").Model(&model.TraceTaskHlr{}) // 查询条件拼接 - var conditions []string - var params []any - if querys.IMSI != "" { - conditions = append(conditions, "imsi like concat(?, '%')") - params = append(params, querys.IMSI) + if query.IMSI != "" { + tx = tx.Where("imsi like ?", fmt.Sprintf("%s%%", query.IMSI)) } - if querys.MSISDN != "" { - conditions = append(conditions, "msisdn like concat(?, '%')") - params = append(params, querys.MSISDN) + if query.MSISDN != "" { + tx = tx.Where("msisdn like ?", fmt.Sprintf("%s%%", query.MSISDN)) } - if querys.StartTime != "" && len(querys.StartTime) == 13 { - conditions = append(conditions, "start_time >= ?") - params = append(params, querys.StartTime) + if query.StartTime != "" && len(query.StartTime) == 13 { + tx = tx.Where("start_time >= ?", query.StartTime) } - if querys.EndTime != "" && len(querys.EndTime) == 13 { - conditions = append(conditions, "end_time <= ?") - params = append(params, querys.EndTime) + if query.EndTime != "" && len(query.EndTime) == 13 { + tx = tx.Where("end_time >= ?", query.StartTime) } - // 构建查询条件语句 - whereSql := "" - if len(conditions) > 0 { - whereSql += " where " + strings.Join(conditions, " and ") + // 查询结果 + var total int64 = 0 + rows := []model.TraceTaskHlr{} + + // 查询数量为0直接返回 + if err := tx.Count(&total).Error; err != nil || total <= 0 { + return rows, total } - result := map[string]any{ - "total": 0, - "rows": []model.TraceTaskHlr{}, - } - - // 查询数量 长度为0直接返回 - totalSql := "select count(1) as 'total' from trace_task_hlr" - totalRows, err := datasource.RawDB("", totalSql+whereSql, params) - if err != nil { - logger.Errorf("total err => %v", err) - return result - } - total := parse.Number(totalRows[0]["total"]) - if total == 0 { - return result - } else { - result["total"] = total - } - - // 分页 - pageNum, pageSize := repo.PageNumSize(querys.PageNum, querys.PageSize) - pageSql := " limit ?,? " - params = append(params, pageNum*pageSize) - params = append(params, pageSize) + // 查询数据分页 + pageNum, pageSize := db.PageNumSize(query.PageNum, query.PageSize) + tx = tx.Limit(pageSize).Offset(pageSize * pageNum) // 排序 - orderSql := "" - if querys.SortField != "" { - sortSql := querys.SortField - if querys.SortOrder != "" { - if querys.SortOrder == "desc" { + if query.SortField != "" { + sortSql := query.SortField + if query.SortOrder != "" { + if query.SortOrder == "desc" { sortSql += " desc " } else { sortSql += " asc " } } - orderSql = fmt.Sprintf(" order by id desc, %s ", sortSql) + tx.Order(fmt.Sprintf("id desc, %s ", sortSql)) } + err := tx.Find(&rows).Error + if err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows, total + } + return rows, total +} + +// SelectByIds 通过ID查询信息 +func (r TraceTaskHlr) SelectByIds(ids []int64) []model.TraceTaskHlr { + rows := []model.TraceTaskHlr{} + if len(ids) <= 0 { + return rows + } + tx := db.DB("").Model(&model.TraceTaskHlr{}) + // 构建查询条件 + tx = tx.Where("id in ?", ids) // 查询数据 - querySql := r.selectSql + whereSql + orderSql + pageSql - results, err := datasource.RawDB("", querySql, params) - if err != nil { - logger.Errorf("query err => %v", err) - } - - // 转换实体 - result["rows"] = r.convertResultRows(results) - return result -} - -// SelectList 根据实体查询 -func (r *TraceTaskHlr) SelectList(task model.TraceTaskHlr) []model.TraceTaskHlr { - // 查询条件拼接 - var conditions []string - var params []any - if task.IMSI != "" { - conditions = append(conditions, "imsi = ?") - params = append(params, task.IMSI) - } - if task.MSISDN != "" { - conditions = append(conditions, "msisdn = ?") - params = append(params, task.MSISDN) - } - - // 构建查询条件语句 - whereSql := "" - if len(conditions) > 0 { - whereSql += " where " + strings.Join(conditions, " and ") - } - - // 查询数据 - querySql := r.selectSql + whereSql + " order by id desc " - results, err := datasource.RawDB("", querySql, params) - if err != nil { - logger.Errorf("query err => %v", err) - } - - // 转换实体 - return r.convertResultRows(results) -} - -// SelectByIds 通过ID查询 -func (r *TraceTaskHlr) SelectByIds(ids []string) []model.TraceTaskHlr { - placeholder := repo.KeyPlaceholderByQuery(len(ids)) - querySql := r.selectSql + " where id in (" + placeholder + ")" - parameters := repo.ConvertIdsSlice(ids) - results, err := datasource.RawDB("", querySql, parameters) - if err != nil { - logger.Errorf("query err => %v", err) - return []model.TraceTaskHlr{} - } - // 转换实体 - return r.convertResultRows(results) -} - -// Insert 新增信息 -func (r *TraceTaskHlr) Insert(task model.TraceTaskHlr) string { - // 参数拼接 - params := make(map[string]any) - if task.TraceId != "" { - params["trace_id"] = task.TraceId - } - if task.IMSI != "" { - params["imsi"] = task.IMSI - } - if task.MSISDN != "" { - params["msisdn"] = task.MSISDN - } - if task.StartTime != 0 { - params["start_time"] = task.StartTime - } - if task.EndTime != 0 { - params["end_time"] = task.EndTime - } - if task.Status != "" { - params["status"] = task.Status - } - if task.Msg != "" { - params["msg"] = task.Msg - } - if task.Remark != "" { - params["remark"] = task.Remark - } - if task.CreateBy != "" { - params["create_by"] = task.CreateBy - params["create_time"] = time.Now().UnixMilli() - } - - // 构建执行语句 - keys, placeholder, values := repo.KeyPlaceholderValueByInsert(params) - sql := "insert into trace_task_hlr (" + strings.Join(keys, ",") + ")values(" + placeholder + ")" - - db := datasource.DefaultDB() - // 开启事务 - tx := db.Begin() - // 执行插入 - err := tx.Exec(sql, values...).Error - if err != nil { - logger.Errorf("insert row : %v", err.Error()) - tx.Rollback() - return "" - } - // 获取生成的自增 ID - var insertedID string - err = tx.Raw("select last_insert_id()").Row().Scan(&insertedID) - if err != nil { - logger.Errorf("insert last id : %v", err.Error()) - tx.Rollback() - return "" - } - // 提交事务 - tx.Commit() - return insertedID -} - -// Update 修改信息 -func (r *TraceTaskHlr) Update(task model.TraceTaskHlr) int64 { - // 参数拼接 - params := make(map[string]any) - if task.TraceId != "" { - params["trace_id"] = task.TraceId - } - if task.IMSI != "" { - params["imsi"] = task.IMSI - } - if task.MSISDN != "" { - params["msisdn"] = task.MSISDN - } - if task.StartTime != 0 { - params["start_time"] = task.StartTime - } - if task.EndTime != 0 { - params["end_time"] = task.EndTime - } - if task.Status != "" { - params["status"] = task.Status - } - if task.Msg != "" { - params["msg"] = task.Msg - } - if task.Remark != "" { - params["remark"] = task.Remark - } - if task.UpdateBy != "" { - params["update_by"] = task.UpdateBy - params["update_time"] = time.Now().UnixMilli() - } - - // 构建执行语句 - keys, values := repo.KeyValueByUpdate(params) - sql := "update trace_task_hlr set " + strings.Join(keys, ",") + " where id = ?" - - // 执行更新 - values = append(values, task.ID) - rows, err := datasource.ExecDB("", sql, values) - if err != nil { - logger.Errorf("update row : %v", err.Error()) - return 0 + if err := tx.Find(&rows).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return rows } return rows } -// DeleteByIds 批量删除信息 -func (r *TraceTaskHlr) DeleteByIds(ids []string) int64 { - placeholder := repo.KeyPlaceholderByQuery(len(ids)) - sql := "delete from trace_task_hlr where id in (" + placeholder + ")" - parameters := repo.ConvertIdsSlice(ids) - results, err := datasource.ExecDB("", sql, parameters) - if err != nil { - logger.Errorf("delete err => %v", err) +// Insert 新增信息 返回新增数据ID +func (r TraceTaskHlr) Insert(param model.TraceTaskHlr) int64 { + if param.CreateBy != "" { + ms := time.Now().UnixMilli() + param.UpdateBy = param.CreateBy + param.UpdateTime = ms + param.CreateTime = ms + } + // 执行插入 + if err := db.DB("").Create(¶m).Error; err != nil { + logger.Errorf("insert err => %v", err.Error()) return 0 } - return results + return param.ID +} + +// Update 修改信息 返回受影响行数 +func (r TraceTaskHlr) Update(param model.TraceTaskHlr) int64 { + if param.ID <= 0 { + return 0 + } + if param.UpdateBy != "" { + param.UpdateTime = time.Now().UnixMilli() + } + tx := db.DB("").Model(&model.TraceTaskHlr{}) + // 构建查询条件 + tx = tx.Where("id = ?", param.ID) + tx = tx.Omit("id", "create_by", "create_time") + // 执行更新 + if err := tx.Updates(param).Error; err != nil { + logger.Errorf("update err => %v", err.Error()) + return 0 + } + return tx.RowsAffected +} + +// DeleteByIds 批量删除信息 返回受影响行数 +func (r TraceTaskHlr) DeleteByIds(ids []int64) int64 { + if len(ids) <= 0 { + return 0 + } + tx := db.DB("").Where("id in ?", ids) + if err := tx.Delete(&model.TraceTaskHlr{}).Error; err != nil { + logger.Errorf("delete err => %v", err.Error()) + return 0 + } + return tx.RowsAffected } // LastID 最后一条ID -func (r *TraceTaskHlr) LastID() int64 { +func (r TraceTaskHlr) LastID() int64 { + tx := db.DB("").Model(&model.TraceTaskHlr{}) // 查询数据 - querySql := "SELECT id as 'str' FROM trace_task_hlr ORDER BY id DESC LIMIT 1" - results, err := datasource.RawDB("", querySql, nil) - if err != nil { - logger.Errorf("query err %v", err) - return 0 + var id int64 = 0 + if err := tx.Select("id").Order("id DESC").Limit(1).Find(&id).Error; err != nil { + logger.Errorf("query find err => %v", err.Error()) + return id } - if len(results) > 0 { - return parse.Number(results[0]["str"]) - } - return 0 + return id } diff --git a/src/modules/trace/service/packet.go b/src/modules/trace/service/packet.go index 64cc6430..4c705374 100644 --- a/src/modules/trace/service/packet.go +++ b/src/modules/trace/service/packet.go @@ -1,21 +1,64 @@ package service import ( - "be.ems/src/framework/vo" - packetTask "be.ems/src/modules/trace/packet_task" + "encoding/base64" + "fmt" + "net" + "os" + "path/filepath" + "runtime" + "strings" + "sync" + "sync/atomic" + "time" + + "github.com/gopacket/gopacket" + "github.com/gopacket/gopacket/layers" + "github.com/gopacket/gopacket/pcap" + "github.com/gopacket/gopacket/pcapgo" + + "be.ems/src/framework/logger" + wsService "be.ems/src/modules/ws/service" ) +// Task 任务信息 +type Task struct { + TaskNo string // 任务编号 + Handle *pcap.Handle // 捕获句柄 + File *os.File // 捕获信息输出文件句柄 + Writer *pcapgo.Writer // 捕获信息输出句柄 + Filter string // 过滤表达式 + Ticker *time.Ticker // 任务失效定时器 +} + +// FrameMeta 数据帧元信息 +type FrameMeta struct { + Number int `json:"number"` + Time int64 `json:"time"` + Source string `json:"source"` + Destination string `json:"destination"` + Protocol string `json:"protocol"` + Length int `json:"length"` + Info string `json:"info"` + Data string `json:"data"` // 原始数据byte[] base64 编码数据 +} + // 实例化服务层 Packet 结构体 -var NewPacket = &Packet{} +var NewPacket = &Packet{ + taskMap: sync.Map{}, +} // 信令跟踪 服务层处理 -type Packet struct{} +type Packet struct { + taskMap sync.Map +} // NetworkDevices 获取网卡设备信息 -func (s *Packet) NetworkDevices() []vo.TreeSelect { - arr := make([]vo.TreeSelect, 0) - devices, err := packetTask.NetworkDevices() +func (s *Packet) NetworkDevices() []map[string]any { + arr := make([]map[string]any, 0) + devices, err := pcap.FindAllDevs() if err != nil { + logger.Errorf("interfaces find all devices err: %s", err.Error()) return arr } @@ -28,16 +71,16 @@ func (s *Packet) NetworkDevices() []vo.TreeSelect { if lable == "" { lable = device.Name } - item := vo.TreeSelect{ - ID: device.Name, - Label: lable, - Children: []vo.TreeSelect{}, + item := map[string]any{ + "id": device.Name, + "label": lable, + "children": []map[string]any{}, } for _, address := range device.Addresses { if address.IP != nil { ip := address.IP.String() - item.Children = append(item.Children, vo.TreeSelect{ID: ip, Label: ip}) + item["children"] = append(item["children"].([]map[string]any), map[string]any{"id": ip, "label": ip}) } } arr = append(arr, item) @@ -48,20 +91,343 @@ func (s *Packet) NetworkDevices() []vo.TreeSelect { // LiveStart 开始捕获数据 func (s *Packet) LiveStart(taskNo, deviceName, filterBPF string, outputPCAP bool) (string, error) { - return packetTask.LiveStart(taskNo, deviceName, filterBPF, outputPCAP) + if _, ok := s.taskMap.Load(taskNo); ok { + return "", fmt.Errorf("task no. %s already exist", taskNo) + } + + // Verify the specified network interface exists + device, deviceOk := s.verifyDevice(deviceName) + if !deviceOk { + return "", fmt.Errorf("network device not exist: %s", deviceName) + } + + // listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes + snapshotLength := 262144 + + // open device + handle, err := pcap.OpenLive(device, int32(snapshotLength), true, pcap.BlockForever) + if err != nil { + logger.Errorf("open live err: %s", err.Error()) + if strings.Contains(err.Error(), "operation not permitted") { + return "", fmt.Errorf("you don't have permission to capture on that/these device(s)") + } + return "", err + } + + // write a new file + var w *pcapgo.Writer + var f *os.File + if outputPCAP { + // 网管本地路径 + localFilePath := fmt.Sprintf("/tmp/omc/packet/%s.pcap", taskNo) + if runtime.GOOS == "windows" { + localFilePath = fmt.Sprintf("C:%s", localFilePath) + } + f, w, err = s.outputPCAPFile(uint32(snapshotLength), handle.LinkType(), localFilePath) + if err != nil { + return "", err + } + } + + // set filter + if filterBPF != "" { + if err = handle.SetBPFFilter(filterBPF); err != nil { + logger.Errorf("packet BPF Filter %s => %s", filterBPF, err.Error()) + filterBPF = "" + } + } + + // save tasks + taskInfo := &Task{ + TaskNo: taskNo, + Handle: handle, + File: f, + Writer: w, + Filter: filterBPF, + Ticker: time.NewTicker(time.Second * 120), + } + + go s.capturePacketSource(taskInfo) + s.taskMap.Store(taskNo, taskInfo) + return fmt.Sprintf("task no: %s initiated", taskNo), nil +} + +// verifyDevice 检查网卡设备是否存在 +func (s *Packet) verifyDevice(str string) (string, bool) { + devices, err := pcap.FindAllDevs() + if err != nil { + logger.Errorf("interfaces find all devices err: %s", err.Error()) + return "", false + } + for _, device := range devices { + if len(device.Addresses) == 0 { + continue + } + if device.Name == str { + return device.Name, true + } + for _, address := range device.Addresses { + if address.IP.String() == str { + return device.Name, true + } + } + } + return "", false +} + +// capturePacketSource 捕获数据 +func (s *Packet) capturePacketSource(taskInfo *Task) { + // capture packets + packetSource := gopacket.NewPacketSource(taskInfo.Handle, taskInfo.Handle.LinkType()) + packetSource.Lazy = false + packetSource.NoCopy = true + packetSource.DecodeStreamsAsDatagrams = true + + // 协程停止后关闭句柄并移除任务信息 + defer func() { + taskInfo.Ticker.Stop() + taskInfo.Handle.Close() + if taskInfo.File != nil { + taskInfo.File.Close() + } + s.taskMap.Delete(taskInfo.TaskNo) + }() + + var frameNumber int64 = 0 // 帧编号 + + for { + select { + case <-taskInfo.Ticker.C: + return + case packet := <-packetSource.Packets(): + if packet == nil { + continue + } + if packet.Metadata().Timestamp.Before(time.Now()) { + continue + } + + // 使用原子操作获取当前帧号并自增 + currentFrameNumber := atomic.AddInt64(&frameNumber, 1) + frameSrc := "" // 源主机IP + frameDst := "" // 目的主机IP + frameProtocol := "" // 协议 + frameInfo := "" // 信息 + // fmt.Printf("---------- packet %d layers:%d time: %s, len: %d \n", currentFrameNumber, len(packet.Layers()), packet.Metadata().Timestamp, packet.Metadata().Length) + + // 网络层 + // fmt.Println(packet.NetworkLayer()) + if networkLayer := packet.NetworkLayer(); networkLayer != nil { + src, dst := networkLayer.NetworkFlow().Endpoints() + frameSrc = src.String() + frameDst = dst.String() + if frameDst == "ff:ff:ff:ff" { + frameDst = "Broadcast" + } + } + + // 传输层 + // fmt.Println(packet.TransportLayer()) + if transportLayer := packet.TransportLayer(); transportLayer != nil { + frameProtocol = transportLayer.LayerType().String() + switch layer := transportLayer.(type) { + case *layers.TCP: // 传输控制协议,提供可靠的数据传输。 + var flagsDesc []string + if layer.FIN { + flagsDesc = append(flagsDesc, "FIN") + } + if layer.SYN { + flagsDesc = append(flagsDesc, "SYN") + } + if layer.RST { + flagsDesc = append(flagsDesc, "RST") + } + if layer.PSH { + flagsDesc = append(flagsDesc, "PSH") + } + if layer.ACK { + flagsDesc = append(flagsDesc, "ACK") + } + if layer.URG { + flagsDesc = append(flagsDesc, "URG") + } + if layer.ECE { + flagsDesc = append(flagsDesc, "ECE") + } + if layer.CWR { + flagsDesc = append(flagsDesc, "CWR") + } + if layer.NS { + flagsDesc = append(flagsDesc, "NS") + } + + frameInfo = fmt.Sprintf("%v -> %v [%s], Seq=%d Ack=%d Win=%d Len=%d ", layer.SrcPort, layer.DstPort, strings.Join(flagsDesc, ", "), layer.Seq, layer.Ack, layer.Window, len(layer.Payload)) + case *layers.UDP: // 用户数据报协议,提供无连接的快速数据传输。 + frameInfo = fmt.Sprintf("%v -> %v Len=%d ", layer.SrcPort, layer.DstPort, len(layer.Payload)) + case *layers.UDPLite: + frameInfo = fmt.Sprintf("%v -> %v Len=%d ", layer.SrcPort, layer.DstPort, len(layer.Payload)) + case *layers.SCTP: // 流控制传输协议,支持多流和多宿主机。 + frameInfo = fmt.Sprintf("%v -> %v Len=%d ", layer.SrcPort, layer.DstPort, len(layer.Payload)) + } + } + + // 应用协议层判断 + switch { + case packet.Layer(layers.LayerTypeARP) != nil: + arp := packet.Layer(layers.LayerTypeARP).(*layers.ARP) + frameSrc = net.IP(arp.SourceProtAddress).String() + frameDst = net.IP(arp.DstProtAddress).String() + frameProtocol = "ARP" + frameInfo = fmt.Sprintf("Who has %s? Tell %s", frameDst, frameSrc) + case packet.Layer(layers.LayerTypeVRRP) != nil: + frameProtocol = "VRRP" + frameInfo = "Announcement (v2)" + case packet.Layer(layers.LayerTypeIGMP) != nil: + switch layer := packet.Layer(layers.LayerTypeIGMP).(type) { + case *layers.IGMP: + frameProtocol = fmt.Sprintf("IGMPv%d", layer.Version) + frameInfo = fmt.Sprintf("%s %s", layer.Type.String(), layer.GroupAddress.String()) + case *layers.IGMPv1or2: + frameProtocol = fmt.Sprintf("IGMPv%d", layer.Version) + frameInfo = fmt.Sprintf("%s %s", layer.Type.String(), layer.GroupAddress.String()) + } + case packet.Layer(layers.LayerTypeICMPv4) != nil: + icmpv4 := packet.Layer(layers.LayerTypeICMPv4).(*layers.ICMPv4) + frameProtocol = "ICMP" + frameInfo = icmpv4.TypeCode.String() + case packet.Layer(layers.LayerTypeICMPv6) != nil: + icmpv6 := packet.Layer(layers.LayerTypeICMPv6).(*layers.ICMPv6) + frameProtocol = "ICMPv6" + frameInfo = icmpv6.TypeCode.String() + case packet.Layer(layers.LayerTypeSTP) != nil: + stp := packet.Layer(layers.LayerTypeSTP).(*layers.STP) + rootIdentifier := stp.RouteID + frameSrc = rootIdentifier.HwAddr.String() + frameDst = stp.BridgeID.HwAddr.String() + frameProtocol = "STP" + frameInfo = fmt.Sprintf("MST. Root = %d/%d/%s Cost = %d Port = 0x%x", rootIdentifier.Priority, rootIdentifier.SysID, frameSrc, stp.Cost, stp.PortID) + case packet.Layer(layers.LayerTypeSIP) != nil: + sip := packet.Layer(layers.LayerTypeSIP).(*layers.SIP) + frameProtocol = "SIP" + if sip.IsResponse { + frameInfo = fmt.Sprintf("%d %s", sip.ResponseCode, sip.ResponseStatus) + } else { + frameInfo = fmt.Sprintf("%s %s", sip.Method, sip.RequestURI) + } + case packet.Layer(layers.LayerTypeDNS) != nil: + dns := packet.Layer(layers.LayerTypeDNS).(*layers.DNS) + frameProtocol = "DNS" + question := []string{} + if len(dns.Questions) > 0 { + question = append(question, fmt.Sprintf("%s %s", dns.Questions[0].Type, dns.Questions[0].Name)) + } + frameInfo = fmt.Sprintf("%s %s 0x%x %s Answers %d", dns.ResponseCode.String(), dns.OpCode.String(), dns.ID, question, len(dns.Answers)) + case packet.Layer(layers.LayerTypeDHCPv6) != nil: + dhcpv6 := packet.Layer(layers.LayerTypeDHCPv6).(*layers.DHCPv6) + frameProtocol = "DHCPv6" + frameInfo = fmt.Sprintf("%s XID: 0x%+x", dhcpv6.MsgType.String(), dhcpv6.TransactionID) + case packet.Layer(layers.LayerTypeTLS) != nil: + tls := packet.Layer(layers.LayerTypeTLS).(*layers.TLS) + if len(tls.AppData) > 0 { + item := tls.AppData[0] + frameProtocol = item.Version.String() + frameInfo = item.ContentType.String() + } else if len(tls.Handshake) > 0 { + item := tls.Handshake[0] + frameProtocol = item.ClientHello.ProtocolVersion.String() + frameInfo = "Client Hello" + } else { + frameProtocol = "TLS" + frameInfo = "Unknown" + } + } + + if frameProtocol == "" { + continue + } + + // 数据 + frameMeta := FrameMeta{ + Number: int(currentFrameNumber), + Time: packet.Metadata().Timestamp.UnixNano(), + Source: frameSrc, + Destination: frameDst, + Protocol: frameProtocol, + Length: packet.Metadata().Length, + Info: frameInfo, + Data: base64.StdEncoding.EncodeToString(packet.Data()), + } + // 推送到ws订阅组 + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%s", wsService.GROUP_TRACE_PACKET, taskInfo.TaskNo), frameMeta) + + // 写入文件 + if taskInfo.Writer != nil { + taskInfo.Writer.WritePacket(packet.Metadata().CaptureInfo, packet.Data()) + } + } + } +} + +// outputPCAPFile 输出 pcap 文件 +// 新文件时需要 snaplen 最大长度 linktype 链路类型 +func (s *Packet) outputPCAPFile(snaplen uint32, linktype layers.LinkType, outputFile string) (*os.File, *pcapgo.Writer, error) { + var err error + var f *os.File + if err := os.MkdirAll(filepath.Dir(outputFile), 0775); err != nil { + return nil, nil, err + } + + // 检查文件是否存在 + if _, err = os.Stat(outputFile); os.IsNotExist(err) { + f, err = os.Create(outputFile) + if err != nil { + return nil, nil, err + } + w := pcapgo.NewWriter(f) + w.WriteFileHeader(snaplen, linktype) // new file, must do this. + return f, w, nil + } + + f, err = os.OpenFile(outputFile, os.O_APPEND, 0700) + if err != nil { + return nil, nil, err + } + w := pcapgo.NewWriter(f) + return f, w, nil } // LiveFilter 捕获过滤 func (s *Packet) LiveFilter(taskNo, expr string) error { - return packetTask.LiveFilter(taskNo, expr) + info, ok := s.taskMap.Load(taskNo) + if !ok { + return fmt.Errorf("task no: %s does not exist or has stopped", taskNo) + } + task := info.(*Task) + task.Filter = expr + err := task.Handle.SetBPFFilter(expr) + if err != nil { + logger.Errorf("packet BPF Filter %s => %s", expr, err.Error()) + return fmt.Errorf("can't parse filter expression") + } + return nil } // LiveTimeout 更新捕获失效时间 func (s *Packet) LiveTimeout(taskNo string, seconds int) error { - return packetTask.LiveTimeout(taskNo, seconds) + info, ok := s.taskMap.Load(taskNo) + if !ok { + return fmt.Errorf("task no: %s does not exist or has stopped", taskNo) + } + info.(*Task).Ticker.Reset(time.Duration(seconds) * time.Second) + return nil } // LiveStop 停止捕获数据 func (s *Packet) LiveStop(taskNo string) error { - return packetTask.LiveStop(taskNo) + info, ok := s.taskMap.Load(taskNo) + if !ok { + return fmt.Errorf("task no: %s does not exist or has stopped", taskNo) + } + info.(*Task).Ticker.Reset(time.Millisecond) + return nil } diff --git a/src/modules/trace/service/trace_data.go b/src/modules/trace/service/trace_data.go index 4a9ee7c6..8d26e51a 100644 --- a/src/modules/trace/service/trace_data.go +++ b/src/modules/trace/service/trace_data.go @@ -18,14 +18,14 @@ type TraceData struct { traceDataRepository *repository.TraceData } -// SelectPage 根据条件分页查询 -func (r *TraceData) SelectPage(query map[string]any) map[string]any { - return r.traceDataRepository.SelectPage(query) +// FindByPage 根据条件分页查询 +func (r *TraceData) FindByPage(query map[string]string) ([]model.TraceData, int64) { + return r.traceDataRepository.SelectByPage(query) } -// SelectById 通过ID查询 -func (r *TraceData) SelectById(id string) model.TraceData { - tasks := r.traceDataRepository.SelectByIds([]string{id}) +// FindById 通过ID查询 +func (r *TraceData) FindById(id int64) model.TraceData { + tasks := r.traceDataRepository.SelectByIds([]int64{id}) if len(tasks) > 0 { return tasks[0] } @@ -33,12 +33,12 @@ func (r *TraceData) SelectById(id string) model.TraceData { } // Insert 新增信息 -func (r *TraceData) Insert(task model.TraceData) string { +func (r *TraceData) Insert(task model.TraceData) int64 { return r.traceDataRepository.Insert(task) } // DeleteByIds 批量删除信息 -func (r *TraceData) DeleteByIds(ids []string) (int64, error) { +func (r *TraceData) DeleteByIds(ids []int64) (int64, error) { // 检查是否存在 rows := r.traceDataRepository.SelectByIds(ids) if len(rows) <= 0 { diff --git a/src/modules/trace/service/trace_task.go b/src/modules/trace/service/trace_task.go index 15f09976..ac75ac12 100644 --- a/src/modules/trace/service/trace_task.go +++ b/src/modules/trace/service/trace_task.go @@ -2,7 +2,6 @@ package service import ( "encoding/base64" - "encoding/json" "fmt" "net" "strings" @@ -13,6 +12,7 @@ import ( "be.ems/src/framework/utils/date" "be.ems/src/framework/utils/parse" neFetchlink "be.ems/src/modules/network_element/fetch_link" + neModel "be.ems/src/modules/network_element/model" neService "be.ems/src/modules/network_element/service" "be.ems/src/modules/trace/model" "be.ems/src/modules/trace/repository" @@ -37,20 +37,11 @@ type TraceTask struct { } // CreateUDP 创建UDP数据通道 -func (r *TraceTask) CreateUDP() error { +func (r TraceTask) CreateUDP() error { // 跟踪配置是否开启 - if v := config.Get("trace.enabled"); v != nil { - if !v.(bool) { - return nil - } - } - host := "127.0.0.1" - if v := config.Get("trace.host"); v != nil { - host = v.(string) - } - var port int64 = 33033 - if v := config.Get("trace.port"); v != nil { - port = parse.Number(v) + host, port, err := r.traceNotify() + if err != nil { + return err } // 初始化UDP服务 @@ -67,123 +58,117 @@ func (r *TraceTask) CreateUDP() error { } // 读取数据 - buf := make([]byte, 2048) + buf := make([]byte, 10*1048) n, addr, err := conn.ReadFromUDPAddrPort(buf) if err != nil { logger.Errorf("UDP Resolve ReadFromUDPAddrPort Error: %s", err.Error()) return } - logger.Infof("socket UDP: %s", string(buf[:n])) - // logger.Infof("socket UDP Base64: %s", base64.StdEncoding.EncodeToString(buf[:n])) - mData, err := UDPDataHandler(buf, n) - if err != nil { - logger.Errorf("UDP Resolve UDPDataHandler Error: %s", err.Error()) + // logger.Infof("socket UDP: %s", string(buf[:n])) + logger.Infof("socket UDP Base64 Encode: %s", base64.StdEncoding.EncodeToString(buf[:n])) + + // 解析数据 + if err := r.pasreUDPData(buf[:n]); err != nil { + logger.Errorf("UDP Resolve UDPData Error: %s", err.Error()) return } - taskId := parse.Number(mData["taskId"]) - - // 插入数据库做记录 - r.traceDataRepository.Insert(model.TraceData{ - TaskId: taskId, - IMSI: mData["imsi"].(string), - SrcAddr: mData["srcAddr"].(string), - DstAddr: mData["dstAddr"].(string), - IfType: parse.Number(mData["ifType"]), - MsgType: parse.Number(mData["msgType"]), - MsgDirect: parse.Number(mData["msgDirect"]), - Length: parse.Number(mData["dataLen"]), - RawMsg: mData["dataInfo"].(string), - Timestamp: parse.Number(mData["timestamp"]), - DecMsg: mData["decMsg"].(string), - }) - - // 推送文件 - if v, ok := mData["pcapFile"]; ok && v != "" { - logger.Infof("pcapFile: %s", v) - wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE_NE, taskId), taskId) - } // 发送响应 if _, err := conn.WriteToUDPAddrPort([]byte("udp>"), addr); err != nil { logger.Errorf("UDP Resolve WriteToUDPAddrPort Error: %s", err.Error()) } + buf = nil }) - // ============ 测试接收网元UDP发过来的数据 - // 初始化TCP服务 后续调整TODO - tcpService := socket.SocketTCP{Addr: host, Port: port + 1} - if _, err := tcpService.New(); err != nil { - return err - } - // 接收处理TCP数据 - go tcpService.Resolve(func(conn *net.Conn, err error) { - if err != nil { - logger.Errorf("TCP Resolve %s", err.Error()) - return + // ============ 本地测试接收网元UDP发过来的数据 后续调整TODO + if config.Env() == "local" { + // 初始化TCP服务 + tcpService := socket.SocketTCP{Addr: host, Port: port + 1} + if _, err := tcpService.New(); err != nil { + return err } + // 接收处理TCP数据 + go tcpService.Resolve(func(conn *net.Conn, err error) { + if err != nil { + logger.Errorf("TCP Resolve %s", err.Error()) + return + } - c := (*conn) - // 读取数据 - buf := make([]byte, 2048) - n, err := c.Read(buf) - if err != nil { - logger.Errorf("TCP Resolve Read Error: %s", err.Error()) - return - } + c := (*conn) + // 读取数据 + buf := make([]byte, 2048) + n, err := c.Read(buf) + if err != nil { + logger.Errorf("TCP Resolve Read Error: %s", err.Error()) + return + } - logger.Infof("socket TCP: %s", string(buf[:n])) - deData, _ := base64.StdEncoding.DecodeString(string(buf[:n])) - logger.Infof("socket TCP Base64: %s", deData) - mData, err := UDPDataHandler(deData, len(deData)) - if err != nil { - logger.Errorf("TCP Resolve UDPDataHandler Error: %s", err.Error()) - return - } - taskId := parse.Number(mData["taskId"]) + // logger.Infof("socket TCP: %s", string(buf[:n])) + deData, _ := base64.StdEncoding.DecodeString(string(buf[:n])) + // logger.Infof("socket TCP Base64 Decode: %s", deData) - // 插入数据库做记录 - r.traceDataRepository.Insert(model.TraceData{ - TaskId: taskId, - IMSI: mData["imsi"].(string), - SrcAddr: mData["srcAddr"].(string), - DstAddr: mData["dstAddr"].(string), - IfType: parse.Number(mData["ifType"]), - MsgType: parse.Number(mData["msgType"]), - MsgDirect: parse.Number(mData["msgDirect"]), - Length: parse.Number(mData["dataLen"]), - RawMsg: mData["dataInfo"].(string), - Timestamp: parse.Number(mData["timestamp"]), - DecMsg: mData["decMsg"].(string), + if err := r.pasreUDPData(deData); err != nil { + logger.Errorf("TCP Resolve UDPData Error: %s", err.Error()) + return + } + + // 发送响应 + if _, err = c.Write([]byte("tcp>")); err != nil { + logger.Errorf("TCP Resolve Write Error: %s", err.Error()) + } + buf = nil }) + } - // 推送文件 - if v, ok := mData["pcapFile"]; ok && v != "" { - logger.Infof("pcapFile: %s", v) - wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s%d", wsService.GROUP_TRACE_NE, taskId), taskId) - } - - // 发送响应 - if _, err = c.Write([]byte("tcp>")); err != nil { - logger.Errorf("TCP Resolve Write Error: %s", err.Error()) - } - }) return nil } +// pasreUDPData 解析数据 +func (r TraceTask) pasreUDPData(buf []byte) error { + data, err := traceHandler(buf) + if err != nil { + logger.Errorf("UDP Resolve UDPDataHandler Error: %s", err.Error()) + return err + } + taskId := parse.Number(data.NfTraceMsg.TraceId) + + // 插入数据库做记录 + item := model.TraceData{ + TraceId: taskId, + IMSI: data.NfTraceMsg.IMSI, + SrcAddr: data.NfTraceMsg.SrcIpStr, + DstAddr: data.NfTraceMsg.DstIpStr, + IfType: data.NfTraceMsg.IfType, + MsgType: data.NfTraceMsg.MsgType, + MsgDirect: data.NfTraceMsg.MsgDirect, + MsgNe: data.NfTraceMsg.NfName, + MsgEvent: data.NfTraceMsg.MsgEvent, + Length: int64(data.TracePayloadLen), + RawMsg: base64.StdEncoding.EncodeToString(data.TracePayload), + Timestamp: data.NfTraceMsg.Timestamp, + } + item.ID = r.traceDataRepository.Insert(item) + + // 推送到ws订阅组 + item.RawMsg = "" // 不推送原始数据 + wsService.NewWSSend.ByGroupID(fmt.Sprintf("%s_%d", wsService.GROUP_TRACE_NE, taskId), item) + return err +} + // CloseUDP 关闭UDP数据通道 -func (r *TraceTask) CloseUDP() { +func (r TraceTask) CloseUDP() { r.udpService.Close() } -// SelectPage 根据条件分页查询 -func (r *TraceTask) SelectPage(query map[string]any) map[string]any { - return r.traceTaskRepository.SelectPage(query) +// FindByPage 根据条件分页查询 +func (r TraceTask) FindByPage(query map[string]string) ([]model.TraceTask, int64) { + return r.traceTaskRepository.SelectByPage(query) } -// SelectById 通过ID查询 -func (r *TraceTask) SelectById(id string) model.TraceTask { - tasks := r.traceTaskRepository.SelectByIds([]string{id}) +// FindById 通过ID查询 +func (r TraceTask) FindById(id int64) model.TraceTask { + tasks := r.traceTaskRepository.SelectByIds([]int64{id}) if len(tasks) > 0 { return tasks[0] } @@ -191,12 +176,52 @@ func (r *TraceTask) SelectById(id string) model.TraceTask { } // Insert 新增信息 -func (r *TraceTask) Insert(task model.TraceTask) error { +func (r TraceTask) Insert(task model.TraceTask) error { // 跟踪配置是否开启 - if v := config.Get("trace.enabled"); v != nil { - if !v.(bool) { - return fmt.Errorf("tracking is not enabled") + host, port, err := r.traceNotify() + if err != nil { + return err + } + task.NotifyUrl = fmt.Sprintf("udp:%s:%d", host, port) + // 网元列表 + neList := strings.Split(task.NeList, ",") + if len(neList) <= 0 { + return fmt.Errorf("ne list is empty") + } + // 生成任务ID + traceId := r.traceTaskRepository.LastID() + 1 // 生成任务ID < 65535 + task.TraceId = fmt.Sprint(traceId) + + // 发送任务给网元 + for _, neTypeID := range neList { + neTypeIDArr := strings.Split(neTypeID, "_") + if len(neTypeIDArr) != 2 { + logger.Warnf("ne type id is error") + continue } + neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neTypeIDArr[0], neTypeIDArr[1]) + if neInfo.NeType != neTypeIDArr[0] || neInfo.IP == "" { + logger.Warnf("ne type id is not exist") + continue + } + if err := r.createTaskToNe(neInfo, task); err != nil { + logger.Errorf("task to %s error: %s", neTypeID, err.Error()) + return fmt.Errorf("task to %s error: %s", neTypeID, err.Error()) + } + } + + // 插入数据库 + insertId := r.traceTaskRepository.Insert(task) + if insertId <= 0 { + return fmt.Errorf("insert task error") + } + return nil +} + +// traceNotify 网元通知地址 +func (r TraceTask) traceNotify() (string, int64, error) { + if v := config.Get("trace.enabled"); !parse.Boolean(v) { + return "", 0, fmt.Errorf("trace is not enabled") } host := "127.0.0.1" if v := config.Get("trace.host"); v != nil { @@ -206,120 +231,43 @@ func (r *TraceTask) Insert(task model.TraceTask) error { if v := config.Get("trace.port"); v != nil { port = parse.Number(v) } - task.NotifyUrl = fmt.Sprintf("udp:%s:%d", host, port) + return host, port, nil +} - // 查询网元获取IP - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(task.NeType, task.NeId) - if neInfo.NeId != task.NeId || neInfo.IP == "" { - return fmt.Errorf("app.common.noNEInfo") - } - traceId := r.traceTaskRepository.LastID() + 1 // 生成任务ID < 65535 - task.TraceId = fmt.Sprint(traceId) - - // 发送任务给网元 - data := map[string]any{ - "neType": neInfo.NeType, - "neId": neInfo.NeId, - "notifyUrl": task.NotifyUrl, - "id": traceId, - "startTime": date.ParseDateToStr(task.StartTime, date.YYYY_MM_DD_HH_MM_SS), - "endTime": date.ParseDateToStr(task.EndTime, date.YYYY_MM_DD_HH_MM_SS), +// createTaskToNe 网元创建任务 +func (r TraceTask) createTaskToNe(neInfo neModel.NeInfo, task model.TraceTask) error { + data := model.TraceReq{ + TraceId: parse.Number(task.TraceId), + NotifyUrl: task.NotifyUrl, + StartTime: date.ParseDateToStr(task.StartTime, date.YYYY_MM_DD_HH_MM_SS), + EndTime: date.ParseDateToStr(task.EndTime, date.YYYY_MM_DD_HH_MM_SS), } switch task.TraceType { case "1": // Interface - data["traceType"] = "Interface" - data["interfaces"] = strings.Split(task.Interfaces, ",") + data.TraceType = "Interface" + data.Interfaces = strings.Split(task.Interfaces, ",") case "2": // Device - data["traceType"] = "Device" - data["ueIp"] = task.UeIp - data["srcIp"] = task.SrcIp - data["dstIp"] = task.DstIp - data["signalPort"] = task.SignalPort - task.UeIp = neInfo.IP + data.TraceType = "Device" + data.SrcIp = task.SrcIp + data.DstIp = task.DstIp case "3": // UE - data["traceType"] = "UE" - data["imsi"] = task.IMSI - data["msisdn"] = task.MSISDN + data.TraceType = "UE" + data.IMSI = fmt.Sprintf("imsi-%s", task.IMSI) default: - return fmt.Errorf("trace type is not disabled") + return fmt.Errorf("trace type is not support") } msg, err := neFetchlink.NeTraceAdd(neInfo, data) if err != nil { return err } - s, _ := json.Marshal(msg) - task.FetchMsg = string(s) - - // 插入数据库 - r.traceTaskRepository.Insert(task) - return nil -} - -// Update 修改信息 -func (r *TraceTask) Update(task model.TraceTask) error { - // 跟踪配置是否开启 - if v := config.Get("trace.enabled"); v != nil { - if !v.(bool) { - return fmt.Errorf("tracking is not enabled") - } + if v, ok := msg["cause"]; ok { + return fmt.Errorf("trace task add failed, %v", v) } - host := "127.0.0.1" - if v := config.Get("trace.host"); v != nil { - host = v.(string) - } - var port int64 = 33033 - if v := config.Get("trace.port"); v != nil { - port = parse.Number(v) - } - task.NotifyUrl = fmt.Sprintf("udp:%s:%d", host, port) - - // 查询网元获取IP - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(task.NeType, task.NeId) - if neInfo.NeId != task.NeId || neInfo.IP == "" { - return fmt.Errorf("app.common.noNEInfo") - } - - // 查询网元任务信息 - if msg, err := neFetchlink.NeTraceInfo(neInfo, task.TraceId); err == nil { - s, _ := json.Marshal(msg) - task.FetchMsg = string(s) - // 修改任务信息 - data := map[string]any{ - "neType": neInfo.NeType, - "neId": neInfo.NeId, - "notifyUrl": task.NotifyUrl, - "id": parse.Number(task.TraceId), - "startTime": date.ParseDateToStr(task.StartTime, date.YYYY_MM_DD_HH_MM_SS), - "endTime": date.ParseDateToStr(task.EndTime, date.YYYY_MM_DD_HH_MM_SS), - } - switch task.TraceType { - case "1": // Interface - data["traceType"] = "Interface" - data["interfaces"] = strings.Split(task.Interfaces, ",") - case "2": // Device - task.UeIp = neInfo.IP - data["traceType"] = "Device" - data["ueIp"] = task.UeIp - data["srcIp"] = task.SrcIp - data["dstIp"] = task.DstIp - data["signalPort"] = task.SignalPort - case "3": // UE - data["traceType"] = "UE" - data["imsi"] = task.IMSI - data["msisdn"] = task.MSISDN - default: - return fmt.Errorf("trace type is not disabled") - } - neFetchlink.NeTraceEdit(neInfo, data) - } - - // 更新数据库 - r.traceTaskRepository.Update(task) return nil } // DeleteByIds 批量删除信息 -func (r *TraceTask) DeleteByIds(ids []string) (int64, error) { +func (r TraceTask) DeleteByIds(ids []int64) (int64, error) { // 检查是否存在 rows := r.traceTaskRepository.SelectByIds(ids) if len(rows) <= 0 { @@ -327,14 +275,30 @@ func (r *TraceTask) DeleteByIds(ids []string) (int64, error) { } if len(rows) == len(ids) { - // 停止任务 + // 删除数据同时给网元发送停止任务 for _, v := range rows { - neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(v.NeType, v.NeId) - if neInfo.NeId != v.NeId || neInfo.IP == "" { + // 删除数据 + r.traceDataRepository.DeleteByTraceId(v.TraceId) + + // 网元列表 + neList := strings.Split(v.NeList, ",") + if len(neList) <= 0 { continue } - neFetchlink.NeTraceDelete(neInfo, v.TraceId) + // 停止任务 + for _, neTypeID := range neList { + neTypeIDArr := strings.Split(neTypeID, "_") + if len(neTypeIDArr) != 2 { + continue + } + neInfo := neService.NewNeInfo.SelectNeInfoByNeTypeAndNeID(neTypeIDArr[0], neTypeIDArr[1]) + if neInfo.NeType != neTypeIDArr[0] || neInfo.IP == "" { + continue + } + neFetchlink.NeTraceDelete(neInfo, v.TraceId) + } } + num := r.traceTaskRepository.DeleteByIds(ids) return num, nil } diff --git a/src/modules/trace/service/trace_task_hlr.go b/src/modules/trace/service/trace_task_hlr.go index 791cc12c..2768f614 100644 --- a/src/modules/trace/service/trace_task_hlr.go +++ b/src/modules/trace/service/trace_task_hlr.go @@ -26,14 +26,14 @@ type TraceTaskHlr struct { neInfoService *neService.NeInfo // 网元信息服务 } -// SelectPage 根据条件分页查询 -func (r *TraceTaskHlr) SelectPage(querys model.TraceTaskHlrQuery) map[string]any { - return r.traceTaskHlrRepository.SelectPage(querys) +// FindByPage 根据条件分页查询 +func (r *TraceTaskHlr) FindByPage(querys model.TraceTaskHlrQuery) ([]model.TraceTaskHlr, int64) { + return r.traceTaskHlrRepository.SelectByPage(querys) } -// SelectById 通过ID查询 -func (r *TraceTaskHlr) SelectById(id string) model.TraceTaskHlr { - tasks := r.traceTaskHlrRepository.SelectByIds([]string{id}) +// FindById 通过ID查询 +func (r *TraceTaskHlr) FindById(id int64) model.TraceTaskHlr { + tasks := r.traceTaskHlrRepository.SelectByIds([]int64{id}) if len(tasks) > 0 { return tasks[0] } @@ -41,7 +41,7 @@ func (r *TraceTaskHlr) SelectById(id string) model.TraceTaskHlr { } // Insert 新增信息 -func (r *TraceTaskHlr) Insert(task model.TraceTaskHlr) string { +func (r *TraceTaskHlr) Insert(task model.TraceTaskHlr) int64 { return r.traceTaskHlrRepository.Insert(task) } @@ -51,7 +51,7 @@ func (r *TraceTaskHlr) Update(task model.TraceTaskHlr) int64 { } // DeleteByIds 批量删除信息 -func (r *TraceTaskHlr) DeleteByIds(ids []string) (int64, error) { +func (r *TraceTaskHlr) DeleteByIds(ids []int64) (int64, error) { // 检查是否存在 rows := r.traceTaskHlrRepository.SelectByIds(ids) if len(rows) <= 0 { @@ -79,7 +79,7 @@ func (r *TraceTaskHlr) DeleteByIds(ids []string) (int64, error) { } // Start 创建任务 -func (r *TraceTaskHlr) Start(task model.TraceTaskHlr) (string, error) { +func (r *TraceTaskHlr) Start(task model.TraceTaskHlr) (int64, error) { hlrList := []map[string]any{} traceId := r.traceTaskHlrRepository.LastID() + 1 // 生成任务ID < 65535 data := map[string]any{ @@ -88,7 +88,7 @@ func (r *TraceTaskHlr) Start(task model.TraceTaskHlr) (string, error) { "msisdn": task.MSISDN, } if task.StartTime > task.EndTime { - return "", fmt.Errorf("startTime must less than endTime") + return 0, fmt.Errorf("startTime must less than endTime") } if task.StartTime > 0 { data["startTime"] = date.ParseDateToStr(task.StartTime, date.YYYY_MM_DDTHH_MM_SSZ) @@ -119,8 +119,8 @@ func (r *TraceTaskHlr) Start(task model.TraceTaskHlr) (string, error) { task.Status = "1" task.TraceId = fmt.Sprint(traceId) id := r.traceTaskHlrRepository.Insert(task) - if id == "" { - return "", fmt.Errorf("start task fail") + if id <= 0 { + return 0, fmt.Errorf("start task fail") } return id, nil } diff --git a/src/modules/trace/service/trace_task_udp_data.go b/src/modules/trace/service/trace_task_udp_data.go index 2f007f38..2722566c 100644 --- a/src/modules/trace/service/trace_task_udp_data.go +++ b/src/modules/trace/service/trace_task_udp_data.go @@ -1,334 +1,271 @@ package service import ( - "encoding/base64" + "bytes" "encoding/binary" "fmt" + "net" "os" "path/filepath" "runtime" - "strings" "time" - "golang.org/x/net/http/httpguts" - "golang.org/x/net/http2/hpack" + "be.ems/src/modules/trace/model" ) -const ( - GTPU_V1_VERSION = 1 << 5 - GTPU_VER_MASK = 7 << 5 - GTPU_PT_GTP = 1 << 4 - GTPU_HEADER_LEN = 12 - GTPU_E_S_PB_BIT = 7 - GTPU_E_BI = 1 << 2 -) - -const ( - GTPU_HEADER_VERSION_INDEX = 0 - GTPU_HEADER_MSG_TYPE_INDEX = 1 - GTPU_HEADER_LENGTH_INDEX = 2 - GTPU_HEADER_TEID_INDEX = 4 -) - -type ExtHeader struct { - TaskId uint32 - IMSI string - IfType int - MsgType int - MsgDirect int // 0-recv,1-send - TimeStamp int64 - SrcIP string - DstIP string - SrcPort uint16 - DstPort uint16 - Proto int // Protocol - PPI int // only for SCTP - DataLen uint16 - DataInfo []byte +// TraceMsgToOamTraceData 结构体定义 +type TraceMsgToOamTraceData struct { + NfTraceMsg *model.TraceMsg + TimestampStr string + TracePayloadLen uint16 + TracePayload []byte } -// parseUDPData 解析UDP数据 -func parseUDPData(rvMsg []byte, rvLen int) (ExtHeader, error) { - var extHdr ExtHeader - // var tr dborm.TraceData - var off int - msg := rvMsg - - verFlags := msg[GTPU_HEADER_VERSION_INDEX] - - gtpuHdrLen := GTPU_HEADER_LEN - - localTeid := binary.BigEndian.Uint32(msg[GTPU_HEADER_TEID_INDEX:]) - - extHdr.TaskId = localTeid - - if (verFlags & GTPU_E_S_PB_BIT) != 0 { - if (verFlags & GTPU_E_BI) != 0 { - extTypeIndex := GTPU_HEADER_LEN - 1 - - extType := msg[extTypeIndex] - - if extType == 0xFE { - extHdr.IMSI = string(msg[extTypeIndex+2 : extTypeIndex+17]) - extHdr.IfType = int(msg[extTypeIndex+17]) - extHdr.MsgType = int(msg[extTypeIndex+18]) - extHdr.MsgDirect = int(msg[extTypeIndex+19]) - - extHdr.TimeStamp = time.Now().UTC().UnixMilli() - // extHdr.TimeStamp = int64(binary.BigEndian.Uint64(msg[extTypeIndex+19:])) - // fmt.Printf("ext info %v %s %d %d %d \n", msg[(extTypeIndex+2):(extTypeIndex+20)], extHdr.IMSI, extHdr.IfType, extHdr.MsgType, extHdr.MsgDirect) - // set offset of IP Packet - off = 40 + 4 - //src ip: msg+40+12 - extHdr.SrcIP = fmt.Sprintf("%d.%d.%d.%d", msg[off+12], msg[off+13], msg[off+14], msg[off+15]) - //dst ip: msg+40+12+4 - extHdr.DstIP = fmt.Sprintf("%d.%d.%d.%d", msg[off+16], msg[off+17], msg[off+18], msg[off+19]) - extHdr.SrcPort = uint16(binary.BigEndian.Uint16(msg[off+20:])) - extHdr.DstPort = uint16(binary.BigEndian.Uint16(msg[off+22:])) - // fmt.Printf("info %s:%d %s:%d \n", extHdr.SrcIP, extHdr.SrcPort, extHdr.DstIP, extHdr.DstPort) - // ip header start msg+40 - extHdr.DataLen = uint16(rvLen - off) - extHdr.DataInfo = make([]byte, int(rvLen-off)) - copy(extHdr.DataInfo, []byte(msg[off:])) - - // 132 SCTP - // 6 TCP - // 17 UDP - extHdr.Proto = int(msg[off+9]) - if extHdr.Proto == 132 { - extHdr.PPI = int(msg[off+47]) - extHdr.DataLen = uint16(binary.BigEndian.Uint16(msg[(off+34):]) - 16) - // fmt.Printf("dat len %d %d \n", extHdr.DataLen, extHdr.PPI) - } - } - - for extType != 0 && extTypeIndex < rvLen { - extLen := msg[extTypeIndex+1] << 2 - if extLen == 0 { - return extHdr, fmt.Errorf("error, extLen is zero") - } - - gtpuHdrLen += int(extLen) - extTypeIndex += int(extLen) - extType = msg[extTypeIndex] - } - } - } else { - gtpuHdrLen -= 4 - } - return extHdr, nil -} - -// UDPDataHandler UDP数据处理 -func UDPDataHandler(data []byte, n int) (map[string]any, error) { - extHdr, err := parseUDPData(data, n) +// traceHandler 处理跟踪数据 +func traceHandler(data []byte) (*TraceMsgToOamTraceData, error) { + decodeData, err := decodeTraceData(data) if err != nil { - return nil, err + return decodeData, err } - if extHdr.TaskId == 0 || extHdr.DataLen < 1 { - return nil, fmt.Errorf("data error") + fmt.Printf("TraceHandler get oamData: %s,%+v\n, payload=len(%d,%d)", decodeData.TimestampStr, decodeData.NfTraceMsg, decodeData.TracePayloadLen, len(decodeData.TracePayload)) + // Return parsed message and payload + if len(decodeData.TracePayload) != int(decodeData.TracePayloadLen) { + return decodeData, fmt.Errorf("trace payload is bad, len=%d, shall be:%d", len(decodeData.TracePayload), int(decodeData.TracePayloadLen)) } - m := map[string]any{ - "taskId": extHdr.TaskId, - "imsi": extHdr.IMSI, - "ifType": extHdr.IfType, - "srcAddr": fmt.Sprintf("%s:%d", extHdr.SrcIP, extHdr.SrcPort), - "dstAddr": fmt.Sprintf("%s:%d", extHdr.DstIP, extHdr.DstPort), - "msgType": extHdr.MsgType, - "msgDirect": extHdr.MsgDirect, - "timestamp": extHdr.TimeStamp, - "dataLen": extHdr.DataLen, - // "dataInfo": extHdr.DataInfo, - "decMsg": "", - } - // Base64 编码 - m["dataInfo"] = base64.StdEncoding.EncodeToString(extHdr.DataInfo) - - if extHdr.Proto == 6 { // TCP - // 取响应数据 - iplen := uint16(binary.BigEndian.Uint16(extHdr.DataInfo[2:])) - tcplen := uint16(iplen - 32 - 20) - hdrlen := uint16(binary.BigEndian.Uint16(extHdr.DataInfo[20+32+1:])) - offset := uint16(52) - // fmt.Printf("HTTP %d %d %d \n", iplen, tcplen, hdrlen) - if tcplen > (hdrlen + 9) { // has data - doffset := uint16(offset + hdrlen + 9) - datlen := uint16(binary.BigEndian.Uint16(extHdr.DataInfo[doffset+1:])) - // fmt.Printf("HTTP datlen %d \n", datlen) - m["decMsg"], _ = httpDataMsg(extHdr.DataInfo[offset+9:offset+9+hdrlen], extHdr.DataInfo[doffset+9:doffset+datlen+9]) - } else { - m["decMsg"], _ = httpDataMsg(extHdr.DataInfo[offset+9:hdrlen], nil) - } - } - - // pcap文件 - m["pcapFile"] = writePcap(extHdr) - return m, nil -} - -// =========== TCP协议Body =========== - -// httpDataMsg Http数据信息处理 -func httpDataMsg(header []byte, data []byte) (string, error) { - var remainSize = uint32(16 << 20) - var sawRegular bool - var invalid bool // pseudo header field errors - var Fields []hpack.HeaderField - - invalid = false - hdec := hpack.NewDecoder(4096, nil) - hdec.SetEmitEnabled(true) - hdec.SetMaxStringLength(int(16 << 20)) - hdec.SetEmitFunc(func(hf hpack.HeaderField) { - if !httpguts.ValidHeaderFieldValue(hf.Value) { - // Don't include the value in the error, because it may be sensitive. - invalid = true - } - isPseudo := strings.HasPrefix(hf.Name, ":") - if isPseudo { - if sawRegular { - invalid = true - } - } else { - sawRegular = true - if !validWireHeaderFieldName(hf.Name) { - invalid = true - } - } - - if invalid { - hdec.SetEmitEnabled(false) - return - } - - size := hf.Size() - if size > remainSize { - hdec.SetEmitEnabled(false) - //mh.Truncated = true - return - } - remainSize -= size - - Fields = append(Fields, hf) - }) - - // defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {}) - - frag := header - if _, err := hdec.Write(frag); err != nil { - return "", err - } - - if err := hdec.Close(); err != nil { - return "", err - } - - // hdec.SetEmitFunc(func(hf hpack.HeaderField) {}) - - var headers []byte - var line string - for i := range Fields { - line = fmt.Sprintf("\"%s\":\"%s\",", Fields[i].Name, Fields[i].Value) - headers = append(headers, []byte(line)...) - } - - if len(data) > 0 { - return fmt.Sprintf("{ %s \"content\":%s }", string(headers), string(data)), nil - } else { - return fmt.Sprintf("{ %s }", string(headers)), nil - } -} - -// validWireHeaderFieldName 校验报文头字段名称 -func validWireHeaderFieldName(v string) bool { - if len(v) == 0 { - return false - } - for _, r := range v { - if !httpguts.IsTokenRune(r) { - return false - } - if 'A' <= r && r <= 'Z' { - return false - } - } - return true -} - -// =========== writePcap 写Pcap文件 =========== - -const magicMicroseconds = 0xA1B2C3D4 -const versionMajor = 2 -const versionMinor = 4 - -func writeEmptyPcap(filename string, timeStamp int64, length int, data []byte) error { - var err error - var file *os.File - if err := os.MkdirAll(filepath.Dir(filename), 0775); err != nil { - return err - } - if _, err = os.Stat(filename); os.IsNotExist(err) { - file, err = os.Create(filename) - // File Header - var fileHeaderBuf [24]byte - binary.LittleEndian.PutUint32(fileHeaderBuf[0:4], magicMicroseconds) - binary.LittleEndian.PutUint16(fileHeaderBuf[4:6], versionMajor) - binary.LittleEndian.PutUint16(fileHeaderBuf[6:8], versionMinor) - // bytes 8:12 stay 0 (timezone = UTC) - // bytes 12:16 stay 0 (sigfigs is always set to zero, according to - // http://wiki.wireshark.org/Development/LibpcapFileFormat - binary.LittleEndian.PutUint32(fileHeaderBuf[16:20], 0x00040000) - binary.LittleEndian.PutUint32(fileHeaderBuf[20:24], 0x00000071) - if _, err := file.Write(fileHeaderBuf[:]); err != nil { - return err - } - } else { - file, err = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND, 0666) - } - if err != nil { - return err - } - defer file.Close() - - // Packet Header - var packetHeaderBuf [24]byte - t := time.UnixMilli(timeStamp) - if t.IsZero() { - t = time.Now() - } - secs := t.Unix() - usecs := t.Nanosecond() / 1000 - binary.LittleEndian.PutUint32(packetHeaderBuf[0:4], uint32(secs)) - binary.LittleEndian.PutUint32(packetHeaderBuf[4:8], uint32(usecs)) - binary.LittleEndian.PutUint32(packetHeaderBuf[8:12], uint32(length+16)) - binary.LittleEndian.PutUint32(packetHeaderBuf[12:16], uint32(length+16)) - if _, err := file.Write(packetHeaderBuf[:]); err != nil { - return err - } - - // 数据包内容的定义 - cooked := [...]byte{0x00, 0x00, 0x03, 0x04, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00} - if _, err := file.Write(cooked[:]); err != nil { - return err - } - - // Packet Data - if _, err := file.Write(data); err != nil { - return err - } - return nil -} - -// writePcap 写Pcap文件并返回文件路径 -func writePcap(extHdr ExtHeader) string { - filePath := fmt.Sprintf("/tmp/omc/trace/task_%d.pcap", extHdr.TaskId) + // 输出到文件 + filePath := fmt.Sprintf("/tmp/omc/trace/task_%d.pcap", decodeData.NfTraceMsg.TraceId) if runtime.GOOS == "windows" { filePath = fmt.Sprintf("C:%s", filePath) } - err := writeEmptyPcap(filePath, extHdr.TimeStamp, int(extHdr.DataLen), extHdr.DataInfo) - if err != nil { - return "" - } - return filePath + err = writePCAP(filePath, decodeData.NfTraceMsg.Timestamp, decodeData.TracePayload) + + return decodeData, err +} + +// decodeTraceData 解析跟踪数据 +func decodeTraceData(data []byte) (*TraceMsgToOamTraceData, error) { + buf := bytes.NewBuffer(data) + oamData := new(TraceMsgToOamTraceData) + msg := new(model.TraceMsg) + + // 1. Parse Flag (1 byte) + var flag uint8 + if err := binary.Read(buf, binary.BigEndian, &flag); err != nil { + return nil, err + } + + // Parse message type (bits 1-2) + switch flag & 0x3 { + case 0x1: + msg.MsgType = model.MSG_TYPE_REQ + case 0x2: + msg.MsgType = model.MSG_TYPE_RSP + } + + // Parse message direction (bits 3-4) + switch flag & 0xc { + case 0x4: + msg.MsgDirect = model.MSG_DIRECT_SEND + case 0x8: + msg.MsgDirect = model.MSG_DIRECT_RECV + } + + // 2. Parse TraceId (4 bytes) + var traceId uint32 + if err := binary.Read(buf, binary.BigEndian, &traceId); err != nil { + return nil, err + } + msg.TraceId = int(traceId) + + // 3. Parse IMSI (15 bytes fixed length) + imsi := make([]byte, 15) + if _, err := buf.Read(imsi); err != nil { + return nil, err + } + msg.IMSI = string(imsi) + + // 4. Parse IfType (1 byte) + ifTypeByte, err := buf.ReadByte() + if err != nil { + return nil, err + } + msg.IfType = byte2Iftype(ifTypeByte) + + // 5. Parse Timestamp (8 bytes) + if err := binary.Read(buf, binary.BigEndian, &msg.Timestamp); err != nil { + return nil, err + } + + // 6. Parse SrcIp (4 bytes IPv4) + srcIp := make([]byte, 4) + if flag&0x20 != 0 { + srcIp = make([]byte, 16) + } + if _, err := buf.Read(srcIp); err != nil { + return nil, err + } + msg.SrcIpStr = net.IP(srcIp).String() + // 7. Parse DstIp (4 bytes IPv4) + dstIp := make([]byte, 4) + if flag&0x20 != 0 { + dstIp = make([]byte, 16) + } + if _, err := buf.Read(dstIp); err != nil { + return nil, err + } + msg.DstIpStr = net.IP(dstIp).String() + + // 8. Parse NfName (variable length) + nfNameLen, err := buf.ReadByte() + if err != nil { + return nil, err + } + nfName := make([]byte, nfNameLen) + if _, err := buf.Read(nfName); err != nil { + return nil, err + } + msg.NfName = string(nfName) + + // 9. Parse MsgEvent (variable length) + msgEventLen, err := buf.ReadByte() + if err != nil { + return nil, err + } + msgEvent := make([]byte, msgEventLen) + if _, err := buf.Read(msgEvent); err != nil { + return nil, err + } + msg.MsgEvent = string(msgEvent) + + // 10. Parse ExtenBuf (variable length) + extenBufLen, err := buf.ReadByte() + if err != nil { + return nil, err + } + if extenBufLen > 0 { + extenBuf := make([]byte, extenBufLen) + if _, err := buf.Read(extenBuf); err != nil { + return nil, err + } + // TODO: Parse extended fields according to actual protocol + } + // 11. len of payload(2 byte) + var len uint16 + if err := binary.Read(buf, binary.BigEndian, &len); err != nil { + return nil, err + } + + oamData.NfTraceMsg = msg + oamData.TimestampStr = time.Unix(0, msg.Timestamp).Format("2006-01-02 15:04:05.999999999") + oamData.TracePayloadLen = len + oamData.TracePayload = buf.Bytes() + return oamData, nil +} + +// byte2Iftype 将字节转换为接口类型字符串 +// 参考:3GPP TS 32.422 V17.0.0 (2022-06) 5G; 3GPP TS 29.244 V17.0.0 (2022-06) 5G +func byte2Iftype(val uint8) string { + ret := "" + switch val { + case 1: + ret = "N1" + case 2: + ret = "N2" + case 3: + ret = "N1/N2" + case 4: + ret = "N4" + case 7: + ret = "N7" + case 8: + ret = "N8" + case 10: + ret = "N10" + case 11: + ret = "N11" + case 12: + ret = "N12" + case 13: + ret = "N13" + case 15: + ret = "N15" + } + return ret +} + +// writePCAP 写入PCAP文件 +func writePCAP(filename string, timeStamp int64, data []byte) error { + var err error + var file *os.File + + // 1. 创建目录(含权限控制) + if err := os.MkdirAll(filepath.Dir(filename), 0775); err != nil { + return err + } + + // 2. 智能打开文件(原子操作避免竞态) + if _, err = os.Stat(filename); os.IsNotExist(err) { + file, err = os.Create(filename) + if err != nil { + return err + } + // 写入PCAP全局头(严格兼容Wireshark) + fileHeader := [24]byte{ + 0xD4, 0xC3, 0xB2, 0xA1, // magic_number (微秒级) + 0x02, 0x00, 0x04, 0x00, // version_major(2) + version_minor(4) + 0x00, 0x00, 0x00, 0x00, // thiszone (UTC) + 0x00, 0x00, 0x00, 0x00, // sigfigs (固定0) + 0x00, 0x00, 0x04, 0x00, // snaplen (1024) + 0x71, 0x00, 0x00, 0x00, // network (LINKTYPE_LINUX_SLL) + } + if _, err := file.Write(fileHeader[:]); err != nil { + return err + } + } else { + // 追加模式打开(避免截断已有内容) + file, err = os.OpenFile(filename, os.O_WRONLY|os.O_APPEND|os.O_SYNC, 0666) + if err != nil { + return err + } + } + defer file.Close() + + // 3. 构造Linux cooked头(RFC 3580规范) + linuxSLLHeaderLen := 16 // Linux cooked模式头长度 + cookedHeader := make([]byte, linuxSLLHeaderLen) + binary.BigEndian.PutUint16(cookedHeader[0:2], 0x0000) // 数据包类型(主机→网络) + binary.BigEndian.PutUint16(cookedHeader[2:4], 0x0304) // 地址类型(ARPHRD_ETHER) + binary.BigEndian.PutUint16(cookedHeader[4:6], 0x0008) // 协议类型(ETH_P_IP) + binary.BigEndian.PutUint16(cookedHeader[14:16], 0x0800) // 数据包类型(PACKET_HOST) + + // 4. 合并链路层头与数据(兼容IPv4选项) + fullData := append(cookedHeader, data...) + pktLen := len(fullData) + + // 5. 生成精确时间戳(处理闰秒和时区) + t := time.Unix(0, timeStamp).UTC() + if t.IsZero() { + t = time.Now().UTC() + } + secs := t.Unix() + usecs := t.Nanosecond() / 1000 // 微秒级时间戳 + + // 6. 构造PCAP报文头(16字节) + var packetHeader [16]byte + binary.LittleEndian.PutUint32(packetHeader[0:4], uint32(secs)) // 时间戳秒 + binary.LittleEndian.PutUint32(packetHeader[4:8], uint32(usecs)) // 时间戳微秒 + binary.LittleEndian.PutUint32(packetHeader[8:12], uint32(pktLen)) // 捕获长度 + binary.LittleEndian.PutUint32(packetHeader[12:16], uint32(pktLen)) // 原始长度 + + // 7. 原子写入操作(避免部分写入) + buf := new(bytes.Buffer) + buf.Write(packetHeader[:]) + buf.Write(fullData) + if _, err := file.Write(buf.Bytes()); err != nil { + return err + } + + // 8. 强制刷盘并验证写入 + return file.Sync() } diff --git a/src/modules/trace/trace.go b/src/modules/trace/trace.go index 0fe3b742..273a2c4a 100644 --- a/src/modules/trace/trace.go +++ b/src/modules/trace/trace.go @@ -63,6 +63,10 @@ func Setup(router *gin.Engine) { middleware.PreAuthorize(nil), controller.NewPacket.KeepAlive, ) + packetGroup.GET("/filePull", + middleware.PreAuthorize(nil), + controller.NewPacket.FilePull, + ) } // 跟踪任务 网元HLR (免登录) @@ -71,7 +75,7 @@ func Setup(router *gin.Engine) { taskHLRGroup.GET("/list", controller.NewTraceTaskHlr.List, ) - taskHLRGroup.DELETE("/:ids", + taskHLRGroup.DELETE("/:id", controller.NewTraceTaskHlr.Remove, ) taskHLRGroup.POST("/start", @@ -104,12 +108,7 @@ func Setup(router *gin.Engine) { collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.task", collectlogs.BUSINESS_TYPE_INSERT)), controller.NewTraceTask.Add, ) - taskGroup.PUT("", - middleware.PreAuthorize(nil), - collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.task", collectlogs.BUSINESS_TYPE_UPDATE)), - controller.NewTraceTask.Edit, - ) - taskGroup.DELETE("/:ids", + taskGroup.DELETE("/:id", middleware.PreAuthorize(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.task", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewTraceTask.Remove, @@ -127,7 +126,11 @@ func Setup(router *gin.Engine) { middleware.PreAuthorize(nil), controller.NewTraceData.List, ) - taskDataGroup.DELETE("/:ids", + taskDataGroup.GET("/:id", + middleware.PreAuthorize(nil), + controller.NewTraceData.Info, + ) + taskDataGroup.DELETE("/:id", middleware.PreAuthorize(nil), collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.taskData", collectlogs.BUSINESS_TYPE_DELETE)), controller.NewTraceData.Remove,