├── conf ├── sresar.cron ├── Makefile ├── healing.sh ├── sresar.service ├── ssar.conf ├── sresard ├── ssar.1 ├── zh_CN.ssar.1 └── sys.conf ├── ssar ├── Makefile ├── ssar+.py ├── gzstream.hpp └── ssar.h ├── debian ├── control ├── postinst ├── prerm └── build.sh ├── sresar ├── collection.h ├── Makefile ├── utils.h ├── collection.c ├── sresar.h ├── utils.c ├── toml.h ├── readprocess.h └── readprocess.c ├── CONTRIBUTOR ├── Makefile ├── spec └── ssar.spec ├── LICENSE └── README.md /conf/sresar.cron: -------------------------------------------------------------------------------- 1 | * * * * * root /usr/lib/os_health/ssar/healing.sh > /dev/null 2>&1 2 | -------------------------------------------------------------------------------- /ssar/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | g++ -g -std=c++11 -rdynamic -DCPPTOML_USE_MAP ssar.cpp -o ssar -lz 3 | clean: 4 | rm -fr ssar 5 | -------------------------------------------------------------------------------- /conf/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | gzip -c ssar.1 > ssar.1.gz 3 | gzip -c zh_CN.ssar.1 > zh_CN.ssar.1.gz 4 | clean: 5 | rm -fr ssar.1.gz zh_CN.ssar.1.gz 6 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Package: ssar 2 | Version: 1.0.5-1 3 | Architecture: amd64 4 | Section: utils 5 | Maintainer: Miles Wen 6 | Description: log the system details 7 | 8 | -------------------------------------------------------------------------------- /conf/healing.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | LOCKFILE="/run/lock/os_health/sresar.pid" 4 | exec {FD}<> $LOCKFILE 5 | if [ ! -e /etc/ssar/sresar.disable ];then 6 | if flock -x -n $FD; then 7 | flock --unlock $FD 8 | /usr/bin/sresar -D > /dev/null 2>&1 & 9 | fi 10 | fi 11 | -------------------------------------------------------------------------------- /conf/sresar.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=sresar service 3 | ConditionPathExists=!/etc/ssar/sresar.disable 4 | 5 | [Service] 6 | Type=simple 7 | Restart=always 8 | StartLimitInterval=0 9 | StartLimitBurst=6000 10 | ExecStart=/usr/bin/sresar -D 11 | StandardOutput=journal 12 | StandardError=journal 13 | MemoryLimit=200M 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /sresar/collection.h: -------------------------------------------------------------------------------- 1 | #ifndef SRESAR_COLLECTION_H 2 | #define SRESAR_COLLECTION_H 3 | 4 | typedef struct _node{ 5 | int load5s_state; 6 | int zoom_state; 7 | int load5s; 8 | double load1; 9 | struct _node *next; 10 | struct _node *prev; 11 | }Node; 12 | 13 | void circular_linkedlist_init(Node *plist, int list_size); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /CONTRIBUTOR: -------------------------------------------------------------------------------- 1 | # This file contains a list of people who've made non-trivial contribution to the sresar project. 2 | # People who commit code to the project are encouraged to add their names here. 3 | # Please keep the list sorted by first names. 4 | 5 | Ccheng 6 | Dust.Li 7 | MilesWen 8 | TonyLu 9 | Xlpang 10 | 11 | -------------------------------------------------------------------------------- /sresar/Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | gcc -g -std=gnu99 -rdynamic -c toml.c -o toml.o 3 | gcc -g -std=gnu99 -rdynamic -c utils.c -o utils.o 4 | gcc -g -std=gnu99 -rdynamic -c collection.c -o collection.o 5 | gcc -g -std=gnu99 -rdynamic -c readprocess.c -o readprocess.o 6 | gcc -g -std=gnu99 -rdynamic -c sresar.c -o sresar.o 7 | gcc -g -std=gnu99 -rdynamic toml.o utils.o collection.o readprocess.o sresar.o -o sresar -lpthread -lm -lz 8 | clean: 9 | rm -fr sresar 10 | rm -fr toml.o utils.o collection.o readprocess.o sresar.o 11 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $(cat /proc/1/sched | head -n 1 | grep systemd) ]]; then 4 | # in host 5 | cp -f /usr/src/os_health/ssar/sresar.service /etc/systemd/system/sresar.service 6 | chown root:root /etc/systemd/system/sresar.service 7 | systemctl daemon-reload 8 | systemctl is-enabled sresar.service && systemctl disable sresar.service 9 | systemctl enable sresar.service 10 | systemctl is-active sresar.service && systemctl stop sresar.service 11 | systemctl start sresar.service 12 | else 13 | # in docker 14 | cp -f /usr/src/os_health/ssar/sresar.cron /etc/cron.d/sresar.cron 15 | chown root:root /etc/cron.d/sresar.cron 16 | cp -f /usr/src/os_health/ssar/sresard /etc/init.d/sresard 17 | chown root:root /etc/init.d/sresard 18 | chmod a+x /etc/init.d/sresard 19 | chkconfig --add sresard 20 | /usr/lib/os_health/ssar/healing.sh 21 | fi 22 | -------------------------------------------------------------------------------- /sresar/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef SRESAR_UTILS_H 2 | #define SRESAR_UTILS_H 3 | 4 | #define MALLOC __attribute__ ((__malloc__)) 5 | 6 | // Utility buffer 7 | typedef struct utlbuf_s { 8 | int len; 9 | char *buf; 10 | } utlbuf_s; 11 | 12 | // Utility Arrry 13 | typedef struct utlarr_i { 14 | int len; 15 | int *arr; 16 | } utlarr_i; 17 | 18 | extern int find_char(char **strings, char *value); 19 | extern int remove_directory(const char *path); 20 | extern void randomlize(int *arr, int n); 21 | extern void fmt_datetime(time_t timestamp, char *fmt_datetime, const char *format); 22 | extern char* replace_char(char* str, char find, char replace); 23 | 24 | typedef void (*message_fn)(const char *__restrict, ...) __attribute__((format(printf,1,2))); 25 | extern message_fn xalloc_err_handler; 26 | extern void *xxcalloc(unsigned int size) MALLOC; 27 | extern void *xxmalloc(size_t size) MALLOC; 28 | extern void *xxrealloc(void *oldp, unsigned int size) MALLOC; 29 | extern char *strrchr2(register const char *s, int c); 30 | 31 | 32 | #endif 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /conf/ssar.conf: -------------------------------------------------------------------------------- 1 | [main] 2 | duration_threshold=168 # 168 hour >168 will stop. 3 | inode_use_threshold=90 # disk df_inode_use >90% will stop. 4 | disk_use_threshold=90 # disk df_use >90% will stop. 5 | disk_available_threshold=1000 # disk df_avail <1GB will stop. 6 | duration_restart=10 # restart sresar per 10 hour. 7 | work_path='/var/log' # work root path 8 | scatter_second=0 # the offset of collect time point 9 | load5s_flag=true # if false, will disable load5s collect 10 | proc_flag=true # if false, will disable process collect 11 | sys_flag=true # if false, will disable sys info collect 12 | 13 | [load] 14 | load5s_threshold=1 # load5s/corenum >1 will collect load 15 | load1m_threshold=1 # load1m/corenum >1 will collect load 16 | realtime_priority=0 # realtime priority [1-99], 0 will disable realtime. 17 | stack_sample_disable=false # if true, will collect all D state task stack 18 | 19 | [proc] 20 | proc_gzip_disable=false # if true, will disable process file gzip. 21 | -------------------------------------------------------------------------------- /debian/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ "$1" == "remove" ]]; then 4 | if [[ $(cat /proc/1/sched | head -n 1 | grep systemd) ]]; then 5 | # in host 6 | systemctl stop sresar.service 7 | systemctl disable sresar.service 8 | rm -f /etc/systemd/system/sresar.service 9 | systemctl daemon-reload 10 | systemctl reset-failed 11 | else 12 | # in docker 13 | chkconfig --del sresard 14 | rm -f /etc/cron.d/sresar.cron 15 | rm -f /etc/init.d/sresard 16 | fi 17 | 18 | if [[ -e %{work_path}"/sre_proc/" ]];then 19 | for i1 in $(ls %{work_path}"/sre_proc/") 20 | do 21 | rm -fr %{work_path}"/sre_proc/"${i1} 22 | sleep 0.01 23 | done 24 | rm -fr %{work_path}"/sre_proc/" 25 | fi 26 | 27 | if [[ -e "/var/log/sre_proc/" ]];then 28 | for i2 in $(ls "/var/log/sre_proc/") 29 | do 30 | rm -fr "/var/log/sre_proc/"${i2} 31 | sleep 0.01 32 | done 33 | rm -fr "/var/log/sre_proc/" 34 | fi 35 | 36 | customized_work_path=$(cat /etc/ssar/ssar.conf | grep work_path | awk -F= '{print $2}') 37 | if [[ -e ${customized_work_path}"/sre_proc/" ]];then 38 | for i3 in $(ls ${customized_work_path}"/sre_proc/") 39 | do 40 | rm -fr ${customized_work_path}"/sre_proc/"${i3} 41 | sleep 0.01 42 | done 43 | rm -fr ${customized_work_path}"/sre_proc/" 44 | fi 45 | fi 46 | -------------------------------------------------------------------------------- /sresar/collection.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2021 Alibaba Inc. 4 | * SRESAR is licensed under Mulan PSL v2. 5 | * You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | * You may obtain a copy of Mulan PSL v2 at: 7 | * http://license.coscl.org.cn/MulanPSL2 8 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | * See the Mulan PSL v2 for more details. 12 | * 13 | * Part of SRESAR (Site Reliability Engineering System Activity Reporter) 14 | * 15 | * Author: Miles Wen 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | #include "collection.h" 22 | 23 | void circular_linkedlist_init(Node *plist, int list_size){ 24 | int i; 25 | Node* first_node = plist; 26 | Node* current_node = plist; 27 | Node* prev_node = NULL; 28 | Node* next_node = current_node + 1; 29 | current_node->next = next_node; 30 | current_node->load1 = (double)0; 31 | for(i = 0; i < list_size - 2; i++){ 32 | prev_node = current_node; 33 | current_node = next_node; 34 | next_node = current_node + 1; 35 | 36 | current_node->prev = prev_node; 37 | current_node->next = next_node; 38 | current_node->load1 = (double)0; 39 | } 40 | prev_node = current_node; 41 | current_node = next_node; 42 | next_node = first_node; 43 | current_node->prev = prev_node; 44 | current_node->next = next_node; 45 | current_node->load1 = (double)0; 46 | 47 | first_node->prev = current_node; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /sresar/sresar.h: -------------------------------------------------------------------------------- 1 | #ifndef SRESAR_SRESAR_H 2 | #define SRESAR_SRESAR_H 3 | 4 | #define SRC_USER 10001 5 | #define SRC_DAEMON 10002 6 | #define SRC_LOADRD 10003 7 | #define SRC_STACK 10004 8 | 9 | #define COLLECT_SIZE 256 10 | #define FILE_SIZE 32 11 | #define UNAME_SIZE 32 12 | #define WORK_PATH_SIZE 128 13 | 14 | typedef struct{ 15 | int src; 16 | double load5s_threshold; 17 | double load1m_threshold; 18 | int load5s_baseline; 19 | int load1m_baseline; 20 | int duration_threshold; 21 | unsigned long inode_use_threshold; 22 | unsigned long disk_use_threshold; 23 | unsigned long disk_available_threshold; 24 | int duration_restart; 25 | int scatter_second; 26 | int realtime_priority; 27 | int load_collect_interval; 28 | bool stack_sample_disable; 29 | bool proc_gzip_disable; 30 | bool load5s_flag; 31 | bool proc_flag; 32 | bool sys_flag; 33 | char work_path[WORK_PATH_SIZE]; 34 | char sys_srcs[COLLECT_SIZE][8 * FILE_SIZE]; 35 | char sys_targets[COLLECT_SIZE][FILE_SIZE]; 36 | int sys_gzips[COLLECT_SIZE]; 37 | int pid_fd; 38 | int nprocessors; 39 | char ssar_path[2 * WORK_PATH_SIZE]; 40 | char log_path[2 * WORK_PATH_SIZE]; 41 | char data_path[2 * WORK_PATH_SIZE]; 42 | char data_path_hour[2 * WORK_PATH_SIZE]; 43 | char log_file[2 * WORK_PATH_SIZE]; 44 | char load5s_file[2 * WORK_PATH_SIZE]; 45 | FILE *sresar_stderr; 46 | int load5s_fd; 47 | int eventfd_load1; 48 | int eventfd_cmdinfo; 49 | int eventfd_thread; 50 | int return_value; 51 | pthread_t main_mtid; 52 | volatile int partition_insufficient; 53 | volatile int hour_lock; 54 | volatile int hour_timestamp_lock; 55 | }seq_options; 56 | 57 | typedef struct{ 58 | int turn; 59 | int gzip; 60 | char src_path[8 * FILE_SIZE]; 61 | char cfile[FILE_SIZE]; 62 | char uname[UNAME_SIZE]; 63 | } collect; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | default: 2 | make -C conf 3 | make -C ssar 4 | make -C sresar 5 | clean: 6 | make -C conf clean 7 | make -C ssar clean 8 | make -C sresar clean 9 | install: 10 | install -d /etc/ssar/ 11 | install conf/ssar.conf /etc/ssar/ 12 | install conf/sys.conf /etc/ssar/ 13 | install -d /usr/src/os_health/ssar/ 14 | install conf/sresar.service /usr/src/os_health/ssar/ 15 | install -d /usr/bin/ 16 | install ssar/ssar /usr/bin/ssar 17 | install ssar/ssar+.py /usr/bin/ssar+ 18 | install ssar/tsar2.py /usr/bin/tsar2 19 | install sresar/sresar /usr/bin/sresar 20 | install -d /run/lock/os_health/ 21 | touch /run/lock/os_health/sresar.pid 22 | cp -f /usr/src/os_health/ssar/sresar.service /etc/systemd/system/sresar.service 23 | chown root:root /etc/systemd/system/sresar.service 24 | systemctl daemon-reload 25 | if [ systemctl is-enabled sresar.service ]; then \ 26 | systemctl disable sresar.service; \ 27 | fi 28 | systemctl enable sresar.service 29 | if systemctl is-active sresar.service; then \ 30 | systemctl stop sresar.service; \ 31 | fi 32 | systemctl start sresar.service 33 | uninstall: 34 | systemctl stop sresar.service 35 | systemctl disable sresar.service 36 | rm -f /etc/systemd/system/sresar.service 37 | systemctl daemon-reload 38 | systemctl reset-failed 39 | if [[ -e "/var/log/sre_proc/" ]];then \ 40 | for i2 in $(ls "/var/log/sre_proc/"); do \ 41 | rm -fr "/var/log/sre_proc/"${i2}; \ 42 | sleep 0.01; \ 43 | done; \ 44 | rm -fr "/var/log/sre_proc/"; \ 45 | fi 46 | customized_work_path=$(cat /etc/ssar/ssar.conf | grep work_path | awk -F= '{print $2}') 47 | if [[ -e ${customized_work_path}"/sre_proc/" ]];then \ 48 | for i3 in $(ls ${customized_work_path}"/sre_proc/"); do \ 49 | rm -fr ${customized_work_path}"/sre_proc/"${i3}; \ 50 | sleep 0.01; \ 51 | done; \ 52 | rm -fr ${customized_work_path}"/sre_proc/"; \ 53 | fi 54 | rm -fr /etc/ssar/ 55 | rm -fr /usr/src/os_health/ssar/ 56 | rm -f /usr/bin/ssar 57 | rm -f /usr/bin/ssar+ 58 | rm -f /usr/bin/tsar2 59 | rm -f /usr/bin/sresar 60 | rm -fr /run/lock/os_health/ 61 | -------------------------------------------------------------------------------- /debian/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | deb_workspace=$(cd $(dirname $0);pwd) 4 | echo $deb_workspace 5 | 6 | sourcedir=${deb_workspace}"/../" 7 | builddir=${deb_workspace}"/.deb_create/BUILD/" 8 | buildrootdir=${deb_workspace}"/.deb_create/BUILDROOT/" 9 | debdir=${deb_workspace}"/.deb_create/DEBS/" 10 | 11 | rm -fr .deb_create 12 | mkdir -p $builddir 13 | mkdir -p $buildrootdir 14 | mkdir -p $debdir 15 | 16 | # prep 17 | install -d $builddir/sresar/ 18 | install -d $builddir/ssar/ 19 | install -d $builddir/conf/ 20 | install -v -D $sourcedir/sresar/* $builddir/sresar/ 21 | install -v -D $sourcedir/ssar/* $builddir/ssar/ 22 | install -v -D $sourcedir/conf/* $builddir/conf/ 23 | install -v $sourcedir/Makefile $builddir/Makefile 24 | install -d $builddir/debian/ 25 | install -v -D $sourcedir/debian/* $builddir/debian/ 26 | 27 | # make 28 | make -C $builddir 29 | 30 | # install 31 | install -d ${buildrootdir}/etc/ssar/ 32 | install $builddir/conf/ssar.conf ${buildrootdir}/etc/ssar/ 33 | install $builddir/conf/sys.conf ${buildrootdir}/etc/ssar/ 34 | install -d ${buildrootdir}/usr/share/man/man1/ 35 | install $builddir/conf/ssar.1.gz ${buildrootdir}/usr/share/man/man1/ 36 | install -d ${buildrootdir}/usr/src/os_health/ssar/ 37 | install $builddir/conf/sresar.service ${buildrootdir}/usr/src/os_health/ssar/ 38 | install $builddir/conf/sresar.cron ${buildrootdir}/usr/src/os_health/ssar/ 39 | install $builddir/conf/sresard ${buildrootdir}/usr/src/os_health/ssar/ 40 | install -d ${buildrootdir}/usr/lib/os_health/ssar/ 41 | install $builddir/conf/healing.sh ${buildrootdir}/usr/lib/os_health/ssar/healing.sh 42 | install -d ${buildrootdir}/usr/bin/ 43 | install $builddir/ssar/ssar ${buildrootdir}/usr/bin/ssar 44 | install $builddir/ssar/ssar+.py ${buildrootdir}/usr/bin/ssar+ 45 | install $builddir/ssar/tsar2.py ${buildrootdir}/usr/bin/tsar2 46 | install $builddir/sresar/sresar ${buildrootdir}/usr/bin/sresar 47 | install -d ${buildrootdir}/run/lock/os_health/ 48 | touch ${buildrootdir}/run/lock/os_health/sresar.pid 49 | 50 | # install plus 51 | install -d ${buildrootdir}/DEBIAN/ 52 | install $builddir/debian/control ${buildrootdir}/DEBIAN/ 53 | install $builddir/debian/postinst ${buildrootdir}/DEBIAN/ 54 | install $builddir/debian/prerm ${buildrootdir}/DEBIAN/ 55 | 56 | # build 57 | package_name=$(grep -F Package ${buildrootdir}/DEBIAN/control | head -n 1 | awk -F: '{print $2}') 58 | version_name=$(grep -F Version ${buildrootdir}/DEBIAN/control | head -n 1 | awk -F: '{print $2}') 59 | architecture_name=$(grep -F Architecture ${buildrootdir}/DEBIAN/control | head -n 1 | awk -F: '{print $2}') 60 | 61 | package_name=$(echo $package_name) 62 | version_name=$(echo $version_name) 63 | architecture_name=$(echo $architecture_name) 64 | 65 | dpkg-deb --build ${buildrootdir} ${debdir}/${package_name}"_"${version_name}"_"${architecture_name}".deb" 66 | 67 | # bakup 68 | cp ${debdir}/${package_name}"_"${version_name}"_"${architecture_name}".deb" ${deb_workspace}/ 69 | -------------------------------------------------------------------------------- /ssar/ssar+.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import os 5 | import sys 6 | import argparse 7 | 8 | MAX_SUB_HELP_POSITION = 45 9 | MAX_HELP_WIDTH = 150 10 | 11 | class SeqOptions(object): 12 | pass 13 | 14 | class ItFormatter(argparse.RawTextHelpFormatter): 15 | def format_help(self): 16 | help = self._root_section.format_help() 17 | if help: 18 | help = self._long_break_matcher.sub('\n\n', help) 19 | help = help.strip('\n') + '\n' 20 | return help 21 | 22 | def sysfunc(args): 23 | print('ssar+ is the future of tsar2') 24 | #print('sysfunc === ', args) 25 | def workers(args): 26 | print('ssar+ is the future of tsar2.', args) 27 | #print('workers === ', args) 28 | def procs(args): 29 | print('ssar+ is the future of tsar2.', args) 30 | #print('procs === ', args) 31 | 32 | seq_option = SeqOptions() 33 | 34 | def main(): 35 | subcommand_list = ['procs', 'workers'] 36 | subcommand_info = "Subcommands:" + "\n" 37 | for it_subcommand in subcommand_list: 38 | subcommand_info = subcommand_info + " ssar " + it_subcommand + " -h\n" 39 | 40 | root_footer_info = ''' 41 | Examples: 42 | ssar --cpu 43 | ssar --mem 44 | ''' 45 | procs_footer_info = ''' 46 | Examples: 47 | ssar procs --cpu1 48 | ssar procs --mem1 49 | ''' 50 | 51 | # ItFormatterClass = lambda prog: ItFormatter(prog, max_help_position = MAX_SUB_HELP_POSITION, width = MAX_HELP_WIDTH) 52 | ItFormatterClass = lambda prog: ItFormatter(prog) 53 | root_parser = argparse.ArgumentParser(add_help = False, formatter_class = ItFormatterClass, usage = "%(prog)s [OPTIONS] [SUBCOMMAND]", epilog = subcommand_info + root_footer_info) 54 | root_parser.add_argument("-h", "--help", action = "store_true", dest = "root_help", default = False, help = "Display help information") 55 | root_parser.add_argument("--cpu", action = "store_true", dest = "seq_option.cpu", help = "Display cpu information") 56 | root_parser.add_argument("--mem", action = "store_true", dest = "seq_option.mem", help = "Display mem information") 57 | 58 | common_parser = argparse.ArgumentParser() 59 | subparsers = common_parser.add_subparsers(dest='cmd') 60 | 61 | procs_parser = subparsers.add_parser("procs", help = "procs subcommand", formatter_class = ItFormatterClass, epilog = procs_footer_info) 62 | procs_parser.add_argument("-o", "--output", help = "output info") 63 | procs_parser.add_argument("--cpu", action = "store_true", dest = "seq_option.cpu", help = "Display procs cpu information") 64 | procs_parser.add_argument("--mem", action = "store_true", dest = "seq_option.mem", help = "Display procs mem information") 65 | procs_parser.set_defaults(callback = procs) 66 | 67 | workers_parser = subparsers.add_parser("workers", help = "workers Command") 68 | workers_parser.set_defaults(callback = workers) 69 | 70 | root_args, root_extras = root_parser.parse_known_args() 71 | if len(root_extras) > 0: 72 | if root_extras[0] in subcommand_list: 73 | common_args, common_extras = common_parser.parse_known_args() 74 | if len(common_extras) > 0: 75 | subparsers._name_parser_map[root_extras[0]].print_help() # procs_parser.print_help() 76 | exit(201) 77 | else: 78 | common_args.callback(common_args) 79 | else: 80 | root_parser.print_help() 81 | exit(202) 82 | else: 83 | if root_args.root_help: 84 | root_parser.print_help() 85 | exit(203) 86 | else: 87 | sysfunc(root_args) 88 | 89 | if __name__ == "__main__": 90 | main() 91 | -------------------------------------------------------------------------------- /ssar/gzstream.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | bool isGzipFileName(string file_name){ 10 | int file_size = file_name.size(); 11 | if(file_size > 3){ 12 | if(".gz" == file_name.substr(file_size - 3, 3)){ 13 | return true; 14 | } 15 | } 16 | return false; 17 | } 18 | 19 | class gzstreambuf: public streambuf { 20 | public: 21 | static const int bufferSize = 47 + 256; // size of data buff 22 | gzFile file; // file handle for compressed file 23 | char buffer[bufferSize]; // data buffer 24 | char opened; // open/close state of stream 25 | 26 | gzstreambuf() : opened(0) { 27 | this->setg(this->buffer + 4, this->buffer + 4, this->buffer + 4); // setg(gfirst, gnext, glast), beginning of putback area 28 | } 29 | gzstreambuf(const char* name) : gzstreambuf(){ 30 | this->gzsbopen(name); 31 | } 32 | 33 | int is_open(){ 34 | return this->opened; 35 | } 36 | gzstreambuf* gzsbopen(const char* name){ 37 | if(this->is_open()){ 38 | return (gzstreambuf*) 0; 39 | } 40 | this->file = gzopen(name, "rb"); 41 | if (this->file == 0){ 42 | return (gzstreambuf*) 0; 43 | } 44 | this->opened = 1; 45 | return this; 46 | } 47 | 48 | gzstreambuf* gzsbclose(){ 49 | if(this->is_open()) { 50 | this->opened = 0; 51 | if (gzclose(this->file) == Z_OK){ // Z_OK indicates that a gzip stream was completed on the last gzread 52 | return this; 53 | } 54 | } 55 | return (gzstreambuf*) 0; 56 | } 57 | 58 | int gzsbseek(streamoff off, ios::seekdir way){ 59 | int res = gzseek(this->file, off, way); 60 | if(-1 == res){ 61 | ostringstream oss; 62 | oss << (filebuf *) this; 63 | res = gzseek(this->file, off, way); 64 | } 65 | return res; 66 | } 67 | streampos gzsbtell(){ 68 | return (streampos)gztell(this->file); 69 | } 70 | 71 | int underflow(){ // only used for input buffer 72 | if (this->gptr() && (this->gptr() < this->egptr())){ 73 | return *reinterpret_cast(this->gptr()); 74 | } 75 | 76 | if (!this->opened){ 77 | return EOF; 78 | } 79 | int n_putback = this->gptr() - this->eback(); 80 | if (n_putback > 4){ 81 | n_putback = 4; 82 | } 83 | memmove(this->buffer + (4 - n_putback), this->gptr() - n_putback, n_putback); 84 | 85 | int num = gzread(this->file, this->buffer + 4, bufferSize - 4); 86 | if (num <= 0){ // ERROR or EOF 87 | return EOF; 88 | } 89 | 90 | // reset buffer pointers 91 | this->setg(this->buffer + (4 - n_putback), this->buffer + 4, this->buffer + 4 + num); // beginning of putback area, read position. end of buffer 92 | 93 | // return next character 94 | return *reinterpret_cast(this->gptr()); 95 | } 96 | 97 | ~gzstreambuf(){ 98 | if(this->is_open()){ 99 | this->gzsbclose(); 100 | } 101 | } 102 | }; 103 | 104 | 105 | class igzfstream: public ifstream { 106 | gzstreambuf gz_buf; 107 | public: 108 | igzfstream(){} 109 | void open(const string &name, ios::openmode open_mode = ios::in) { 110 | if(isGzipFileName(name)){ 111 | gzstreambuf* res = gz_buf.gzsbopen(name.c_str()); 112 | ios::rdbuf(&gz_buf); 113 | if(!res){ 114 | ios::setstate(ios::failbit|ios::badbit); 115 | } 116 | }else{ 117 | ifstream::open(name, ios::in); 118 | } 119 | } 120 | streambuf* rdbuf(){ 121 | return istream::rdbuf(); 122 | } 123 | igzfstream& seekg(streamoff off, ios::seekdir way){ 124 | if(gz_buf.is_open()){ 125 | gz_buf.gzsbseek(off, way); 126 | }else{ 127 | ifstream::seekg(off, way); 128 | } 129 | return *this; 130 | } 131 | streampos tellg(){ 132 | if(gz_buf.is_open()){ 133 | return gz_buf.gzsbtell(); 134 | }else{ 135 | return ifstream::tellg(); 136 | } 137 | } 138 | }; 139 | -------------------------------------------------------------------------------- /sresar/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2021 Alibaba Inc. 4 | * SRESAR is licensed under Mulan PSL v2. 5 | * You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | * You may obtain a copy of Mulan PSL v2 at: 7 | * http://license.coscl.org.cn/MulanPSL2 8 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | * See the Mulan PSL v2 for more details. 12 | * 13 | * Part of SRESAR (Site Reliability Engineering System Activity Reporter) 14 | * 15 | * Author: Miles Wen 16 | * 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "utils.h" 31 | 32 | #define _unlikely_(x) (__builtin_expect(!!(x), 0)) 33 | 34 | 35 | static void xxdefault_error(const char *restrict fmts, ...) __attribute__((format(printf,1,2))); 36 | static void xxdefault_error(const char *restrict fmts, ...) { 37 | va_list va; 38 | 39 | va_start(va, fmts); 40 | fprintf(stderr, fmts, va); 41 | va_end(va); 42 | } 43 | 44 | message_fn xxalloc_err_handler = xxdefault_error; 45 | 46 | 47 | void *xxcalloc(unsigned int size) { 48 | void * p; 49 | 50 | if (size == 0){ 51 | ++size; 52 | } 53 | p = calloc(1, size); 54 | if (!p) { 55 | xxalloc_err_handler("%s failed to allocate %u bytes of memory", __func__, size); 56 | exit(EXIT_FAILURE); 57 | } 58 | return p; 59 | } 60 | 61 | void *xxmalloc(size_t size) { 62 | void *p; 63 | 64 | if (size == 0){ 65 | ++size; 66 | } 67 | p = malloc(size); 68 | if (!p) { 69 | xxalloc_err_handler("%s failed to allocate %zu bytes of memory", __func__, size); 70 | exit(EXIT_FAILURE); 71 | } 72 | return(p); 73 | } 74 | 75 | void *xxrealloc(void *oldp, unsigned int size) { 76 | void *p; 77 | 78 | if (size == 0){ 79 | ++size; 80 | } 81 | p = realloc(oldp, size); 82 | if (!p) { 83 | xxalloc_err_handler("%s failed to allocate %u bytes of memory", __func__, size); 84 | exit(EXIT_FAILURE); 85 | } 86 | return(p); 87 | } 88 | 89 | 90 | void randomlize(int *arr, int n){ 91 | int i; 92 | int j; 93 | int tmp; 94 | struct timespec nanos; 95 | clock_gettime(CLOCK_MONOTONIC, &nanos); 96 | srand(nanos.tv_nsec); 97 | for(i = 0; i < n; i++){ 98 | j = rand() % (n-i) + i; //rand_r(); 99 | tmp = arr[i]; 100 | arr[i] = arr[j]; 101 | arr[j] = tmp; 102 | } 103 | } 104 | 105 | void fmt_datetime(time_t timestamp, char *it_datetime, const char *format){ 106 | struct tm tm; 107 | time_t tt = timestamp; 108 | localtime_r(&tt, &tm); 109 | strftime(it_datetime, 80, format, &tm); // %Y-%m-%dT%H:%M:%S 110 | } 111 | 112 | int remove_directory(const char *path){ 113 | struct stat statbuf; 114 | if(!stat(path, &statbuf)){ 115 | if(!S_ISDIR(statbuf.st_mode)){ 116 | return unlink(path); 117 | } 118 | }else{ 119 | return -1; 120 | } 121 | 122 | DIR *d = opendir(path); 123 | size_t path_len = strlen(path); 124 | int r = -1; 125 | 126 | if(d){ 127 | struct dirent *p; 128 | r = 0; 129 | 130 | while(!r && (p=readdir(d))){ 131 | int r2 = -1; 132 | char *buf; 133 | size_t len; 134 | 135 | /* Skip the names "." and ".." as we don't want to recurse on them. */ 136 | if(!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")){ 137 | continue; 138 | } 139 | len = path_len + strlen(p->d_name) + 2; 140 | buf = malloc(len); 141 | 142 | if(buf){ 143 | snprintf(buf, len, "%s/%s", path, p->d_name); 144 | if(!stat(buf, &statbuf)){ 145 | if(S_ISDIR(statbuf.st_mode)){ 146 | r2 = remove_directory(buf); 147 | }else{ 148 | r2 = unlink(buf); 149 | } 150 | } 151 | free(buf); 152 | } 153 | r = r2; 154 | } 155 | closedir(d); 156 | } 157 | if(!r){ 158 | r = rmdir(path); 159 | } 160 | 161 | return r; 162 | } 163 | 164 | char* replace_char(char* str, char find, char replace){ 165 | char *current_pos = strchr(str, find); 166 | while(current_pos){ 167 | *current_pos = replace; 168 | current_pos = strchr(current_pos, find); 169 | } 170 | return str; 171 | } 172 | 173 | int find_char(char **strings, char *value){ 174 | char *string; // 字符串循环变量 175 | while((string = *strings++) != NULL){ 176 | if(!strcmp(string, value)){ 177 | return 1; 178 | } 179 | } 180 | 181 | return 0; 182 | } 183 | 184 | char *strrchr2(register const char *s, int c){ 185 | char *rtnval = 0; 186 | 187 | do { 188 | if (*s == c) 189 | rtnval = (char*) s; 190 | } while (*s++); 191 | return (rtnval); 192 | } 193 | 194 | -------------------------------------------------------------------------------- /sresar/toml.h: -------------------------------------------------------------------------------- 1 | /* 2 | MIT License 3 | 4 | Copyright (c) 2017 - 2019 CK Tan 5 | https://github.com/cktan/tomlc99 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | */ 25 | #ifndef TOML_H 26 | #define TOML_H 27 | 28 | 29 | #include 30 | #include 31 | 32 | 33 | #ifdef __cplusplus 34 | #define TOML_EXTERN extern "C" 35 | #else 36 | #define TOML_EXTERN extern 37 | #endif 38 | 39 | typedef struct toml_table_t toml_table_t; 40 | typedef struct toml_array_t toml_array_t; 41 | 42 | /* Parse a file. Return a table on success, or 0 otherwise. 43 | * Caller must toml_free(the-return-value) after use. 44 | */ 45 | TOML_EXTERN toml_table_t* toml_parse_file(FILE* fp, 46 | char* errbuf, 47 | int errbufsz); 48 | 49 | /* Parse a string containing the full config. 50 | * Return a table on success, or 0 otherwise. 51 | * Caller must toml_free(the-return-value) after use. 52 | */ 53 | TOML_EXTERN toml_table_t* toml_parse(char* conf, /* NUL terminated, please. */ 54 | char* errbuf, 55 | int errbufsz); 56 | 57 | /* Free the table returned by toml_parse() or toml_parse_file(). */ 58 | TOML_EXTERN void toml_free(toml_table_t* tab); 59 | 60 | /* Retrieve the key in table at keyidx. Return 0 if out of range. */ 61 | TOML_EXTERN const char* toml_key_in(toml_table_t* tab, int keyidx); 62 | 63 | /* Lookup table by key. Return the element or 0 if not found. */ 64 | TOML_EXTERN const char* toml_raw_in(toml_table_t* tab, const char* key); 65 | TOML_EXTERN toml_array_t* toml_array_in(toml_table_t* tab, const char* key); 66 | TOML_EXTERN toml_table_t* toml_table_in(toml_table_t* tab, const char* key); 67 | 68 | /* Return the array kind: 't'able, 'a'rray, 'v'alue */ 69 | TOML_EXTERN char toml_array_kind(toml_array_t* arr); 70 | 71 | /* For array kind 'v'alue, return the type of values 72 | i:int, d:double, b:bool, s:string, t:time, D:date, T:timestamp 73 | 0 if unknown 74 | */ 75 | TOML_EXTERN char toml_array_type(toml_array_t* arr); 76 | 77 | 78 | /* Return the number of elements in the array */ 79 | TOML_EXTERN int toml_array_nelem(toml_array_t* arr); 80 | 81 | /* Return the key of an array */ 82 | TOML_EXTERN const char* toml_array_key(toml_array_t* arr); 83 | 84 | /* Return the number of key-values in a table */ 85 | TOML_EXTERN int toml_table_nkval(toml_table_t* tab); 86 | 87 | /* Return the number of arrays in a table */ 88 | TOML_EXTERN int toml_table_narr(toml_table_t* tab); 89 | 90 | /* Return the number of sub-tables in a table */ 91 | TOML_EXTERN int toml_table_ntab(toml_table_t* tab); 92 | 93 | /* Return the key of a table*/ 94 | TOML_EXTERN const char* toml_table_key(toml_table_t* tab); 95 | 96 | /* Deref array by index. Return the element at idx or 0 if out of range. */ 97 | TOML_EXTERN const char* toml_raw_at(toml_array_t* arr, int idx); 98 | TOML_EXTERN toml_array_t* toml_array_at(toml_array_t* arr, int idx); 99 | TOML_EXTERN toml_table_t* toml_table_at(toml_array_t* arr, int idx); 100 | 101 | 102 | /* Raw to String. Caller must call free(ret) after use. 103 | * Return 0 on success, -1 otherwise. 104 | */ 105 | TOML_EXTERN int toml_rtos(const char* s, char** ret); 106 | 107 | /* Raw to Boolean. Return 0 on success, -1 otherwise. */ 108 | TOML_EXTERN int toml_rtob(const char* s, int* ret); 109 | 110 | /* Raw to Integer. Return 0 on success, -1 otherwise. */ 111 | TOML_EXTERN int toml_rtoi(const char* s, int64_t* ret); 112 | 113 | /* Raw to Double. Return 0 on success, -1 otherwise. */ 114 | TOML_EXTERN int toml_rtod(const char* s, double* ret); 115 | /* Same as toml_rtod, but return the sanitized double in string form as well */ 116 | TOML_EXTERN int toml_rtod_ex(const char* s, double* ret, char* buf, int buflen); 117 | 118 | /* Timestamp types. The year, month, day, hour, minute, second, z 119 | * fields may be NULL if they are not relevant. e.g. In a DATE 120 | * type, the hour, minute, second and z fields will be NULLs. 121 | */ 122 | typedef struct toml_timestamp_t toml_timestamp_t; 123 | struct toml_timestamp_t { 124 | struct { /* internal. do not use. */ 125 | int year, month, day; 126 | int hour, minute, second, millisec; 127 | char z[10]; 128 | } __buffer; 129 | int *year, *month, *day; 130 | int *hour, *minute, *second, *millisec; 131 | char* z; 132 | }; 133 | 134 | /* Raw to Timestamp. Return 0 on success, -1 otherwise. */ 135 | TOML_EXTERN int toml_rtots(const char* s, toml_timestamp_t* ret); 136 | 137 | /* misc */ 138 | TOML_EXTERN int toml_utf8_to_ucs(const char* orig, int len, int64_t* ret); 139 | TOML_EXTERN int toml_ucs_to_utf8(int64_t code, char buf[6]); 140 | TOML_EXTERN void toml_set_memutil(void* (*xxmalloc)(size_t), 141 | void (*xxfree)(void*), 142 | void* (*xxcalloc)(size_t, size_t), 143 | void* (*xxrealloc)(void*, size_t)); 144 | 145 | #endif /* TOML_H */ 146 | -------------------------------------------------------------------------------- /spec/ssar.spec: -------------------------------------------------------------------------------- 1 | %global __os_install_post %{nil} 2 | %define _ignore_post_scripts_errors %{nil} 3 | %define _enable_debug_packages %{nil} 4 | %define debug_package %{nil} 5 | %define anolis_release 1 6 | %define work_path /var/log 7 | 8 | Name: ssar 9 | Version: 1.0.5 10 | Release: %{?anolis_release}%{?dist} 11 | Url: https://gitee.com/anolis/ssar 12 | Summary: ssar for SRE 13 | Group: System Environment/Base 14 | License: Mulan PSL v2 15 | Source0: %{name}-%{version}.tar.gz 16 | 17 | BuildRequires: zlib-devel 18 | 19 | Vendor: Alibaba 20 | 21 | %description 22 | log the system details 23 | 24 | %prep 25 | cd $RPM_BUILD_DIR 26 | rm -rf %{name}-%{version} 27 | gzip -dc $RPM_SOURCE_DIR/%{name}-%{version}.tar.gz | tar -xvvf - 28 | if [ $? -ne 0 ]; then 29 | exit $? 30 | fi 31 | main_dir=$(tar -tzvf $RPM_SOURCE_DIR/%{name}-%{version}.tar.gz| head -n 1 | awk '{print $NF}' | awk -F/ '{print $1}') 32 | if [ "${main_dir}" == %{name} ];then 33 | mv %{name} %{name}-%{version} 34 | fi 35 | cd %{name}-%{version} 36 | chmod -R a+rX,u+w,g-w,o-w . 37 | 38 | %build 39 | cd %{name}-%{version} 40 | make 41 | 42 | %install 43 | rm -rf $RPM_BUILD_ROOT 44 | 45 | BuildDir=$RPM_BUILD_DIR/%{name}-%{version} 46 | 47 | install -d %{buildroot}/etc/ssar/ 48 | install -p $BuildDir/conf/ssar.conf %{buildroot}/etc/ssar/ 49 | install -p $BuildDir/conf/sys.conf %{buildroot}/etc/ssar/ 50 | install -d %{buildroot}/usr/share/man/man1/ 51 | install -p $BuildDir/conf/ssar.1.gz %{buildroot}/usr/share/man/man1/ 52 | install -d %{buildroot}/usr/src/os_health/ssar/ 53 | install -p $BuildDir/conf/sresar.service %{buildroot}/usr/src/os_health/ssar/ 54 | install -p $BuildDir/conf/sresar.cron %{buildroot}/usr/src/os_health/ssar/ 55 | install -p $BuildDir/conf/sresard %{buildroot}/usr/src/os_health/ssar/ 56 | install -d %{buildroot}/usr/lib/os_health/ssar/ 57 | install -p $BuildDir/conf/healing.sh %{buildroot}/usr/lib/os_health/ssar/healing.sh 58 | install -d %{buildroot}/usr/bin/ 59 | install -p $BuildDir/ssar/ssar %{buildroot}/usr/bin/ssar 60 | install -p $BuildDir/ssar/ssar+.py %{buildroot}/usr/bin/ssar+ 61 | install -p $BuildDir/ssar/tsar2.py %{buildroot}/usr/bin/tsar2 62 | install -p $BuildDir/sresar/sresar %{buildroot}/usr/bin/sresar 63 | install -d %{buildroot}/run/lock/os_health/ 64 | touch %{buildroot}/run/lock/os_health/sresar.pid 65 | 66 | %clean 67 | [ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT" 68 | rm -rf $RPM_BUILD_DIR/%{name}-%{version} 69 | 70 | %files 71 | %defattr(-,root,root,-) 72 | %dir %attr(755, root, root) /etc/ssar/ 73 | %config %attr(644, root, root) /etc/ssar/ssar.conf 74 | %config %attr(644, root, root) /etc/ssar/sys.conf 75 | %dir %attr(755, root, root) /usr/src/os_health/ssar/ 76 | %config %attr(644, root, root) /usr/src/os_health/ssar/sresar.service 77 | %config %attr(644, root, root) /usr/src/os_health/ssar/sresar.cron 78 | %config %attr(644, root, root) /usr/src/os_health/ssar/sresard 79 | %doc %attr(644, root, root) /usr/share/man/man1/ssar.1.gz 80 | /usr/bin/sresar 81 | /usr/bin/ssar 82 | /usr/bin/ssar+ 83 | /usr/bin/tsar2 84 | /usr/lib/os_health/ssar/healing.sh 85 | /run/lock/os_health/sresar.pid 86 | 87 | %pre 88 | 89 | %post 90 | /usr/bin/env python --version >/dev/null 2>&1 91 | if [ $? -ne 0 ];then 92 | sed -i 's:/usr/bin/env python:/usr/bin/env python3:' /usr/bin/tsar2 93 | fi 94 | 95 | if [[ $(cat /proc/1/sched | head -n 1 | grep systemd) ]]; then 96 | # in host 97 | cp -f /usr/src/os_health/ssar/sresar.service /etc/systemd/system/sresar.service 98 | chown root:root /etc/systemd/system/sresar.service 99 | systemctl daemon-reload 100 | systemctl is-enabled sresar.service && systemctl disable sresar.service 101 | systemctl enable sresar.service 102 | systemctl is-active sresar.service && systemctl stop sresar.service 103 | systemctl start sresar.service 104 | else 105 | # in docker 106 | cp -f /usr/src/os_health/ssar/sresar.cron /etc/cron.d/sresar.cron 107 | chown root:root /etc/cron.d/sresar.cron 108 | cp -f /usr/src/os_health/ssar/sresard /etc/init.d/sresard 109 | chown root:root /etc/init.d/sresard 110 | chmod a+x /etc/init.d/sresard 111 | chkconfig --add sresard 112 | /usr/lib/os_health/ssar/healing.sh 113 | fi 114 | 115 | %preun 116 | if [ "$1" = "0" ]; then 117 | if [[ $(cat /proc/1/sched | head -n 1 | grep systemd) ]]; then 118 | # in host 119 | systemctl stop sresar.service 120 | systemctl disable sresar.service 121 | rm -f /etc/systemd/system/sresar.service 122 | else 123 | # in docker 124 | chkconfig --del sresard 125 | rm -f /etc/cron.d/sresar.cron 126 | rm -f /etc/init.d/sresard 127 | fi 128 | 129 | if [[ -e %{work_path}"/sre_proc/" ]];then 130 | for i1 in $(ls %{work_path}"/sre_proc/") 131 | do 132 | rm -fr %{work_path}"/sre_proc/"${i1} 133 | sleep 0.01 134 | done 135 | rm -fr %{work_path}"/sre_proc/" 136 | fi 137 | 138 | if [[ -e "/var/log/sre_proc/" ]];then 139 | for i2 in $(ls "/var/log/sre_proc/") 140 | do 141 | rm -fr "/var/log/sre_proc/"${i2} 142 | sleep 0.01 143 | done 144 | rm -fr "/var/log/sre_proc/" 145 | fi 146 | 147 | customized_work_path=$(cat /etc/ssar/ssar.conf | grep work_path | awk -F= '{print $2}') 148 | if [[ -e ${customized_work_path}"/sre_proc/" ]];then 149 | for i3 in $(ls ${customized_work_path}"/sre_proc/") 150 | do 151 | rm -fr ${customized_work_path}"/sre_proc/"${i3} 152 | sleep 0.01 153 | done 154 | rm -fr ${customized_work_path}"/sre_proc/" 155 | fi 156 | fi 157 | 158 | %postun 159 | 160 | %changelog 161 | * Mon Feb 24 2025 MilesWen - 1.0.5-1 162 | - enable collection of sockstat data. 163 | * Mon Mar 13 2023 MilesWen - 1.0.4-1 164 | - Fix some segfault. 165 | * Wed Jul 13 2022 MilesWen - 1.0.3-1 166 | - Release ssar RPM package 167 | --end 168 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 木兰宽松许可证, 第2版 2 | 木兰宽松许可证, 第2版 3 | 4 | 2020年1月 http://license.coscl.org.cn/MulanPSL2 5 | 6 | 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: 7 | 8 | 0. 定义 9 | 10 | “软件” 是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 11 | 12 | “贡献” 是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 13 | 14 | “贡献者” 是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 15 | 16 | “法人实体” 是指提交贡献的机构及其“关联实体”。 17 | 18 | “关联实体” 是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 19 | 20 | 1. 授予版权许可 21 | 22 | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 23 | 24 | 2. 授予专利许可 25 | 26 | 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 27 | 28 | 3. 无商标许可 29 | 30 | “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 31 | 32 | 4. 分发限制 33 | 34 | 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 35 | 36 | 5. 免责声明与责任限制 37 | 38 | “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 39 | 40 | 6. 语言 41 | 42 | “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 43 | 44 | 条款结束 45 | 46 | 如何将木兰宽松许可证,第2版,应用到您的软件 47 | 48 | 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: 49 | 50 | 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; 51 | 52 | 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; 53 | 54 | 3, 请将如下声明文本放入每个源文件的头部注释中。 55 | 56 | Copyright (c) [Year] [name of copyright holder] 57 | [Software Name] is licensed under Mulan PSL v2. 58 | You can use this software according to the terms and conditions of the Mulan PSL v2. 59 | You may obtain a copy of Mulan PSL v2 at: 60 | http://license.coscl.org.cn/MulanPSL2 61 | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 62 | EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 63 | MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 64 | See the Mulan PSL v2 for more details. 65 | Mulan Permissive Software License,Version 2 66 | Mulan Permissive Software License,Version 2 (Mulan PSL v2) 67 | 68 | January 2020 http://license.coscl.org.cn/MulanPSL2 69 | 70 | Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: 71 | 72 | 0. Definition 73 | 74 | Software means the program and related documents which are licensed under this License and comprise all Contribution(s). 75 | 76 | Contribution means the copyrightable work licensed by a particular Contributor under this License. 77 | 78 | Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. 79 | 80 | Legal Entity means the entity making a Contribution and all its Affiliates. 81 | 82 | Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. 83 | 84 | 1. Grant of Copyright License 85 | 86 | Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. 87 | 88 | 2. Grant of Patent License 89 | 90 | Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. 91 | 92 | 3. No Trademark License 93 | 94 | No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in section 4. 95 | 96 | 4. Distribution Restriction 97 | 98 | You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. 99 | 100 | 5. Disclaimer of Warranty and Limitation of Liability 101 | 102 | THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 103 | 104 | 6. Language 105 | 106 | THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. 107 | 108 | END OF THE TERMS AND CONDITIONS 109 | 110 | How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software 111 | 112 | To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: 113 | 114 | Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; 115 | Create a file named "LICENSE" which contains the whole context of this License in the first directory of your software package; 116 | Attach the statement to the appropriate annotated syntax at the beginning of each source file. 117 | Copyright (c) [Year] [name of copyright holder] 118 | [Software Name] is licensed under Mulan PSL v2. 119 | You can use this software according to the terms and conditions of the Mulan PSL v2. 120 | You may obtain a copy of Mulan PSL v2 at: 121 | http://license.coscl.org.cn/MulanPSL2 122 | THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 123 | EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 124 | MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 125 | See the Mulan PSL v2 for more details. 126 | -------------------------------------------------------------------------------- /sresar/readprocess.h: -------------------------------------------------------------------------------- 1 | #ifndef SRESAR_READPROC_H 2 | #define SRESAR_READPROC_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "utils.h" 9 | 10 | #define PROCPATHLEN 512 // must hold /proc/2000222000/task/2000222000/cmdline 11 | #define GROWWIDTH 512 12 | #define WHITESPACE " \t\n\r" 13 | 14 | 15 | #define likely(x) __builtin_expect(!!(x),1) 16 | #define unlikely(x) __builtin_expect(!!(x),0) 17 | 18 | typedef struct proc_t { 19 | int ptype; // (special) 1 user process, 2 kernel process 20 | char state; // stat,status single-char code for process state 21 | int tid; // (special) task id, the POSIX thread ID 22 | int ppid; // stat,status pid of parent process 23 | int pgid; // stat process group id 24 | int sid; // stat session id 25 | int nlwp; // stat,status number of threads 26 | int tgid; // (special) thread group ID, the POSIX PID 27 | int tpgid; // stat terminal process group id 28 | int processor; // stat current CPU number 29 | long prio; // stat kernel scheduling priority 30 | long nice; // stat standard unix nice level of process 31 | long rss; // stat identical to 'resident' 32 | long size; // statm total virtual memory 33 | long share; // statm shared (mmap'd) memory 34 | unsigned long rtprio; // stat real-time priority 35 | unsigned long sched; // stat scheduling class 36 | unsigned long flags; // stat kernel flags for the process 37 | unsigned long long utime; // stat user-mode CPU time accumulated by process 38 | unsigned long long stime; // stat kernel-mode CPU time accumulated by process 39 | unsigned long long start_time; // stat start time of process -- seconds since 1970-01-01T00:00:00 40 | unsigned long min_flt; // stat number of minor page faults since process start 41 | unsigned long maj_flt; // stat number of major page faults since process start 42 | unsigned long nvcsw; // status voluntary context switches 43 | unsigned long nivcsw; // status nvoluntary context switches 44 | char cmd[16]; // stat,status basename of executable file in call to exec(2) 45 | int tty; // stat full device number of controlling terminal 46 | long alarm; // stat 47 | long resident; // statm resident non-swapped memory 48 | long trs; // statm text (exe) resident set 49 | long lrs; // statm library resident set 50 | long drs; // statm data+stack resident set 51 | long dt; // statm dirty pages 52 | unsigned long vsize; // stat number of pages of virtual memory 53 | unsigned long rss_rlim; // stat resident set size limit 54 | unsigned long cmin_flt; // stat cumulative min_flt of process and child processes 55 | unsigned long cmaj_flt; // stat cumulative maj_flt of process and child processes 56 | unsigned long vm_size; // status equals size, as kb 57 | unsigned long vm_lock; // status locked pages, as kb 58 | unsigned long vm_rss; // status equals rss and/or resident, as kb 59 | unsigned long vm_data; // status data only size, as kb 60 | unsigned long vm_stack; // status stack only size, as kb 61 | unsigned long vm_swap; // status swap ents, as kb 62 | unsigned long vm_exe; // status equals trs, as kb 63 | unsigned long vm_lib; // status total, not just used, library pages 64 | unsigned long long cutime; // stat cumulative utime of process and reaped children 65 | unsigned long long cstime; // stat cumulative stime of process and reaped children 66 | } proc_t; 67 | 68 | typedef struct cmdinfo_t { 69 | int ptype; // (special) 1 user process, 2 kernel process 70 | char state; // stat,status single-char code for process state 71 | int tgid; // (special) thread group ID, the POSIX PID 72 | char cmd[16]; // stat,status basename of executable file in call to exec(2) 73 | } cmdinfo_t; 74 | 75 | typedef struct task_t { 76 | char state; 77 | int tid; 78 | int ppid; 79 | int pgid; 80 | int sid; 81 | int nlwp; 82 | int tgid; 83 | int processor; 84 | long prio; 85 | long nice; 86 | unsigned long rtprio; 87 | unsigned long sched; 88 | unsigned long flags; 89 | char cmd[16]; 90 | unsigned long long utime; 91 | unsigned long long stime; 92 | unsigned long long cutime; 93 | unsigned long long cstime; 94 | unsigned long long start_time; 95 | } task_t; 96 | 97 | typedef struct PROCTAB { 98 | DIR* procfs; 99 | DIR* taskdir; // for threads 100 | pid_t taskdir_user; // for threads 101 | pid_t task_owner; // the current process pid. 102 | char path[PROCPATHLEN]; // must hold /proc/2000222000/task/2000222000/cmdline 103 | int (*finder_proc )(struct PROCTAB *__restrict const, proc_t *__restrict const); 104 | int (*finder_task )(struct PROCTAB *__restrict const, proc_t *__restrict const, const pid_t, char *__restrict const); 105 | int (*finder_cmdline )(struct PROCTAB *__restrict const, cmdinfo_t *__restrict const); 106 | proc_t* (*reader_proc )(struct PROCTAB *__restrict const, proc_t *__restrict const, int cmd_flag, utlbuf_s *ufbuf); 107 | proc_t* (*reader_task )(struct PROCTAB *__restrict const, proc_t *__restrict const, const pid_t, char *__restrict const); 108 | cmdinfo_t*(*reader_cmdline )(struct PROCTAB *__restrict const, cmdinfo_t *__restrict const, utlbuf_s *ufbuf); 109 | }PROCTAB; 110 | 111 | // init a PROCTAB structure 112 | extern PROCTAB* openproc(PROCTAB* PT); 113 | extern PROCTAB* mini_openproc(PROCTAB* PT); 114 | 115 | // clean open files, etc from the openproc() 116 | extern void closeproc(PROCTAB* PT); 117 | extern void mini_closeproc(PROCTAB* PT); 118 | 119 | extern proc_t* read_proc( PROCTAB *__restrict const PT, proc_t *__restrict p, int cmd_flag, utlbuf_s *ubuf); 120 | extern pid_t mini_read_proc(PROCTAB *__restrict const PT ); 121 | extern cmdinfo_t* read_cmdline( PROCTAB *__restrict const PT, cmdinfo_t *__restrict c, utlbuf_s *ubuf); 122 | extern proc_t* read_task( PROCTAB *__restrict const PT, proc_t *__restrict t, const pid_t p ); 123 | 124 | 125 | extern char *read_stack_file(unsigned tid, utlbuf_s *ubuf, utlbuf_s *ufbuf, char* nwchan); 126 | extern int get_uptime(void); 127 | extern unsigned long get_btime(void); 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## SRESAR 2 | 3 | English | [中文](README_zh-cn.md) 4 | 5 | SRESAR (Site Reliability Engineering System Activity Reporter) is a new addition to the family of sar tools and provides the overall specifications, process-level metrics and featured Load metrics. 6 | 7 | ## Table of Contents 8 | 9 | * [Introduction](#introduction) 10 | * [Advantage](#advantage) 11 | * [Installation](#installation) 12 | * [AnolisOS CentOS](#anolisos-centos) 13 | * [Ubuntu](#other-parsers) 14 | * [Source Code](#source-code) 15 | * [Architecture](#architecture) 16 | * [Beginner Guide](#beginner-guide) 17 | * [Reference](#feference) 18 | * [LICENSE](#license) 19 | * [Dependencies](#dependencies) 20 | * [Get Support](#get-support) 21 | * [Contributor](#contributor) 22 | 23 | ## Introduction 24 | 25 | SRESAR (Site Reliability Engineering System Activity Reporter) is a new addition to the family of sar tools. It covers most of the main functions of traditional sar tools, but also extends the overall specifications. Added process-level metrics and featured Load metrics. 26 | 27 | ## Advantage 28 | 29 | Compared to other sar family tools, SRESAR has several features: 30 | 31 | * Traditional sar tools can only collect some major system indicators on a fixed basis. ssar tools can extend almost any indicator of the system by simply modifying the configuration file within a few minutes without modifying the code. 32 | * Traditional sar tools may not be able to secondary development, or secondary development threshold is high, ssar tools support the use of Python language secondary development, secondary development threshold is low; 33 | * Traditional sar tools record process-level indicators more preliminarily, while ssar tools record key indicators of all processes in the system. 34 | * For Linux load metrics, the ssar tool also provides detailed load metrics. Load5s is an industry-unique indicator now. 35 | 36 | Of course, collecting more data requires more disk storage. In the last 20 years, with the development of storage technology, disk space has increased 1000 times with the same cost structure. In this context, it is cost-effective to collect more data metrics for the appropriate storage space. 37 | 38 | ## Installation 39 | 40 | To use, there are several methods: 41 | 42 | ### AnolisOS CentOS 43 | 44 | Method under AnolisOS and centos. 45 | 46 | ```bash 47 | $ yum install zlib-devel gcc-c++ 48 | $ yum install rpm-build rpmdevtools git 49 | $ rpmdev-setuptree 50 | $ cd /tmp/ 51 | $ git clone https://gitee.com/anolis/ssar.git 52 | $ tar -zcvf ~/rpmbuild/SOURCES/ssar-$(cat ssar/spec/ssar.spec |grep Version |awk '{print $2}').tar.gz ssar 53 | $ cp ssar/spec/ssar.spec ~/rpmbuild/SPECS/ 54 | $ rpmbuild -bb ~/rpmbuild/SPECS/ssar.spec 55 | $ cd ~/rpmbuild/RPMS/x86_64/ 56 | $ sudo rpm -ivh $(ls) 57 | $ sudo rpm -e ssar # remove package 58 | ``` 59 | 60 | ### Ubuntu 61 | 62 | Method under Ubuntu. 63 | 64 | ```bash 65 | $ apt-get update 66 | $ apt install zlib1g-dev git 67 | $ cd ~/ 68 | $ git clone https://gitee.com/anolis/ssar.git 69 | $ cd ssar/debian 70 | $ ./build.sh 71 | $ dpkg -i ssar_*_amd64.deb 72 | $ dpkg -r ssar # remove package 73 | ``` 74 | 75 | ### Source Code 76 | 77 | Source code installation method (not recommended). 78 | 79 | ```bash 80 | $ yum install zlib-devel # ubuntu need zlib1g-dev 81 | $ cd ~/ 82 | $ git clone https://gitee.com/anolis/ssar.git 83 | $ make 84 | $ sudo make install 85 | $ sudo make uninstall # remove 86 | ``` 87 | 88 | ## Architecture 89 | 90 | A brief introduction to the SRESAR project architecture: 91 | 92 | * The sresar resident process is the data collector for SRESAR project, and the data is stored under /var/log/sre_proc. 93 | * The ssar command is the generic data parser from the disk data collected by the sresar process. The ssar command can directly display results to the consumer. 94 | * The tsar2 command is just a wrapper of the ssar command, providing consumers with more comprehensive results. 95 | * ssar+ command is the future of tsar2, various option parameters and implementations of ssar+ are currently being planned. 96 | 97 | ## Beginner Guide 98 | 99 | Here's a quick start with some common commands 100 | 101 | ```bash 102 | $ ssar --help # Display help Information 103 | $ ssar # the historical data output of the default indicator is displayed 104 | $ ssar --cpu # Display the output historical data of THE CPU category. 105 | $ ssar -f 2020-09-29T18:34:00 # Specifies the end time of a time interval 106 | $ ssar -r 60 # The specified duration is 60 minutes. The default value is 300 minutes 107 | $ ssar -i 1 # In the specified time range, the display accuracy is 1 minute. The default value is 10 minutes 108 | $ ssar --api # If selected, the information is output in JSON format 109 | $ ssar -f +10 -i 1s # with real-time mode, the acquisition output accuracy is 1 second, the default value is 5 seconds. 110 | $ ssar -o user,shmem,memfree # Only user, shmem, and memfree indicators are output 111 | $ ssar -o "dev|eth0:|2|d;snmp:8:11:d" # Indicators can be separated by semicolons (;) 112 | $ ssar -o 'metric=c|cfile=meminfo|line_begin=MemFree:|column=2|alias=free' # Take the value of MemFree from memInfo and name it free 113 | $ ssar -o 'metric=d:cfile=snmp:line=8:column=13:alias=retranssegs' # Take the difference between the values in line 8 and column 13 in snmp 114 | $ ssar -o 'metric=c|cfile=loadavg|line=1|column=1|dtype=float|alias=load1' # Get the load1 data of type float 115 | $ ssar -o 'metric=c|cfile=loadavg|line=1|column=4|dtype=string|alias=runq_plit' # Get string information like 2/1251 116 | $ ssar -o 'metric=d|cfile=stat|line=2|column=2-11|alias=cpu0_{column};' # Displays data for columns 2 through 11 of CPU0 117 | $ ssar -o 'metric=d|cfile=stat|line=2-17|column=5|alias=idle_{line};' # Display idle data for cpu0 through CPU15 118 | $ ssar procs # Display the historical information about the process indicator 119 | $ ssar procs --mem # A combination of process memory indicators 120 | $ ssar procs -k -ppid,+sid,pid # Specifies sort fields in descending order by ppid, ascending order by sid, and ascending order by pid (built-in) 121 | $ ssar procs -l 100 # If more than 100 messages are displayed, only 100 results are displayed 122 | $ ssar proc -p 1 # Display the historical information about the process whose pid is 1. 123 | $ ssar load5s # Display historical information about load of the server 124 | $ ssar load5s -z # Only load values that trigger details collection are displayed 125 | $ ssar load2p -c 2020-10-07T07:45:25 # The load details are displayed 126 | $ tsar2 --help # The help information about the tsar2 wrapper is displayed 127 | $ tsar2 --io -I sda,sda3,sdb1 # You can display indicators of both the sda disk and the sda3 partition 128 | $ tsar2 --cpu -I cpu,cpu1,cpu4 # It can display the performance indicators of both the entire CPU and a single CPU 129 | $ tsar2 --traffic -I eth0,lo # You can display indicators for both eth0 and lo 130 | $ tsar2 --retran # Display detailed information about TCP retransmission 131 | $ tsar2 --tcpofo # Display detailed information about Tcp Out-Of-Order 132 | $ tsar2 --tcpdrop # Display detailed information about Tcp Drop 133 | $ tsar2 --tcperr # Display detailed information about Tcp Err 134 | $ tsar2 irqtop -C 7,30-32 # Displays interrupt details for cpus 7 and 30 through 32 135 | $ tsar2 cputop -l -i 1 -S sirq # Displays the top 4 softirq cpu usage of all cpu 136 | ``` 137 | 138 | ## Reference 139 | 140 | for more usage with ssar tools,visit reference,[查看参考手册](./README_zh-cn.md) 141 | 142 | ## LICENSE 143 | 144 | It is distributed under the Mulan Permissive Software License,Version 2 - see the accompanying [LICENSE](./LICENSE) file for more details. Some component dependencies and their copyright are listed below. 145 | 146 | ## Dependencies 147 | 148 | Each Dependency component and it's licensed: 149 | 150 | * [tomlc99][tomlc99] project is licensed under [MIT License](https://github.com/cktan/tomlc99/blob/master/LICENSE). 151 | 152 | * [cpptoml](https://github.com/skystrife/cpptoml.git) project is licensed under [MIT License](https://github.com/skystrife/cpptoml/blob/master/LICENSE). 153 | 154 | * [nlohmann json](https://github.com/nlohmann/json.git) project is licensed under [MIT License](https://github.com/nlohmann/json/blob/develop/LICENSE.MIT). 155 | 156 | * [CLI11](https://github.com/CLIUtils/CLI11.git) project is licensed under [3-clause BSD License](https://github.com/CLIUtils/CLI11/blob/master/LICENSE). 157 | 158 | ## Get Support 159 | 160 | DingDing group number 33304007 161 | 162 | ## Contributor 163 | 164 | This project was created by Wen Maoquan (English Name Miles Wen) who working for Alibaba Cloud-Computing Platform. Special thanks to all the [contributors](./CONTRIBUTOR). 165 | 166 | Ccheng 167 | 168 | Dust.Li 169 | 170 | MilesWen 171 | 172 | TonyLu 173 | 174 | Xlpang 175 | 176 | [tomlc99]: https://github.com/cktan/tomlc99.git 177 | -------------------------------------------------------------------------------- /conf/sresard: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # chkconfig: 2345 10 90 4 | # description: sresar service 5 | 6 | prog=sresar 7 | condition_file=/etc/ssar/sresar.disable 8 | 9 | # Check if any of $pid (could be plural) are running 10 | checkpid() { 11 | local i 12 | 13 | for i in $* ; do 14 | [ -d "/proc/$i" ] && return 0 15 | done 16 | return 1 17 | } 18 | 19 | echo_success() { 20 | [ "$BOOTUP" = "color" ] && $MOVE_TO_COL 21 | echo -n "[" 22 | [ "$BOOTUP" = "color" ] && $SETCOLOR_SUCCESS 23 | echo -n $" OK " 24 | [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL 25 | echo -n "]" 26 | echo -ne "\r" 27 | return 0 28 | } 29 | 30 | echo_failure() { 31 | [ "$BOOTUP" = "color" ] && $MOVE_TO_COL 32 | echo -n "[" 33 | [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE 34 | echo -n $"FAILED" 35 | [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL 36 | echo -n "]" 37 | echo -ne "\r" 38 | return 1 39 | } 40 | 41 | # Log that something failed 42 | failure() { 43 | local rc=$? 44 | #if [ -z "${IN_INITLOG:-}" ]; then 45 | # initlog $INITLOG_ARGS -n $0 -s "$1" -e 2 46 | #fi 47 | [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_failure 48 | [ -x /usr/bin/rhgb-client ] && /usr/bin/rhgb-client --details=yes 49 | return $rc 50 | } 51 | 52 | # Log that something succeeded 53 | success() { 54 | #if [ -z "${IN_INITLOG:-}" ]; then 55 | # initlog $INITLOG_ARGS -n $0 -s "$1" -e 1 56 | #fi 57 | [ "$BOOTUP" != "verbose" -a -z "${LSB:-}" ] && echo_success 58 | return 0 59 | } 60 | 61 | __pids_var_run() { 62 | local base=${1##*/} 63 | local pid_file=${2:-/var/run/$base.pid} 64 | 65 | pid= 66 | if [ -f "$pid_file" ] ; then 67 | local line p 68 | read line < "$pid_file" 69 | for p in $line ; do 70 | [ -z "${p//[0-9]/}" -a -d "/proc/$p" ] && pid="$pid $p" 71 | done 72 | if [ -n "$pid" ]; then 73 | return 0 74 | fi 75 | return 1 # "Program is dead and /var/run pid file exists" 76 | fi 77 | return 3 # "Program is not running" 78 | } 79 | 80 | # Output PIDs of matching processes, found using pidof 81 | __pids_pidof() { 82 | pidof -c -o $$ -o $PPID -o %PPID -x "$1" || \ 83 | pidof -c -o $$ -o $PPID -o %PPID -x "${1##*/}" 84 | } 85 | 86 | status() { 87 | local base pid pid_file= 88 | 89 | # Test syntax. 90 | if [ "$#" = 0 ] ; then 91 | echo $"Usage: status [-p pidfile] {program}" 92 | return 1 93 | fi 94 | if [ "$1" = "-p" ]; then 95 | pid_file=$2 96 | shift 2 97 | fi 98 | base=${1##*/} 99 | 100 | # First try "pidof" 101 | __pids_var_run "$1" "$pid_file" 102 | RC=$? 103 | if [ -z "$pid_file" -a -z "$pid" ]; then 104 | pid="$(__pids_pidof "$1")" 105 | fi 106 | if [ -n "$pid" ]; then 107 | echo $"${base} (pid $pid) is running..." 108 | return 0 109 | fi 110 | 111 | case "$RC" in 112 | 0) 113 | echo $"${base} (pid $pid) is running..." 114 | return 0 115 | ;; 116 | 1) 117 | echo $"${base} dead but pid file exists" 118 | return 1 119 | ;; 120 | esac 121 | # See if /var/lock/subsys/${base} exists 122 | if [ -f /var/lock/subsys/${base} ]; then 123 | echo $"${base} dead but subsys locked" 124 | return 2 125 | fi 126 | echo $"${base} is stopped" 127 | return 3 128 | } 129 | 130 | 131 | # A function to stop a program. 132 | killproc() { 133 | local RC killlevel= base pid pid_file= delay 134 | 135 | RC=0; delay=3 136 | # Test syntax. 137 | if [ "$#" -eq 0 ]; then 138 | echo $"Usage: killproc [-p pidfile] [ -d delay] {program} [-signal]" 139 | return 1 140 | fi 141 | if [ "$1" = "-p" ]; then 142 | pid_file=$2 143 | shift 2 144 | fi 145 | if [ "$1" = "-d" ]; then 146 | delay=$2 147 | shift 2 148 | fi 149 | 150 | 151 | # check for second arg to be kill level 152 | [ -n "${2:-}" ] && killlevel=$2 153 | 154 | # Save basename. 155 | base=${1##*/} 156 | 157 | # Find pid. 158 | __pids_var_run "$1" "$pid_file" 159 | if [ -z "$pid_file" -a -z "$pid" ]; then 160 | pid="$(__pids_pidof "$1")" 161 | fi 162 | 163 | # Kill it. 164 | if [ -n "$pid" ] ; then 165 | [ "$BOOTUP" = "verbose" -a -z "${LSB:-}" ] && echo -n "$base " 166 | if [ -z "$killlevel" ] ; then 167 | if checkpid $pid 2>&1; then 168 | # TERM first, then KILL if not dead 169 | kill -TERM $pid >/dev/null 2>&1 170 | sleep 0.1 171 | if checkpid $pid && sleep 1 && 172 | checkpid $pid && sleep $delay && 173 | checkpid $pid ; then 174 | kill -KILL $pid >/dev/null 2>&1 175 | sleep 0.1 176 | fi 177 | fi 178 | checkpid $pid 179 | RC=$? 180 | [ "$RC" -eq 0 ] && failure $"$base shutdown" || success $"$base shutdown" 181 | RC=$((! $RC)) 182 | # use specified level only 183 | else 184 | if checkpid $pid; then 185 | kill $killlevel $pid >/dev/null 2>&1 186 | RC=$? 187 | [ "$RC" -eq 0 ] && success $"$base $killlevel" || failure $"$base $killlevel" 188 | elif [ -n "${LSB:-}" ]; then 189 | RC=7 # Program is not running 190 | fi 191 | fi 192 | else 193 | if [ -n "${LSB:-}" -a -n "$killlevel" ]; then 194 | RC=7 # Program is not running 195 | else 196 | failure $"$base shutdown" 197 | RC=0 198 | fi 199 | fi 200 | 201 | # Remove pid file if any. 202 | if [ -z "$killlevel" ]; then 203 | rm -f "${pid_file:-/var/run/$base.pid}" 204 | fi 205 | return $RC 206 | } 207 | 208 | # A function to start a program. 209 | daemon() { 210 | # Test syntax. 211 | local gotbase= force= nicelevel corelimit 212 | local pid base= user= nice= bg= pid_file= 213 | nicelevel=0 214 | while [ "$1" != "${1##[-+]}" ]; do 215 | case $1 in 216 | '') echo $"$0: Usage: daemon [+/-nicelevel] {program}" 217 | return 1;; 218 | --check) 219 | base=$2 220 | gotbase="yes" 221 | shift 2 222 | ;; 223 | --check=?*) 224 | base=${1#--check=} 225 | gotbase="yes" 226 | shift 227 | ;; 228 | --user) 229 | user=$2 230 | shift 2 231 | ;; 232 | --user=?*) 233 | user=${1#--user=} 234 | shift 235 | ;; 236 | --pidfile) 237 | pid_file=$2 238 | shift 2 239 | ;; 240 | --pidfile=?*) 241 | pid_file=${1#--pidfile=} 242 | shift 243 | ;; 244 | --force) 245 | force="force" 246 | shift 247 | ;; 248 | [-+][0-9]*) 249 | nice="nice -n $1" 250 | shift 251 | ;; 252 | *) echo $"$0: Usage: daemon [+/-nicelevel] {program}" 253 | return 1;; 254 | esac 255 | done 256 | 257 | # Save basename. 258 | [ -z "$gotbase" ] && base=${1##*/} 259 | 260 | # See if it's already running. Look *only* at the pid file. 261 | __pids_var_run "$base" "$pid_file" 262 | 263 | [ -n "$pid" -a -z "$force" ] && return 264 | 265 | # make sure it doesn't core dump anywhere unless requested 266 | corelimit="ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0}" 267 | 268 | # if they set NICELEVEL in /etc/sysconfig/foo, honor it 269 | [ -n "${NICELEVEL:-}" ] && nice="nice -n $NICELEVEL" 270 | 271 | # Echo daemon 272 | [ "${BOOTUP:-}" = "verbose" -a -z "${LSB:-}" ] && echo -n " $base" 273 | 274 | # And start it up. 275 | if [ -z "$user" ]; then 276 | $nice /bin/bash -c "$corelimit >/dev/null 2>&1 ; $*" 277 | else 278 | $nice runuser -s /bin/bash $user -c "$corelimit >/dev/null 2>&1 ; $*" 279 | fi 280 | [ "$?" -eq 0 ] && success $"$base startup" || failure $"$base startup" 281 | } 282 | 283 | start() { 284 | # Start daemon. 285 | echo -n $"Starting $prog: " 286 | #/usr/bin/sresar -D >/dev/null 2>&1 & 287 | daemon $prog -D > /dev/null 2>&1 & 288 | RETVAL=$? 289 | echo 290 | [ $RETVAL -eq 0 ] && rm -f $condition_file 291 | return $RETVAL 292 | } 293 | 294 | stop() { 295 | echo -n $"Shutting down $prog: " 296 | killproc $prog 297 | RETVAL=$? 298 | echo 299 | [ $RETVAL -eq 0 ] && touch $condition_file 300 | return $RETVAL 301 | } 302 | 303 | # See how we were called. 304 | case "$1" in 305 | start) 306 | start 307 | ;; 308 | stop) 309 | stop 310 | ;; 311 | status) 312 | status $prog 313 | ;; 314 | restart|force-reload) 315 | stop 316 | start 317 | ;; 318 | try-restart|condrestart) 319 | if status $prog > /dev/null; then 320 | stop 321 | start 322 | fi 323 | ;; 324 | reload) 325 | exit 3 326 | ;; 327 | *) 328 | echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" 329 | exit 2 330 | esac 331 | -------------------------------------------------------------------------------- /conf/ssar.1: -------------------------------------------------------------------------------- 1 | .TH ssar 1 "August 2021" "ssar" "User Commands" 2 | .SH NAME 3 | ssar \- Collect, save and report system activity information. 4 | .SH SYNOPSIS 5 | \fBssar\fP [OPTIONS] [SUBCOMMAND] 6 | .SH DESCRIPTION 7 | \fBssar\fP displays information about a history of the system activity information. 8 | .SH OPTIONS 9 | .TP 10 | \fB\-h, \-\-help\fP 11 | Print this help message and exit 12 | .TP 13 | \fB\-V, \-\-version\fP 14 | Print the version message and exit 15 | .TP 16 | \fB\-\-api\fP Excludes: --no-headers 17 | If selected, output is json format, otherwise shell format. 18 | .TP 19 | \fB\-f, \-\-finish\fP \fITEXT\fR 20 | Assign the output datetime, allow history datetime. default value is current datetime. 21 | .TP 22 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 23 | Range from begin to finish, default 5 minutes. 24 | .TP 25 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 26 | Assign the compare datetime by the finish 27 | .TP 28 | \fB\-H, \-\-no-headers\fP Excludes: --api 29 | Disable the header info. 30 | .TP 31 | \fB\-P, \-\-purify\fP 32 | Hide the - * < > = no number data info.. 33 | .TP 34 | \fB\-o, \-\-format\fP \fITEXT\fR Excludes: --extra --cpu --mem --job --sched 35 | User-defined format. syntax is field1,field2 36 | .TP 37 | \fB\-O, \-\-extra\fP \fITEXT\fR Excludes: --format 38 | User-defined extra format. syntax is field1,field2 39 | .TP 40 | \fB\-\-cpu\fP Excludes: --format 41 | Display cpu-oriented format. 42 | .TP 43 | \fB\-\-mem\fP Excludes: --format 44 | Display virtual memory format. 45 | .TP 46 | \fB\-\-tcp\fP Excludes: --format 47 | Display tcp format 48 | .TP 49 | \fB\-\-udp\fP Excludes: --format 50 | Display udp format 51 | .SH EXAMPLES: 52 | .TP 53 | To see every process on the system history using standard syntax: 54 | \fBssar 55 | .br 56 | \fBssar -V 57 | .br 58 | \fBssar --cpu 59 | .br 60 | \fBssar --mem 61 | .br 62 | \fBssar --tcp 63 | .br 64 | \fBssar --udp 65 | .br 66 | \fBssar -r 60 67 | .br 68 | \fBssar -f 2020-03-02T18:34:00 69 | .br 70 | \fBssar -f -10 71 | .br 72 | \fBssar -f -5.5h 73 | .br 74 | \fBssar -f -1.2d 75 | .br 76 | \fBssar -b 2020-03-02T17:34:00 77 | .br 78 | \fBssar -P 79 | .br 80 | \fBssar -H 81 | .br 82 | \fBssar -o 'shmem,meminfo:2:2,snmp|8|11|d' 83 | .br 84 | \fBssar -O "dev|eth0:|2|d;snmp:8:11:d" --cpu 85 | .br 86 | \fBssar -o 'metric=d:cfile=snmp:line=8:column=13:alias=retranssegs' 87 | .br 88 | \fBssar -o 'metric=c|cfile=meminfo|line_begin=MemFree:|column=2|alias=free' 89 | .br 90 | \fBssar -o 'metric=c|cfile=loadavg|line=1|column=1|dtype=float|alias=load1' 91 | .br 92 | \fBssar -o 'metric=c|cfile=loadavg|line=1|column=4|dtype=string|alias=runq_plit' 93 | .br 94 | \fBssar -o 'metric=d|cfile=stat|line=2|column=2-11|alias=cpu0_{column};' 95 | .br 96 | \fBssar -o 'metric=d|cfile=stat|line=2-17|column=5|alias=idle_{line};' 97 | .br 98 | \fBssar -f +10 99 | .br 100 | \fBssar -f +10 -i 5s 101 | .br 102 | \fBssar --api 103 | .SH FORMAT SPECIFIERS 104 | Here are the indicator exmaples. 105 | .PP 106 | For example: 107 | .B ssar 108 | .PP 109 | .TP 110 | \fBFIELD 111 | \fBDESCRIPTION 112 | .TP 113 | \fBuser/s 114 | The average user value per second from the previous time point to the current time point. 115 | .TP 116 | \fBdirty 117 | The scale value of the current point in time. 118 | .SH SUBCOMMANDS 119 | .TP 120 | \fBprocs 121 | all process subcommand. 122 | .TP 123 | \fBproc 124 | single process subcommand. 125 | .TP 126 | \fBload5s 127 | load list of five second precision sudcommand. 128 | .TP 129 | \fBload2p 130 | Load to process subcommand. 131 | .SH PROCS COMMAND OPTIONS 132 | .TP 133 | \fB\-h, \-\-help\fP 134 | Print this help message and exit 135 | .TP 136 | \fB\-\-api\fP Excludes: --no-headers 137 | If selected, output is json format, otherwise shell format. 138 | .TP 139 | \fB\-f, \-\-finish\fP \fITEXT\fR 140 | Assign the output datetime, allow history datetime. default value is current datetime. 141 | .TP 142 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 143 | Range from begin to finish, default 5 minutes. 144 | .TP 145 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 146 | Assign the compare datetime by the finish 147 | .TP 148 | \fB\-k, \-\-key, \-\-sort\fP \fITEXT\fR 149 | Specify sorting order. Sorting syntax is [+|-]key[,[+|-]key[,...]] 150 | .TP 151 | \fB\-l, \-\-lines\fP \fIINT\fR 152 | Limit the output. 153 | .TP 154 | \fB\-H, \-\-no-headers\fP Excludes: --api 155 | Disable the header info. 156 | .TP 157 | \fB\-o, \-\-format\fP \fITEXT\fR Excludes: --extra --cpu --mem --job --sched 158 | User-defined format. syntax is field1,field2 159 | .TP 160 | \fB\-O, \-\-extra\fP \fITEXT\fR Excludes: --format 161 | User-defined extra format. syntax is field1,field2 162 | .TP 163 | \fB\-\-cpu\fP Excludes: --format 164 | Display cpu-oriented format. 165 | .TP 166 | \fB\-\-mem\fP Excludes: --format 167 | Display virtual memory format. 168 | .TP 169 | \fB\-\-job\fP Excludes: --format 170 | Display job control format 171 | .TP 172 | \fB\-\-sched\fP Excludes: --format 173 | Display sched format 174 | .SH PROCS COMMAND EXAMPLES: 175 | .TP 176 | To see every process on the system history using standard syntax: 177 | \fBssar procs 178 | .br 179 | \fBssar procs --cpu 180 | .br 181 | \fBssar procs --mem 182 | .br 183 | \fBssar procs --job 184 | .br 185 | \fBssar procs --sched 186 | .br 187 | \fBssar procs -r 60 188 | .br 189 | \fBssar procs -f 2020-03-02T18:34:00 190 | .br 191 | \fBssar procs -f -10 192 | .br 193 | \fBssar procs -f -5.5h 194 | .br 195 | \fBssar procs -f -1.2d 196 | .br 197 | \fBssar procs -b 2020-03-02T17:34:00 198 | .br 199 | \fBssar procs -k -ppid,pid,+start_datetime 200 | .br 201 | \fBssar procs -l 100 202 | .br 203 | \fBssar procs -H 204 | .br 205 | \fBssar procs -o ppid,pid,start_datetime 206 | .br 207 | \fBssar procs -O pgid 208 | .br 209 | \fBssar procs --api 210 | .SH PROCS COMMAND FORMAT SPECIFIERS 211 | Here are the keywords that may be used to control the output format (e.g. with option -o) or to sort the processes with the --sort option. 212 | .PP 213 | For example: 214 | .B ssar \-o pid \-\-sort rss 215 | .PP 216 | .TP 217 | \fBFIELD 218 | \fBDESCRIPTION 219 | .TP 220 | \fBpid 221 | a number representing the process ID (alias tgid). 222 | .TP 223 | \fBtgid 224 | alias pid. 225 | .TP 226 | \fBppid 227 | parent process ID. 228 | .TP 229 | \fBpgid 230 | process group ID or, equivalently, the process ID of the process group leader. 231 | .TP 232 | \fBsid 233 | session ID or, equivalently, the process ID of the session leader. 234 | .TP 235 | \fBtpgid 236 | ID of the foreground process group on the tty (terminal) that the process is connected to, or -1 if the process is not connected to a tty. 237 | .TP 238 | \fBnlwp 239 | Number of lwps (threads) in the process. 240 | .TP 241 | \fBflags 242 | Flags associated with the process. 243 | .TP 244 | \fBsched 245 | Scheduling policy of the process. The policies SCHED_OTHER (SCHED_NORMAL), SCHED_FIFO, SCHED_RR, SCHED_BATCH, SCHED_ISO, and SCHED_IDLE are respectively displayed as 0, 1, 2, 3, 4, and 5. 246 | .TP 247 | \fBcls 248 | Scheduling class of the process, see also sched. Field's possible values are TS(SCHED_OTHER) FF(SCHED_FIFO) RR(SCHED_RR) B(SCHED_BATCH) IDL(SCHED_IDLE) 249 | .TP 250 | \fBnice 251 | Nice value. This ranges from 19 (nicest) to -20 (not nice to others). 252 | .TP 253 | \fBrtprio 254 | Realtime priority. This ranges from 1 to 99. 255 | .TP 256 | \fBprio 257 | Priority of the process. Higher number means lower priority. 258 | .TP 259 | \fBvcswch 260 | Total number of voluntary context switches the task made. A voluntary context switch occurs when a task blocks because it requires a resource that is unavailable. 261 | .TP 262 | \fBncswch 263 | Total number of non voluntary context switches the task made. A involuntary context switch takes place when a task executes for the duration of its time slice and then is forced to relinquish the processor. 264 | .TP 265 | \fBvcswchs 266 | Total number of voluntary context switches the task made per second. 267 | .TP 268 | \fBncswchs 269 | Total number of non voluntary context switches the task made per second. 270 | .TP 271 | \fBs 272 | minimal state display (one character). 273 | .TP 274 | \fBetimes 275 | elapsed time since the process was started, in seconds. 276 | .TP 277 | \fBetime 278 | elapsed time since the process was started, in the form [[DD-]hh:]mm:ss. 279 | .TP 280 | \fBstart_time 281 | time the command started, in seconds. 282 | .TP 283 | \fBstart_datetime 284 | time the command started. "YY-mm-ddThh:mm:ss" format. 285 | .TP 286 | \fBbegin_datetime 287 | time the range started, approximate begin. "YY-mm-ddThh:mm:ss" format. 288 | .TP 289 | \fBfinish_datetime 290 | time the range finished, approximate finish. "YY-mm-ddThh:mm:ss" format. 291 | .TP 292 | \fBrealtime 293 | time the duration, approximate range, in seconds. 294 | .TP 295 | \fBtime 296 | cumulative CPU time, in seconds. 297 | .TP 298 | \fButime 299 | cumulative CPU User time, in seconds. 300 | .TP 301 | \fBstime 302 | cumulative CPU Sys time, in seconds. 303 | .TP 304 | \fBcputime 305 | cumulative CPU time, "[DD-]hh:mm:ss" format. 306 | .TP 307 | \fBcpu_utime 308 | cumulative CPU user time, "[DD-]hh:mm:ss" format. 309 | .TP 310 | \fBcpu_stime 311 | cumulative CPU sys time, "[DD-]hh:mm:ss" format. 312 | .TP 313 | \fBtime_dlt 314 | delta CPU time from begin_datetime to finish_datetime, in seconds. 315 | .TP 316 | \fButime_dlt 317 | delta CPU utime from begin_datetime to finish_datetime, in seconds. 318 | .TP 319 | \fBstime_dlt 320 | delta CPU stime from begin_datetime to finish_datetime, in seconds. 321 | .TP 322 | \fBpcpu 323 | cpu utilization of the process in "##.#" format, (cputime delta)/realtime ratio. 324 | .TP 325 | \fBpucpu 326 | cpu utilization of the process in "##.#" format, (cpu_utime delta)/realtime ratio. 327 | .TP 328 | \fBpscpu 329 | cpu utilization of the process in "##.#" format, (cpu_stime delta)/realtime ratio. 330 | .TP 331 | \fBsize 332 | approximate amount of swap space that would be required if the process were to dirty all writable pages and then be swapped out. 333 | .TP 334 | \fBrss 335 | resident set size, the non-swapped physical memory that a task has used (in kiloBytes). 336 | .TP 337 | \fBmaj_flt 338 | The number of major page faults that have occurred with this process. 339 | .TP 340 | \fBmin_flt 341 | The number of minor page faults that have occurred with this process. 342 | .TP 343 | \fBrss_dlt 344 | delta rss from begin_datetime to finish_datetime. 345 | .TP 346 | \fBmaj_dlt 347 | delta maj_flt from begin_datetime to finish_datetime. 348 | .TP 349 | \fBmin_dlt 350 | delta min_flt from begin_datetime to finish_datetime. 351 | .TP 352 | \fBcmd 353 | command name (only the executable name). 354 | .TP 355 | \fBcmdline 356 | command with all its arguments as a string. 357 | .TP 358 | \fBfullcmd 359 | only cmd fullpath. 360 | .TP 361 | \fBb 362 | show the pid if exist at begin_datetime. if exist, value =, not exist value <. 363 | .SH PROC COMMAND OPTIONS 364 | .TP 365 | \fB\-h, \-\-help\fP 366 | Print this help message and exit 367 | .TP 368 | \fB\-\-api\fP Excludes: --no-headers 369 | If selected, output is json format, otherwise shell format. 370 | .TP 371 | \fB\-p, \-\-pid\fP \fIINT\fR REQUIRED 372 | process id. 373 | .TP 374 | \fB\-i, \-\-interval\fP \fIINT\fR 375 | interval, default 10 minutes. 376 | .TP 377 | \fB\-f, \-\-finish\fP \fITEXT\fR 378 | Assign the output datetime, allow history datetime. default value is current datetime. 379 | .TP 380 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 381 | Range from begin to finish, default 300 minutes. 382 | .TP 383 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 384 | Assign the compare datetime by the finish 385 | .TP 386 | \fB\-H, \-\-no-headers\fP Excludes: --api 387 | Disable the header info. 388 | .TP 389 | \fB\-o, \-\-format\fP \fITEXT\fR Excludes: --extra --cpu --mem --job --sched 390 | User-defined format. syntax is field1,field2 391 | .TP 392 | \fB\-O, \-\-extra\fP \fITEXT\fR Excludes: --format 393 | User-defined extra format. syntax is field1,field2 394 | .TP 395 | \fB\-\-cpu\fP Excludes: --format 396 | Display cpu-oriented format. 397 | .TP 398 | \fB\-\-mem\fP Excludes: --format 399 | Display virtual memory format. 400 | .SH PROC COMMAND EXAMPLES: 401 | .TP 402 | To see history of one process using standard syntax: 403 | \fBssar proc -p 1 404 | .br 405 | \fBssar proc -p 1 --cpu 406 | .br 407 | \fBssar proc -p 1 --mem 408 | .br 409 | \fBssar proc -p 1 -r 60 410 | .br 411 | \fBssar proc -p 1 -i 1 412 | .br 413 | \fBssar proc -p 1 -f 2020-03-02T18:34:00 414 | .br 415 | \fBssar proc -p 1 -f -10 416 | .br 417 | \fBssar proc -p 1 -f -5.5h 418 | .br 419 | \fBssar proc -p 1 -f -1.2d 420 | .br 421 | \fBssar proc -p 1 -b 2020-03-02T17:34:00 422 | .br 423 | \fBssar proc -p 1 -H 424 | .br 425 | \fBssar proc -p 1 -o ppid,pid,start_datetime 426 | .br 427 | \fBssar proc -p 1 -O pgid 428 | .br 429 | \fBssar proc -p 1 --api 430 | .br 431 | .SH PROC COMMAND FORMAT SPECIFIERS 432 | Here are the keywords that may be used to control the output format (e.g. with option -p). 433 | .PP 434 | For example: 435 | .B ssar proc \-p 436 | .PP 437 | .TP 438 | See also PROCS COMMAND FORMAT SPECIFIERS 439 | .PP 440 | .SH LOAD5S COMMAND OPTIONS 441 | .TP 442 | \fB\-h, \-\-help\fP 443 | Print this help message and exit 444 | .TP 445 | \fB\-\-api\fP Excludes: --no-headers 446 | If selected, output is json format, otherwise shell format. 447 | .TP 448 | \fB\-f, \-\-finish\fP \fITEXT\fR 449 | Assign the output datetime, allow history datetime. default value is current datetime. 450 | .TP 451 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 452 | Range from begin to finish, default 300 minutes. 453 | .TP 454 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 455 | Assign the compare datetime by the finish 456 | .TP 457 | \fB\-H, \-\-no-headers\fP Excludes: --api 458 | Disable the header info. 459 | .TP 460 | \fB\-y, \-\-yes\fP \fIINT\fR Excludes: --zoom 461 | Just display Y sstate collect datetime. 462 | .TP 463 | \fB\-z, \-\-zoom\fP \fIINT\fR Excludes: --yes 464 | Just display loadrd detail collect datetime. 465 | .SH LOAD5S COMMAND EXAMPLES: 466 | .TP 467 | To see history of one process using standard syntax: 468 | \fBssar load5s 469 | .br 470 | \fBssar load5s -r 60 471 | .br 472 | \fBssar load5s -f 2020-03-02T18:34:00 473 | .br 474 | \fBssar load5s -f -10 475 | .br 476 | \fBssar load5s -f -5.5h 477 | .br 478 | \fBssar load5s -f -1.2d 479 | .br 480 | \fBssar load5s -b 2020-03-02T17:34:00 481 | .br 482 | \fBssar load5s -H 483 | .br 484 | \fBssar load5s -y 485 | .br 486 | \fBssar load5s -z 487 | .br 488 | \fBssar load5s --api 489 | .br 490 | .SH LOAD5S COMMAND FORMAT SPECIFIERS 491 | Here are the keywords of the output format 492 | .PP 493 | For example: 494 | .B ssar load5s 495 | .PP 496 | .TP 497 | \fBFIELD 498 | \fBDESCRIPTION 499 | .TP 500 | \fBload5s 501 | load5s is 5 second precision load. 502 | .PP 503 | .SH LOAD2P COMMAND OPTIONS 504 | .TP 505 | \fB\-h, \-\-help\fP 506 | Print this help message and exit 507 | .TP 508 | \fB\-\-api\fP Excludes: --no-headers 509 | If selected, output is json format, otherwise shell format. 510 | .TP 511 | \fB\-c, \-\-collect\fP \fIINT\fR REQUIRED 512 | collect datetime. 513 | .TP 514 | \fB\-l, \-\-lines\fP \fIINT\fR 515 | Limit the output. 516 | .TP 517 | \fB\-H, \-\-no-headers\fP Excludes: --api 518 | Disable the header info. 519 | .TP 520 | \fB\-\-loadr\fP 521 | Display loadr format. 522 | .TP 523 | \fB\-\-loadd\fP 524 | Display loadd format. 525 | .TP 526 | \fB\-\-psr\fP 527 | Display psr format. 528 | .TP 529 | \fB\-\-stackinfo\fP 530 | Display stackinfo format. 531 | .TP 532 | \fB\-\-loadrd\fP 533 | Display loadrd format. 534 | .TP 535 | \fB\-\-stack\fP 536 | Display stack format. 537 | .SH LOAD2P COMMAND EXAMPLES: 538 | .TP 539 | To see history of one process using standard syntax: 540 | \fBssar load2p -c 2020-05-11T19:49:12 541 | .br 542 | \fBssar load2p -c 2020-05-11T19:49:12 -l 10 543 | .br 544 | \fBssar load2p -c 2020-05-11T19:49:12 -H 545 | .br 546 | \fBssar load2p -c 2020-05-11T19:49:12 --loadr 547 | .br 548 | \fBssar load2p -c 2020-05-11T19:49:12 --loadd 549 | .br 550 | \fBssar load2p -c 2020-05-11T19:49:12 --psr 551 | .br 552 | \fBssar load2p -c 2020-05-11T19:49:12 --stackinfo 553 | .br 554 | \fBssar load2p -c 2020-05-11T19:49:12 --loadrd 555 | .br 556 | \fBssar load2p -c 2020-05-11T19:49:12 --stack 557 | .br 558 | \fBssar load2p -c 2020-05-11T19:49:12 --loadd --stackinfo 559 | .br 560 | \fBssar load2p -c 2020-05-11T19:49:12 --api 561 | .br 562 | .SH LOAD2P COMMAND FORMAT SPECIFIERS 563 | Here are the keywords of the output format 564 | .PP 565 | For example: 566 | .B ssar load2p \-c 567 | .PP 568 | .TP 569 | \fBFIELD 570 | \fBDESCRIPTION 571 | .TP 572 | \fBcount 573 | load count 574 | .PP 575 | .SH FILES 576 | .TP 577 | .I /etc/ssar/ssar.conf 578 | Configuration file for ssar. 579 | .TP 580 | .I /etc/ssar/sys.conf 581 | Configuration file for ssar sys indicator. 582 | .SH BUGS 583 | .I /proc 584 | filesystem must be mounted for the 585 | .B ssar 586 | command to work. 587 | 588 | All the statistics are not necessarily available, depending on the kernel version used. 589 | -------------------------------------------------------------------------------- /conf/zh_CN.ssar.1: -------------------------------------------------------------------------------- 1 | .TH ssar 1 "August 2021" "ssar" "User Commands" 2 | .SH NAME 3 | ssar \- Collect, save and report system activity information. 4 | .SH SYNOPSIS 5 | \fBssar\fP [OPTIONS] [SUBCOMMAND] 6 | .SH DESCRIPTION 7 | \fBssar\fP displays information about a history of the system activity information. 8 | .SH OPTIONS 9 | .TP 10 | \fB\-h, \-\-help\fP 11 | Print this help message and exit 12 | .TP 13 | \fB\-V, \-\-version\fP 14 | Print the version message and exit 15 | .TP 16 | \fB\-\-api\fP Excludes: --no-headers 17 | If selected, output is json format, otherwise shell format. 18 | .TP 19 | \fB\-f, \-\-finish\fP \fITEXT\fR 20 | Assign the output datetime, allow history datetime. default value is current datetime. 21 | .TP 22 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 23 | Range from begin to finish, default 5 minutes. 24 | .TP 25 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 26 | Assign the compare datetime by the finish 27 | .TP 28 | \fB\-H, \-\-no-headers\fP Excludes: --api 29 | Disable the header info. 30 | .TP 31 | \fB\-P, \-\-purify\fP 32 | Hide the - * < > = no number data info.. 33 | .TP 34 | \fB\-o, \-\-format\fP \fITEXT\fR Excludes: --extra --cpu --mem --job --sched 35 | User-defined format. syntax is field1,field2 36 | .TP 37 | \fB\-O, \-\-extra\fP \fITEXT\fR Excludes: --format 38 | User-defined extra format. syntax is field1,field2 39 | .TP 40 | \fB\-\-cpu\fP Excludes: --format 41 | Display cpu-oriented format. 42 | .TP 43 | \fB\-\-mem\fP Excludes: --format 44 | Display virtual memory format. 45 | .TP 46 | \fB\-\-tcp\fP Excludes: --format 47 | Display tcp format 48 | .TP 49 | \fB\-\-udp\fP Excludes: --format 50 | Display udp format 51 | .SH EXAMPLES: 52 | .TP 53 | To see every process on the system history using standard syntax: 54 | \fBssar 55 | .br 56 | \fBssar -V 57 | .br 58 | \fBssar --cpu 59 | .br 60 | \fBssar --mem 61 | .br 62 | \fBssar --tcp 63 | .br 64 | \fBssar --udp 65 | .br 66 | \fBssar -r 60 67 | .br 68 | \fBssar -f 2020-03-02T18:34:00 69 | .br 70 | \fBssar -f -10 71 | .br 72 | \fBssar -f -5.5h 73 | .br 74 | \fBssar -f -1.2d 75 | .br 76 | \fBssar -b 2020-03-02T17:34:00 77 | .br 78 | \fBssar -P 79 | .br 80 | \fBssar -H 81 | .br 82 | \fBssar -o 'shmem,meminfo:2:2,snmp|8|11|d' 83 | .br 84 | \fBssar -O "dev|eth0:|2|d;snmp:8:11:d" --cpu 85 | .br 86 | \fBssar -o 'metric=d:cfile=snmp:line=8:column=13:alias=retranssegs' 87 | .br 88 | \fBssar -o 'metric=c|cfile=meminfo|line_begin=MemFree:|column=2|alias=free' 89 | .br 90 | \fBssar -o 'metric=c|cfile=loadavg|line=1|column=1|dtype=float|alias=load1' 91 | .br 92 | \fBssar -o 'metric=c|cfile=loadavg|line=1|column=4|dtype=string|alias=runq_plit' 93 | .br 94 | \fBssar -o 'metric=d|cfile=stat|line=2|column=2-11|alias=cpu0_{column};' 95 | .br 96 | \fBssar -o 'metric=d|cfile=stat|line=2-17|column=5|alias=idle_{line};' 97 | .br 98 | \fBssar -f +10 99 | .br 100 | \fBssar -f +10 -i 5s 101 | .br 102 | \fBssar --api 103 | .SH FORMAT SPECIFIERS 104 | Here are the indicator exmaples. 105 | .PP 106 | For example: 107 | .B ssar 108 | .PP 109 | .TP 110 | \fBFIELD 111 | \fBDESCRIPTION 112 | .TP 113 | \fBuser/s 114 | The average user value per second from the previous time point to the current time point. 115 | .TP 116 | \fBdirty 117 | The scale value of the current point in time. 118 | .SH SUBCOMMANDS 119 | .TP 120 | \fBprocs 121 | all process subcommand. 122 | .TP 123 | \fBproc 124 | single process subcommand. 125 | .TP 126 | \fBload5s 127 | load list of five second precision sudcommand. 128 | .TP 129 | \fBload2p 130 | Load to process subcommand. 131 | .SH PROCS COMMAND OPTIONS 132 | .TP 133 | \fB\-h, \-\-help\fP 134 | Print this help message and exit 135 | .TP 136 | \fB\-\-api\fP Excludes: --no-headers 137 | If selected, output is json format, otherwise shell format. 138 | .TP 139 | \fB\-f, \-\-finish\fP \fITEXT\fR 140 | Assign the output datetime, allow history datetime. default value is current datetime. 141 | .TP 142 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 143 | Range from begin to finish, default 5 minutes. 144 | .TP 145 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 146 | Assign the compare datetime by the finish 147 | .TP 148 | \fB\-k, \-\-key, \-\-sort\fP \fITEXT\fR 149 | Specify sorting order. Sorting syntax is [+|-]key[,[+|-]key[,...]] 150 | .TP 151 | \fB\-l, \-\-lines\fP \fIINT\fR 152 | Limit the output. 153 | .TP 154 | \fB\-H, \-\-no-headers\fP Excludes: --api 155 | Disable the header info. 156 | .TP 157 | \fB\-o, \-\-format\fP \fITEXT\fR Excludes: --extra --cpu --mem --job --sched 158 | User-defined format. syntax is field1,field2 159 | .TP 160 | \fB\-O, \-\-extra\fP \fITEXT\fR Excludes: --format 161 | User-defined extra format. syntax is field1,field2 162 | .TP 163 | \fB\-\-cpu\fP Excludes: --format 164 | Display cpu-oriented format. 165 | .TP 166 | \fB\-\-mem\fP Excludes: --format 167 | Display virtual memory format. 168 | .TP 169 | \fB\-\-job\fP Excludes: --format 170 | Display job control format 171 | .TP 172 | \fB\-\-sched\fP Excludes: --format 173 | Display sched format 174 | .SH PROCS COMMAND EXAMPLES: 175 | .TP 176 | To see every process on the system history using standard syntax: 177 | \fBssar procs 178 | .br 179 | \fBssar procs --cpu 180 | .br 181 | \fBssar procs --mem 182 | .br 183 | \fBssar procs --job 184 | .br 185 | \fBssar procs --sched 186 | .br 187 | \fBssar procs -r 60 188 | .br 189 | \fBssar procs -f 2020-03-02T18:34:00 190 | .br 191 | \fBssar procs -f -10 192 | .br 193 | \fBssar procs -f -5.5h 194 | .br 195 | \fBssar procs -f -1.2d 196 | .br 197 | \fBssar procs -b 2020-03-02T17:34:00 198 | .br 199 | \fBssar procs -k -ppid,pid,+start_datetime 200 | .br 201 | \fBssar procs -l 100 202 | .br 203 | \fBssar procs -H 204 | .br 205 | \fBssar procs -o ppid,pid,start_datetime 206 | .br 207 | \fBssar procs -O pgid 208 | .br 209 | \fBssar procs --api 210 | .SH PROCS COMMAND FORMAT SPECIFIERS 211 | Here are the keywords that may be used to control the output format (e.g. with option -o) or to sort the processes with the --sort option. 212 | .PP 213 | For example: 214 | .B ssar \-o pid \-\-sort rss 215 | .PP 216 | .TP 217 | \fBFIELD 218 | \fBDESCRIPTION 219 | .TP 220 | \fBpid 221 | a number representing the process ID (alias tgid). 222 | .TP 223 | \fBtgid 224 | alias pid. 225 | .TP 226 | \fBppid 227 | parent process ID. 228 | .TP 229 | \fBpgid 230 | process group ID or, equivalently, the process ID of the process group leader. 231 | .TP 232 | \fBsid 233 | session ID or, equivalently, the process ID of the session leader. 234 | .TP 235 | \fBtpgid 236 | ID of the foreground process group on the tty (terminal) that the process is connected to, or -1 if the process is not connected to a tty. 237 | .TP 238 | \fBnlwp 239 | Number of lwps (threads) in the process. 240 | .TP 241 | \fBflags 242 | Flags associated with the process. 243 | .TP 244 | \fBsched 245 | Scheduling policy of the process. The policies SCHED_OTHER (SCHED_NORMAL), SCHED_FIFO, SCHED_RR, SCHED_BATCH, SCHED_ISO, and SCHED_IDLE are respectively displayed as 0, 1, 2, 3, 4, and 5. 246 | .TP 247 | \fBcls 248 | Scheduling class of the process, see also sched. Field's possible values are TS(SCHED_OTHER) FF(SCHED_FIFO) RR(SCHED_RR) B(SCHED_BATCH) IDL(SCHED_IDLE) 249 | .TP 250 | \fBnice 251 | Nice value. This ranges from 19 (nicest) to -20 (not nice to others). 252 | .TP 253 | \fBrtprio 254 | Realtime priority. This ranges from 1 to 99. 255 | .TP 256 | \fBprio 257 | Priority of the process. Higher number means lower priority. 258 | .TP 259 | \fBvcswch 260 | Total number of voluntary context switches the task made. A voluntary context switch occurs when a task blocks because it requires a resource that is unavailable. 261 | .TP 262 | \fBncswch 263 | Total number of non voluntary context switches the task made. A involuntary context switch takes place when a task executes for the duration of its time slice and then is forced to relinquish the processor. 264 | .TP 265 | \fBvcswchs 266 | Total number of voluntary context switches the task made per second. 267 | .TP 268 | \fBncswchs 269 | Total number of non voluntary context switches the task made per second. 270 | .TP 271 | \fBs 272 | minimal state display (one character). 273 | .TP 274 | \fBetimes 275 | elapsed time since the process was started, in seconds. 276 | .TP 277 | \fBetime 278 | elapsed time since the process was started, in the form [[DD-]hh:]mm:ss. 279 | .TP 280 | \fBstart_time 281 | time the command started, in seconds. 282 | .TP 283 | \fBstart_datetime 284 | time the command started. "YY-mm-ddThh:mm:ss" format. 285 | .TP 286 | \fBbegin_datetime 287 | time the range started, approximate begin. "YY-mm-ddThh:mm:ss" format. 288 | .TP 289 | \fBfinish_datetime 290 | time the range finished, approximate finish. "YY-mm-ddThh:mm:ss" format. 291 | .TP 292 | \fBrealtime 293 | time the duration, approximate range, in seconds. 294 | .TP 295 | \fBtime 296 | cumulative CPU time, in seconds. 297 | .TP 298 | \fButime 299 | cumulative CPU User time, in seconds. 300 | .TP 301 | \fBstime 302 | cumulative CPU Sys time, in seconds. 303 | .TP 304 | \fBcputime 305 | cumulative CPU time, "[DD-]hh:mm:ss" format. 306 | .TP 307 | \fBcpu_utime 308 | cumulative CPU user time, "[DD-]hh:mm:ss" format. 309 | .TP 310 | \fBcpu_stime 311 | cumulative CPU sys time, "[DD-]hh:mm:ss" format. 312 | .TP 313 | \fBtime_dlt 314 | delta CPU time from begin_datetime to finish_datetime, in seconds. 315 | .TP 316 | \fButime_dlt 317 | delta CPU utime from begin_datetime to finish_datetime, in seconds. 318 | .TP 319 | \fBstime_dlt 320 | delta CPU stime from begin_datetime to finish_datetime, in seconds. 321 | .TP 322 | \fBpcpu 323 | cpu utilization of the process in "##.#" format, (cputime delta)/realtime ratio. 324 | .TP 325 | \fBpucpu 326 | cpu utilization of the process in "##.#" format, (cpu_utime delta)/realtime ratio. 327 | .TP 328 | \fBpscpu 329 | cpu utilization of the process in "##.#" format, (cpu_stime delta)/realtime ratio. 330 | .TP 331 | \fBsize 332 | approximate amount of swap space that would be required if the process were to dirty all writable pages and then be swapped out. 333 | .TP 334 | \fBrss 335 | resident set size, the non-swapped physical memory that a task has used (in kiloBytes). 336 | .TP 337 | \fBmaj_flt 338 | The number of major page faults that have occurred with this process. 339 | .TP 340 | \fBmin_flt 341 | The number of minor page faults that have occurred with this process. 342 | .TP 343 | \fBrss_dlt 344 | delta rss from begin_datetime to finish_datetime. 345 | .TP 346 | \fBmaj_dlt 347 | delta maj_flt from begin_datetime to finish_datetime. 348 | .TP 349 | \fBmin_dlt 350 | delta min_flt from begin_datetime to finish_datetime. 351 | .TP 352 | \fBcmd 353 | command name (only the executable name). 354 | .TP 355 | \fBcmdline 356 | command with all its arguments as a string. 357 | .TP 358 | \fBfullcmd 359 | only cmd fullpath. 360 | .TP 361 | \fBb 362 | show the pid if exist at begin_datetime. if exist, value =, not exist value <. 363 | .SH PROC COMMAND OPTIONS 364 | .TP 365 | \fB\-h, \-\-help\fP 366 | Print this help message and exit 367 | .TP 368 | \fB\-\-api\fP Excludes: --no-headers 369 | If selected, output is json format, otherwise shell format. 370 | .TP 371 | \fB\-p, \-\-pid\fP \fIINT\fR REQUIRED 372 | process id. 373 | .TP 374 | \fB\-i, \-\-interval\fP \fIINT\fR 375 | interval, default 10 minutes. 376 | .TP 377 | \fB\-f, \-\-finish\fP \fITEXT\fR 378 | Assign the output datetime, allow history datetime. default value is current datetime. 379 | .TP 380 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 381 | Range from begin to finish, default 300 minutes. 382 | .TP 383 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 384 | Assign the compare datetime by the finish 385 | .TP 386 | \fB\-H, \-\-no-headers\fP Excludes: --api 387 | Disable the header info. 388 | .TP 389 | \fB\-o, \-\-format\fP \fITEXT\fR Excludes: --extra --cpu --mem --job --sched 390 | User-defined format. syntax is field1,field2 391 | .TP 392 | \fB\-O, \-\-extra\fP \fITEXT\fR Excludes: --format 393 | User-defined extra format. syntax is field1,field2 394 | .TP 395 | \fB\-\-cpu\fP Excludes: --format 396 | Display cpu-oriented format. 397 | .TP 398 | \fB\-\-mem\fP Excludes: --format 399 | Display virtual memory format. 400 | .SH PROC COMMAND EXAMPLES: 401 | .TP 402 | To see history of one process using standard syntax: 403 | \fBssar proc -p 1 404 | .br 405 | \fBssar proc -p 1 --cpu 406 | .br 407 | \fBssar proc -p 1 --mem 408 | .br 409 | \fBssar proc -p 1 -r 60 410 | .br 411 | \fBssar proc -p 1 -i 1 412 | .br 413 | \fBssar proc -p 1 -f 2020-03-02T18:34:00 414 | .br 415 | \fBssar proc -p 1 -f -10 416 | .br 417 | \fBssar proc -p 1 -f -5.5h 418 | .br 419 | \fBssar proc -p 1 -f -1.2d 420 | .br 421 | \fBssar proc -p 1 -b 2020-03-02T17:34:00 422 | .br 423 | \fBssar proc -p 1 -H 424 | .br 425 | \fBssar proc -p 1 -o ppid,pid,start_datetime 426 | .br 427 | \fBssar proc -p 1 -O pgid 428 | .br 429 | \fBssar proc -p 1 --api 430 | .br 431 | .SH PROC COMMAND FORMAT SPECIFIERS 432 | Here are the keywords that may be used to control the output format (e.g. with option -p). 433 | .PP 434 | For example: 435 | .B ssar proc \-p 436 | .PP 437 | .TP 438 | See also PROCS COMMAND FORMAT SPECIFIERS 439 | .PP 440 | .SH LOAD5S COMMAND OPTIONS 441 | .TP 442 | \fB\-h, \-\-help\fP 443 | Print this help message and exit 444 | .TP 445 | \fB\-\-api\fP Excludes: --no-headers 446 | If selected, output is json format, otherwise shell format. 447 | .TP 448 | \fB\-f, \-\-finish\fP \fITEXT\fR 449 | Assign the output datetime, allow history datetime. default value is current datetime. 450 | .TP 451 | \fB\-r, \-\-range\fP \fIINT\fR Excludes: --begin 452 | Range from begin to finish, default 300 minutes. 453 | .TP 454 | \fB\-b, \-\-begin\fP \fITEXT\fR Excludes: --range 455 | Assign the compare datetime by the finish 456 | .TP 457 | \fB\-H, \-\-no-headers\fP Excludes: --api 458 | Disable the header info. 459 | .TP 460 | \fB\-y, \-\-yes\fP \fIINT\fR Excludes: --zoom 461 | Just display Y sstate collect datetime. 462 | .TP 463 | \fB\-z, \-\-zoom\fP \fIINT\fR Excludes: --yes 464 | Just display loadrd detail collect datetime. 465 | .SH LOAD5S COMMAND EXAMPLES: 466 | .TP 467 | To see history of one process using standard syntax: 468 | \fBssar load5s 469 | .br 470 | \fBssar load5s -r 60 471 | .br 472 | \fBssar load5s -f 2020-03-02T18:34:00 473 | .br 474 | \fBssar load5s -f -10 475 | .br 476 | \fBssar load5s -f -5.5h 477 | .br 478 | \fBssar load5s -f -1.2d 479 | .br 480 | \fBssar load5s -b 2020-03-02T17:34:00 481 | .br 482 | \fBssar load5s -H 483 | .br 484 | \fBssar load5s -y 485 | .br 486 | \fBssar load5s -z 487 | .br 488 | \fBssar load5s --api 489 | .br 490 | .SH LOAD5S COMMAND FORMAT SPECIFIERS 491 | Here are the keywords of the output format 492 | .PP 493 | For example: 494 | .B ssar load5s 495 | .PP 496 | .TP 497 | \fBFIELD 498 | \fBDESCRIPTION 499 | .TP 500 | \fBload5s 501 | load5s is 5 second precision load. 502 | .PP 503 | .SH LOAD2P COMMAND OPTIONS 504 | .TP 505 | \fB\-h, \-\-help\fP 506 | Print this help message and exit 507 | .TP 508 | \fB\-\-api\fP Excludes: --no-headers 509 | If selected, output is json format, otherwise shell format. 510 | .TP 511 | \fB\-c, \-\-collect\fP \fIINT\fR REQUIRED 512 | collect datetime. 513 | .TP 514 | \fB\-l, \-\-lines\fP \fIINT\fR 515 | Limit the output. 516 | .TP 517 | \fB\-H, \-\-no-headers\fP Excludes: --api 518 | Disable the header info. 519 | .TP 520 | \fB\-\-loadr\fP 521 | Display loadr format. 522 | .TP 523 | \fB\-\-loadd\fP 524 | Display loadd format. 525 | .TP 526 | \fB\-\-psr\fP 527 | Display psr format. 528 | .TP 529 | \fB\-\-stackinfo\fP 530 | Display stackinfo format. 531 | .TP 532 | \fB\-\-loadrd\fP 533 | Display loadrd format. 534 | .TP 535 | \fB\-\-stack\fP 536 | Display stack format. 537 | .SH LOAD2P COMMAND EXAMPLES: 538 | .TP 539 | To see history of one process using standard syntax: 540 | \fBssar load2p -c 2020-05-11T19:49:12 541 | .br 542 | \fBssar load2p -c 2020-05-11T19:49:12 -l 10 543 | .br 544 | \fBssar load2p -c 2020-05-11T19:49:12 -H 545 | .br 546 | \fBssar load2p -c 2020-05-11T19:49:12 --loadr 547 | .br 548 | \fBssar load2p -c 2020-05-11T19:49:12 --loadd 549 | .br 550 | \fBssar load2p -c 2020-05-11T19:49:12 --psr 551 | .br 552 | \fBssar load2p -c 2020-05-11T19:49:12 --stackinfo 553 | .br 554 | \fBssar load2p -c 2020-05-11T19:49:12 --loadrd 555 | .br 556 | \fBssar load2p -c 2020-05-11T19:49:12 --stack 557 | .br 558 | \fBssar load2p -c 2020-05-11T19:49:12 --loadd --stackinfo 559 | .br 560 | \fBssar load2p -c 2020-05-11T19:49:12 --api 561 | .br 562 | .SH LOAD2P COMMAND FORMAT SPECIFIERS 563 | Here are the keywords of the output format 564 | .PP 565 | For example: 566 | .B ssar load2p \-c 567 | .PP 568 | .TP 569 | \fBFIELD 570 | \fBDESCRIPTION 571 | .TP 572 | \fBcount 573 | load count 574 | .PP 575 | .SH FILES 576 | .TP 577 | .I /etc/ssar/ssar.conf 578 | Configuration file for ssar. 579 | .TP 580 | .I /etc/ssar/sys.conf 581 | Configuration file for ssar sys indicator. 582 | .SH BUGS 583 | .I /proc 584 | filesystem must be mounted for the 585 | .B ssar 586 | command to work. 587 | 588 | All the statistics are not necessarily available, depending on the kernel version used. 589 | -------------------------------------------------------------------------------- /conf/sys.conf: -------------------------------------------------------------------------------- 1 | [file] 2 | default=[ 3 | {src_path='loadavg', turn=true}, 4 | {src_path='buddyinfo', turn=true}, 5 | {src_path='meminfo', turn=true}, 6 | {src_path='vmstat', turn=true}, 7 | {src_path='stat', turn=true}, 8 | {src_path='diskstats', turn=true}, 9 | {src_path='softirqs', turn=true}, 10 | {src_path='/proc/net/dev', turn=true}, 11 | {src_path='/proc/net/netstat', turn=true}, 12 | {src_path='/proc/net/snmp', turn=true}, 13 | {src_path='/proc/net/sockstat',turn=true}, 14 | {src_path='/sys/kernel/debug/extfrag/extfrag_index', turn=true, cfile='extfrag'}, 15 | {src_path='/sys/kernel/debug/extfrag/unusable_index', turn=true, cfile='unusable'}, 16 | {src_path='sched_debug', gzip=true}, 17 | {src_path='schedstat', gzip=true}, 18 | {src_path='slabinfo'}, 19 | {src_path='zoneinfo'}, 20 | {src_path='interrupts', gzip=true}, 21 | ] 22 | 23 | '3.10.0'=[ 24 | {src_path='schedstat', gzip=true}, 25 | ] 26 | 27 | '4.9.'=[ 28 | {src_path='schedstat', gzip=true}, 29 | ] 30 | 31 | [view] 32 | default = ['user','system','iowait','softirq','memfree','anonpages','shmem','dirty'] 33 | cpu = ['user','nice','system','idle','iowait','irq','softirq','steal','guest','guest_nice'] 34 | mem = ['memtotal','memfree','memavailable','buffers','cached','anonpages','shmem','sreclaimable','sunreclaim','mlocked','dirty','writeback'] 35 | tcp = ['activeopens','passiveopens','insegs','outsegs','estabresets','attemptfails','currestab','retranssegs'] 36 | udp = ['indatagrams','noports','inerrors','outdatagrams','rcvbuferrors','sndbuferrors','incsumerrors'] 37 | vm = ['pgalloc','pgfree','pgactivate','pgdeactivate','pgfault','pgmajfault','pgrefill','allocstall','pageoutrun','pgscan_direct','pgsteal_direct','pgscan_kswapd','pgsteal_kswapd'] 38 | softirq = ['sum_softirq','hi','timer','net_tx','net_rx','block','irq_poll','tasklet','sched','hrtimer','rcu'] 39 | node0 = ['order0','order1','order2','order3','order4','order5','order6','order7','order8','order9','order10'] 40 | node1 = ['n1order0','n1order1','n1order2','n1order3','n1order4','n1order5','n1order6','n1order7','n1order8','n1order9','n1order10'] 41 | retran = ['retranssegs', 'lostretransmit', 'fastretrans', 'forwardretrans', 'slowstartretrans', 'RTORetrans', 'retransfail', 'synretrans'] 42 | tcpofo = ['ofopruned', 'dsackofosent', 'dsackoforecv', 'ofoqueue', 'ofodrop', 'ofomerge'] 43 | tcpdrop = ['lockdroppedicmps', 'listendrops', 'prequeuedropped', 'backlogdrop', 'minttldrop', 'deferacceptdrop', 'reqqfulldrop', 'ofodrop'] 44 | tcperr = ['RenoFailures', 'SackFailures', 'LossFailures', 'AbortOnMemory', 'AbortFailed', 'TimeWaitOverflow', 'FastOpenListenOverflow'] 45 | extfrag = ['e0order0','e0order1','e0order2','e0order3','e0order4','e0order5','e0order6','e0order7','e0order8','e0order9','e0order10'] 46 | unusable = ['u0order0','u0order1','u0order2','u0order3','u0order4','u0order5','u0order6','u0order7','u0order8','u0order9','u0order10'] 47 | 48 | [indicator] 49 | [indicator.default] 50 | user = {cfile='stat', line_begin='cpu', column=2, width=10, metric='d'} 51 | nice = {cfile='stat', line_begin='cpu', column=3, width=10, metric='d'} 52 | system = {cfile='stat', line_begin='cpu', column=4, width=10, metric='d'} 53 | idle = {cfile='stat', line_begin='cpu', column=5, width=10, metric='d'} 54 | iowait = {cfile='stat', line_begin='cpu', column=6, width=10, metric='d'} 55 | irq = {cfile='stat', line_begin='cpu', column=7, width=10, metric='d'} 56 | softirq = {cfile='stat', line_begin='cpu', column=8, width=10, metric='d'} 57 | steal = {cfile='stat', line_begin='cpu', column=9, width=10, metric='d'} 58 | guest = {cfile='stat', line_begin='cpu', column=10, width=10, metric='d'} 59 | guest_nice = {cfile='stat', line_begin='cpu', column=11, width=12, metric='d'} 60 | 61 | memtotal = {cfile='meminfo', line_begin='MemTotal:', column=2, width=10, metric='c'} 62 | memfree = {cfile='meminfo', line_begin='MemFree:', column=2, width=10, metric='c'} 63 | memavailable = {cfile='meminfo', line_begin='MemAvailable:', column=2, width=12, metric='c'} 64 | buffers = {cfile='meminfo', line_begin='Buffers:', column=2, width=10, metric='c'} 65 | cached = {cfile='meminfo', line_begin='Cached:', column=2, width=10, metric='c'} 66 | anonpages = {cfile='meminfo', line_begin='AnonPages:', column=2, metric='c'} 67 | shmem = {cfile='meminfo', line_begin='Shmem:', column=2, width=10, metric='c'} 68 | sreclaimable = {cfile='meminfo', line_begin='SReclaimable:', column=2, width=12, metric='c'} 69 | sunreclaim = {cfile='meminfo', line_begin='SUnreclaim:', column=2, width=10, metric='c'} 70 | mlocked = {cfile='meminfo', line_begin='Mlocked:', column=2, width=10, metric='c'} 71 | dirty = {cfile='meminfo', line_begin='Dirty:', column=2, width=10, metric='c'} 72 | writeback = {cfile='meminfo', line_begin='Writeback:', column=2, width=10, metric='c'} 73 | 74 | pgalloc = {cfile='vmstat', line_begin='pgalloc_normal',column=2, width=10, metric='d'} 75 | pgfree = {cfile='vmstat', line_begin='pgfree', column=2, width=10, metric='d'} 76 | pgactivate = {cfile='vmstat', line_begin='pgactivate', column=2, width=12, metric='d'} 77 | pgdeactivate = {cfile='vmstat', line_begin='pgdeactivate', column=2, width=14, metric='d'} 78 | pgfault = {cfile='vmstat', line_begin='pgfault', column=2, width=10, metric='d'} 79 | pgmajfault = {cfile='vmstat', line_begin='pgmajfault', column=2, width=12, metric='d'} 80 | pgrefill = {cfile='vmstat', line_begin='pgrefill', column=2, width=10, metric='d'} 81 | pageoutrun = {cfile='vmstat', line_begin='pageoutrun', column=2, width=12, metric='d'} 82 | allocstall = {cfile='vmstat', line_begin='allocstall_normal',column=2, width=12, metric='d'} 83 | pgscan_direct = {cfile='vmstat', line_begin='pgscan_direct', column=2, width=15, metric='d'} 84 | pgsteal_direct= {cfile='vmstat', line_begin='pgsteal_direct',column=2, width=16, metric='d'} 85 | pgscan_kswapd = {cfile='vmstat', line_begin='pgscan_kswapd', column=2, width=15, metric='d'} 86 | pgsteal_kswapd= {cfile='vmstat', line_begin='pgsteal_kswapd',column=2, width=16, metric='d'} 87 | 88 | activeopens = {cfile='snmp', line=8, column=6, width=13, metric='d'} 89 | passiveopens = {cfile='snmp', line=8, column=7, width=14, metric='d'} 90 | insegs = {cfile='snmp', line=8, column=11, width=10, metric='d'} 91 | outsegs = {cfile='snmp', line=8, column=12, width=10, metric='d'} 92 | estabresets = {cfile='snmp', line=8, column=9, width=13, metric='d'} 93 | attemptfails = {cfile='snmp', line=8, column=8, width=14, metric='d'} 94 | currestab = {cfile='snmp', line=8, column=10, width=10, metric='c'} 95 | retranssegs = {cfile='snmp', line=8, column=13, width=13, metric='d'} 96 | 97 | indatagrams = {cfile='snmp', line=10, column=2, width=13, metric='d'} 98 | noports = {cfile='snmp', line=10, column=3, width=13, metric='d'} 99 | inerrors = {cfile='snmp', line=10, column=4, width=13, metric='d'} 100 | outdatagrams = {cfile='snmp', line=10, column=5, width=13, metric='d'} 101 | rcvbuferrors = {cfile='snmp', line=10, column=6, width=13, metric='d'} 102 | sndbuferrors = {cfile='snmp', line=10, column=7, width=13, metric='d'} 103 | incsumerrors = {cfile='snmp', line=10, column=8, width=13, metric='d'} 104 | ignoredmulti = {cfile='snmp', line=10, column=9, width=13, metric='d'} 105 | 106 | ofopruned = {cfile='netstat', line_begin='TcpExt:', column=8, width=11, metric='d'} 107 | dsackofosent = {cfile='netstat', line_begin='TcpExt:', column=57, width=14, metric='d'} 108 | dsackoforecv = {cfile='netstat', line_begin='TcpExt:', column=59, width=14, metric='d'} 109 | ofoqueue = {cfile='netstat', line_begin='TcpExt:', column=85, width=10, metric='d'} 110 | ofodrop = {cfile='netstat', line_begin='TcpExt:', column=86, width=9, metric='d'} 111 | ofomerge = {cfile='netstat', line_begin='TcpExt:', column=87, width=10, metric='d'} 112 | 113 | lostretransmit = {cfile='netstat', line_begin='TcpExt:', column=42, width=16, metric='d'} 114 | fastretrans = {cfile='netstat', line_begin='TcpExt:', column=46, width=13, metric='d'} 115 | forwardretrans = {cfile='netstat', line_begin='TcpExt:', column=47, width=16, metric='d'} 116 | slowstartretrans = {cfile='netstat', line_begin='TcpExt:', column=48, width=17, metric='d'} 117 | RTORetrans = {cfile='netstat', line_begin='TcpExt:', column=49, width=12, metric='d'} 118 | retransfail = {cfile='netstat', line_begin='TcpExt:', column=83, width=13, metric='d'} 119 | synretrans = {cfile='netstat', line_begin='TcpExt:', column=102,width=12, metric='d'} 120 | 121 | lockdroppedicmps = {cfile='netstat', line_begin='TcpExt:', column=10, width=18, metric='d'} 122 | listendrops = {cfile='netstat', line_begin='TcpExt:', column=22, width=13, metric='d'} 123 | prequeuedropped = {cfile='netstat', line_begin='TcpExt:', column=26, width=17, metric='d'} 124 | backlogdrop = {cfile='netstat', line_begin='TcpExt:', column=76, width=13, metric='d'} 125 | minttldrop = {cfile='netstat', line_begin='TcpExt:', column=77, width=12, metric='d'} 126 | deferacceptdrop = {cfile='netstat', line_begin='TcpExt:', column=78, width=17, metric='d'} 127 | reqqfulldrop = {cfile='netstat', line_begin='TcpExt:', column=82, width=14, metric='d'} 128 | 129 | RenoFailures = {cfile='netstat', line_begin='TcpExt:', column=43, width=14, metric='d'} 130 | SackFailures = {cfile='netstat', line_begin='TcpExt:', column=44, width=14, metric='d'} 131 | LossFailures = {cfile='netstat', line_begin='TcpExt:', column=45, width=14, metric='d'} 132 | AbortOnMemory = {cfile='netstat', line_begin='TcpExt:', column=62, width=15, metric='d'} 133 | AbortFailed = {cfile='netstat', line_begin='TcpExt:', column=65, width=13, metric='d'} 134 | TimeWaitOverflow = {cfile='netstat', line_begin='TcpExt:', column=80, width=18, metric='d'} 135 | FastOpenListenOverflow={cfile='netstat',line_begin='TcpExt:', column=94, width=24, metric='d'} 136 | 137 | sum_softirq = {cfile='stat', line_begin='softirq', column=2, width=13, metric='d'} 138 | hi = {cfile='stat', line_begin='softirq', column=3, width=10, metric='d'} 139 | timer = {cfile='stat', line_begin='softirq', column=4, width=10, metric='d'} 140 | net_tx = {cfile='stat', line_begin='softirq', column=5, width=10, metric='d'} 141 | net_rx = {cfile='stat', line_begin='softirq', column=6, width=10, metric='d'} 142 | block = {cfile='stat', line_begin='softirq', column=7, width=10, metric='d'} 143 | irq_poll = {cfile='stat', line_begin='softirq', column=8, width=10, metric='d'} 144 | tasklet = {cfile='stat', line_begin='softirq', column=9, width=10, metric='d'} 145 | sched = {cfile='stat', line_begin='softirq', column=10, width=10, metric='d'} 146 | hrtimer = {cfile='stat', line_begin='softirq', column=11, width=10, metric='d'} 147 | rcu = {cfile='stat', line_begin='softirq', column=12, width=10, metric='d'} 148 | 149 | eth0_rx_bytes = {cfile='dev', line_begin='eth0:', column=2, width=15, metric='d', position='a'} 150 | eth0_rx_packets= {cfile='dev', line_begin='eth0:', column=3, width=17, metric='d', position='a'} 151 | eth0_rx_errs = {cfile='dev', line_begin='eth0:', column=4, width=14, metric='d', position='a'} 152 | eth0_rx_drop = {cfile='dev', line_begin='eth0:', column=5, width=14, metric='d', position='a'} 153 | eth0_tx_bytes = {cfile='dev', line_begin='eth0:', column=10, width=15, metric='d', position='a'} 154 | eth0_tx_packets= {cfile='dev', line_begin='eth0:', column=11, width=17, metric='d', position='a'} 155 | eth0_tx_errs = {cfile='dev', line_begin='eth0:', column=12, width=14, metric='d', position='a'} 156 | eth0_tx_drop = {cfile='dev', line_begin='eth0:', column=13, width=14, metric='d', position='a'} 157 | bond0_rx_bytes = {cfile='dev', line_begin='bond0:', column=2, width=16, metric='d', position='a'} 158 | bond0_rx_packets= {cfile='dev', line_begin='bond0:', column=3, width=18, metric='d', position='a'} 159 | bond0_rx_errs = {cfile='dev', line_begin='bond0:', column=4, width=15, metric='d', position='a'} 160 | bond0_rx_drop = {cfile='dev', line_begin='bond0:', column=5, width=15, metric='d', position='a'} 161 | bond0_tx_bytes = {cfile='dev', line_begin='bond0:', column=10, width=16, metric='d', position='a'} 162 | bond0_tx_packets= {cfile='dev', line_begin='bond0:', column=11, width=18, metric='d', position='a'} 163 | bond0_tx_errs = {cfile='dev', line_begin='bond0:', column=12, width=15, metric='d', position='a'} 164 | bond0_tx_drop = {cfile='dev', line_begin='bond0:', column=13, width=15, metric='d', position='a'} 165 | 166 | order0 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=5, width=10, metric='c'} 167 | order1 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=6, width=10, metric='c'} 168 | order2 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=7, width=10, metric='c'} 169 | order3 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=8, width=10, metric='c'} 170 | order4 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=9, width=10, metric='c'} 171 | order5 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=10, width=10, metric='c'} 172 | order6 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=11, width=10, metric='c'} 173 | order7 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=12, width=10, metric='c'} 174 | order8 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=13, width=10, metric='c'} 175 | order9 = {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=14, width=10, metric='c'} 176 | order10= {cfile='buddyinfo',line_begin='Node 0, zone Normal',column=15, width=10, metric='c'} 177 | n1order0 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=5, width=10, metric='c'} 178 | n1order1 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=6, width=10, metric='c'} 179 | n1order2 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=7, width=10, metric='c'} 180 | n1order3 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=8, width=10, metric='c'} 181 | n1order4 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=9, width=10, metric='c'} 182 | n1order5 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=10, width=10, metric='c'} 183 | n1order6 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=11, width=10, metric='c'} 184 | n1order7 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=12, width=10, metric='c'} 185 | n1order8 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=13, width=10, metric='c'} 186 | n1order9 = {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=14, width=10, metric='c'} 187 | n1order10= {cfile='buddyinfo',line_begin='Node 1, zone Normal',column=15, width=10, metric='c'} 188 | 189 | u0order0 = {cfile='unusable',line_begin='Node 0, zone Normal',column=5, width=10, metric='c',dtype='string'} 190 | u0order1 = {cfile='unusable',line_begin='Node 0, zone Normal',column=6, width=10, metric='c',dtype='string'} 191 | u0order2 = {cfile='unusable',line_begin='Node 0, zone Normal',column=7, width=10, metric='c',dtype='string'} 192 | u0order3 = {cfile='unusable',line_begin='Node 0, zone Normal',column=8, width=10, metric='c',dtype='string'} 193 | u0order4 = {cfile='unusable',line_begin='Node 0, zone Normal',column=9, width=10, metric='c',dtype='string'} 194 | u0order5 = {cfile='unusable',line_begin='Node 0, zone Normal',column=10, width=10, metric='c',dtype='string'} 195 | u0order6 = {cfile='unusable',line_begin='Node 0, zone Normal',column=11, width=10, metric='c',dtype='string'} 196 | u0order7 = {cfile='unusable',line_begin='Node 0, zone Normal',column=12, width=10, metric='c',dtype='string'} 197 | u0order8 = {cfile='unusable',line_begin='Node 0, zone Normal',column=13, width=10, metric='c',dtype='string'} 198 | u0order9 = {cfile='unusable',line_begin='Node 0, zone Normal',column=14, width=10, metric='c',dtype='string'} 199 | u0order10= {cfile='unusable',line_begin='Node 0, zone Normal',column=15, width=10, metric='c',dtype='string'} 200 | e0order0 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=5, width=10, metric='c',dtype='string'} 201 | e0order1 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=6, width=10, metric='c',dtype='string'} 202 | e0order2 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=7, width=10, metric='c',dtype='string'} 203 | e0order3 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=8, width=10, metric='c',dtype='string'} 204 | e0order4 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=9, width=10, metric='c',dtype='string'} 205 | e0order5 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=10, width=10, metric='c',dtype='string'} 206 | e0order6 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=11, width=10, metric='c',dtype='string'} 207 | e0order7 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=12, width=10, metric='c',dtype='string'} 208 | e0order8 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=13, width=10, metric='c',dtype='string'} 209 | e0order9 = {cfile='extfrag',line_begin='Node 0, zone Normal',column=14, width=10, metric='c',dtype='string'} 210 | e0order10= {cfile='extfrag',line_begin='Node 0, zone Normal',column=15, width=10, metric='c',dtype='string'} 211 | 212 | [indicator.'3.10.0-'] 213 | allocstall = {cfile='vmstat',line_begin='allocstall', column=2,width=12,metric='d'} 214 | pgscan_direct = {cfile='vmstat',line_begin='pgscan_direct_normal', column=2,width=15,metric='d'} 215 | pgsteal_direct= {cfile='vmstat',line_begin='pgsteal_direct_normal',column=2,width=16,metric='d'} 216 | pgscan_kswapd = {cfile='vmstat',line_begin='pgscan_kswapd_normal', column=2,width=15,metric='d'} 217 | pgsteal_kswapd= {cfile='vmstat',line_begin='pgsteal_kswapd_normal',column=2,width=16,metric='d'} 218 | pgrefill = {cfile='vmstat',line_begin='pgrefill_normal', column=2,width=10,metric='d'} 219 | 220 | [indicator.'4.9.'] 221 | ofoqueue = {cfile='netstat', line_begin='TcpExt:', column=86, width=10, metric='d'} 222 | ofodrop = {cfile='netstat', line_begin='TcpExt:', column=87, width=9, metric='d'} 223 | ofomerge = {cfile='netstat', line_begin='TcpExt:', column=88, width=10, metric='d'} 224 | 225 | retransfail = {cfile='netstat', line_begin='TcpExt:', column=84, width=13, metric='d'} 226 | synretrans = {cfile='netstat', line_begin='TcpExt:', column=103,width=12, metric='d'} 227 | 228 | backlogdrop = {cfile='netstat', line_begin='TcpExt:', column=77, width=13, metric='d'} 229 | minttldrop = {cfile='netstat', line_begin='TcpExt:', column=78, width=12, metric='d'} 230 | deferacceptdrop = {cfile='netstat', line_begin='TcpExt:', column=79, width=17, metric='d'} 231 | reqqfulldrop = {cfile='netstat', line_begin='TcpExt:', column=83, width=14, metric='d'} 232 | 233 | TimeWaitOverflow = {cfile='netstat', line_begin='TcpExt:', column=81, width=18, metric='d'} 234 | FastOpenListenOverflow={cfile='netstat',line_begin='TcpExt:', column=95, width=24, metric='d'} 235 | 236 | [indicator.'4.18.'] 237 | dsackofosent = {cfile='netstat', line_begin='TcpExt:', column=49, width=14, metric='d'} 238 | dsackoforecv = {cfile='netstat', line_begin='TcpExt:', column=51, width=14, metric='d'} 239 | ofoqueue = {cfile='netstat', line_begin='TcpExt:', column=80, width=10, metric='d'} 240 | ofodrop = {cfile='netstat', line_begin='TcpExt:', column=81, width=9, metric='d'} 241 | ofomerge = {cfile='netstat', line_begin='TcpExt:', column=82, width=10, metric='d'} 242 | 243 | lostretransmit = {cfile='netstat', line_begin='TcpExt:', column=35, width=16, metric='d'} 244 | fastretrans = {cfile='netstat', line_begin='TcpExt:', column=39, width=13, metric='d'} 245 | slowstartretrans = {cfile='netstat', line_begin='TcpExt:', column=40, width=17, metric='d'} 246 | RTORetrans = {cfile='netstat', line_begin='TcpExt:', column=41, width=12, metric='d'} 247 | retransfail = {cfile='netstat', line_begin='TcpExt:', column=78, width=13, metric='d'} 248 | synretrans = {cfile='netstat', line_begin='TcpExt:', column=98, width=12, metric='d'} 249 | 250 | listendrops = {cfile='netstat', line_begin='TcpExt:', column=21, width=13, metric='d'} 251 | backlogdrop = {cfile='netstat', line_begin='TcpExt:', column=70, width=13, metric='d'} 252 | minttldrop = {cfile='netstat', line_begin='TcpExt:', column=72, width=12, metric='d'} 253 | deferacceptdrop = {cfile='netstat', line_begin='TcpExt:', column=73, width=17, metric='d'} 254 | reqqfulldrop = {cfile='netstat', line_begin='TcpExt:', column=77, width=14, metric='d'} 255 | 256 | RenoFailures = {cfile='netstat', line_begin='TcpExt:', column=36, width=14, metric='d'} 257 | SackFailures = {cfile='netstat', line_begin='TcpExt:', column=37, width=14, metric='d'} 258 | LossFailures = {cfile='netstat', line_begin='TcpExt:', column=38, width=14, metric='d'} 259 | AbortOnMemory = {cfile='netstat', line_begin='TcpExt:', column=54, width=15, metric='d'} 260 | AbortFailed = {cfile='netstat', line_begin='TcpExt:', column=57, width=13, metric='d'} 261 | TimeWaitOverflow = {cfile='netstat', line_begin='TcpExt:', column=75, width=18, metric='d'} 262 | FastOpenListenOverflow={cfile='netstat',line_begin='TcpExt:', column=89, width=24, metric='d'} 263 | 264 | [indicator.'4.19.'] 265 | dsackofosent = {cfile='netstat', line_begin='TcpExt:', column=48, width=14, metric='d'} 266 | dsackoforecv = {cfile='netstat', line_begin='TcpExt:', column=50, width=14, metric='d'} 267 | ofoqueue = {cfile='netstat', line_begin='TcpExt:', column=79, width=10, metric='d'} 268 | ofodrop = {cfile='netstat', line_begin='TcpExt:', column=80, width=9, metric='d'} 269 | ofomerge = {cfile='netstat', line_begin='TcpExt:', column=81, width=10, metric='d'} 270 | 271 | lostretransmit = {cfile='netstat', line_begin='TcpExt:', column=35, width=16, metric='d'} 272 | fastretrans = {cfile='netstat', line_begin='TcpExt:', column=39, width=13, metric='d'} 273 | slowstartretrans = {cfile='netstat', line_begin='TcpExt:', column=40, width=17, metric='d'} 274 | RTORetrans = {cfile='netstat', line_begin='TcpExt:', column=41, width=12, metric='d'} 275 | retransfail = {cfile='netstat', line_begin='TcpExt:', column=77, width=13, metric='d'} 276 | synretrans = {cfile='netstat', line_begin='TcpExt:', column=97, width=12, metric='d'} 277 | 278 | listendrops = {cfile='netstat', line_begin='TcpExt:', column=21, width=13, metric='d'} 279 | backlogdrop = {cfile='netstat', line_begin='TcpExt:', column=69, width=13, metric='d'} 280 | minttldrop = {cfile='netstat', line_begin='TcpExt:', column=71, width=12, metric='d'} 281 | deferacceptdrop = {cfile='netstat', line_begin='TcpExt:', column=72, width=17, metric='d'} 282 | reqqfulldrop = {cfile='netstat', line_begin='TcpExt:', column=76, width=14, metric='d'} 283 | 284 | RenoFailures = {cfile='netstat', line_begin='TcpExt:', column=36, width=14, metric='d'} 285 | SackFailures = {cfile='netstat', line_begin='TcpExt:', column=37, width=14, metric='d'} 286 | LossFailures = {cfile='netstat', line_begin='TcpExt:', column=38, width=14, metric='d'} 287 | AbortOnMemory = {cfile='netstat', line_begin='TcpExt:', column=53, width=15, metric='d'} 288 | AbortFailed = {cfile='netstat', line_begin='TcpExt:', column=56, width=13, metric='d'} 289 | TimeWaitOverflow = {cfile='netstat', line_begin='TcpExt:', column=74, width=18, metric='d'} 290 | FastOpenListenOverflow={cfile='netstat',line_begin='TcpExt:', column=88, width=24, metric='d'} 291 | -------------------------------------------------------------------------------- /sresar/readprocess.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2021 Alibaba Inc. 4 | * SRESAR is licensed under Mulan PSL v2. 5 | * You can use this software according to the terms and conditions of the Mulan PSL v2. 6 | * You may obtain a copy of Mulan PSL v2 at: 7 | * http://license.coscl.org.cn/MulanPSL2 8 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 9 | * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 10 | * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 11 | * See the Mulan PSL v2 for more details. 12 | * 13 | * Part of SRESAR (Site Reliability Engineering System Activity Reporter) 14 | * 15 | * Author: Miles Wen 16 | * 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "utils.h" 37 | #include "readprocess.h" 38 | 39 | #define STAT_FILE "/proc/stat" 40 | 41 | #define F(x) {#x, sizeof(#x)-1, &&case_##x}, 42 | #define NUL {"", 0, 0}, 43 | 44 | static int uptime_fd = -1; 45 | static char buf[8192]; 46 | 47 | typedef struct status_table_struct { 48 | unsigned char name[7]; 49 | unsigned char len; 50 | void *addr; 51 | } status_table_struct; 52 | 53 | /************************************************************************************ 54 | *** * 55 | *** sysinfo part * 56 | *** * 57 | ************************************************************************************/ 58 | 59 | unsigned long get_btime(void) { 60 | static unsigned long btime = 0; 61 | bool found_btime = false; 62 | FILE *f; 63 | 64 | if(btime){ 65 | return btime; 66 | } 67 | 68 | if ((f = fopen(STAT_FILE, "r")) == NULL) { 69 | fputs("/proc must be mounted\n", stderr); 70 | exit(1); 71 | } 72 | 73 | while((fgets(buf, sizeof buf, f))) { 74 | if (sscanf(buf, "btime %lu", &btime) == 1) { 75 | found_btime = true; 76 | break; 77 | } 78 | } 79 | if (f) { 80 | fclose(f); 81 | f = NULL; 82 | } 83 | 84 | if(!found_btime) { 85 | fputs("missing btime in " STAT_FILE "\n", stderr); 86 | exit(1); 87 | } 88 | 89 | return btime; 90 | } 91 | 92 | int get_uptime() { 93 | double up=0, idle=0; 94 | char *savelocale; 95 | 96 | static int local_n; 97 | if(uptime_fd == -1 && (uptime_fd = open("/proc/uptime", O_RDONLY)) == -1) { 98 | perror("/proc must be mounted\n"); 99 | exit(2); 100 | } 101 | lseek(uptime_fd, 0L, SEEK_SET); 102 | if ((local_n = read(uptime_fd, buf, sizeof(buf) - 1)) < 0) { 103 | perror("/proc/uptime"); 104 | exit(3); 105 | } 106 | buf[local_n] = '\0'; 107 | savelocale = strdup(setlocale(LC_NUMERIC, NULL)); 108 | setlocale(LC_NUMERIC, "C"); 109 | if(sscanf(buf, "%lf %lf", &up, &idle) < 2) { 110 | setlocale(LC_NUMERIC, savelocale); 111 | free(savelocale); 112 | perror("bad data in /proc/uptime\n"); 113 | return 0; 114 | } 115 | setlocale(LC_NUMERIC, savelocale); 116 | free(savelocale); 117 | 118 | return up; 119 | } 120 | 121 | /************************************************************************************ 122 | *** * 123 | *** stack part * 124 | *** * 125 | ************************************************************************************/ 126 | 127 | char *read_stack_file(unsigned tid, utlbuf_s *ubuf, utlbuf_s *ufbuf, char * nwchan){ 128 | char path[GROWWIDTH]; 129 | char *tmp; 130 | int fd; 131 | unsigned int num; 132 | unsigned int tmp_num; 133 | int total_read = 0; 134 | int counter = 0; 135 | int saved_errno; 136 | char error_buf[256]; 137 | ubuf->buf[0] = '\0'; 138 | ufbuf->buf[0] = '\0'; 139 | 140 | snprintf(path, sizeof(path), "/proc/%d/stack", tid); 141 | fd = open(path, O_RDONLY|O_NONBLOCK); 142 | saved_errno = errno; 143 | if(fd == -1){ 144 | strerror_r(saved_errno, error_buf, 256); 145 | replace_char(error_buf, '-', '_'); 146 | replace_char(error_buf, '/', '_'); 147 | replace_char(error_buf, '.', '_'); 148 | replace_char(error_buf, ':', '_'); 149 | replace_char(error_buf, ' ', '_'); 150 | sprintf(ubuf->buf, "%d?%s", saved_errno, error_buf); 151 | strcpy(nwchan, "000000"); 152 | return ubuf->buf; 153 | } 154 | while(0 < (num = read(fd, ufbuf->buf + total_read, GROWWIDTH))){ 155 | if(num == -1){ 156 | strcpy(ubuf->buf, "-"); 157 | strcpy(nwchan, "000000"); 158 | return ubuf->buf; 159 | break; 160 | }else if(num == 0){ 161 | break; 162 | } 163 | total_read += num; 164 | 165 | if(total_read + GROWWIDTH >= ufbuf->len){ 166 | ufbuf->len += GROWWIDTH; 167 | ufbuf->buf = (char*)realloc(ufbuf->buf, ufbuf->len * sizeof(char*)); 168 | } 169 | }; 170 | ufbuf->buf[total_read] = '\0'; 171 | close(fd); 172 | 173 | char* cur_line = ufbuf->buf; 174 | char* line_break_pos; 175 | int is_nwchan = 0; 176 | while(cur_line){ 177 | line_break_pos = strchr(cur_line, '\n'); 178 | if(line_break_pos){ 179 | *line_break_pos = '\0'; 180 | } 181 | 182 | if(!is_nwchan){ 183 | strncpy(nwchan, cur_line + 12, 6); 184 | is_nwchan = 1; 185 | } 186 | 187 | if((cur_line = strchr(cur_line, ']')) == NULL){ 188 | break; 189 | } 190 | cur_line = cur_line + 2; 191 | if((tmp = strrchr2(cur_line + 2, '+')) == NULL){ 192 | break; 193 | } 194 | tmp_num = tmp - cur_line; 195 | cur_line[tmp_num] = '\0'; 196 | if(0 != counter){ 197 | if(strlen(ubuf->buf) + strlen(",") >= ubuf->len){ 198 | ubuf->len += GROWWIDTH; 199 | ubuf->buf = (char*)realloc(ubuf->buf, ubuf->len * sizeof(char*)); 200 | } 201 | strcat(ubuf->buf, ","); 202 | } 203 | for(;;){ 204 | if(strlen(ubuf->buf) + tmp_num >= ubuf->len){ 205 | ubuf->len += GROWWIDTH; 206 | ubuf->buf = (char*)realloc(ubuf->buf, ubuf->len * sizeof(char*)); 207 | }else{ 208 | break; 209 | } 210 | } 211 | strncat(ubuf->buf, cur_line, tmp_num); 212 | counter++; 213 | 214 | cur_line = line_break_pos ? (line_break_pos + 1) : NULL; 215 | } 216 | 217 | return ubuf->buf; 218 | } 219 | 220 | 221 | /************************************************************************************ 222 | *** * 223 | *** cmdline part * 224 | *** * 225 | ************************************************************************************/ 226 | 227 | char *delete_trailing_chars(char *s, const char *bad) { 228 | char *p, *c = s; 229 | 230 | if(!s){ 231 | return NULL; 232 | } 233 | 234 | if(!bad){ 235 | bad = "\t\n\r"; 236 | } 237 | for(p = s; *p; p++){ 238 | if (!strchr(bad, *p)){ 239 | c = p + 1; 240 | } 241 | } 242 | *c = 0; 243 | 244 | return s; 245 | } 246 | 247 | int get_process_cmdline(const char* directory, utlbuf_s *ubuf) { 248 | int fd; 249 | char *t = NULL; 250 | char path[100] = {0,}; 251 | ssize_t num; 252 | size_t total_read = 0; 253 | int ret = 0; 254 | int max_loop_time; 255 | int i = 0; 256 | 257 | max_loop_time = (int)(2097152 / GROWWIDTH); 258 | 259 | if(!ubuf->buf){ 260 | return -ENOMEM; 261 | } 262 | 263 | sprintf(path, "%s/cmdline", directory); 264 | fd = open(path, O_RDONLY|O_CLOEXEC|O_NONBLOCK); 265 | while((num = read(fd, ubuf->buf + total_read, GROWWIDTH)) > 0){ 266 | if(i > max_loop_time){ 267 | break; 268 | } 269 | total_read += num; 270 | i++; 271 | 272 | if(total_read + GROWWIDTH >= ubuf->len){ 273 | ubuf->len += GROWWIDTH; 274 | ubuf->buf = (char*)realloc(ubuf->buf, ubuf->len * sizeof(char*)); 275 | } 276 | }; 277 | ubuf->buf[total_read] = '\0'; 278 | if(total_read > 0){ 279 | for(size_t i = 0; i < total_read; i++){ 280 | if(ubuf->buf[i] == '\0' || ubuf->buf[i] == '\x9' || ubuf->buf[i] == '\xa'){ 281 | ubuf->buf[i] = ' '; 282 | } 283 | } 284 | ret = 1; 285 | }else{ 286 | strncpy(ubuf->buf, "[]", 2); 287 | ubuf->buf[2] = '\0'; 288 | ret = 2; 289 | } 290 | delete_trailing_chars(ubuf->buf, WHITESPACE); 291 | close(fd); 292 | 293 | return ret; 294 | } 295 | 296 | /************************************************************************************ 297 | *** * 298 | *** parser part * 299 | *** * 300 | ************************************************************************************/ 301 | 302 | void parse_status(char *S, proc_t *restrict P){ 303 | 304 | // 128 entries 305 | static const unsigned char asso[] = { 306 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 307 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 308 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 309 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 310 | 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 311 | 64, 64, 64, 64, 64, 64, 64, 64, 28, 64, 312 | 64, 64, 64, 64, 64, 64, 8, 25, 23, 25, 313 | 6, 25, 0, 3, 64, 64, 3, 64, 25, 64, 314 | 20, 1, 1, 5, 0, 30, 0, 0, 64, 64, 315 | 64, 64, 64, 64, 64, 64, 64, 3, 64, 0, 316 | 0, 18, 64, 10, 64, 10, 64, 64, 64, 20, 317 | 64, 20, 0, 64, 25, 64, 3, 15, 64, 0, 318 | 30, 64, 64, 64, 64, 64, 64, 64 319 | }; 320 | 321 | static const status_table_struct table[] = { 322 | F(VmHWM) 323 | NUL NUL 324 | F(VmLck) 325 | NUL 326 | F(VmSwap) 327 | F(VmRSS) 328 | NUL 329 | F(VmStk) 330 | NUL 331 | F(Tgid) 332 | F(State) 333 | NUL 334 | F(VmLib) 335 | NUL 336 | F(VmSize) 337 | F(SigQ) 338 | NUL 339 | F(SigIgn) 340 | NUL 341 | F(VmPTE) 342 | F(FDSize) 343 | NUL 344 | F(SigBlk) 345 | NUL 346 | F(ShdPnd) 347 | F(VmData) 348 | NUL 349 | F(CapInh) 350 | NUL 351 | F(PPid) 352 | NUL NUL 353 | F(CapBnd) 354 | NUL 355 | F(SigPnd) 356 | NUL NUL 357 | F(VmPeak) 358 | NUL 359 | F(SigCgt) 360 | NUL NUL 361 | F(Threads) 362 | NUL 363 | F(CapPrm) 364 | NUL NUL 365 | F(Pid) 366 | NUL 367 | F(CapEff) 368 | NUL NUL 369 | F(Gid) 370 | NUL 371 | F(VmExe) 372 | NUL NUL 373 | F(Uid) 374 | NUL 375 | F(Groups) 376 | NUL NUL 377 | F(Name) 378 | }; 379 | 380 | char *colon; 381 | status_table_struct entry; 382 | int table_index; 383 | goto base; 384 | 385 | for(;;){ 386 | S = strchr(S, '\n'); 387 | if(unlikely(!S)){ 388 | break; // if no newline 389 | } 390 | S++; 391 | 392 | base: 393 | if(unlikely(!*S)){ 394 | break; 395 | } 396 | table_index = 63 & (asso[(int)S[3]] + asso[(int)S[2]] + asso[(int)S[0]]); 397 | colon = strchr(S, ':'); 398 | 399 | if(table_index == 15){ 400 | if(unlikely(!memcmp("voluntary_ctxt_switches",S,colon-S))){ 401 | S = colon+2; 402 | goto case_nvcsw; 403 | } 404 | } 405 | if(table_index == 0){ 406 | if(unlikely(!memcmp("nonvoluntary_ctxt_switches",S,colon-S))){ 407 | S = colon+2; 408 | goto case_nivcsw; 409 | } 410 | } 411 | 412 | entry = table[table_index]; 413 | if(unlikely(!colon)){ 414 | break; 415 | } 416 | if(unlikely(colon[1]!='\t')){ 417 | break; 418 | } 419 | if(unlikely(colon-S != entry.len)){ 420 | continue; 421 | } 422 | if(unlikely(memcmp(entry.name,S,colon-S))){ 423 | continue; 424 | } 425 | 426 | S = colon+2; // past the '\t' 427 | 428 | goto *entry.addr; 429 | 430 | case_Name: 431 | case_ShdPnd: 432 | case_SigBlk: 433 | case_SigCgt: 434 | case_SigIgn: 435 | case_SigPnd: 436 | case_State: 437 | case_Tgid: 438 | case_Pid: 439 | case_PPid: 440 | case_Threads: 441 | case_Uid: 442 | case_Gid: 443 | case_VmData: 444 | case_VmExe: 445 | case_VmLck: 446 | case_VmLib: 447 | case_VmRSS: 448 | case_VmSize: 449 | case_VmStk: 450 | case_VmSwap: 451 | case_Groups: 452 | case_CapBnd: 453 | case_CapEff: 454 | case_CapInh: 455 | case_CapPrm: 456 | case_FDSize: 457 | case_SigQ: 458 | case_VmHWM: 459 | case_VmPTE: 460 | case_VmPeak: 461 | continue; 462 | case_nvcsw: 463 | P->nvcsw = strtol(S,&S,10); 464 | continue; 465 | case_nivcsw: 466 | P->nivcsw = strtol(S,&S,10); 467 | continue; 468 | } 469 | } 470 | 471 | static void parse_stat(const char* S, proc_t *restrict P){ 472 | unsigned num; 473 | char* tmp; 474 | 475 | // fill in default values 476 | P->processor = 0; 477 | P->rtprio = -1; 478 | P->sched = -1; 479 | P->nlwp = 0; 480 | 481 | S = strchr(S, '(') + 1; 482 | tmp = strrchr2(S, ')'); 483 | num = tmp - S; 484 | if(unlikely(num >= sizeof(P->cmd))) { 485 | num = sizeof(P->cmd) - 1; 486 | } 487 | memcpy(P->cmd, S, num); 488 | P->cmd[num] = '\0'; 489 | S = tmp + 2; // skip ") " 490 | 491 | long priority; 492 | long flags; 493 | num = sscanf(S, 494 | "%c " 495 | "%d %d %d %d %d " 496 | "%lu %lu %lu %lu %lu " 497 | "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */ 498 | "%ld %ld " 499 | "%d " 500 | "%ld " 501 | "%Lu " /* start_time */ 502 | "%lu " 503 | "%ld " 504 | "%*u %*u %*u %*u %*u %*u " 505 | "%*s %*s %*s %*s " 506 | "%*u %*u %*u " 507 | "%*d " 508 | "%d " 509 | "%lu %lu", 510 | &P->state, 511 | &P->ppid, &P->pgid, &P->sid, &P->tty, &P->tpgid, 512 | &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt, 513 | &P->utime, &P->stime, &P->cutime, &P->cstime, 514 | &priority, &P->nice, 515 | &P->nlwp, 516 | &P->alarm, 517 | &P->start_time, 518 | &P->vsize, 519 | &P->rss, 520 | //&P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip, 521 | //&P->signal, &P->blocked, &P->sigignore,&P->sigcatch, 522 | //&P->wchan, &P->nswap, &P->cnswap, 523 | //&P->exit_signal, 524 | &P->processor, 525 | &P->rtprio, &P->sched 526 | ); 527 | P->prio = priority + 100; 528 | P->flags = (unsigned)(flags>>6U)&0x7U; 529 | 530 | if(!P->nlwp){ 531 | P->nlwp = 1; 532 | } 533 | 534 | } 535 | 536 | static void mini_parse_stat(const char* S, cmdinfo_t *restrict P){ 537 | unsigned num; 538 | char* tmp; 539 | 540 | S = strchr(S, '(') + 1; 541 | tmp = strrchr2(S, ')'); 542 | num = tmp - S; 543 | if(unlikely(num >= sizeof(P->cmd))) { 544 | num = sizeof(P->cmd) - 1; 545 | } 546 | memcpy(P->cmd, S, num); 547 | P->cmd[num] = '\0'; 548 | S = tmp + 2; // skip ") " 549 | 550 | num = sscanf(S, "%c ", &P->state); 551 | } 552 | 553 | static void parse_statm(const char* s, proc_t *restrict P){ 554 | int num; 555 | long size = 0; 556 | long resident = 0; 557 | long share = 0; 558 | num = sscanf(s, "%ld %ld %ld %ld %ld %ld %ld", 559 | &size, &resident, &share, &P->trs, &P->lrs, &P->drs, &P->dt); 560 | P->size = 4 * size; // 4 = 4096 / 1024 561 | P->resident = 4 * resident; // 4 = 4096 / 1024 562 | P->share = 4 * share; // 4 = 4096 / 1024 563 | } 564 | 565 | static int file2str(const char *directory, const char *what, utlbuf_s *ubuf){ 566 | char path[PROCPATHLEN]; 567 | int fd; 568 | int num; 569 | int total_read = 0; 570 | 571 | ubuf->len = GROWWIDTH; 572 | if(ubuf->buf){ 573 | ubuf->buf[0] = '\0'; 574 | }else { 575 | ubuf->buf = xxcalloc(GROWWIDTH); 576 | } 577 | sprintf(path, "%s/%s", directory, what); 578 | if(-1 == (fd = open(path, O_RDONLY, 0))){ 579 | return -1; 580 | } 581 | 582 | while(0 < (num = read(fd, ubuf->buf + total_read, ubuf->len - total_read))) { 583 | total_read += num; 584 | if (total_read < ubuf->len){ 585 | break; 586 | } 587 | ubuf->len += GROWWIDTH; 588 | ubuf->buf = xxrealloc(ubuf->buf, ubuf->len); 589 | }; 590 | 591 | ubuf->buf[total_read] = '\0'; 592 | close(fd); 593 | if(unlikely(total_read < 1)){ 594 | return -1; 595 | } 596 | return total_read; 597 | } 598 | 599 | /************************************************************************************ 600 | *** * 601 | *** iterator part * 602 | *** * 603 | ************************************************************************************/ 604 | 605 | static int next_pid_proc(PROCTAB *restrict const PT, proc_t *restrict const p) { 606 | static struct dirent *ent; 607 | char *restrict const path = PT->path; 608 | 609 | for(;;){ 610 | ent = readdir(PT->procfs); 611 | if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))){ 612 | return 0; 613 | } 614 | if(likely(likely(*ent->d_name > '0') && likely(*ent->d_name <= '9'))){ 615 | break; 616 | } 617 | } 618 | p->tgid = strtoul(ent->d_name, NULL, 10); 619 | p->tid = p->tgid; 620 | memcpy(path, "/proc/", 6); 621 | strcpy(path+6, ent->d_name); 622 | 623 | return 1; 624 | } 625 | 626 | static int next_pid_cmdline(PROCTAB *restrict const PT, cmdinfo_t *restrict const c) { 627 | static struct dirent *ent; 628 | char *restrict const path = PT->path; 629 | 630 | for(;;){ 631 | ent = readdir(PT->procfs); 632 | if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))){ 633 | return 0; 634 | } 635 | if(likely(likely(*ent->d_name > '0') && likely(*ent->d_name <= '9'))){ 636 | break; 637 | } 638 | } 639 | c->tgid = strtoul(ent->d_name, NULL, 10); 640 | memcpy(path, "/proc/", 6); 641 | strcpy(path+6, ent->d_name); 642 | 643 | return 1; 644 | } 645 | 646 | static int next_tid_task(PROCTAB *restrict const PT, proc_t *restrict const t, const pid_t p, char *restrict const path) { 647 | static struct dirent *ent; 648 | if(PT->taskdir_user != p){ 649 | if(PT->taskdir){ 650 | closedir(PT->taskdir); 651 | } 652 | snprintf(path, PROCPATHLEN, "/proc/%d/task", p); 653 | PT->taskdir = opendir(path); 654 | if(!PT->taskdir){ 655 | return 0; 656 | } 657 | PT->taskdir_user = p; 658 | } 659 | for (;;) { 660 | ent = readdir(PT->taskdir); 661 | if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))){ 662 | return 0; 663 | } 664 | if(likely(likely(*ent->d_name > '0') && likely(*ent->d_name <= '9'))){ 665 | break; 666 | } 667 | } 668 | t->tid = strtoul(ent->d_name, NULL, 10); 669 | t->tgid = p; 670 | snprintf(path, PROCPATHLEN, "/proc/%d/task/%s", p, ent->d_name); 671 | return 1; 672 | } 673 | 674 | static proc_t* readinfo_proc(PROCTAB *restrict const PT, proc_t *restrict const p, int cmd_flag, utlbuf_s *ufbuf){ 675 | static utlbuf_s ubuf = {0, NULL}; // buf for stat,statm 676 | static struct stat sb; // stat() buffer 677 | char *restrict const path = PT->path; 678 | 679 | if(unlikely(stat(path, &sb) == -1)){ // no such dirent 680 | goto next_proc; 681 | } 682 | 683 | if(unlikely(file2str(path, "stat", &ubuf) == -1)){ // read /proc/#/stat 684 | goto next_proc; 685 | } 686 | parse_stat(ubuf.buf, p); 687 | 688 | if(likely(file2str(path, "statm", &ubuf) != -1)){ // read /proc/#/statm 689 | parse_statm(ubuf.buf, p); 690 | } 691 | 692 | if(likely(file2str(path, "status", &ubuf) != -1)){ // read /proc/#/status 693 | parse_status(ubuf.buf, p); 694 | } 695 | 696 | if(cmd_flag){ 697 | p->ptype = get_process_cmdline(path, ufbuf); // read /proc/#/cmdline 698 | } 699 | 700 | return p; 701 | next_proc: 702 | return NULL; 703 | } 704 | 705 | static cmdinfo_t* readinfo_cmdline(PROCTAB *restrict const PT, cmdinfo_t *restrict const c, utlbuf_s *ufbuf){ 706 | static utlbuf_s ubuf = {0, NULL}; // buf for stat,statm 707 | static struct stat sb; // stat() buffer 708 | char *restrict const path = PT->path; 709 | 710 | if(unlikely(stat(path, &sb) == -1)){ // no such dirent 711 | goto next_proc; 712 | } 713 | 714 | if(unlikely(file2str(path, "stat", &ubuf) == -1)){ // read /proc/#/stat 715 | goto next_proc; 716 | } 717 | mini_parse_stat(ubuf.buf, c); 718 | 719 | c->ptype = get_process_cmdline(path, ufbuf); // read /proc/#/cmdline 720 | 721 | return c; 722 | next_proc: 723 | return NULL; 724 | } 725 | 726 | static proc_t* readinfo_task(PROCTAB *restrict const PT, proc_t *restrict const t, const pid_t p, char *restrict const path) { 727 | static char stat_info[GROWWIDTH] = {0}; 728 | char * S = stat_info; 729 | 730 | char file_path[PROCPATHLEN]; 731 | int fd; 732 | int read_num; 733 | //int total_read = 0; 734 | 735 | memset(stat_info,'\0', GROWWIDTH); 736 | sprintf(file_path, "%s/stat", path); 737 | if(-1 == (fd = open(file_path, O_RDONLY))){ 738 | return NULL; 739 | } 740 | 741 | read_num = read(fd, stat_info, GROWWIDTH); 742 | close(fd); 743 | if(unlikely(read_num < 1)){ 744 | return NULL; 745 | } 746 | stat_info[read_num] = '\0'; 747 | 748 | char* tmp; 749 | unsigned num; 750 | 751 | t->processor = 0; 752 | t->rtprio = -1; 753 | t->sched = -1; 754 | t->nlwp = 0; 755 | 756 | S = strchr(S, '(') + 1; 757 | tmp = strrchr2(S, ')'); 758 | num = tmp - S; 759 | if(unlikely(num >= sizeof(t->cmd))) { 760 | num = sizeof(t->cmd) - 1; 761 | } 762 | memcpy(t->cmd, S, num); 763 | t->cmd[num] = '\0'; 764 | S = tmp + 2; // skip ") " 765 | 766 | long priority; 767 | num = sscanf(S, 768 | "%c " 769 | "%*d %*d %*d %*d %*d " 770 | "%*u %*u %*u %*u %*u " 771 | "%Lu %Lu %*u %*u " 772 | "%ld %*d " 773 | "%*d " 774 | "%*d " 775 | "%Lu " 776 | "%*u " 777 | "%*d " 778 | "%*u %*u %*u %*u %*u %*u " 779 | "%*s %*s %*s %*s " 780 | "%*u %*u %*u " 781 | "%*d " 782 | "%d " 783 | "%lu %lu", 784 | &t->state, &t->utime, &t->stime, &priority, &t->start_time, &t->processor, &t->rtprio, &t->sched 785 | ); 786 | if(!(t->state == 'D' || t->state == 'R')){ 787 | return NULL; 788 | } 789 | t->prio = priority + 100; 790 | 791 | return t; 792 | } 793 | 794 | /************************************************************************************ 795 | *** * 796 | *** api part * 797 | *** * 798 | ************************************************************************************/ 799 | 800 | PROCTAB* openproc(PROCTAB* PT) { 801 | int task_dir_missing; 802 | struct stat sbuf; 803 | int did_stat = 0; 804 | char target_path[10]; 805 | ssize_t len; 806 | char *ptr; 807 | 808 | PT->task_owner = -1; 809 | if(!did_stat){ 810 | task_dir_missing = lstat("/proc/self", &sbuf); 811 | did_stat = 1; 812 | if(!task_dir_missing && S_ISLNK(sbuf.st_mode)){ 813 | if((len = readlink("/proc/self", target_path, sizeof(target_path)-1)) != -1){ 814 | target_path[len] = '\0'; 815 | PT->task_owner = strtoul(target_path, &ptr, 10); 816 | } 817 | } 818 | } 819 | PT->taskdir = NULL; 820 | PT->taskdir_user = -1; 821 | PT->finder_proc = next_pid_proc; 822 | PT->reader_proc = readinfo_proc; 823 | PT->finder_cmdline = next_pid_cmdline; 824 | PT->reader_cmdline = readinfo_cmdline; 825 | PT->procfs = opendir("/proc"); 826 | if(!PT->procfs){ 827 | free(PT); 828 | return NULL; 829 | } 830 | 831 | return PT; 832 | } 833 | 834 | PROCTAB* mini_openproc(PROCTAB* PT) { 835 | int task_dir_missing; 836 | struct stat sbuf; 837 | ssize_t len; 838 | char target_path[10]; 839 | 840 | PT->taskdir = NULL; 841 | PT->taskdir_user = -1; 842 | PT->finder_task = next_tid_task; 843 | PT->reader_task = readinfo_task; 844 | PT->procfs = opendir("/proc"); 845 | PT->task_owner = -1; 846 | task_dir_missing = lstat("/proc/self", &sbuf); 847 | if(!task_dir_missing && S_ISLNK(sbuf.st_mode)){ 848 | if((len = readlink("/proc/self", target_path, sizeof(target_path)-1)) != -1){ 849 | target_path[len] = '\0'; 850 | PT->task_owner = strtoul(target_path, NULL, 10); 851 | } 852 | } 853 | if(!PT->procfs){ 854 | return NULL; 855 | } 856 | 857 | return PT; 858 | } 859 | 860 | proc_t* read_proc(PROCTAB *restrict const PT, proc_t *restrict p, int cmd_flag, utlbuf_s *ubuf) { 861 | proc_t *ret; 862 | 863 | memset(p, '\0', sizeof(proc_t)); 864 | for(;;){ 865 | if (unlikely(!PT->finder_proc(PT, p))){ // next_pid_proc 866 | goto out; 867 | } 868 | ret = PT->reader_proc(PT, p, cmd_flag, ubuf); // readinfo_proc 869 | if(ret){ 870 | return ret; 871 | } 872 | } 873 | 874 | out: 875 | return NULL; 876 | } 877 | 878 | pid_t mini_read_proc(PROCTAB *restrict const PT) { 879 | pid_t ret; 880 | static struct dirent *ent; 881 | 882 | for(;;){ 883 | ent = readdir(PT->procfs); 884 | if(unlikely(unlikely(!ent) || unlikely(!ent->d_name))){ 885 | return 0; 886 | } 887 | if(likely(likely(*ent->d_name > '0') && likely(*ent->d_name <= '9'))){ 888 | ret = strtoul(ent->d_name, NULL, 10); 889 | if(PT->task_owner == ret){ // filter current process 890 | continue; 891 | } 892 | break; 893 | } 894 | } 895 | return ret; 896 | } 897 | 898 | cmdinfo_t* read_cmdline(PROCTAB *restrict const PT, cmdinfo_t *restrict c, utlbuf_s *ubuf) { 899 | cmdinfo_t *ret; 900 | 901 | for(;;){ 902 | if (unlikely(!PT->finder_cmdline(PT, c))){ // next_pid_proc 903 | goto out; 904 | } 905 | ret = PT->reader_cmdline(PT, c, ubuf); // readinfo_proc 906 | if(ret){ 907 | return ret; 908 | } 909 | } 910 | 911 | out: 912 | return NULL; 913 | } 914 | 915 | proc_t* read_task(PROCTAB *restrict const PT, proc_t *restrict t, const pid_t p){ 916 | char path[PROCPATHLEN]; 917 | proc_t *ret; 918 | 919 | memset(t,'\0', sizeof(proc_t)); 920 | for(;;){ 921 | if(unlikely(!PT->finder_task(PT,t,p,path))){ 922 | break; 923 | } 924 | ret = PT->reader_task(PT, t, p, path); 925 | if(ret){ 926 | return ret; 927 | } 928 | } 929 | return NULL; 930 | } 931 | 932 | void closeproc(PROCTAB* PT) { 933 | if(PT){ 934 | if (PT->procfs){ 935 | closedir(PT->procfs); 936 | } 937 | if (PT->taskdir){ 938 | closedir(PT->taskdir); 939 | } 940 | } 941 | } 942 | 943 | void mini_closeproc(PROCTAB* PT) { 944 | if(PT){ 945 | if (PT->procfs){ 946 | closedir(PT->procfs); 947 | } 948 | if (PT->taskdir){ 949 | closedir(PT->taskdir); 950 | } 951 | } 952 | } 953 | 954 | -------------------------------------------------------------------------------- /ssar/ssar.h: -------------------------------------------------------------------------------- 1 | #ifndef SSAR_SSAR_H 2 | #define SSAR_SSAR_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "json.hpp" 8 | 9 | using namespace std; 10 | using json = nlohmann::json; 11 | 12 | typedef struct sproc_t { 13 | int count; 14 | int record_type; 15 | string s; 16 | int tid; 17 | int ppid; 18 | int pgid; 19 | int sid; 20 | int nlwp; 21 | int tgid; 22 | int pid; 23 | int psr; 24 | long prio; 25 | long nice; 26 | unsigned long rtprio; 27 | unsigned long sched; 28 | string cls; 29 | unsigned long flags; 30 | unsigned long long vcswch; 31 | unsigned long long ncswch; 32 | unsigned long long vcswchs; 33 | unsigned long long ncswchs; 34 | unsigned long long utime; 35 | unsigned long long stime; 36 | unsigned long long cutime; 37 | unsigned long long cstime; 38 | unsigned long long start_time; 39 | unsigned long long etimes; 40 | int tty; 41 | int tpgid; 42 | long rss; 43 | long shr; 44 | long alarm; 45 | long size; 46 | long resident; 47 | long share; 48 | long trs; 49 | long lrs; 50 | long drs; 51 | long dt; 52 | unsigned long vsize; 53 | unsigned long rss_rlim; 54 | unsigned long min_flt; 55 | unsigned long maj_flt; 56 | unsigned long cmin_flt; 57 | unsigned long cmaj_flt; 58 | string cmd; 59 | string fullcmd; 60 | string cmdline; 61 | unsigned long long time; 62 | unsigned long long realtime; 63 | unsigned long long time_dlt; 64 | unsigned long long utime_dlt; 65 | unsigned long long stime_dlt; 66 | float pcpu; 67 | float pucpu; 68 | float pscpu; 69 | unsigned long maj_dlt; 70 | unsigned long min_dlt; 71 | long rss_dlt; 72 | long shr_dlt; 73 | string etime; 74 | string cputime; 75 | string cpu_utime; 76 | string cpu_stime; 77 | string start_datetime; 78 | string begin_datetime; 79 | string finish_datetime; 80 | string collect_datetime; 81 | string b; 82 | unsigned long collect_time; 83 | } sproc_t; 84 | 85 | typedef struct aproc_t { 86 | int tgid; 87 | string cmd; 88 | string fullcmd; 89 | string cmdline; 90 | } aproc_t; 91 | 92 | typedef struct load5s_t{ 93 | unsigned long collect_time; 94 | string collect_datetime; 95 | int threads; 96 | int runq; 97 | double load1; 98 | int load5s; 99 | int load5s_type; // 1(1m) or 5(5s) 100 | int load5s_state; // 0(N) or 2(Y) 101 | int zoom_state; // 0(U) or 3(Z) 102 | string stype; // 1(1m) or 5(5s) 103 | string sstate; // 0(N) or 2(Y) 104 | string zstate; // 0(U) or 3(Z) 105 | int act; // active 106 | int actr; // active R 107 | int actd; // active D 108 | double act_rto; // act ratio 109 | double actr_rto; // actr ratio 110 | int record_type; 111 | } load5s_t; 112 | 113 | typedef struct active_t{ 114 | int actr; 115 | int actd; 116 | } active_t; 117 | 118 | typedef struct load2p_t{ 119 | int count; 120 | string s; // state 121 | int tid; 122 | int tgid; 123 | int pid; 124 | int psr; 125 | int prio; 126 | string cmd; 127 | string cmdline; 128 | string wchan; 129 | string nwchan; 130 | string stackinfo; 131 | string full_stackinfo; 132 | string s_unit; 133 | } load2p_t; 134 | 135 | typedef struct indicator_t{ 136 | int line; 137 | int column; 138 | int width; 139 | string cfile; 140 | string line_begin; 141 | string position; 142 | string metric; 143 | string dtype; 144 | string indicator; 145 | string alias; 146 | int gzip; // inherit from cfile 147 | string src_path; // inherit from cfile 148 | } indicator_t; 149 | 150 | typedef struct cfile_t{ 151 | int turn; 152 | int gzip; 153 | string src_path; 154 | string cfile; 155 | } cfile_t; 156 | 157 | list procs_default_formats = {"start_datetime","pid","ppid","cputime","pcpu","size","rss","etime","nlwp","cmd"}; 158 | list procs_cpu_formats = {"pid","ppid","cputime","cpu_utime","cpu_stime","pcpu","pucpu","pscpu","vcswchs","ncswchs","s","cmd"}; 159 | list procs_mem_formats = {"pid","ppid","size","rss","shr","maj_flt","min_flt","rss_dlt","shr_dlt","maj_dlt","min_dlt","cmd"}; 160 | list procs_job_formats = {"start_datetime","pid","ppid","pgid","sid","tpgid","etime","s","cmd"}; 161 | list procs_sched_formats = {"start_datetime","pid","ppid","flags","cls","nice","rtprio","prio","cmd"}; 162 | 163 | list proc_default_formats = {"collect_datetime","etime","cputime","pcpu","size","rss","nlwp","cmd"}; 164 | list proc_cpu_formats = {"collect_datetime","etime","cputime","cpu_utime","cpu_stime","pcpu","pucpu","pscpu","vcswchs","ncswchs","s","cmd"}; 165 | list proc_mem_formats = {"collect_datetime","etime","size","rss","shr","maj_flt","min_flt","rss_dlt","shr_dlt","maj_dlt","min_dlt","cmd"}; 166 | list load5s_default_formats= {"collect_datetime","threads","load1","runq","load5s","stype","sstate","zstate","act","act_rto","actr","actr_rto","actd"}; 167 | list load2p_default_formats= {"loadr", "loadd", "psr", "stackinfo"}; 168 | list load2p_loadpid_formats= {"count", "s", "pid", "cmd", "cmdline"}; 169 | list load2p_psr_formats = {"count", "psr"}; 170 | list load2p_stackinfo_formats = {"count", "s_unit", "nwchan","wchan","stackinfo"}; 171 | list load2p_loadrd_formats = {"s", "tid", "pid", "psr", "prio","cmd"}; 172 | list load2p_stack_formats = {"tid","pid","cmd","nwchan","wchan","stackinfo"}; 173 | 174 | //list sys_default_formats = {"stat:cpu:2:d","stat:cpu:4:d","stat:cpu:6:d","stat:cpu:8:d","meminfo|MemFree:|2","meminfo|AnonPages:|2","meminfo|Shmem:|2","meminfo|Dirty:|2"}; 175 | list sys_default_formats = {"metric=d:src_path=/proc/stat:line_begin=cpu:column=2:alias=user","metric=d:src_path=/proc/stat:line_begin=cpu:column=4:alias=system","metric=d:src_path=/proc/stat:line_begin=cpu:column=6:alias=iowait","metric=d:src_path=/proc/stat:line_begin=cpu:column=8:alias=softirq","src_path=/proc/meminfo|line_begin=MemFree:|column=2|alias=memfree","src_path=/proc/meminfo|line_begin=AnonPages:|column=2|alias=anonpages","src_path=/proc/meminfo|line_begin=Shmem:|column=2|alias=shmem","src_path=/proc/meminfo|line_begin=Dirty:|column=2|alias=dirty"}; 176 | 177 | unordered_map sched2cls { 178 | {0,"TS"}, 179 | {1,"FF"}, 180 | {2,"RR"}, 181 | {3,"B"}, 182 | {5,"IDL"} 183 | }; 184 | 185 | unordered_map> field_attribute { 186 | {"record_type",{{"f_width","11"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 187 | {"s",{{"f_width","1"},{"k_order","-"},{"adjust","left"},{"unit","scale"}}}, 188 | {"tid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 189 | {"ppid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 190 | {"pgid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 191 | {"sid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 192 | {"nlwp",{{"f_width","4"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 193 | {"tgid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 194 | {"pid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 195 | {"psr",{{"f_width","3"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 196 | {"prio",{{"f_width","4"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 197 | {"nice",{{"f_width","4"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 198 | {"rtprio",{{"f_width","6"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 199 | {"sched",{{"f_width","5"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 200 | {"cls",{{"f_width","3"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 201 | {"flags",{{"f_width","5"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 202 | {"vcswch",{{"f_width","6"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 203 | {"ncswch",{{"f_width","6"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 204 | {"vcswchs",{{"f_width","7"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 205 | {"ncswchs",{{"f_width","7"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 206 | {"utime",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 207 | {"stime",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 208 | {"cutime",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 209 | {"cstime",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 210 | {"start_time",{{"f_width","10"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 211 | {"etimes",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 212 | {"tty",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 213 | {"tpgid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 214 | {"rss",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 215 | {"shr",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 216 | {"alarm",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 217 | {"size",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 218 | {"resident",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 219 | {"share",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 220 | {"trs",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 221 | {"lrs",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 222 | {"drs",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 223 | {"dt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 224 | {"vsize",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 225 | {"rss_rlim",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 226 | {"min_flt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 227 | {"maj_flt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 228 | {"cmin_flt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 229 | {"cmaj_flt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 230 | {"cmd",{{"f_width","15"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 231 | {"fullcmd",{{"f_width","30"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 232 | {"cmdline",{{"f_width","50"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 233 | {"time",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 234 | {"realtime",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 235 | {"time_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 236 | {"utime_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 237 | {"stime_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 238 | {"pcpu",{{"f_width","7"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 239 | {"pucpu",{{"f_width","7"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 240 | {"pscpu",{{"f_width","7"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 241 | {"maj_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 242 | {"min_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 243 | {"rss_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 244 | {"shr_dlt",{{"f_width","10"},{"k_order","-"},{"adjust","right"},{"unit","scope"}}}, 245 | {"etime",{{"f_width","13"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 246 | {"cputime",{{"f_width","13"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 247 | {"cpu_utime",{{"f_width","13"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 248 | {"cpu_stime",{{"f_width","13"},{"k_order","-"},{"adjust","right"},{"unit","scale"}}}, 249 | {"start_datetime",{{"f_width","19"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 250 | {"begin_datetime",{{"f_width","19"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 251 | {"finish_datetime",{{"f_width","19"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 252 | {"collect_datetime",{{"f_width","19"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 253 | {"b",{{"f_width","1"},{"k_order","+"},{"adjust","left"},{"unit","scope"}}} 254 | }; 255 | 256 | unordered_map> load5s_field_attribute{ 257 | {"collect_datetime",{{"f_width","19"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 258 | {"threads",{{"f_width","10"},{"zoom_state","3"},{"adjust","right"},{"unit","scale"}}}, 259 | {"load1",{{"f_width","8"},{"zoom_state","3"},{"adjust","right"},{"unit","scale"}}}, 260 | {"runq",{{"f_width","6"},{"zoom_state","3"},{"adjust","right"},{"unit","scale"}}}, 261 | {"load5s",{{"f_width","6"},{"zoom_state","3"},{"adjust","right"},{"unit","scale"}}}, 262 | {"load5s_type",{{"f_width","5"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 263 | {"stype",{{"f_width","5"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 264 | {"load5s_state",{{"f_width","6"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 265 | {"sstate",{{"f_width","6"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 266 | {"zoom_state",{{"f_width","6"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 267 | {"zstate",{{"f_width","6"},{"zoom_state","3"},{"adjust","left"},{"unit","scale"}}}, 268 | {"act",{{"f_width","6"},{"zoom_state","0"},{"adjust","right"},{"unit","scale"}}}, 269 | {"act_rto",{{"f_width","7"},{"zoom_state","0"},{"adjust","right"},{"unit","scale"}}}, 270 | {"actr",{{"f_width","6"},{"zoom_state","0"},{"adjust","right"},{"unit","scale"}}}, 271 | {"actr_rto",{{"f_width","8"},{"zoom_state","0"},{"adjust","right"},{"unit","scale"}}}, 272 | {"actd",{{"f_width","6"},{"zoom_state","0"},{"adjust","right"},{"unit","scale"}}} 273 | }; 274 | 275 | unordered_map> load2p_field_attribute{ 276 | {"count",{{"f_width","8"},{"k_order","-"},{"adjust","rigth"},{"unit","scale"}}}, 277 | {"s",{{"f_width","1"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 278 | {"tid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 279 | {"tgid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 280 | {"pid",{{"f_width","7"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 281 | {"psr",{{"f_width","3"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 282 | {"prio",{{"f_width","4"},{"k_order","+"},{"adjust","right"},{"unit","scale"}}}, 283 | {"nwchan",{{"f_width","6"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 284 | {"wchan",{{"f_width","32"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 285 | {"s_unit",{{"f_width","7"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 286 | {"stackinfo",{{"f_width","6"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 287 | {"full_stackinfo",{{"f_width","6"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 288 | {"cmd",{{"f_width","15"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}}, 289 | {"cmdline",{{"f_width","6"},{"k_order","+"},{"adjust","left"},{"unit","scale"}}} 290 | }; 291 | 292 | struct SeqOptions { 293 | string src; 294 | bool api; 295 | chrono::system_clock::time_point time_point_begin; 296 | chrono::system_clock::time_point time_point_begin_hard; 297 | chrono::system_clock::time_point time_point_finish; 298 | chrono::system_clock::time_point time_point_collect; 299 | chrono::system_clock::time_point time_point_begin_adjust; 300 | chrono::system_clock::time_point time_point_finish_adjust; 301 | chrono::system_clock::time_point time_point_begin_real; 302 | chrono::system_clock::time_point time_point_finish_real; 303 | int range; 304 | chrono::duration duration_range; 305 | chrono::duration duration_real; 306 | string interval; 307 | int intervals; 308 | string begin; 309 | string finish; 310 | string collect; 311 | bool live_mode; 312 | string key; 313 | list> keys; 314 | int lines; 315 | bool noheaders; 316 | bool purify; 317 | bool version; 318 | string format; 319 | string extra; 320 | list formats; 321 | list formated; 322 | bool cpu; 323 | bool mem; 324 | bool job; 325 | bool sched; 326 | bool yes; 327 | bool zoom; 328 | bool loadr; 329 | bool loadd; 330 | bool psr; 331 | bool stackinfo; 332 | bool loadrd; 333 | bool stack; 334 | bool adjust; 335 | string uts_release; 336 | int pid; 337 | bool ssar_conf; 338 | bool sys_conf; 339 | bool has_cmdline; 340 | bool proc_gzip_disable; 341 | string work_path; 342 | string ssar_path; 343 | string data_path; 344 | map views; 345 | unordered_map *sys_files; 346 | map> *sys_view; 347 | map, greater> *group_files; 348 | map, greater> *sys_indicator; 349 | map>> *sys_hierarchy_line; 350 | map>> *sys_hierarchy_begin; 351 | map>> *sys_hierarchy_dtype_line; 352 | map>> *sys_hierarchy_dtype_begin; 353 | map> *delta_hierarchy; 354 | map> *cumulate_hierarchy; 355 | unordered_map *sys_dtype; 356 | vector *reboot_times; 357 | explicit SeqOptions( 358 | const string &it_src = "sys", 359 | const bool &it_api = false, 360 | const chrono::system_clock::time_point &it_time_point_begin = chrono::time_point{}, 361 | const chrono::system_clock::time_point &it_time_point_begin_hard = chrono::time_point{}, 362 | const chrono::system_clock::time_point &it_time_point_finish = chrono::system_clock::now(), 363 | const chrono::system_clock::time_point &it_time_point_begin_adjust = chrono::time_point{}, 364 | const chrono::system_clock::time_point &it_time_point_finish_adjust = chrono::time_point{}, 365 | const chrono::system_clock::time_point &it_time_point_begin_real = chrono::time_point{}, 366 | const chrono::system_clock::time_point &it_time_point_finish_real = chrono::time_point{}, 367 | const int &it_range = 0, 368 | const chrono::duration &it_duration_range = chrono::duration(60), 369 | const chrono::duration &it_duration_real = chrono::duration(0), 370 | const string &it_interval = "", 371 | const int &it_intervals = 60, 372 | const string &it_begin = "", 373 | const string &it_finish = "", 374 | const string &it_collect = "", 375 | const bool &it_live_mode = false, 376 | const string &it_key = "", 377 | const list> &it_keys = {{"start_time","+"}}, 378 | const int &it_lines = 0, 379 | const bool &it_noheaders = false, 380 | const bool &it_purify = false, 381 | const bool &it_version = false, 382 | const string &it_format = "", 383 | const string &it_extra = "", 384 | const list &it_formats = {}, 385 | const list &it_formated = {}, 386 | const bool &it_cpu = false, 387 | const bool &it_mem = false, 388 | const bool &it_job = false, 389 | const bool &it_sched = false, 390 | const bool &it_yes = false, 391 | const bool &it_zoom = false, 392 | const bool &it_loadr = false, 393 | const bool &it_loadd = false, 394 | const bool &it_psr = false, 395 | const bool &it_stackinfo = false, 396 | const bool &it_loadrd = false, 397 | const bool &it_stack = false, 398 | const bool &it_adjust = false, 399 | const string &it_uts_release = "", 400 | const int &it_pid = 0, 401 | const bool &it_ssar_conf = true, 402 | const bool &it_sys_conf = true, 403 | const bool &it_has_cmdline = false, 404 | const bool &it_proc_gzip_disable = false, 405 | const string &it_work_path = "/var/log", 406 | const string &it_ssar_path = "", 407 | const string &it_data_path = "", 408 | const map &it_views = {{}}, 409 | unordered_map *const &it_sys_files = NULL, 410 | unordered_map *const &it_file_position = NULL, 411 | map> *const &it_sys_view = NULL, 412 | map, greater> *const &it_group_files = NULL, 413 | map, greater> *const &it_sys_indicator = NULL, 414 | map>> *const &it_sys_hierarchy_line = NULL, 415 | map>> *const &it_sys_hierarchy_begin = NULL, 416 | map>> *const &it_sys_hierarchy_dtype_line = NULL, 417 | map>> *const &it_sys_hierarchy_dtype_begin = NULL, 418 | map> *const &it_delta_hierarchy = NULL, 419 | map> *const &it_cumulate_hierarchy = NULL, 420 | unordered_map *const &it_sys_dtype = NULL, 421 | vector *const &it_reboot_times = NULL 422 | ) : 423 | src(it_src), 424 | api(it_api), 425 | time_point_begin(it_time_point_begin), 426 | time_point_begin_hard(it_time_point_begin_hard), 427 | time_point_finish(it_time_point_finish), 428 | time_point_begin_adjust(it_time_point_begin_adjust), 429 | time_point_finish_adjust(it_time_point_finish_adjust), 430 | time_point_begin_real(it_time_point_begin_real), 431 | time_point_finish_real(it_time_point_finish_real), 432 | range(it_range), 433 | duration_range(it_duration_range), 434 | duration_real(it_duration_real), 435 | interval(it_interval), 436 | intervals(it_intervals), 437 | begin(it_begin), 438 | finish(it_finish), 439 | collect(it_collect), 440 | live_mode(it_live_mode), 441 | key(it_key), 442 | keys(it_keys), 443 | lines(it_lines), 444 | noheaders(it_noheaders), 445 | purify(it_purify), 446 | version(it_version), 447 | format(it_format), 448 | extra(it_extra), 449 | formats(it_formats), 450 | formated(it_formated), 451 | cpu(it_cpu), 452 | mem(it_mem), 453 | job(it_job), 454 | sched(it_sched), 455 | yes(it_yes), 456 | zoom(it_zoom), 457 | loadr(it_loadr), 458 | loadd(it_loadd), 459 | psr(it_psr), 460 | stackinfo(it_stackinfo), 461 | loadrd(it_loadrd), 462 | stack(it_stack), 463 | adjust(it_adjust), 464 | uts_release(it_uts_release), 465 | pid(it_pid), 466 | ssar_conf(it_ssar_conf), 467 | sys_conf(it_sys_conf), 468 | has_cmdline(it_has_cmdline), 469 | proc_gzip_disable(it_proc_gzip_disable), 470 | work_path(it_work_path), 471 | ssar_path(it_ssar_path), 472 | data_path(it_data_path), 473 | views(it_views), 474 | sys_files(it_sys_files), 475 | sys_view(it_sys_view), 476 | group_files(it_group_files), 477 | sys_indicator(it_sys_indicator), 478 | sys_hierarchy_line(it_sys_hierarchy_line), 479 | sys_hierarchy_begin(it_sys_hierarchy_begin), 480 | sys_hierarchy_dtype_line(it_sys_hierarchy_dtype_line), 481 | sys_hierarchy_dtype_begin(it_sys_hierarchy_dtype_begin), 482 | delta_hierarchy(it_delta_hierarchy), 483 | cumulate_hierarchy(it_cumulate_hierarchy), 484 | sys_dtype(it_sys_dtype), 485 | reboot_times(it_reboot_times) 486 | {} 487 | }; 488 | 489 | class SreProc{ 490 | private: 491 | set dirs; 492 | set files; 493 | string data_hour_path; 494 | string data_dir; 495 | string data_path; 496 | string data_datetime; 497 | int data_timestamp; 498 | string suffix = ""; // sresar + column_number 499 | string dir_format = "%Y%m%d%H"; // %Y%m%d 500 | string file_format_minute = "%Y%m%d%H%M"; 501 | string file_format_second = "%Y%m%d%H%M%S"; 502 | chrono::system_clock::time_point time_point; 503 | chrono::system_clock::time_point time_point_real; 504 | int adjust_unit = 60; 505 | bool adjust = false; 506 | bool adjusted = false; 507 | bool adjust_forward = false; 508 | 509 | private: 510 | int GetDirLists(string &path, set &dirs); 511 | int GetDataFile(); 512 | int GetDataDir(); 513 | int GetDataHourPath(chrono::system_clock::time_point &it_time_point); 514 | int _MakeDataHourPath(const chrono::system_clock::time_point &it_time_point); 515 | 516 | public: 517 | int MakeDataHours(string data_path); 518 | int MakeDataHourPath(const chrono::system_clock::time_point &it_time_point); 519 | string GetFirstHour(){ 520 | return *(this->dirs.cbegin()); 521 | }; 522 | string GetDataHourPath(){ 523 | return this->data_hour_path; 524 | }; 525 | int GetDataTimestamp(){ 526 | return this->data_timestamp; 527 | }; 528 | string GetDataDatetime(){ 529 | return this->data_datetime; 530 | }; 531 | chrono::system_clock::time_point GetDataTimePointReal(){ 532 | return this->time_point_real; 533 | }; 534 | void EnableAdjust(){ 535 | this->adjust = true; 536 | } 537 | void DisableAdjust(){ 538 | this->adjust = false; 539 | } 540 | bool GetAdjusted(){ 541 | return this->adjusted; 542 | } 543 | void SetDataPath(string data_path){ 544 | this->data_path = data_path; 545 | } 546 | void SetSuffix(string suffix){ 547 | this->suffix = suffix; 548 | } 549 | void SetAdjustUnit(int adjust_unit){ 550 | this->adjust_unit = adjust_unit; 551 | } 552 | void SetAdjustForward(bool adjust_forward){ 553 | this->adjust_forward = adjust_forward; 554 | } 555 | SreProc(){ 556 | }; 557 | }; 558 | 559 | class Load5s{ 560 | private: 561 | string data_hour_path; 562 | string data_path; 563 | string data_datetime; 564 | int data_timestamp; 565 | string suffix = ""; 566 | chrono::system_clock::time_point time_point_real; 567 | bool adjust = false; 568 | bool adjusted = false; 569 | 570 | private: 571 | 572 | public: 573 | int GetActiveCounts(int collect_time, active_t &act); 574 | void SetDataPath(string data_path){ 575 | this->data_path = data_path; 576 | } 577 | void SetSuffix(string suffix){ 578 | this->suffix = suffix; 579 | } 580 | Load5s(){ 581 | }; 582 | }; 583 | 584 | class DataException :public exception{ 585 | public: 586 | DataException(string c){ 587 | m_p = c; 588 | } 589 | virtual string what(){ 590 | return m_p; 591 | } 592 | private: 593 | string m_p; 594 | }; 595 | 596 | void MakeRangeIndicators(list &it_list_sproc_t,unordered_map &begin_sproc_t,list &it_sproc_t,int it_count); 597 | int ReadLoad5sFileData(SeqOptions &seq_option, chrono::system_clock::time_point &it_time_point, list &it_list_load5s_t); 598 | int ReadProcFileData(SeqOptions &seq_option, string &it_path, string &addon_path, list &it_sproc_t, int pid = -1); 599 | int ParserDatetime(string &fmt_datetime, chrono::system_clock::time_point &time_point, const string &format); 600 | string FmtDatetime(const chrono::system_clock::time_point &time_point, const string &format); 601 | string FmtTime(unsigned long long time); 602 | void RemoveDuplicateElement(list &input); 603 | void ActivityReporter(SeqOptions &seq_options); 604 | void InitOptions(SeqOptions &seq_options); 605 | void ReportProcs(SeqOptions &seq_options, list &it_sproc_t); 606 | void ReportProc(SeqOptions &seq_options, list &it_sproc_t); 607 | void DisplayProcJson(SeqOptions &seq_options, list &it_sproc_t); 608 | void DisplayProcShell(SeqOptions &seq_options, list &it_sproc_t); 609 | void InitChecks(SeqOptions &seq_options); 610 | int SprocCompare(const sproc_t &itema, const sproc_t &itemb, const pair &key); 611 | int ReadRebootTimes(vector &reboot_times); 612 | void DisplayLoad5sShell(SeqOptions &seq_option, list &it_load5s_t); 613 | void DisplayLoad5sJson(SeqOptions &seq_option, list &it_load5s_t); 614 | int ReadLoadrdFileData(SeqOptions &seq_option, list &it_list_load2p_t); 615 | int ReadStackFileData(SeqOptions &seq_option, list &it_list_load2p_t); 616 | void DisplayLoad2pShell(SeqOptions &seq_option, list it_formats, list &it_load2p_data); 617 | json DisplayLoad2pJson(SeqOptions &seq_option, list &it_formats, list &it_list_load2p_t); 618 | void DisplaySysShell(SeqOptions &seq_option, list> &it_combines); 619 | void DisplaySysJson(SeqOptions &seq_option, list> &it_combines); 620 | 621 | namespace ssar_cli { 622 | const string THROW_KEY_EMPTY = "key is empty "; 623 | const string THROW_COMPARE_KEY = "compare key is not set "; 624 | const string THROW_FINISH_DATETIME = "finish datetime is not correct "; 625 | const string THROW_BEGIN_DATETIME = "begin datetime is not correct "; 626 | const string THROW_BEGIN_COMPARE_FINISH = "begin datetime is not lower then finish datetime "; 627 | const string THROW_NO_KEY = " key not found "; 628 | const string THROW_FINISH_DATA_HOUR_PATH = "finish data path is not exist "; 629 | const string THROW_BEGIN_DATA_HOUR_PATH = "begin data path is not exist "; 630 | const string THROW_BEGIN_DATA_FILE = "begin data file is not exist "; 631 | const string THROW_FINISH_DATA_FILE = "finish data file is not exist "; 632 | 633 | const string DEFAULT_OPTIONS_HELP = R"help(Examples: 634 | ssar 635 | ssar -V 636 | ssar --mem 637 | ssar --cpu --mem 638 | ssar --api 639 | ssar -r 60 640 | ssar -i 1 641 | ssar -f 2020-09-29T18:34:00 642 | ssar -f 20210731155500 643 | ssar -f 202107311555 644 | ssar -f 2021073115 645 | ssar -f 20210731 646 | ssar -f -10 647 | ssar -f -5.5h 648 | ssar -f -1.8d 649 | ssar -b 2020-03-02T17:34:00 650 | ssar -H 651 | ssar -P 652 | ssar -o 'shmem,meminfo:2:2,snmp|8|11|d' 653 | ssar -O "dev|eth0:|2|d;snmp:8:11:d" --cpu 654 | ssar -o 'metric=d:cfile=snmp:line=8:column=13:alias=retranssegs' 655 | ssar -o 'metric=c|cfile=meminfo|line_begin=MemFree:|column=2|alias=free' 656 | ssar -o 'metric=c|cfile=loadavg|line=1|column=1|dtype=float|alias=load1' 657 | ssar -o 'metric=c|cfile=loadavg|line=1|column=4|dtype=string|alias=runq_plit' 658 | ssar -o 'metric=d|cfile=stat|line=2|column=2-11|alias=cpu0_{column};' 659 | ssar -o 'metric=d|cfile=stat|line=2-17|column=5|alias=idle_{line};' 660 | ssar -f +10 661 | ssar -f +10 -i 5s 662 | 663 | For more details see ssar(1). 664 | )help"; 665 | 666 | const string PROCS_OPTIONS_HELP = R"help(Examples: 667 | ssar procs 668 | ssar procs --cpu 669 | ssar procs --mem 670 | ssar procs --job 671 | ssar procs --sched 672 | ssar procs -r 60 673 | ssar procs -f 2020-03-02T18:34:00 674 | ssar procs -f -10 675 | ssar procs -f -5.5h 676 | ssar procs -f -1.2d 677 | ssar procs -b 2020-03-02T17:34:00 678 | ssar procs -k -ppid,pid,+start_datetime 679 | ssar procs -l 100 680 | ssar procs -H 681 | ssar procs -o ppid,pid,start_datetime 682 | ssar procs -O pgid 683 | ssar procs --api 684 | 685 | For more details see ssar(1). 686 | )help"; 687 | 688 | const string PROC_OPTIONS_HELP = R"help(Examples: 689 | ssar proc -p 1 690 | ssar proc -p 1 --cpu 691 | ssar proc -p 1 --mem 692 | ssar proc -p 1 -r 60 693 | ssar proc -p 1 -i 1 694 | ssar proc -p 1 -f 2020-03-02T18:34:00 695 | ssar proc -p 1 -f -10 696 | ssar proc -p 1 -f -5.5h 697 | ssar proc -p 1 -f -1.2d 698 | ssar proc -p 1 -b 2020-03-02T17:34:00 699 | ssar proc -p 1 -H 700 | ssar proc -p 1 -P 701 | ssar proc -p 1 -o ppid,pid,start_datetime 702 | ssar proc -p 1 -O pgid 703 | ssar proc -p 1 --api 704 | 705 | For more details see ssar(1). 706 | )help"; 707 | 708 | const string LOAD5S_OPTIONS_HELP = R"help(Examples: 709 | ssar load5s 710 | ssar load5s -r 60 711 | ssar load5s -f 2020-03-02T18:34:00 712 | ssar load5s -f -10 713 | ssar load5s -f -5.5h 714 | ssar load5s -f -1.2d 715 | ssar load5s -b 2020-03-02T17:34:00 716 | ssar load5s -H 717 | ssar load5s -y 718 | ssar load5s -z 719 | ssar load5s --api 720 | 721 | For more details see ssar(1). 722 | )help"; 723 | 724 | const string LOAD2P_OPTIONS_HELP = R"help(Examples: 725 | ssar load2p -c 2020-05-11T19:49:12 726 | ssar load2p -c 2020-05-11T19:49:12 -l 10 727 | ssar load2p -c 2020-05-11T19:49:12 -H 728 | ssar load2p -c 2020-05-11T19:49:12 --loadr 729 | ssar load2p -c 2020-05-11T19:49:12 --loadd 730 | ssar load2p -c 2020-05-11T19:49:12 --psr 731 | ssar load2p -c 2020-05-11T19:49:12 --stackinfo 732 | ssar load2p -c 2020-05-11T19:49:12 --loadrd 733 | ssar load2p -c 2020-05-11T19:49:12 --stack 734 | ssar load2p -c 2020-05-11T19:49:12 --loadd --stackinfo 735 | ssar load2p -c 2020-05-11T19:49:12 --api 736 | 737 | For more details see ssar(1). 738 | )help"; 739 | 740 | } 741 | 742 | #endif 743 | --------------------------------------------------------------------------------