From 76b53884ed59d2792077db6e69345581ffad484e Mon Sep 17 00:00:00 2001 From: yangxin Date: Tue, 13 May 2025 00:04:38 +0800 Subject: [PATCH 1/2] Add collect interval to sresar. Signed-off-by: yangxin --- README_zh-cn.md | 1 + conf/ssar.conf | 1 + sresar/sresar.c | 27 ++++++++++++++++++++++++--- sresar/sresar.h | 1 + 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/README_zh-cn.md b/README_zh-cn.md index 34a53f7..78c10f9 100644 --- a/README_zh-cn.md +++ b/README_zh-cn.md @@ -1096,6 +1096,7 @@ sre_proc/data/2020093021/20200930215900_stat # 除以上外,皆为整 ```bash $ cat /etc/ssar/ssar.conf [main] +collect_interval=60 # 采集间隔设置为60秒,任何小于60的数会被设置为一个大于等于他的60的因子,任何大于60的数会被设置为大于等于它的60的倍数 duration_threshold=168 # 采集数据保存168个小时,最老的数据会被自动清理 inode_use_threshold=90 # 数据所在分区磁盘inode大于90%开始清理老数据,无法清理时则停止采集 disk_use_threshold=90 # 数据所在分区磁盘容量大于90%开始清理老数据,无法清理时则停止采集 diff --git a/conf/ssar.conf b/conf/ssar.conf index 0420e48..cbbeba8 100644 --- a/conf/ssar.conf +++ b/conf/ssar.conf @@ -1,4 +1,5 @@ [main] +collect_interval=60 # sresar data collect interval: 60 seconds. duration_threshold=168 # 168 hour >168 will stop. inode_use_threshold=90 # disk df_inode_use >90% will stop. disk_use_threshold=90 # disk df_use >90% will stop. diff --git a/sresar/sresar.c b/sresar/sresar.c index bbeb3a6..1f179ac 100644 --- a/sresar/sresar.c +++ b/sresar/sresar.c @@ -329,7 +329,7 @@ void* rotate_thread(void * args){ } new_value.it_value.tv_nsec = 0; - new_value.it_interval.tv_sec = 60; + new_value.it_interval.tv_sec = opts->collect_interval; new_value.it_interval.tv_nsec = 0; if(timerfd_settime(timerfd_fd, TFD_TIMER_ABSTIME, &new_value, NULL) != 0){ // TFD_TIMER_ABSTIME = 1 THREAD_ERROR("timerfd_settime() error"); @@ -683,7 +683,7 @@ void* snapsys_thread(void * args){ new_value.it_value.tv_sec = new_value.it_value.tv_sec + 60; } new_value.it_value.tv_nsec = 0; - new_value.it_interval.tv_sec = 60; + new_value.it_interval.tv_sec = opts->collect_interval; new_value.it_interval.tv_nsec = 0; if(timerfd_settime(timerfd_fd, TFD_TIMER_ABSTIME, &new_value, NULL) != 0){ // TFD_TIMER_ABSTIME = 1 THREAD_ERROR("timerfd_settime() error"); @@ -921,7 +921,7 @@ void* sresar_thread(void * args){ } new_value.it_value.tv_nsec = 0; - new_value.it_interval.tv_sec = 60; + new_value.it_interval.tv_sec = opts->collect_interval; new_value.it_interval.tv_nsec = 0; if(timerfd_settime(timerfd_fd, TFD_TIMER_ABSTIME, &new_value, NULL) != 0){ // TFD_TIMER_ABSTIME = 1 THREAD_ERROR("timerfd_settime() error"); @@ -1909,6 +1909,27 @@ int init_basic_config(seq_options* opts){ fprintf(opts->sresar_stderr, "ERROR: path %s is not dir\n", opts->work_path); exit(150); } + }else if(!strcmp(i_key, "collect_interval")){ + if(toml_rtoi(i_value, &i_num)){ + fprintf(opts->sresar_stderr, "collect_interval %s is not correct.\n", i_value); + exit(150); + } + int collect_interval[]={1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60}; + int tmp_interval = i_num; + int i = 0; + if (i_num <=60) { + for (; i < 12; i++) { + if (tmp_interval <= collect_interval[i]) { + tmp_interval = collect_interval[i]; + break; + } + } + } else { + tmp_interval = (tmp_interval + 60 - 1) / 60 * 60; + } + + fprintf(opts->sresar_stderr, "Collection Interval set to %d seconds.\n", tmp_interval); + opts->collect_interval = tmp_interval; }else if(!strcmp(i_key, "duration_threshold")){ if(toml_rtoi(i_value, &i_num)){ fprintf(opts->sresar_stderr, "duration_threshold %s is not correct.\n", i_value); diff --git a/sresar/sresar.h b/sresar/sresar.h index f2dd2bb..a125f0d 100644 --- a/sresar/sresar.h +++ b/sresar/sresar.h @@ -52,6 +52,7 @@ typedef struct{ volatile int partition_insufficient; volatile int hour_lock; volatile int hour_timestamp_lock; + unsigned int collect_interval; }seq_options; typedef struct{ -- Gitee From 68137bbdb3d74b6571fdbddc605e892fde692938 Mon Sep 17 00:00:00 2001 From: yangxin Date: Tue, 13 May 2025 15:58:39 +0800 Subject: [PATCH 2/2] suppert second level interval in ssar. Signed-off-by: yangxin --- README.md | 2 +- README_zh-cn.md | 21 ++++++++++++++++++++- conf/ssar.1 | 2 +- conf/zh_CN.ssar.1 | 2 +- ssar/ssar.cpp | 47 +++++++++++++++++++++++++++-------------------- ssar/ssar.h | 1 + 6 files changed, 51 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 5e48999..9ef539d 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ $ ssar # the historical data output of the defau $ ssar --cpu # Display the output historical data of THE CPU category. $ ssar -f 2020-09-29T18:34:00 # Specifies the end time of a time interval $ ssar -r 60 # The specified duration is 60 minutes. The default value is 300 minutes -$ ssar -i 1 # In the specified time range, the display accuracy is 1 minute. The default value is 10 minutes +$ ssar -i 1 # In the specified time range, the display accuracy is 1 minute. The default value is 1 minutes, can be set to any value with time units such as 1s, 2s, 10min, 2h, will be adjuested to value not smaller than collect interval of sresar. $ ssar --api # If selected, the information is output in JSON format $ ssar -f +10 -i 1s # with real-time mode, the acquisition output accuracy is 1 second, the default value is 5 seconds. $ ssar -o user,shmem,memfree # Only user, shmem, and memfree indicators are output diff --git a/README_zh-cn.md b/README_zh-cn.md index 78c10f9..a7577ff 100644 --- a/README_zh-cn.md +++ b/README_zh-cn.md @@ -188,7 +188,7 @@ $ ssar -f -5.5h # 指定时间区间的结束时间点为当前 $ ssar -f -1.8d # 指定时间区间的结束时间点为当前时刻之前1.8天 $ ssar -r 60 # 指定时间区间长度为60分钟,默认值为300分钟 $ ssar -b 2020-09-29T17:34:00 # 指定时间区间的开始时间点,默认为结束时间点减去时间长度 -$ ssar -i 1 # 指定时间区间长度范围内展示精度为1分钟,默认为10分钟 +$ ssar -i 1 # 指定时间区间长度范围内展示精度为1分钟,默认为1分钟,可以设置为任意间隔,比如1s、3s、10m、2h,但是设置的间隔会被转换成大于等于该值的sresar collect_interval的倍数。 $ ssar -H # 选中则不显示指标的标题信息 $ ssar -P # 选中则不显示- * < > =等非数字指标 $ ssar --api # 选中则以json格式输出信息 @@ -230,6 +230,25 @@ collect_datetime user/s system/s iowait/s softirq/s memfree anonpa 2021-08-21T10:41:00 2.67 3.78 0.82 0.00 2538176 175248 1292 620 ``` +``` +$ ssar -i 5s + +collect_datetime user/s system/s iowait/s softirq/s memfree anonpages shmem dirty +2025-05-13T15:13:02 - - - - 496863852 2542880 106100 50360 +2025-05-13T15:13:07 134.40 26.80 0.00 1.40 496843700 2550772 106152 48296 +2025-05-13T15:13:12 41.20 20.40 1.20 1.00 496829656 2566996 106164 424 +2025-05-13T15:13:17 86.60 19.40 0.00 1.00 496756548 2553076 116408 11056 +2025-05-13T15:13:22 77.20 21.40 0.40 1.20 496865112 2531584 106180 344 +2025-05-13T15:13:27 72.60 21.00 1.60 1.00 496855164 2535076 106196 92 +2025-05-13T15:13:32 105.80 26.80 0.20 1.40 496846884 2544980 106204 20456 +2025-05-13T15:13:37 69.60 19.00 0.60 1.20 496825692 2554992 106248 916 +2025-05-13T15:13:42 46.80 55.60 0.20 1.60 496788408 2581824 106240 0 +2025-05-13T15:13:47 164.60 92.00 0.00 2.00 496791536 2575640 106256 24380 +2025-05-13T15:13:52 50.60 79.20 0.20 1.80 496805920 2561116 106276 24788 +2025-05-13T15:13:57 70.20 73.00 0.40 1.80 496829280 2531264 106292 5612 +2025-05-13T15:14:02 108.80 69.40 0.20 1.60 496837744 2521668 106312 25324 +``` +   这里对输出结果中的关键点做一些说明: * 第一列是指标采集的时间点信息,精确到秒。 diff --git a/conf/ssar.1 b/conf/ssar.1 index 547fe40..a0da786 100644 --- a/conf/ssar.1 +++ b/conf/ssar.1 @@ -372,7 +372,7 @@ If selected, output is json format, otherwise shell format. process id. .TP \fB\-i, \-\-interval\fP \fIINT\fR -interval, default 10 minutes. +interval, default 1 minutes. can be set as any value with time unit, e.g. 6s, 2m, 10h... .TP \fB\-f, \-\-finish\fP \fITEXT\fR Assign the output datetime, allow history datetime. default value is current datetime. diff --git a/conf/zh_CN.ssar.1 b/conf/zh_CN.ssar.1 index 547fe40..a0da786 100644 --- a/conf/zh_CN.ssar.1 +++ b/conf/zh_CN.ssar.1 @@ -372,7 +372,7 @@ If selected, output is json format, otherwise shell format. process id. .TP \fB\-i, \-\-interval\fP \fIINT\fR -interval, default 10 minutes. +interval, default 1 minutes. can be set as any value with time unit, e.g. 6s, 2m, 10h... .TP \fB\-f, \-\-finish\fP \fITEXT\fR Assign the output datetime, allow history datetime. default value is current datetime. diff --git a/ssar/ssar.cpp b/ssar/ssar.cpp index 5deb149..d2b43aa 100644 --- a/ssar/ssar.cpp +++ b/ssar/ssar.cpp @@ -568,13 +568,16 @@ int SreProc::GetDataDir(){ } int SreProc::GetDataFile(){ + string it_sec; string it_minute; string sub_dir; string sub_file = ""; string it_file = ""; + string it_file_sec = ""; bool geted = false; time_t tt; + it_sec = FmtDatetime(this->time_point, this->file_format_second); it_minute = FmtDatetime(this->time_point, this->file_format_minute); sub_dir += this->data_path; sub_dir += this->data_dir; @@ -582,9 +585,11 @@ int SreProc::GetDataFile(){ set::const_iterator i_element = this->files.cbegin(); for(;i_element != this->files.cend(); ++i_element){ sub_file = (*i_element); + if ((sub_file.size() == this->suffix.size() + 15) && sub_file.find(it_sec, 0) == 0 && 14 == sub_file.rfind("_" + this->suffix, 14)) { + it_file_sec = sub_file; + } if((sub_file.size() == this->suffix.size() + 15) && 0 == sub_file.find(it_minute, 0) && 14 == sub_file.rfind("_" + this->suffix, 14)){ it_file = sub_file; - break; } } if(it_file.empty()){ @@ -598,7 +603,11 @@ int SreProc::GetDataFile(){ break; } } - this->data_datetime = it_file.substr(0, 14); + if (it_file_sec.empty()) { + this->data_datetime = it_file.substr(0, 14); + } else { + this->data_datetime = it_file_sec.substr(0, 14); + } if(0 != ParserDatetime(this->data_datetime, this->time_point_real, this->file_format_second)){ return 1; } @@ -623,7 +632,6 @@ int SreProc::_MakeDataHourPath(const chrono::system_clock::time_point &it_time_p this->data_hour_path += this->data_datetime; this->data_hour_path += "_"; this->data_hour_path += this->suffix; - return 0; } @@ -904,7 +912,6 @@ time_point_end: string exception_info = "lines must more than 0."; throw exception_info; } - // init interval if(!seq_option.interval.empty()){ if((seq_option.interval.size()-1) == seq_option.interval.rfind("d", (seq_option.interval.size()-1))){ @@ -914,20 +921,11 @@ time_point_end: }else if((seq_option.interval.size()-1) == seq_option.interval.rfind("m", (seq_option.interval.size()-1))){ seq_option.intervals = int(60 * stof(seq_option.interval.substr(0,(seq_option.interval.size()-1)))); }else if((seq_option.interval.size()-1) == seq_option.interval.rfind("s", (seq_option.interval.size()-1))){ - if("sys"==seq_option.src){ - if(seq_option.live_mode){ - seq_option.intervals = int(stof(seq_option.interval.substr(0,(seq_option.interval.size()-1)))); - }else{ - string exception_info = "interval not support Second level precision."; - throw exception_info; - } - }else if("proc"==seq_option.src){ - string exception_info = "interval not support Second level precision."; - throw exception_info; - } + seq_option.intervals = int(stof(seq_option.interval.substr(0,(seq_option.interval.size()-1)))); }else{ seq_option.intervals = int(60 * stoi(seq_option.interval)); } + seq_option.intervals = (seq_option.intervals + seq_option.collect_interval - 1) / seq_option.collect_interval * seq_option.collect_interval; }else{ if("sys" == seq_option.src && seq_option.live_mode){ seq_option.intervals = 1; @@ -1705,8 +1703,15 @@ void ReportProc(SeqOptions &seq_option){ it_sre_proc.SetDataPath(seq_option.data_path); int read_file_ret; int data_hour_path_ret; - chrono::system_clock::time_point it_time_point = seq_option.time_point_finish; - chrono::system_clock::time_point time_point_real = seq_option.time_point_finish; + if(0 == it_sre_proc.MakeDataHourPath(seq_option.time_point_finish)){ + seq_option.time_point_finish_real = it_sre_proc.GetDataTimePointReal(); + seq_option.adjust = it_sre_proc.GetAdjusted(); + }else{ + seq_option.time_point_finish_real = seq_option.time_point_finish; + seq_option.adjust = true; + } + chrono::system_clock::time_point it_time_point = seq_option.time_point_finish_real; + chrono::system_clock::time_point time_point_real = seq_option.time_point_finish_real; chrono::system_clock::time_point time_point_after_last = chrono::time_point{}; chrono::system_clock::time_point time_point_before_first = chrono::time_point{}; chrono::system_clock::time_point start_decide_time_point = chrono::time_point{}; @@ -4020,7 +4025,6 @@ int main(int argc, char *argv[]){ map> cumulate_hierarchy; unordered_map sys_dtype; vector reboot_times; - SeqOptions opts = SeqOptions(); opts.sys_view = &sys_view; opts.sys_files = &sys_files; @@ -4047,6 +4051,9 @@ int main(int argc, char *argv[]){ if(main_ini->contains_qualified("work_path")){ opts.work_path = main_ini->get_qualified("work_path")->as()->get(); } + if(main_ini->contains_qualified("collect_interval")){ + opts.collect_interval = main_ini->get_as("collect_interval").value_or(60); + } } if(ssar_config && ssar_config->contains("proc")){ shared_ptr proc_ini = ssar_config->get_table("proc"); @@ -4203,7 +4210,7 @@ int main(int argc, char *argv[]){ CLI::Option* cli_sys_finish_option = cli_global.add_option("--finish,-f", opts.finish, "Assign the output datetime, allow history datetime. default value is current datetime."); CLI::Option* cli_sys_range_option = cli_global.add_option("--range,-r", opts.range, "Range from begin to finish, default 300 minutes."); CLI::Option* cli_sys_begin_option = cli_global.add_option("--begin,-b", opts.begin, "Assign the compare datetime by the finish"); - CLI::Option* cli_sys_interval_option = cli_global.add_option("--interval,-i", opts.interval, "interval, default 10 minutes."); + CLI::Option* cli_sys_interval_option = cli_global.add_option("--interval,-i", opts.interval, "interval, default 1 minutes. can be set as any value with time unit, default time unit is minutes, e.g. 6s, 2m, 10h..."); CLI::Option* cli_sys_noheaders_option = cli_global.add_flag("--no-headers,-H", opts.noheaders, "Disable the header info.")->excludes(cli_sys_api_option); CLI::Option* cli_sys_purify_option = cli_global.add_flag("--purify,-P", opts.purify, "Hide the - * < > = no number data info."); CLI::Option* cli_sys_format_option = cli_global.add_option("--format,-o", opts.format, "User-defined format. syntax is field1,field2"); @@ -4245,7 +4252,7 @@ int main(int argc, char *argv[]){ cli_proc->add_option("--finish,-f", opts.finish, "Assign the output datetime, allow history datetime. default value is current datetime."); CLI::Option* cli_proc_range_option = cli_proc->add_option("--range,-r", opts.range, "Range from begin to finish, default 300 minutes."); cli_proc->add_option("--begin,-b", opts.begin, "Assign the compare datetime by the finish"); - cli_proc->add_option("--interval,-i", opts.interval, "interval, default 10 minutes.."); + cli_proc->add_option("--interval,-i", opts.interval, "interval, default 1 minutes. can be set as any value with time unit, default time unit is minutes, e.g. 6s, 2m, 10h..."); cli_proc->add_flag("--no-headers,-H", opts.noheaders, "Disable the header info.")->excludes(cli_proc_api_option); cli_proc->add_flag("--purify,-P", opts.purify, "Hide the - * < > = no number data info."); CLI::Option* cli_proc_format_option = cli_proc->add_option("--format,-o", opts.format, "User-defined format. syntax is field1,field2"); diff --git a/ssar/ssar.h b/ssar/ssar.h index f110857..9496bd0 100644 --- a/ssar/ssar.h +++ b/ssar/ssar.h @@ -305,6 +305,7 @@ struct SeqOptions { chrono::duration duration_real; string interval; int intervals; + int collect_interval; string begin; string finish; string collect; -- Gitee