diff --git a/0008-add-command-check-config-check-test-case.patch b/0008-add-command-check-config-check-test-case.patch new file mode 100644 index 0000000..6e21808 --- /dev/null +++ b/0008-add-command-check-config-check-test-case.patch @@ -0,0 +1,324 @@ +From eb0e130cc72a9d5d6f6e53fa96d74a11a3b8f6eb Mon Sep 17 00:00:00 2001 +From: LHesperus <2639350497@qq.com> +Date: Sat, 25 Nov 2023 15:45:14 +0800 +Subject: [PATCH] add command check, config check , test case + +--- + extra-tools/da-tool/script/da-tool.sh | 68 +++++++++++++++++- + .../da-tool/test/config_check/config_check.sh | 70 +++++++++++++++++++ + .../test/config_check/config_test1.conf | 2 + + .../test/config_check/config_test2.conf | 2 + + .../test/config_check/config_test3.conf | 2 + + .../test/config_check/config_test4.conf | 2 + + .../test/config_check/config_test5.conf | 2 + + .../test/config_check/config_test6.conf | 2 + + .../test/config_check/config_test7.conf | 2 + + extra-tools/da-tool/test/opt_test/opt_test.sh | 49 +++++++++++++ + 10 files changed, 198 insertions(+), 3 deletions(-) + create mode 100755 extra-tools/da-tool/test/config_check/config_check.sh + create mode 100644 extra-tools/da-tool/test/config_check/config_test1.conf + create mode 100644 extra-tools/da-tool/test/config_check/config_test2.conf + create mode 100644 extra-tools/da-tool/test/config_check/config_test3.conf + create mode 100644 extra-tools/da-tool/test/config_check/config_test4.conf + create mode 100644 extra-tools/da-tool/test/config_check/config_test5.conf + create mode 100644 extra-tools/da-tool/test/config_check/config_test6.conf + create mode 100644 extra-tools/da-tool/test/config_check/config_test7.conf + create mode 100644 extra-tools/da-tool/test/opt_test/opt_test.sh + +diff --git a/extra-tools/da-tool/script/da-tool.sh b/extra-tools/da-tool/script/da-tool.sh +index efc9592..a25c347 100755 +--- a/extra-tools/da-tool/script/da-tool.sh ++++ b/extra-tools/da-tool/script/da-tool.sh +@@ -96,7 +96,7 @@ while getopts "t:h" opt; do + is_sample_with_analysis=false + ;; + t) +- if [[ $OPTARG =~ ^[0-9]+$ ]]; then ++ if [[ $OPTARG =~ ^[0-9]{1,3}$ ]]; then + sleep_time=$OPTARG + else + usage +@@ -122,6 +122,13 @@ while getopts "t:h" opt; do + esac + done + ++shift $((OPTIND - 1)) ++if [[ $# -ne 0 ]]; then ++ echo "Illegal parameter :$@" ++ usage ++ exit 1 ++fi ++ + function config_display() { + echo "kernel_symbols:" >>$sample_log + for item in "${kernel_symbols[@]}"; do +@@ -154,7 +161,57 @@ function arr_repet_ele_check() { + for element in "${arr[@]}"; do + count=$(printf '%s\n' "${arr[@]}" | grep -c -w "$element") + if [ $count -ge 2 ]; then +- echo " '$element' duplicate configuration, please check '$config_file'" ++ echo " '$element' duplicate configuration, please check '$config_file'!!!" ++ exit 1 ++ fi ++ done ++} ++ ++# function names cannot contain '.' ++function arr_check_function_support() { ++ local symbols_tmp=("$@") ++ for symbol in "${symbols_tmp[@]}"; do ++ if [[ $symbol =~ \. ]]; then ++ echo "$symbol have '.', not support, please check '$config_file!!!'" | tee -a $sample_log ++ exit 1 ++ fi ++ done ++} ++ ++# kernel symbols should be found in '/proc/kallsyms' ++function arr_check_kernel_symbols_exist() { ++ local symbols_tmp=("$@") ++ for symbol in "${symbols_tmp[@]}"; do ++ if grep "\<$symbol\>" /proc/kallsyms >/dev/null; then ++ echo "$symbol exist in /proc/kallsyms" >>$sample_log ++ else ++ echo "$symbol does not exist in /proc/kallsyms, please check '$config_file'!!!" | tee -a $sample_log ++ exit 1 ++ fi ++ done ++} ++ ++# user symbols should be found by 'nm bin' ++function arr_check_user_symbols_exist() { ++ binary=$1 ++ local symbols_tmp=("${@:2}") ++ for symbol in "${symbols_tmp[@]}"; do ++ if nm "$binary" | grep -q "\<$symbol\>"; then ++ echo "$symbol dost exist in $binary" >>$sample_log ++ else ++ echo "$symbol does not exist in $binary, please check '$config_file'!!!" | tee -a $sample_log ++ exit 1 ++ fi ++ done ++} ++ ++function arr_check_sched() { ++ local sched_tmp=("$@") ++ for sched in "${sched_tmp[@]}"; do ++ if [[ $sched == "sched_switch" ]]; then ++ echo "sched_switch match" >>$sample_log ++ else ++ echo "s only support sched_switch, please check '$config_file'!!!" | tee -a $sample_log + exit 1 + fi + done +@@ -162,7 +219,10 @@ function arr_repet_ele_check() { + + function config_file_check() { + arr_repet_ele_check ${kernel_symbols[@]} # check kernel +- arr_repet_ele_check ${sched_symbols[@]} # check sched ++ arr_check_kernel_symbols_exist ${kernel_symbols[@]} ++ arr_check_function_support ${kernel_symbols[@]} ++ arr_repet_ele_check ${sched_symbols[@]} # check sched ++ arr_check_sched ${sched_symbols[@]} + + spl_begin=0 + declare -a target_path_tmp +@@ -176,6 +236,8 @@ function config_file_check() { + done + spl_begin=${spl_end} + arr_repet_ele_check ${user_symbols_arr_tmp[@]} # check user symbol of same bin ++ arr_check_function_support ${user_symbols_arr_tmp[@]} ++ arr_check_user_symbols_exist ${target_path_tmp[-1]} ${user_symbols_arr_tmp[@]} + done + arr_repet_ele_check "${target_path_tmp[@]}" # check bin + } +diff --git a/extra-tools/da-tool/test/config_check/config_check.sh b/extra-tools/da-tool/test/config_check/config_check.sh +new file mode 100755 +index 0000000..20c06a1 +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_check.sh +@@ -0,0 +1,70 @@ ++#!/bin/bash ++ ++script_dir=$( ++ cd $(dirname $0) ++ pwd ++) ++cd $script_dir/ ++ ++datool="../../script/da-tool.sh" ++case1_path="../../test" ++config_file="/etc/da-tool.conf" ++config_tmp="config.tmp" ++output_file="config_test.log" ++ ++err_config=( ++ ./"config_test1.conf" ++ ./"config_test2.conf" ++ ./"config_test3.conf" ++ ./"config_test4.conf" ++ ./"config_test5.conf" ++ ./"config_test6.conf" ++ ./"config_test7.conf" ++) ++ ++cat $config_file >$config_tmp ++ ++echo >$output_file ++ ++# loop test config ++echo "=========================================================================================" >>$output_file ++echo "===================================== err_configs ======================================" >>$output_file ++echo "=========================================================================================" >>$output_file ++for config_test in "${err_config[@]}"; do ++ echo >$config_file ++ echo "================================" "$config_test" "================================" >>$output_file ++ cat $config_test >$config_file ++ echo "#config start" >>$output_file ++ cat $config_test >>$output_file ++ echo "#config end" >>$output_file ++ $datool -t 1 >>$output_file 2>&1 ++done ++ ++# user check ++g++ $case1_path/case/case1/case1.cpp -o case1_test ++ ++err_user_config=( ++ ./"config_user_test1.conf" ++ ./"config_user_test2.conf" ++ ./"config_user_test3.conf" ++) ++ ++echo "u,$script_dir/,case1_test,_Z5funcAv,aaaa" >./"config_user_test1.conf" ++echo "u,$script_dir/,case1_test,_Z5funcAv,_Z5funcAv" >./"config_user_test2.conf" ++echo "u,$script_dir/,case1_test,_Z5funcAv.a" >./"config_user_test3.conf" ++ ++# loop test config ++echo "=========================================================================================" >>$output_file ++echo "===================================== user err_configs ======================================" >>$output_file ++echo "=========================================================================================" >>$output_file ++for config_test in "${err_user_config[@]}"; do ++ echo >$config_file ++ echo "================================" "$config_test" "================================" >>$output_file ++ cat $config_test >$config_file ++ echo "#config start" >>$output_file ++ cat $config_test >>$output_file ++ echo "#config end" >>$output_file ++ $datool -t 1 >>$output_file 2>&1 ++done ++ ++cat $config_tmp >$config_file +diff --git a/extra-tools/da-tool/test/config_check/config_test1.conf b/extra-tools/da-tool/test/config_check/config_test1.conf +new file mode 100644 +index 0000000..cc75ca7 +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test1.conf +@@ -0,0 +1,2 @@ ++# kernel repet config ++k,udp_recvmsg,udp_recvmsg +diff --git a/extra-tools/da-tool/test/config_check/config_test2.conf b/extra-tools/da-tool/test/config_check/config_test2.conf +new file mode 100644 +index 0000000..9b1951d +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test2.conf +@@ -0,0 +1,2 @@ ++# u config err ++u,udp_recvmsg +diff --git a/extra-tools/da-tool/test/config_check/config_test3.conf b/extra-tools/da-tool/test/config_check/config_test3.conf +new file mode 100644 +index 0000000..dd8004d +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test3.conf +@@ -0,0 +1,2 @@ ++# kenrel config error symbols ++k,udp_recvmsg,aaaaaa +diff --git a/extra-tools/da-tool/test/config_check/config_test4.conf b/extra-tools/da-tool/test/config_check/config_test4.conf +new file mode 100644 +index 0000000..4afb295 +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test4.conf +@@ -0,0 +1,2 @@ ++# s config error ++s,sched_switch2 +diff --git a/extra-tools/da-tool/test/config_check/config_test5.conf b/extra-tools/da-tool/test/config_check/config_test5.conf +new file mode 100644 +index 0000000..4afb295 +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test5.conf +@@ -0,0 +1,2 @@ ++# s config error ++s,sched_switch2 +diff --git a/extra-tools/da-tool/test/config_check/config_test6.conf b/extra-tools/da-tool/test/config_check/config_test6.conf +new file mode 100644 +index 0000000..4945653 +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test6.conf +@@ -0,0 +1,2 @@ ++# s config repet ++s,sched_switch,sched_switch +diff --git a/extra-tools/da-tool/test/config_check/config_test7.conf b/extra-tools/da-tool/test/config_check/config_test7.conf +new file mode 100644 +index 0000000..6b4088b +--- /dev/null ++++ b/extra-tools/da-tool/test/config_check/config_test7.conf +@@ -0,0 +1,2 @@ ++# not support function check ++k,udp_recvmsg,set_bringup_idt_handler.constprop.0 +diff --git a/extra-tools/da-tool/test/opt_test/opt_test.sh b/extra-tools/da-tool/test/opt_test/opt_test.sh +new file mode 100644 +index 0000000..ab7dd65 +--- /dev/null ++++ b/extra-tools/da-tool/test/opt_test/opt_test.sh +@@ -0,0 +1,49 @@ ++#!/bin/bash ++ ++script_dir=$( ++ cd $(dirname $0) ++ pwd ++) ++cd $script_dir/ ++ ++datool_path="../../script/" ++ ++err_commands=( ++ "./da-tool.sh -t 0" ++ "./da-tool.sh -t 101" ++ "./da-tool.sh -t 1000000000000000000000000000" ++ "./da-tool.sh -t -10" ++ "./da-tool.sh -t 0.12345" ++ "./da-tool.sh -t abc" ++ "./da-tool.sh -t ~" ++ "./da-tool.sh -t -m 5" ++ "./da-tool.sh -a" ++ "./da-tool.sh -x 1" ++ "./da-tool.sh -" ++ "./da-tool.sh 1" ++) ++ ++right_commands=( ++ "./da-tool.sh -h" ++ #"./da-tool.sh -t 1" ++ #"./da-tool.sh" ++) ++ ++output_file="opt_test.log" ++echo >$output_file ++ ++echo "=========================================================================================" >>$output_file ++echo "===================================== err_commands ======================================" >>$output_file ++echo "=========================================================================================" >>$output_file ++for command in "${err_commands[@]}"; do ++ echo "================================" "$command" "================================" >>$output_file ++ $datool_path$command >>$output_file 2>&1 ++done ++ ++echo "=========================================================================================" >>$output_file ++echo "===================================== right_commands ====================================" >>$output_file ++echo "=========================================================================================" >>$output_file ++for command in "${right_commands[@]}"; do ++ echo "================================" "$command" "================================" >>$output_file ++ $datool_path$command >>$output_file 2>&1 ++done +-- +2.33.0 + diff --git a/0009-Dealing-with-situations-where-sched-are-missing.patch b/0009-Dealing-with-situations-where-sched-are-missing.patch new file mode 100644 index 0000000..330c204 --- /dev/null +++ b/0009-Dealing-with-situations-where-sched-are-missing.patch @@ -0,0 +1,463 @@ +From 2d3710909017239828c51cd5901c23415b865c49 Mon Sep 17 00:00:00 2001 +From: LHesperus <2639350497@qq.com> +Date: Sat, 25 Nov 2023 17:05:11 +0800 +Subject: [PATCH] Dealing with situations where 'sched' are missing + +--- + extra-tools/da-tool/analysis/config.cpp | 4 +- + extra-tools/da-tool/analysis/config.h | 3 +- + .../da-tool/analysis/function_stack.cpp | 2 +- + extra-tools/da-tool/analysis/time_pair.cpp | 23 +++- + .../da-tool/analysis/trace_resolve.cpp | 105 +++++++++++++++++- + extra-tools/da-tool/analysis/trace_resolve.h | 28 +++-- + extra-tools/da-tool/main.cpp | 8 +- + extra-tools/da-tool/script/da-tool.sh | 25 +++-- + 8 files changed, 159 insertions(+), 39 deletions(-) + +diff --git a/extra-tools/da-tool/analysis/config.cpp b/extra-tools/da-tool/analysis/config.cpp +index 08420ad..d84cc5b 100644 +--- a/extra-tools/da-tool/analysis/config.cpp ++++ b/extra-tools/da-tool/analysis/config.cpp +@@ -45,7 +45,6 @@ void Config::pathInit() + + // debug + filename[FILE_TYPE_OUTPUT_RUN_LOG] = pathOutputDebug + "/run.log"; +- filename[FILE_TYPE_OUTPUT_FUNC_STACK_ALL_INFO] = pathOutput + "/func_stack_all_info"; + filename[FILE_TYPE_DEBUG_TIME_PAIE] = pathOutputDebug + "/debug_time_pair"; + filename[FILE_TYPE_DEBUG_TRACE] = pathOutputDebug + "/debug_trace"; + filename[FILE_TYPE_DEBUG_FUNC_STACK_TRACE] = pathOutputDebug + "/debug_funcstk_trace"; +@@ -129,6 +128,7 @@ void Config::functionCfgInit() + std::ofstream fileDebug(filename[FILE_TYPE_DEBUG_CONFIG], std::ios::out | std::ios::trunc); + if (!fileDebug) { + std::cout << "file open failed:" << filename[FILE_TYPE_DEBUG_CONFIG] << std::endl; ++ file.close(); + return; + } + +@@ -157,7 +157,7 @@ void Config::configInit(int argc, char *argv[]) + readTraceBegin = std::stoi(optarg); + break; + case 'l': +- readTraceEnd = std::stoi(optarg); ++ readTraceLen = std::stoi(optarg); + break; + case 'g': + if (std::stoi(optarg) < DEBUG_LEVEL_MAX) { +diff --git a/extra-tools/da-tool/analysis/config.h b/extra-tools/da-tool/analysis/config.h +index ccce0f2..e1a5d4a 100644 +--- a/extra-tools/da-tool/analysis/config.h ++++ b/extra-tools/da-tool/analysis/config.h +@@ -26,7 +26,6 @@ typedef enum { + FILE_TYPE_OUTPUT_DELAY, + FILE_TYPE_OUTPUT_RUN_LOG, + FILE_TYPE_OUTPUT_FUNC_STACK_DELALY, +- FILE_TYPE_OUTPUT_FUNC_STACK_ALL_INFO, + FILE_TYPE_OUTPUT_PROCESS_SCHED_INFO, + FILE_TYPE_OUTPUT_SUMMARY_SCHED_INFO, + +@@ -109,7 +108,7 @@ public: // function cfg + std::vector(FILE_TYPE_MAX, "")}; + + int readTraceBegin; +- int readTraceEnd; ++ int readTraceLen; + void configInit(int argc, char *argv[]); + DEBUG_LEVEL_E getDebugLevel(); + }; +diff --git a/extra-tools/da-tool/analysis/function_stack.cpp b/extra-tools/da-tool/analysis/function_stack.cpp +index fcc2a8d..f1a8312 100644 +--- a/extra-tools/da-tool/analysis/function_stack.cpp ++++ b/extra-tools/da-tool/analysis/function_stack.cpp +@@ -341,7 +341,7 @@ void FunctionStack::processDelayAnalysis() + void FunctionStack::stackNodeMapDisplay() + { + Config &cfg = Config::getInstance(); +- std::cout << "Display the function delay of each pid " << std::endl; ++ std::cout << "[INFO] display the function delay of each pid " << std::endl; + for (const auto &processInfo : stackNodeMap) { + int pid = processInfo.first; + if (cfg.filterCfgMap.size() == 0 || cfg.filterCfgMap.count(pid) != 0) { +diff --git a/extra-tools/da-tool/analysis/time_pair.cpp b/extra-tools/da-tool/analysis/time_pair.cpp +index 037bce1..2c1f813 100644 +--- a/extra-tools/da-tool/analysis/time_pair.cpp ++++ b/extra-tools/da-tool/analysis/time_pair.cpp +@@ -85,6 +85,7 @@ void TimePair::saveFuncStkDebugToFile(std::ofstream &file, const int &pid, const + continue; + } + file << "pid" << "," << pid << ","; ++ file << "stk_pid" << "," << stk_pid << ","; + file << "timestamp" << "," << timestamp << ","; + file << "functionIndex" << "," << functionIndex << ","; + file << "isRet" << "," << isRet << ","; +@@ -152,6 +153,20 @@ void TimePair::timePairUpdateLoop(const int &pid, const int &functionIndex, cons + timePairMap[pid].emplace(functionIndex, infoTmp); + } + ++ Config &cfg = Config::getInstance(); ++ bool isCfgSchedSwitch = cfg.funcCfgMap.count("sched_switch") > 0; ++ int sched_switch_funcidx = -1; ++ if (isCfgSchedSwitch) { ++ sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex; ++ const TraceResolve &trace_resolve_inst = TraceResolve::getInstance(); ++ const FirstInfo &firstInfo = trace_resolve_inst.getTraceFirstInfo(); ++ int coreIndex = line_info_tmp.core; ++ // This process cannot find the starting sched switch on this core, ignore trace after timestamp ++ if (timestamp <= firstInfo.schedSwitchTime[coreIndex] && functionIndex != sched_switch_funcidx) { ++ timePairMap[pid][functionIndex].minEndTimeInvalid = timestamp; ++ } ++ } ++ + if (isRet) { + if (timePairMap[pid][functionIndex].startTime.size() == 0) { // fist is endtime ,startime=endtime + timePairMap[pid][functionIndex].startTime.emplace_back(timestamp); +@@ -496,14 +511,18 @@ void TimePair::saveDelayInfoToFile() + file << "call_times(r<0),ave(r<0),sum(r<0),min(r<0),max(r<0),p50(r<0),p80(r<0),p95(r<0),p99(r<0),"; + file << std::endl; + for (const auto &processInfo : timePairMap) { ++ int pid = processInfo.first; ++ if (pid == 0) { ++ continue; ++ } + for (const auto &funcInfo : processInfo.second) { +- if (cfg.filterCfgMap.size() != 0 && cfg.filterCfgMap.count(processInfo.first) == 0) { ++ if (cfg.filterCfgMap.size() != 0 && cfg.filterCfgMap.count(pid) == 0) { + continue; + } + if (funcInfo.second.summary.callTimes[DELAY_INFO_ALL] <= 0) { + continue; + } +- file << "," << processInfo.first << ","; ++ file << "," << pid << ","; + file << cfg.IndexToFunction[funcInfo.first] << ","; + + for (int i = 0; i < DELAY_INFO_MAX; i++) { +diff --git a/extra-tools/da-tool/analysis/trace_resolve.cpp b/extra-tools/da-tool/analysis/trace_resolve.cpp +index 8424464..38e6d2b 100644 +--- a/extra-tools/da-tool/analysis/trace_resolve.cpp ++++ b/extra-tools/da-tool/analysis/trace_resolve.cpp +@@ -56,6 +56,12 @@ const std::vector &TraceResolve::getTraceLine() const + return traceLineVec; + } + ++const FirstInfo &TraceResolve::getTraceFirstInfo() const ++{ ++ return firstInfo; ++} ++ ++ + void SchedSwitchLine::processStateToEnum(std::string state) + { + if (state == "R") { +@@ -68,9 +74,36 @@ void SchedSwitchLine::processStateToEnum(std::string state) + } + } + ++int countLines(const std::string& filename) { ++ std::ifstream file(filename); ++ if (!file.is_open()) { ++ std::cout << "file open failed:" << filename << std::endl; ++ return -1; ++ } ++ ++ int lineCount = 0; ++ std::string line; ++ while (std::getline(file, line)) { ++ lineCount++; ++ } ++ ++ file.close(); ++ return lineCount; ++} ++ + void TraceResolve::resolveTrace() + { + Config &cfg = Config::getInstance(); ++ int readTraceLen = 0; ++ if (cfg.readTraceLen == 0) { ++ readTraceLen = countLines(cfg.filename[FILE_TYPE_TRACE]); ++ if (readTraceLen <= 0) { ++ return; ++ } ++ } else { ++ readTraceLen = cfg.readTraceLen; ++ } ++ + std::ifstream file(cfg.filename[FILE_TYPE_TRACE]); + if (!file) { + std::cout << "file open failed:" << cfg.filename[FILE_TYPE_TRACE] << std::endl; +@@ -83,7 +116,6 @@ void TraceResolve::resolveTrace() + file.close(); + return; + } +- + int line_num = 0; + int regex_num = 0; + bool isFirstMatch = true; +@@ -94,13 +126,15 @@ void TraceResolve::resolveTrace() + std::regex patternSchedSwitch(R"(\s+(.+)-(\d+)\s+\[(\d+)\]\s+(.)(.)(.)(.)\s+(\d+)\.(\d+):\s+(sched_switch):\s+prev_comm=.+prev_pid=(\d+)\s+prev_prio=(\d+)\s+prev_state=(\S+)\s+==>\s+next_comm=.+next_pid=(\d+)\s+next_prio=(\d+))"); + while (getline(file, line)) { + line_num++; +- if (line_num % 10000 == 0) { +- std::cout << regex_num << "/" << line_num << " (matched/lines)" << std::endl; +- } + if (line_num < cfg.readTraceBegin) { + continue; + } +- if (cfg.readTraceEnd != 0 && line_num > cfg.readTraceBegin + cfg.readTraceEnd) { ++ if (line_num % 10000 == 0) { ++ double rate = (line_num - cfg.readTraceBegin) * 1.0/ readTraceLen; ++ std::cout << "[Resolve] " << std::fixed << std::setprecision(3) << rate * 100 << "%, "; ++ std::cout << "Match " << regex_num << std::endl; ++ } ++ if (cfg.readTraceLen != 0 && line_num > cfg.readTraceBegin + cfg.readTraceLen) { + break; + } + +@@ -143,6 +177,9 @@ void TraceResolve::resolveTrace() + if (isMatch) { + if (isFirstMatch) { + startTimeIntPart = std::stoi(match[TRACE_INFO_TIMESTAMP_INT].str()); ++ firstInfo.coreId = std::stoi(match[TRACE_INFO_CPU].str()); ++ firstInfo.startTime = (std::stoi(match[TRACE_INFO_TIMESTAMP_INT].str()) - startTimeIntPart) * MICRO_PER_SEC \ ++ + std::stoi(match[TRACE_INFO_TIMESTAMP_FLOAT].str()); + isFirstMatch = false; + } + match_info.timestamp = (std::stoi(match[TRACE_INFO_TIMESTAMP_INT].str()) - startTimeIntPart) * MICRO_PER_SEC \ +@@ -165,7 +202,7 @@ void TraceResolve::resolveTrace() + } + + if (traceLineVec.size() > 0) { +- std::cout << "trace delay :" << traceLineVec[traceLineVec.size() - 1].timestamp - traceLineVec[0].timestamp << std::endl; ++ std::cout << "[INFO] trace delay : " << traceLineVec[traceLineVec.size() - 1].timestamp - traceLineVec[0].timestamp << std::endl; + } + + file.close(); +@@ -206,8 +243,64 @@ double TraceResolve::convertTimeIntToDouble(const int ×tamp) + return timestamp * 1.0 / MICRO_PER_SEC + startTimeIntPart; + } + ++void TraceResolve::firstSchedSwitchTimeAnalysis() ++{ ++ Config &cfg = Config::getInstance(); ++ bool isCfgSchedSwitch = cfg.funcCfgMap.count("sched_switch") > 0; ++ int sched_switch_funcidx = -1; ++ if (isCfgSchedSwitch) { ++ sched_switch_funcidx = cfg.funcCfgMap["sched_switch"].functionIndex; ++ } else { ++ return; ++ } ++ ++ firstInfo.schedSwitchTime.resize(CPU_CORE_NUM_MAX, INT_MAX); ++ firstInfo.coreTime.resize(CPU_CORE_NUM_MAX, INT_MAX); ++ firstInfo.schedSwitchTime[firstInfo.coreId] = firstInfo.startTime; ++ firstInfo.coreTime[firstInfo.coreId] = firstInfo.startTime; ++ ++ for (const auto &line_info_tmp : traceLineVec) { ++ std::string functionName = line_info_tmp.functionName; ++ int pid = line_info_tmp.pid; ++ if (cfg.funcCfgMap.count(functionName) == 0) { ++ continue; ++ } ++ ++ int timestamp = line_info_tmp.timestamp; ++ int coreIndex = line_info_tmp.core; ++ int functionIndex = cfg.funcCfgMap[functionName].functionIndex; ++ // first appearance of coreIndex in trace ++ if (firstInfo.coreTime[coreIndex] == INT_MAX) { ++ firstInfo.coreTime[coreIndex] = timestamp; ++ } ++ // first appearance of sched_switch in coreIndex's trace ++ if (functionIndex == sched_switch_funcidx && firstInfo.schedSwitchTime[coreIndex] == INT_MAX) { ++ firstInfo.schedSwitchTime[coreIndex] = timestamp; ++ } ++ } ++} ++ + void TraceResolve::trace_resolve_proc() + { + resolveTrace(); + saveTraceRegexRstToFile(); ++ ++ firstSchedSwitchTimeAnalysis(); ++} ++ ++void TraceResolve::trace_check_show() ++{ ++ Config &cfg = Config::getInstance(); ++ for (int coreId = 0; coreId < CPU_CORE_NUM_MAX; coreId++) { ++ int firstSchedSwitchTime = firstInfo.schedSwitchTime[coreId]; ++ int firstCoreTime = firstInfo.coreTime[coreId]; ++ if (cfg.getDebugLevel() >= DEBUG_LEVEL_1) { ++ std::cout << "coreId:" << coreId; ++ std::cout << ",firstSchedSwitchTime:" << firstSchedSwitchTime; ++ std::cout << ",firstCoreTime:" << firstCoreTime << std::endl; ++ } ++ if (firstSchedSwitchTime != firstCoreTime) { ++ std::cout << "[ERROR] core " << coreId << " missing starting scheduling information, result maybe error!!!" << std::endl; ++ } ++ } + } +\ No newline at end of file +diff --git a/extra-tools/da-tool/analysis/trace_resolve.h b/extra-tools/da-tool/analysis/trace_resolve.h +index df330d5..e943d20 100644 +--- a/extra-tools/da-tool/analysis/trace_resolve.h ++++ b/extra-tools/da-tool/analysis/trace_resolve.h +@@ -23,18 +23,8 @@ + // include\linux\sched.h + typedef enum + { +- PROCESS_STATE_TASK_RUNNING, // R +- PROCESS_STATE_TASK_INTERRUPTIBLE, // S +-// PROCESS_STATE_TASK_UNINTERRUPTIBL, // D +-// PROCESS_STATE_TASK_STOPPED, // T +-// PROCESS_STATE_TASK_TRACED, //t +-// +-// PROCESS_STATE_EXIT_DEAD, // X +-// PROCESS_STATE_EXIT_ZOMBIE, // Z +-// PROCESS_STATE_EXIT_TRACE, +-// +-// PROCESS_STATE_TASK_PARKED, // P +-// PROCESS_STATE_TASK_DEAD, // I ++ PROCESS_STATE_TASK_RUNNING, // R ++ PROCESS_STATE_TASK_INTERRUPTIBLE, // S + PROCESS_STATE_MAX, + } PROCESS_STATE_E; + +@@ -64,6 +54,14 @@ public: + int functionIndex; + }; + ++class FirstInfo { ++public: ++ std::vector schedSwitchTime; // [coreId] ++ std::vector coreTime; // [coreId] ++ int coreId; // first core in trace ++ int startTime; ++}; ++ + class TraceResolve { + public: + static TraceResolve &getInstance() { +@@ -81,10 +79,16 @@ private: // regex + void resolveTrace(); + void saveTraceRegexRstToFile(); + ++private: ++ FirstInfo firstInfo; ++ void firstSchedSwitchTimeAnalysis(); ++ + public: + const std::vector &getTraceLine() const; ++ const FirstInfo &getTraceFirstInfo() const; + double convertTimeIntToDouble(const int ×tamp); + void trace_resolve_proc(); ++ void trace_check_show(); + }; + + #endif +\ No newline at end of file +diff --git a/extra-tools/da-tool/main.cpp b/extra-tools/da-tool/main.cpp +index b6ec46d..34652f0 100644 +--- a/extra-tools/da-tool/main.cpp ++++ b/extra-tools/da-tool/main.cpp +@@ -21,10 +21,10 @@ using namespace std; + + int main(int argc, char *argv[]) + { +- cout << "analysis start..." << endl; ++ cout << "[STEP 2] analysis start..." << endl; + Config &cfg = Config::getInstance(); + cfg.configInit(argc, argv); +- cout << "analysis resolve..." << endl; ++ cout << "[STEP 2-1] resolve trace..." << endl; + TraceResolve &trace_resolve_inst = TraceResolve::getInstance(); + trace_resolve_inst.trace_resolve_proc(); + +@@ -36,6 +36,8 @@ int main(int argc, char *argv[]) + + FunctionStack &fstk = FunctionStack::getInstance(); + fstk.function_stack_proc(); +- cout << "analysis finish" << endl; ++ ++ trace_resolve_inst.trace_check_show(); ++ cout << "[STEP 2-2] analysis finish" << endl; + return 0; + } +\ No newline at end of file +diff --git a/extra-tools/da-tool/script/da-tool.sh b/extra-tools/da-tool/script/da-tool.sh +index a25c347..14fd009 100755 +--- a/extra-tools/da-tool/script/da-tool.sh ++++ b/extra-tools/da-tool/script/da-tool.sh +@@ -316,7 +316,7 @@ function opt_check() { + } + + function clear_env() { +- echo "clear env..." ++ echo "[INFO] clear env..." + echo 0 >/sys/kernel/debug/tracing/tracing_on + + events_folder="/sys/kernel/debug/tracing/events/" +@@ -361,7 +361,7 @@ function clear_env() { + echo 0 >"$event_file" + fi + done +- echo "clear env finish" ++ echo "[INFO] clear env finish" + } + + function sample_init() { +@@ -528,10 +528,12 @@ function trace_analysis() { + } + + ###################### main proc #################################### ++echo "[STEP 1] da-tool start" ++echo "[STEP 1-1] resolve config" + config_file_resolve +- ++echo "[STEP 1-2] environment initialization" + if [ $is_clear = true ]; then +- echo "clear" ++ echo "[INFO] clear" + clear_env + exit 1 + fi +@@ -555,28 +557,29 @@ uprobe_event_enable $is_uprobe_sample + kprobe_event_enable $is_kprobe_sample + sched_event_enable $is_kprobe_sample + +-# sampling ++echo "[STEP 1-3] start tracing..." ++# tracing + trace_record_begin + + for ((i = 1; i <= ${sleep_time}; i++)); do +- # trace_line_num=$(wc -l < /sys/kernel/debug/tracing/trace) # wrong +- echo "sampling " $i/${sleep_time} #", trace line" $trace_line_num ++ echo "[INFO] tracing " $i/${sleep_time} + sleep 1 + done +-#trace_line_num=$(wc -l < /sys/kernel/debug/tracing/trace) # slow +-#echo "trace line" $trace_line_num + + trace_record_end ++echo "[STEP 1-4] environment reset..." + + clear_env + gen_config_for_analysis ++ ++echo "[STEP 1-5] save trace..." + storage_data + echo "" >/sys/kernel/debug/tracing/trace + # only enable = 0 , clear event + echo >/sys/kernel/debug/tracing/uprobe_events + echo >/sys/kernel/debug/tracing/kprobe_events +-echo "sample finish" +- ++echo "[STEP 1-6] finish tracing ..." + if [ $is_sample_with_analysis = true ]; then + trace_analysis + fi ++echo "[EXIT] da-tool exit..." +-- +2.33.0 + diff --git a/0010-Soft-links-for-documents.patch b/0010-Soft-links-for-documents.patch new file mode 100644 index 0000000..8db84b1 --- /dev/null +++ b/0010-Soft-links-for-documents.patch @@ -0,0 +1,232 @@ +From 904d42948317e9ebfc1b3ae2a83778de4c9b8d2c Mon Sep 17 00:00:00 2001 +From: LHesperus <2639350497@qq.com> +Date: Sun, 26 Nov 2023 22:17:01 +0800 +Subject: [PATCH] Soft links for documents + +--- + extra-tools/da-tool/README.md | 200 ++-------------------------------- + 1 file changed, 8 insertions(+), 192 deletions(-) + +diff --git a/extra-tools/da-tool/README.md b/extra-tools/da-tool/README.md +index 209b43b..157af65 100644 +--- a/extra-tools/da-tool/README.md ++++ b/extra-tools/da-tool/README.md +@@ -1,26 +1,9 @@ + + # da-tool + +-通过`uprobe`或`kprobe`采样可获得函数执行的`trace`,但配置比较复杂,`trace`包含的信息很多,显示不直观。本工具旨在简易配置采样,以及分析所配置的函数的时延特征。 ++通过`uprobe`或`kprobe`采样可获得函数执行的`trace`,但配置比较复杂,`trace`包含的信息很多,显示不直观。本工具旨在简易配置采样,以及分析所配置的函数的时延特征。 + +-主要应用场景:分析tcp/udp收发相关函数时延特征。 +- +-## 原理 +-基于u/kprobe 采样,可获得内核态和用户态函数的起止执行时间和结束执行时间的trace。 +-可推导出: +-+ 函数间的调用关系 +-+ 函数的执行时间 +-+ 线程的调度特征 +- +-## 主要功能 +- +-+ 推导调用关系(乱序) +-+ 统计各函数调用栈时延信息 +-+ 线程调度特征 +-+ 记录系统信息 +- +-## 使用限制 +-+ 不支持递归函数分析 ++主要应用场景:分析`tcp/udp`收发相关函数时延特征。 + + ## 文件夹说明 + **工程文件夹** +@@ -39,180 +22,13 @@ + + CMakeLists.txt + + test : 测试程序 + +-**本地文件夹** +- +-+ /etc/da-tool.conf : 配置文件,主要配置需要抓取的函数 +-+ /var/da-tool: +- + tmp +- + sample_output_* : 采样文件存放位置,可打包 +- + analysis_input : 临时用于分析程序的依赖文件 +- + analysis_output +- + debug : 可用于调试的参考日志 +- + output : 时延结果信息 +- +-## 使用方法 +-### 命令格式 +-时延分析工具通过`da-tool.sh`命令采集和分析函数时延,使用格式为 +- +-**da-tool.sh** [-t <*probe time*>] +- +-|参数|是否必选|参数函数| +-|----|--------|-------| +-|-t |否| 采集函数 `trace` 的时长,单位秒,最大限制 100,默认10| +- +-### 自定义配置函数 +-配置文件:`/etc/da-tool.conf` +- +-举例如下: +-``` +-# /etc/da-tool.conf +- +-# kernel symbol config (ref: /proc/kallsyms) +-k,udp_recvmsg,udp_sendmsg,dev_queue_xmit,udp_send_skb,sock_recvmsg,__skb_recv_udp,udp_rcv +- +-# sched config +-s,sched_switch +- +-# user symbol config (format : u,path,bin_name,func1,func2,...,funcN) +-# u,/path/,bin_name,sendto +-u,/home/git_repo/nda-tool/nda-tool/test/net_demo2/,server_no_blk,recvfrom +-u,/home/git_repo/nda-tool/nda-tool/test/net_demo2/,client_to_noblk,sendto +-u,/home/git_repo/nda-tool/nda-tool/test/base_demo/,base_demo_cpp,_Z5func1v,_Z5func2v,_Z5func2i,_Z5func3v,_Z5func4v +-# end +-``` +- +-+ k 开头为 kernel 符号,u 开头为用户态程序符号, s 开头为调度配置(目前仅支持`sched_switch`且必须配置) +-+ k 和 s 只能一行配置完 +-+ u 可以多行配置, 格式:`[u,程序路径,二进制名称,追踪的函数]` +-+ 请确保函数存在,否则 `uprobe` 配置不成功,所配置的内核符号应在`/proc/kallsyms`能够查询到,所配置的用户态程序符号仅支持`C/C++`,且通过`objdump`应能够查询到 +-+ 每行末尾不要有逗号 +- +- +-注意,为了支持用户态不同二进制重名函数采集,配置`event`时,命名为`u0_func1`、`u1_func1`...,以上面配置为例,`_Z5func1v`为`u2__Z5func1v`。 +-### 分析结果说明 +- +-+ 终端输出结果:各函数调用栈的时延信息 +-+ 文件夹输出结果 : `/var/da-tool/analysis-output/ouput/` +- + func_delay_stack : 函数调用栈时延结果 +- + process_sched_info :进程的调度信息 +- + summary_delay.csv : 时延分析总结报告 +- + summary_sched.csv : 调度分析总结报告 +- +-#### 终端输出结果介绍 +-``` +-├──pid: 222459{local:(450040, 44.988%), global:(1000346, 100.000%)} +-│ ├─────sched_switch{local:(13160, 1.316%, 453.793), global:(13160, 1.316%, 453.793), times:29, (int)ret>=0 times:29} +-│ └─────u0_recvfrom{local:(422312, 42.217%, 10.729), global:(537146, 53.696%, 13.646), times:39362, (int)ret>=0 times:20} +-│ ├─────sched_switch{local:(2927, 0.293%, 209.071), global:(2927, 0.293%, 209.071), times:14, (int)ret>=0 times:14} +-│ └─────sock_recvmsg{local:(55313, 5.529%, 1.405), global:(111907, 11.187%, 2.843), times:39362, (int)ret>=0 times:20} +-│ └─────udp_recvmsg{local:(36357, 3.634%, 0.924), global:(56594, 5.657%, 1.438), times:39362, (int)ret>=0 times:20} +-│ └─────__skb_recv_udp{local:(20237, 2.023%, 0.514), global:(20237, 2.023%, 0.514), times:39362, (int)ret>=0 times:39342} +- +-``` +-以此结果为例,该进程是一个udp非阻塞收包进程。 +-+ `u0_recvfrom` 为该进程在运行后执行的用户态函数,`u0_` 前缀表示第一个应用程序的函数,实际函数名为`recvfrom`;`sched_switch` 为调度函数;其余函数为内核函数 +-+ `global` 和 `local` 对应的括号内为该函数执行的时延信息,其中 `local` 是剔除掉子函数和调度所执行的时间 , `global` 为该函数实际执行时长 +-+ 每个函数的 `global` 和 `local` 的括号内三个信息分别为,时延,该时延所占进程全部时间的百分比,平均时延(时延/执行次数) +-+ 每一级函数的 `global` 时间等于本级函数`local`时间与下一级所有函数的 `global` 时间之和 +-+ `times` 是该函数调用栈的次数, +-+ `(int)ret>=0 times`:表示该函数返回值转换为`int`后大于等于0的次数,无返回值函数返回值是无效的值 +-+ 以上时间单位为微秒 +- +-#### 文件夹结果介绍 +- +-**时延和调用关系信息**:`/var/da-tool/analysis_output/output/func_delay_stack` +-``` +-# 此部分信息为终端输出结果的文件格式存储 +-pid_222459;sched_switch 13160, localDelaySum ,13160, localAvedelay ,453.793103, localPercentage, 1.316%, globalDelaySum ,13160, globalAvedelay, 453.793103, globalPercentage, 1.316%, times , 29, (int)ret>=0 times ,29 +-pid_222459;u0_recvfrom;sched_switch 2927, localDelaySum ,2927, localAvedelay ,209.071429, localPercentage, 0.293%, globalDelaySum ,2927, globalAvedelay, 209.071429, globalPercentage, 0.293%, times , 14, (int)ret>=0 times ,14 +-pid_222459;u0_recvfrom 422312, localDelaySum ,422312, localAvedelay ,10.728926, localPercentage, 42.217%, globalDelaySum ,537146, globalAvedelay, 13.646309, globalPercentage, 53.696%, times ,39362, (int)ret>=0 times ,20 +-pid_222459;u0_recvfrom;sock_recvmsg 55313, localDelaySum ,55313, localAvedelay ,1.405239, localPercentage, 5.529%, globalDelaySum ,111907, globalAvedelay, 2.843021, globalPercentage, 11.187%, times ,39362, (int)ret>=0 times ,20 +-pid_222459;u0_recvfrom;sock_recvmsg;udp_recvmsg 36357, localDelaySum ,36357, localAvedelay ,0.923657, localPercentage, 3.634%, globalDelaySum ,56594, globalAvedelay, 1.437783, globalPercentage, 5.657%, times ,39362, (int)ret>=0 times ,20 +-pid_222459;u0_recvfrom;sock_recvmsg;udp_recvmsg;__skb_recv_udp 20237, localDelaySum ,20237, localAvedelay ,0.514125, localPercentage, 2.023%, globalDelaySum ,20237, globalAvedelay, 0.514125, globalPercentage, 2.023%, times ,39362, (int)ret>=0 times ,39342 +-``` +- +-**调度信息**:`/var/da-tool/analysis_output/output/process_sched_info` +-``` +-# delaySum : 该pid分析的总时长 +-# schedSwitchDelay : 调度所占的时间 +-# runtime :delaySum - schedSwitchDelay +-# cpuSwitchTimes : 该pid从一个核切换到另一个核的次数 +-# core 2, run time 704927 : 表示在cpu2 上运行时长为 704927 +-# startTime,67551.691078,endTime,67551.701193,coreIndex,2 :在这个时间段内在cpu2上运行 +-# coreIndex,-1 表示该pid被切走的时长(sched_switch) +- +-pid,222459,delaySum ,1000368,schedSwitchDelay ,37201,runtime ,963167,cpuSwitchTimes ,1, +- core 2, run time 704927 +- core 3, run time 258240 +-startTime,67551.691078,endTime,67551.701193,coreIndex,2 +-startTime,67551.701193,endTime,67551.701970,coreIndex,-1 +-startTime,67551.701970,endTime,67551.702503,coreIndex,2 +-startTime,67551.702503,endTime,67551.713700,coreIndex,-1 +-startTime,67551.713700,endTime,67551.723964,coreIndex,2 +-startTime,67551.723964,endTime,67551.724119,coreIndex,-1 +-... +- +-``` +-**时延分析总结报告**:`/var/da-tool/analysis_output/output/summary_delay.csv` +- +-包含信息如下,其中`(r>=0)`表示函数返回值转成`int`后大于等于0的情况。 +-`ave,sum,min,max,p50,p80,p95,p99`等为时延信息的平均值、总和、极值、各百分位下的数值。 +-``` +-pid,function,call_times,ave,sum,min,max,p50,p80,p95,p99, +-call_times(r>=0),ave(r>=0),sum(r>=0),min(r>=0),max(r>=0),p50(r>=0),p80(r>=0),p95(r>=0),p99(r>=0), +-call_times(r<0),ave(r<0),sum(r<0),min(r<0),max(r<0),p50(r<0),p80(r<0),p95(r<0),p99(r<0), +-``` +- +-**调度分析总结报告**:`/var/da-tool/analysis_output/output/summary_sched.csv` +-``` +-pid,delaySum,schedSwitchDelay,schedSwitchPercentage,schedSwitchTimes,cpuSwitchTimes +-``` +-+ delaySum : 总耗时 +-+ schedSwitchDelay : 调度总耗时 +-+ schedSwitchPercentage : schedSwitchDelay 占 delaySum 的百分比 +-+ schedSwitchTimes : 调度次数 +-+ cpuSwitchTimes : cpu 切换次数 +- +-### 扩展功能 +-`da-tool` 生成的结果信息可调用 火焰图生成工具,可视化分析结果, +-`./flamegraph.pl` 可在 `https://gitee.com/mirrors/FlameGraph` 中获取 +-```shell +-# 全部信息 +-cat /var/da-tool/analysis_output/output/func_delay_stack | grep -o '^[^,]*' | ./flamegraph.pl --countname "delay sum" > allpid.svg +-# 指定pid +-cat /var/da-tool/analysis_output/output/func_delay_stack | grep -o '^[^,]*' | grep -E 'pid1|pid2' | ./flamegraph.pl --countname "delay sum" > pid.svg +-``` + +-### 常见错误说明 + +-**配置了不存在的符号** +-``` +-Failed to find symbol aaaa in kernel +- Error: Failed to add events. +-``` +-**符号已存在,重复配置** +-``` +-Error: event "aaaa" already exists. +- Hint: Remove existing event by 'perf probe -d' +- or force duplicates by 'perf probe -f' +- or set 'force=yes' in BPF source. +- Error: Failed to add events. +-``` ++## 详情 + +-采集后会在`/var/da-tool/tmp`文件夹下生成一个`output_时间`格式的文件夹,包含此次采样的结果。 +-采样脚本的采样日志在此路径下: +-``` +-/var/da-tool/tmp/sample_output_时间/da-tool/sample.log +-``` ++|主题|内容简介|是否发布| ++|:----|:-----|:----| ++|[openEuler指南](https://gitee.com/openeuler/community/blob/master/zh/contributors/README.md)| 如何参与openEuler社区 | 已发布 | ++|[da-tool 使用指南](https://gitee.com/openeuler/docs/blob/stable2-20.03_LTS_SP3/docs/zh/docs/A-Ops/da-tool%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C.md)|1. 安装、配置和运行应用程序
2. 分析结果说明
3. 使用注意事项|已发布| ++|da-tool设计文档|1. 技术原理
2. 开发指南 |暂未发布| + +-### 注意事项 +-+ 配置注意事项 +- + 配置`/etc/da-tool.conf` 时,注意所配置符号一定存在 +- + 某些函数名可能存在点(eg:A.B.C),暂**不支持配置此类函数**,例如经过gcc优化选项`-fipa-sra`优化后,函数符号后缀会有`.rsra.num`。 +- + 应用程序名也不要有点,建议函数和应用程序**不要包含特殊符号** +- + 某些函数可能短时间执行大量次数,此时`trace`很大,解析时间会很长,需要认为评估配置的函数运行情况,合理设置采样时间 +- + 由于`trace`可能存在不完整的调用关系,很有可能在`trace`中存在的数据分析时舍弃,如果单次采样没有抓到需要的pid信息,建议多采样几次 +- + 有时`trace`中会有数据丢失,结果可能异常,常见的异常原因为`trace`过大,内核刷新数据时不正常,比如会出现同一个函数只有返回时间没有进入时间的现象,建议减小采样时间。 +- + 不支持递归函数 +-+ 本工具单个CPU所使用的跟踪缓存`RingBuffer`大小为 `40960kb` ,当单核的`trace`大小接近此值时数据可能异常,进而导致分析结果错误。 +-+ 确保`trace` 中有需要采集的函数的完整调用栈 +-- +2.33.0 + diff --git a/aops-ceres.spec b/aops-ceres.spec index 88ae8cf..5f5829b 100644 --- a/aops-ceres.spec +++ b/aops-ceres.spec @@ -2,7 +2,7 @@ Name: aops-ceres Version: v1.3.4 -Release: 9 +Release: 10 Summary: An agent which needs to be adopted in client, it managers some plugins, such as gala-gopher(kpi collection), fluentd(log collection) and so on. License: MulanPSL2 URL: https://gitee.com/openeuler/%{name} @@ -14,6 +14,9 @@ Patch0004: 0004-Modify-method-of-mark-invalid-data-and-add-summary.patch Patch0005: 0005-add-specific-error-information.patch Patch0006: 0006-update-return-log-field-of-the-cve-fix-func.patch Patch0007: 0007-add-usage-and-repet-config-check.patch +Patch0008: 0008-add-command-check-config-check-test-case.patch +Patch0009: 0009-Dealing-with-situations-where-sched-are-missing.patch +Patch0010: 0010-Soft-links-for-documents.patch BuildRequires: python3-setuptools Requires: python3-requests python3-jsonschema python3-libconf @@ -93,6 +96,11 @@ install -b -m755 ./extra-tools/da-tool/script/da-tool.sh ${RPM_BUILD_ROOT} %attr(755, root, root) %{_bindir}/da-tool-analysis %changelog +* Mon Nov 27 2023 liuchanggeng - v1.3.4-10 +- add check of command parameters and configuration files +- handling scenarios with lost scheduling information +- update document + * Thu Nov 23 2023 liuchanggeng - v1.3.4-9 - da-tool add usage - da-tool check for duplicate configurations