├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── Makefile ├── README.md ├── README_cn.md ├── conf ├── tsar.8 ├── tsar.conf ├── tsar.cron └── tsar.logrotate ├── devel ├── Makefile.test ├── mod_test.c ├── mod_test.conf ├── tsar.h └── tsardevel ├── examples └── tsar-lua-nginx │ ├── Makefile │ ├── mod_lua_nginx.conf │ └── mod_lua_nginx.lua ├── include ├── common.h ├── config.h ├── debug.h ├── define.h ├── framework.h ├── output_db.h ├── output_file.h ├── output_nagios.h ├── output_print.h ├── output_tcp.h ├── public.h ├── tsar.h └── tsar_lua_util.h ├── info.md ├── luadevel ├── Makefile.test ├── mod_lua_test.conf ├── mod_lua_test.lua └── tsarluadevel ├── lualib ├── Makefile ├── lua-cjson-2.1.0.tar.gz └── luasocket-2.0.2.tar.gz ├── modules ├── Makefile ├── mod_apache.c ├── mod_cpu.c ├── mod_haproxy.c ├── mod_io.c ├── mod_load.c ├── mod_lvs.c ├── mod_mem.c ├── mod_ncpu.c ├── mod_nginx.c ├── mod_partition.c ├── mod_pcsw.c ├── mod_percpu.c ├── mod_pernic.c ├── mod_proc.c ├── mod_squid.c ├── mod_swap.c ├── mod_tcp.c ├── mod_tcpx.c ├── mod_traffic.c └── mod_udp.c ├── rpm ├── scm.xml ├── tsar-VER.txt ├── tsar-build.sh ├── tsar-devel.spec ├── tsar.spec └── tsar.spec.in ├── src ├── .gitignore ├── Makefile ├── common.c ├── config.c ├── debug.c ├── deps │ └── LuaJIT-2.0.4.tar.gz ├── framework.c ├── output_db.c ├── output_file.c ├── output_nagios.c ├── output_print.c ├── output_tcp.c ├── tsar.c └── tsar_lua_util.c └── tools ├── bytes.sh ├── cpu.sh ├── load.sh ├── mem.sh ├── packets.sh ├── readme.txt └── retran.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | *.so.* 4 | tags 5 | src/tsar 6 | *.DS_Store 7 | *.dSYM 8 | cscope.out 9 | ttsar.sh 10 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | #This file contains a list of people who've made non-trivial 2 | # contribution to the Tsar project. People who commit code 3 | # to the project are encouraged to add their names here. 4 | # Please keep the list sorted by first names. 5 | 6 | kongjian 7 | kuotai 8 | yonghao 9 | zituan 10 | huiyan.jhf 11 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2017-12-12 2 | * 支持Lua语言开发模块 3 | 2015-12-14 4 | * 增加了tsar -w 功能 5 | 2015-07-27 6 | * output_tcp 增加了多目的发送功能,目前最多支持4个地址,以空格隔开 7 | 2013-03-06 8 | * tsar的模块支持参数配置 9 | 2013-01-23 10 | * tsar支持--spec功能,可以指定特定字段来显示 11 | 2013-01-16 12 | * merge inner and opensource tsar version 13 | 2011-05-18 14 | * tsar opensourced 15 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Simple install procedure 2 | ======================== 3 | 4 | % gzip -cd tsar-2.1.0.tar.gz | tar xvf - # unpack the sources 5 | % cd tsar-2.1.0 # change to the toplevel directory 6 | % make # build tsar 7 | 8 | [ Become root if necessary ] 9 | % make install # install tsar 10 | % make uninstall # uninstall tsar 11 | [ if you want install tsardevel ] 12 | % make tsardevel 13 | % make uninstall 14 | 15 | RPM install 16 | ======================== 17 | 18 | %gzip -cd tsar-2.1.0.tar.gz | tar xvf - # unpack the sources 19 | %cd tsar-2.1.0/rpm # change to the rpm directory 20 | %sh tsar-build.sh .. tsar 2.1.0 1 # create rpm for tsar 21 | %rpm -ivh *.rpm # install tsar by rpm 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DIRS = src modules lualib 2 | 3 | all: 4 | for i in $(DIRS); do make -C $$i; done 5 | 6 | clean: 7 | for i in $(DIRS); do cd $$i;make clean;cd ..; done 8 | 9 | install: all 10 | #mkdir for tsar 11 | mkdir -p /usr/local/tsar/modules 12 | mkdir -p /etc/tsar 13 | mkdir -p /usr/local/man/man8/ 14 | #copy tsar shared so 15 | cp modules/*.so /usr/local/tsar/modules 16 | #copy bin file 17 | cp src/tsar /usr/bin/tsar 18 | #copy config file 19 | cp conf/tsar.conf /etc/tsar/tsar.conf 20 | cp conf/tsar.logrotate /etc/logrotate.d/tsar 21 | cp conf/tsar.cron /etc/cron.d/tsar 22 | #copy man file 23 | cp conf/tsar.8 /usr/local/man/man8/ 24 | #install lualib 25 | make -C lualib install 26 | 27 | uninstall: 28 | #rm tsar 29 | rm -rf /usr/local/tsar 30 | rm -rf /etc/tsar/cron.d 31 | rm -f /etc/logrotate.d/tsar 32 | rm -f /etc/cron.d/tsar 33 | rm -f /usr/local/man/man8/tsar.8 34 | #rm tsar 35 | rm -f /usr/bin/tsar 36 | #rm tsardevel 37 | rm -f /usr/bin/tsardevel 38 | #rm tsarluadevel 39 | rm -f /usr/bin/tsarluadevel 40 | #backup configure file 41 | if [ -f /etc/tsar/tsar.conf ]; then mv /etc/tsar/tsar.conf /etc/tsar/tsar.conf.rpmsave; fi 42 | #backup the log data file 43 | if [ -f /var/log/tsar.data ]; then mv /var/log/tsar.data /var/log/tsar.data.bak; fi 44 | 45 | tsardevel: 46 | mkdir -p $(DESTDIR)/usr/local/tsar/devel 47 | cp devel/mod_test.c $(DESTDIR)/usr/local/tsar/devel/mod_test.c 48 | cp devel/mod_test.conf $(DESTDIR)/usr/local/tsar/devel/mod_test.conf 49 | cp devel/tsar.h $(DESTDIR)/usr/local/tsar/devel/tsar.h 50 | cp devel/Makefile.test $(DESTDIR)/usr/local/tsar/devel/Makefile.test 51 | cp devel/tsardevel $(DESTDIR)/usr/bin/tsardevel 52 | 53 | tsarluadevel: 54 | mkdir -p $(DESTDIR)/usr/local/tsar/luadevel 55 | cp luadevel/mod_lua_test.lua $(DESTDIR)/usr/local/tsar/luadevel/mod_lua_test.lua 56 | cp luadevel/mod_lua_test.conf $(DESTDIR)/usr/local/tsar/luadevel/mod_lua_test.conf 57 | cp luadevel/Makefile.test $(DESTDIR)/usr/local/tsar/luadevel/Makefile.test 58 | cp luadevel/tsarluadevel $(DESTDIR)/usr/bin/tsarluadevel 59 | 60 | tags: 61 | ctags -R 62 | cscope -Rbq 63 | 64 | .PHONY: all clean install unintall tsardevel tsarluadevel tags 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ------------ 3 | Tsar (Taobao System Activity Reporter) is a monitoring tool, which can be used to gather and summarize system information, e.g. CPU, load, IO, and application information, e.g. nginx, HAProxy, Squid, etc. The results can be stored at local disk or sent to Nagios. 4 | 5 | Tsar can be easily extended by writing modules, which makes it a powerful and versatile reporting tool. 6 | 7 | Module introduction: [info](https://github.com/alibaba/tsar/blob/master/info.md) 8 | 9 | Installation 10 | ------------- 11 | Tsar is available on GitHub, you can clone and install it as follows: 12 | 13 | $ git clone https://github.com/alibaba/tsar.git 14 | $ cd tsar 15 | $ make 16 | # make install 17 | 18 | Or you can download the zip file and install it: 19 | 20 | $ wget -O tsar.zip https://github.com/alibaba/tsar/archive/master.zip --no-check-certificate 21 | $ unzip tsar.zip 22 | $ cd tsar 23 | $ make 24 | # make install 25 | 26 | After installation, you may see these files: 27 | 28 | * `/etc/tsar/tsar.conf`, which is tsar's main configuration file; 29 | * `/etc/cron.d/tsar`, is used to run tsar to collect information every minute; 30 | * `/etc/logrotate.d/tsar` will rotate tsar's log files every month; 31 | * `/usr/local/tsar/modules` is the directory where all module libraries (*.so) are located; 32 | 33 | Configuration 34 | ------------- 35 | There is no output displayed after installation by default. Just run `tsar -l` to see if the real-time monitoring works, for instance: 36 | 37 | [kongjian@tsar]$ tsar -l -i 1 38 | Time ---cpu-- ---mem-- ---tcp-- -----traffic---- --xvda-- -xvda1-- -xvda2-- -xvda3-- -xvda4-- -xvda5-- ---load- 39 | Time util util retran pktin pktout util util util util util util load1 40 | 11/04/13-14:09:10 0.20 11.57 0.00 9.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 41 | 11/04/13-14:09:11 0.20 11.57 0.00 4.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 42 | 43 | Usually, we configure Tsar by simply editing `/etc/tsar/tsar.conf`: 44 | 45 | * To add a module, add a line like `mod_ on` 46 | * To enable or disable a module, use `mod_ on/off` 47 | * To specify parameters for a module, use `mod_ on parameter` 48 | * `output_stdio_mod` is to set modules output to standard I/O 49 | * `output_file_path` is to set history data file, (you should modify the logrotate script `/etc/logrotate.d/tsar` too) 50 | * `output_interface` specifies tsar data output destination, which by default is a local file. See the Advanced section for more information. 51 | 52 | Usage 53 | ------ 54 | * null :see default mods history data, `tsar` 55 | * --modname :specify module to show, `tsar --cpu` 56 | * -L/--list :list available module, `tsar -L` 57 | * -l/--live :show real-time info, `tsar -l --cpu` 58 | * -i/--interval :set interval for report, `tsar -i 1 --cpu` 59 | * -s/--spec :specify module detail field, `tsar --cpu -s sys,util` 60 | * -D/--detail :do not conver data to K/M/G, `tsar --mem -D` 61 | * -m/--merge :merge multiply item to one, `tsar --io -m` 62 | * -I/--item :show spec item data, `tsar --io -I sda` 63 | * -d/--date :specify data, YYYYMMDD, or n means n days ago 64 | * -C/--check :show the last collect data 65 | * -h/--help :show help, `tsar -h` 66 | 67 | Advanced 68 | -------- 69 | * Output to Nagios 70 | 71 | To turn it on, just set output type `output_interface file,nagios` in the main configuration file. 72 | 73 | You should also specify Nagios' IP address, port, and sending interval, e.g.: 74 | 75 | ####The IP address or the hostname running the NSCA daemon 76 | server_addr nagios.server.com 77 | ####The port on which the daemon is listening - by default it is 5667 78 | server_port 8086 79 | ####The cycle (interval) of sending alerts to Nagios 80 | cycle_time 300 81 | 82 | As tsar uses Nagios' passive mode, so you should specify the nsca binary and its configuration file, e.g.: 83 | 84 | ####nsca client program 85 | send_nsca_cmd /usr/bin/send_nsca 86 | send_nsca_conf /home/a/conf/amon/send_nsca.conf 87 | 88 | Then specify the module and fields to be checked. There are 4 threshold levels. 89 | 90 | ####tsar mod alert config file 91 | ####threshold servicename.key;w-min;w-max;c-min;cmax; 92 | threshold cpu.util;50;60;70;80; 93 | 94 | * Output to MySQL 95 | 96 | To use this feature, just add output type `output_interface file,db` in tsar's configuration file. 97 | 98 | Then specify which module(s) will be enabled: 99 | 100 | output_db_mod mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udpmod_io 101 | 102 | Note that you should set the IP address (or hostname) and port where tsar2db listens, e.g.: 103 | 104 | output_db_addr console2:56677 105 | 106 | Tsar2db receives sql data and flush it to MySQL. You can find more information about tsar2db at https://github.com/alibaba/tsar2db. 107 | 108 | 109 | Module development 110 | ------------------ 111 | Tsar is easily extended. Whenever you want information that is not collected by tsar yet, you can write a module with `C` or `Lua`. 112 | 113 | C Module 114 | -------- 115 | First, install the tsardevel tool (`make tsardevel` will do this for you): 116 | 117 | Then run `tsardevel `, and you will get a directory named yourmodname, e.g.: 118 | 119 | ````bash 120 | [kongjian@tsar]$ tsardevel test 121 | build:make 122 | install:make install 123 | uninstall:make uninstall 124 | 125 | [kongjian@tsar]$ ls test 126 | Makefile mod_test.c mod_test.conf 127 | ```` 128 | 129 | You can modify the read_test_stats() and set_test_record() functions in mod_test.c as you need. 130 | Then run `make;make install` to install your module and run `tsar --yourmodname` to see the output. 131 | 132 | Lua Module 133 | ---------- 134 | First, install the tsarluadevel tool (`make tsarluadevel` will do this for you): 135 | 136 | Then run `tsarluadevel `, and you will get a directory named yourmodname, e.g.: 137 | 138 | ````bash 139 | [kongjian@tsar]$ tsarluadevel test 140 | install:make install 141 | uninstall:make uninstall 142 | test:tsar --list or tsar --lua_test --live -i 1 143 | 144 | [kongjian@tsar]$ ls test 145 | Makefile mod_lua_test.conf mod_lua_test.lua 146 | ```` 147 | 148 | You can modify the register()、read() and set() functions in mod_lua_test.lua as you need. 149 | Then run `make install` to install your module and run `tsar --lua_yourmodname` to see the output. 150 | 151 | More 152 | ---- 153 | Homepage http://tsar.taobao.org 154 | 155 | Any question, please feel free to contact me by kongjian@taobao.com 156 | -------------------------------------------------------------------------------- /README_cn.md: -------------------------------------------------------------------------------- 1 | Tsar介绍 2 | ------------ 3 | Tsar是淘宝的一个用来收集服务器系统和应用信息的采集报告工具,如收集服务器的系统信息(cpu,mem等),以及应用数据(nginx、swift等),收集到的数据存储在服务器磁盘上,可以随时查询历史信息,也可以将数据发送到nagios报警。 4 | 5 | Tsar能够比较方便的增加模块,只需要按照tsar的要求编写数据的采集函数和展现函数,就可以把自定义的模块加入到tsar中。 6 | 7 | 安装 8 | ------------- 9 | Tsar目前托管在github上,下载编译安装步骤: 10 | 11 | $git clone git://github.com/kongjian/tsar.git 12 | $cd tsar 13 | $make 14 | $make install 15 | 16 | 安装后: 17 | 18 | 定时任务配置:`/etc/cron.d/tsar`,负责每分钟调用tsar执行采集任务; 19 | 20 | 日志文件轮转配置:`/etc/logrotate.d/tsar`,每个月会把tsar的本地存储进行轮转; 21 | 22 | Tsar配置文件路径:`/etc/tsar/tsar.conf`,tsar的采集模块和输出的具体配置; 23 | 24 | 模块路径:`/usr/local/tsar/modules`,各个模块的动态库so文件; 25 | 26 | Tsar配置 27 | ------------- 28 | Tsar刚安装完,还没有历史数据,想要check是否正常,执行tsar -l,查看是否有实时信息输出: 29 | 30 | [kongjian@v132172.sqa.cm4 tsar]$ tsar -l -i 1 31 | Time ---cpu-- ---mem-- ---tcp-- -----traffic---- --xvda-- -xvda1-- -xvda2-- -xvda3-- -xvda4-- -xvda5-- ---load- 32 | Time util util retran pktin pktout util util util util util util load1 33 | 11/04/13-14:09:10 0.20 11.57 0.00 9.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 34 | 11/04/13-14:09:11 0.20 11.57 0.00 4.00 2.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 35 | 36 | Tsar的配置主要都在`/etc/tsar/tsar.conf`中,常用的有: 37 | * 增加一个模块,添加 `mod_ on` 到配置文件中 38 | * 打开或者关闭一个模块,修改`mod_ on/off` 39 | * `output_stdio_mod` 能够配置执行tsar时的输出模块 40 | * `output_file_path` 采集到的数据默认保存到的文件(如果修改的话需要对应修改轮转的配置`/etc/logrotate.d/tsar`) 41 | * `output_interface` 指定tsar的数据输出目的,默认file保存本地,nagios/db输出到监控中心/数据库中,这两个功能还需要结合其它配置,具体见后面 42 | 43 | Tsar使用 44 | ------------- 45 | * 查看历史数据,tsar 46 | * -l/--list 查看可用的模块列表 47 | * -l/--live 查看实时数据,tsar -l --cpu 48 | * -i/--interval 指定间隔,历史,tsar -i 1 --cpu 49 | * --modname 指定模块,tsar --cpu 50 | * -s/--spec 指定字段,tsar --cpu -s sys,util 51 | * -d/--date 指定日期,YYYYMMDD或者n代表n天前 52 | * -C/--check 查看最后一次的采集数据 53 | * -d/--detail 能够指定查看主要字段还是模块的所有字段 54 | * -h/--help 帮助功能 55 | 56 | 高级功能 57 | ------------- 58 | * 输出到nagios 59 | 60 | 配置: 61 | 首先配置`output_interface file,nagios`,增加nagios输出 62 | 63 | 然后配置nagios服务器和端口,以及发送的间隔时间 64 | 65 | ####The IP address or the host running the NSCA daemon 66 | server_addr nagios.server.com 67 | ####The port on which the daemon is running - default is 5667 68 | server_port 8086 69 | ####The cycle of send alert to nagios 70 | cycle_time 300 71 | 72 | 由于是nagios的被动监控模式,需要制定nsca的位置和配置文件位置 73 | 74 | ####nsca client program 75 | send_nsca_cmd /usr/bin/send_nsca 76 | send_nsca_conf /home/a/conf/amon/send_nsca.conf 77 | 78 | 接下来制定哪些模块和字段需要进行监控,一共四个阀值对应nagios中的不同报警级别 79 | 80 | ####tsar mod alert config file 81 | ####threshold servicename.key;w-min;w-max;c-min;cmax; 82 | threshold cpu.util;50;60;70;80; 83 | 84 | * 输出到mysql 85 | 86 | 配置: 87 | 首先配置`output_interface file,db`,增加db输出 88 | 89 | 然后配置哪些模块数据需要输出 90 | 91 | output_db_mod mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udpmod_io 92 | 93 | 然后配置sql语句发送的目的地址和端口 94 | 95 | output_db_addr console2:56677 96 | 97 | 目的地址在该端口监听tcp数据,并且把数据入库即可,可以参照tsar2db:https://github.com/kongjian/tsar2db 98 | 99 | 模块开发 100 | ------------- 101 | Tsar的一个比较好的功能是能够增加自己的采集,这时候需要编写模块代码,编译成so文件即可。 102 | 103 | C模块 104 | ----- 105 | 首先安装tsardevel,刚才安装时,如果执行`make tsardevel`,就会把模块开发的基本文件安装到系统 106 | 然后执行tsardevel ,就能在当前模块生成一个模块目录: 107 | 108 | ````bash 109 | [kongjian@v132172.sqa.cm4 tsar]$ tsardevel test 110 | build:make 111 | install:make install 112 | uninstall:make uninstall 113 | 114 | [kongjian@v132172.sqa.cm4 tsar]$ ls test 115 | Makefile mod_test.c mod_test.conf 116 | ```` 117 | 118 | 按照要求修改mod_test.c中的read_test_stats,set_test_record 119 | 完成后`make;make install`就完成新模块的配置文件和so的设置,执行`tsar --yourmodname`就能查看效果 120 | 121 | 另外也可以通过配置文件对自定义模块传递参数,方法是 122 | 修改配置文件中的`mod_test on myparameter` 123 | 然后在mod_test.c中的read_test_stats函数中,通过parameter参数就可以获得刚才配置文件中的内容 124 | 125 | Lua模块 126 | ------- 127 | 首先安装tsarluadevel,刚才安装时,如果执行`make tsarluadevel`,就会把Lua模块开发的基本文件安装到系统 128 | 然后执行tsarluadevel ,就能在当前模块生成一个模块目录: 129 | 130 | ````bash 131 | [kongjian@v132172.sqa.cm4 tsar]$ tsarluadevel test 132 | install:make install 133 | uninstall:make uninstall 134 | test:tsar --list or tsar --lua_test --live -i 1 135 | 136 | [kongjian@v132172.sqa.cm4 tsar]$ ls test 137 | Makefile mod_lua_test.conf mod_lua_test.lua 138 | ```` 139 | 140 | 按照要求修改mod_lua_test.lua中的register(),read()和set()函数 141 | 完成后`make install`就完成新模块的安装,执行`tsar --lua_yourmodname`就能查看效果 142 | 143 | 其它 144 | ------------- 145 | Taocode地址:http://code.taobao.org/p/tsar/ 146 | 有其它问题请联系:kongjian@taobao.com 147 | -------------------------------------------------------------------------------- /conf/tsar.8: -------------------------------------------------------------------------------- 1 | .TH tsar - 2 | .SH NAME 3 | tsar \- Taobao System Activity Reporter 4 | .SH SYNOPSIS 5 | .B tsar 6 | [options] --tsar main function 7 | .PP 8 | tsardevel 9 | [modname] --develop new mod 10 | .SH DESCRIPTION 11 | .PP 12 | \fBtsar\fB is a monitor tool for collect system activity status and apps. 13 | .PP 14 | tsar reads and logs messages to the log files,It support different output target 15 | such as local console or remote db/nagios host.It have a plugin system 16 | that is easy for collect plugin development. 17 | .PP 18 | 19 | .SH OPTIONS 20 | .TP 21 | .B \-check , \-check 22 | display last record for alert,it is just used for taobao inner alert 23 | .TP 24 | .B \-C , \-\-check 25 | display last record for alert.example:tsar --check / tsar --check --cpu --io 26 | .TP 27 | .B \-c , \-\-cron 28 | run in cron mode, output data to file,default is /var/log/tsar.data 29 | .TP 30 | .B \-l ,\-\-live 31 | running print live mode which module will print 32 | .TP 33 | .B \-i , \-\-interval 34 | specify intervals numbers, if not with --live,it is in minutes;if with --live, it is in seconds 35 | .TP 36 | .B \-m , \-\-merge 37 | merge multiply item to one 38 | .TP 39 | .B \-L , \-\-list 40 | list enabled modules 41 | .TP 42 | .B \-n , \-\-ndays 43 | show the value for the past days (default: 1) 44 | .TP 45 | .B \-d , \-\-date 46 | special one day to display,support formate YYYYMMDD or int for somedays ago 47 | .TP 48 | .B \-f , \-\-file 49 | special tsar.data for tsar to read 50 | .TP 51 | .B \-n , \-\-ndays 52 | show the value for the past days (default: 1) 53 | .TP 54 | .B \-D , \-\-detail 55 | do not conver data to K/M/G 56 | .TP 57 | .B \-s , \-\-spec 58 | show spec field data, tsar --cpu -s sys,util 59 | .TP 60 | .B \-h , \-\-help 61 | print help info 62 | .TP 63 | .SH DIAGNOSTICS 64 | It is expected that \fBtsar\fP will run as root 65 | .SH FILES 66 | .TP 67 | .I /etc/tsar/tsar.conf 68 | Configuration file for tsar.output mod list for differnt type 69 | .TP 70 | .I /etc/tsar/cron.d/*.conf 71 | extrat config file, usually tsar devel modules config 72 | .SH BUGS 73 | .PP 74 | If you find any, please send email to the kongjian@taobao.com 75 | -------------------------------------------------------------------------------- /conf/tsar.conf: -------------------------------------------------------------------------------- 1 | ####debug_level(INFO DEBUG WARN ERROR FATAL) 2 | debug_level ERROR 3 | ####[module] 4 | mod_cpu on 5 | mod_mem on 6 | mod_swap on 7 | mod_tcp on 8 | mod_udp on 9 | mod_traffic on 10 | mod_io on 11 | mod_pcsw on 12 | mod_partition on 13 | mod_tcpx on 14 | mod_load on 15 | mod_apache off 16 | mod_lvs off 17 | mod_haproxy off 18 | mod_squid off 19 | mod_nginx off 20 | mod_percpu off 21 | mod_proc off pidname 22 | 23 | #lua package path 24 | lua_package_path /usr/local/tsar/lualib/?.lua 25 | lua_package_cpath /usr/local/tsar/lualib/?.so 26 | 27 | ####output_interface file,db,nagios 28 | output_interface file 29 | 30 | ####[output_file] original data to store 31 | output_file_path /var/log/tsar.data 32 | 33 | ####[output_stdio] these mod will be show as using tsar command 34 | output_stdio_mod mod_swap,mod_partition,mod_cpu,mod_mem,mod_lvs,mod_haproxy,mod_traffic,mod_squid,mod_load,mod_tcp,mod_udp,mod_tcpx,mod_apache,mod_pcsw,mod_io,mod_percpu 35 | 36 | ####[output_db] 37 | #output_db_mod mod_swap,mod_partition,mod_cpu,mod_mem,mod_traffic,mod_load,mod_tcp,mod_udp,mod_pcsw,mod_io 38 | #output_db_addr console2:56677 39 | 40 | ####[output_tcp] 41 | #output_tcp_mod mod_swap,mod_cpu 42 | #output_tcp_addr localhost:9666 43 | #output_tcp_merge on 44 | 45 | ####support include other mod conf 46 | include /etc/tsar/conf.d/*.conf 47 | 48 | ####The IP address or the host running the NSCA daemon 49 | #server_addr nagios.server.com 50 | ####The port on which the daemon is running - default is 5667 51 | #server_port 8086 52 | ####The cycle of send alert to nagios 53 | #cycle_time 300 54 | ####nsca client program 55 | #send_nsca_cmd /usr/bin/send_nsca 56 | #send_nsca_conf /home/a/conf/amon/send_nsca.conf 57 | 58 | ####tsar mod alert config file 59 | ####threshold servicename.key;w-min;w-max;c-min;cmax; 60 | #threshold cpu.util;N;N;N;N; 61 | -------------------------------------------------------------------------------- /conf/tsar.cron: -------------------------------------------------------------------------------- 1 | # cron tsar collect once per minute 2 | MAILTO="" 3 | * * * * * root /usr/bin/tsar --cron > /dev/null 2>&1 4 | -------------------------------------------------------------------------------- /conf/tsar.logrotate: -------------------------------------------------------------------------------- 1 | /var/log/tsar.data 2 | { 3 | monthly 4 | rotate 120 5 | create 6 | nocompress 7 | nodateext 8 | notifempty 9 | prerotate 10 | /usr/bin/chattr -a /var/log/tsar.data 11 | endscript 12 | postrotate 13 | /usr/bin/chattr +a /var/log/tsar.data 14 | endscript 15 | } 16 | -------------------------------------------------------------------------------- /devel/Makefile.test: -------------------------------------------------------------------------------- 1 | CFLAGS = -Wall -fPIC --shared -g -O2 2 | CC = gcc 3 | INCLUDE_DIR = /usr/local/tsar/devel 4 | LINK = $(CC) -I$(INCLUDE_DIR) $(CFLAGS) 5 | 6 | 7 | OBJS = mod_test.so 8 | 9 | all: $(OBJS) 10 | 11 | $(OBJS): %.so: %.c 12 | $(LINK) $< -o $@ 13 | clean: 14 | rm -f *.so; 15 | install: 16 | mkdir -p /etc/tsar/conf.d/ 17 | cp ./mod_test.so /usr/local/tsar/modules/ 18 | cp ./mod_test.conf /etc/tsar/conf.d/test.conf 19 | uninstall: 20 | rm /usr/local/tsar/modules/mod_test.so 21 | rm /etc/tsar/conf.d/test.conf 22 | -------------------------------------------------------------------------------- /devel/mod_test.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include "tsar.h" 21 | 22 | #define STATS_TEST_SIZE (sizeof(struct stats_test)) 23 | 24 | static const char *test_usage = " --test test information"; 25 | 26 | /* 27 | * temp structure for collection infomation. 28 | */ 29 | struct stats_test { 30 | unsigned long long value_1; 31 | unsigned long long value_2; 32 | unsigned long long value_3; 33 | }; 34 | 35 | /* Structure for tsar */ 36 | static struct mod_info test_info[] = { 37 | {"value1", SUMMARY_BIT, 0, STATS_NULL}, 38 | {"value2", DETAIL_BIT, 0, STATS_NULL}, 39 | {"value3", DETAIL_BIT, 0, STATS_NULL} 40 | }; 41 | 42 | static void 43 | read_test_stats(struct module *mod, const char *parameter) 44 | { 45 | /* parameter actually equals to mod->parameter */ 46 | char buf[256]; 47 | struct stats_test st_test; 48 | 49 | memset(buf, 0, sizeof(buf)); 50 | memset(&st_test, 0, sizeof(struct stats_test)); 51 | 52 | st_test.value_1 = 1; 53 | st_test.value_2 = 1; 54 | st_test.value_3 = 1; 55 | 56 | int pos = sprintf(buf, "%llu,%llu,%llu", 57 | /* the store order is not same as read procedure */ 58 | st_test.value_1, 59 | st_test.value_2, 60 | st_test.value_3); 61 | 62 | buf[pos] = '\0'; 63 | /* send data to tsar you can get it by pre_array&cur_array at set_test_record */ 64 | set_mod_record(mod, buf); 65 | return; 66 | } 67 | 68 | static void 69 | set_test_record(struct module *mod, double st_array[], 70 | U_64 pre_array[], U_64 cur_array[], int inter) 71 | { 72 | int i; 73 | /* set st record */ 74 | for (i = 0; i < mod->n_col; i++) { 75 | st_array[i] = cur_array[i]; 76 | } 77 | } 78 | 79 | /* register mod to tsar */ 80 | void 81 | mod_register(struct module *mod) 82 | { 83 | register_mod_fields(mod, "--test", test_usage, test_info, 3, read_test_stats, set_test_record); 84 | } 85 | -------------------------------------------------------------------------------- /devel/mod_test.conf: -------------------------------------------------------------------------------- 1 | mod_test on 2 | 3 | ####add it to tsar default output 4 | output_stdio_mod mod_test 5 | 6 | ####add it to center db 7 | #output_db_mod mod_test 8 | 9 | ####add it to nagios send 10 | ####set nagios threshold for alert 11 | #output_nagios_mod mod_test 12 | 13 | #threshold test.value1;N;N;N;N; 14 | #threshold test.value2;N;N;N;N; 15 | #threshold test.value3;N;N;N;N; 16 | -------------------------------------------------------------------------------- /devel/tsar.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef _TSARMOD_H 21 | #define _TSARMOD_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | 38 | #define U_64 unsigned long long 39 | 40 | #define LEN_32 32 41 | #define LEN_64 64 42 | #define LEN_128 128 43 | #define LEN_256 256 44 | #define LEN_512 512 45 | #define LEN_1024 1024 46 | #define LEN_4096 4096 47 | #define LEN_1M 1048576 48 | 49 | #define ITEM_SPLIT ";" 50 | #define DATA_SPLIT "," 51 | 52 | 53 | struct mod_info { 54 | char hdr[LEN_128]; 55 | int summary_bit; /* bit set indefi summary */ 56 | int merge_mode; 57 | int stats_opt; 58 | }; 59 | 60 | struct module { 61 | 62 | char name[LEN_32]; 63 | char opt_line[LEN_32]; 64 | char record[LEN_1M]; 65 | char usage[LEN_256]; 66 | char parameter[LEN_256]; 67 | char print_item[LEN_256]; 68 | 69 | struct mod_info *info; 70 | void *lib; 71 | int enable; 72 | int spec; 73 | int p_item; 74 | 75 | /* private data used by framework*/ 76 | int n_item; 77 | int n_col; 78 | long n_record; 79 | 80 | int pre_flag:4; 81 | int st_flag:4; 82 | 83 | U_64 *pre_array; 84 | U_64 *cur_array; 85 | double *st_array; 86 | double *max_array; 87 | double *mean_array; 88 | double *min_array; 89 | 90 | /* callback function of module */ 91 | void (*data_collect) (struct module *, char *); 92 | void (*set_st_record) (struct module *, double *, U_64 *, U_64 *, int); 93 | 94 | /* mod manage */ 95 | void (*mod_register) (struct module *); 96 | }; 97 | 98 | void register_mod_fields(struct module *mod, const char *opt, const char *usage, 99 | struct mod_info *info, int n_col, void *data_collect, void *set_st_record); 100 | void set_mod_record(struct module *mod, const char *record); 101 | 102 | enum { 103 | HIDE_BIT, 104 | DETAIL_BIT, 105 | SUMMARY_BIT, 106 | SPEC_BIT 107 | }; 108 | 109 | enum { 110 | MERGE_NULL, 111 | MERGE_SUM, 112 | MERGE_AVG 113 | }; 114 | 115 | enum { 116 | STATS_NULL, 117 | STATS_SUB, 118 | STATS_SUB_INTER 119 | }; 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /devel/tsardevel: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # check argc 4 | usage() 5 | { 6 | echo "Usage:" 7 | echo "tsardevel modname" 8 | exit 0 9 | } 10 | install() 11 | { 12 | echo "build:make" 13 | echo "install:make install" 14 | echo "uninstall:make uninstall" 15 | echo "test:tsar --list or tsar --$modname --live -i 1" 16 | } 17 | if [ $# -ne 1 ] 18 | then 19 | usage 20 | fi 21 | 22 | modname=$1 23 | install_path='/usr/local/tsar/devel' 24 | 25 | for file in mod_test.c mod_test.conf Makefile.test 26 | do 27 | if [ ! -e "$install_path/$file" ] ;then 28 | echo "$install_path/$file not exist!" 29 | echo "make sure you have run 'make tsardevel' when install tsar." 30 | exit 1 31 | fi 32 | done 33 | 34 | 35 | # mk new mod_test 36 | mkdir -p $modname 37 | sed -e "s/test/$modname/g" < $install_path/mod_test.c > ./$modname/mod_$modname.c 38 | sed -e "s/test/$modname/g" < $install_path/mod_test.conf > ./$modname/mod_$modname.conf 39 | sed -e "s/test/$modname/g" < $install_path/Makefile.test > ./$modname/Makefile 40 | if [ $? -eq 0 ] 41 | then 42 | install 43 | fi 44 | -------------------------------------------------------------------------------- /examples/tsar-lua-nginx/Makefile: -------------------------------------------------------------------------------- 1 | install: 2 | mkdir -p /etc/tsar/conf.d/ 3 | cp ./mod_lua_nginx.lua /usr/local/tsar/modules/ 4 | cp ./mod_lua_nginx.conf /etc/tsar/conf.d/lua_nginx.conf 5 | 6 | uninstall: 7 | rm /usr/local/tsar/modules/mod_lua_nginx.lua 8 | rm /etc/tsar/conf.d/lua_nginx.conf 9 | -------------------------------------------------------------------------------- /examples/tsar-lua-nginx/mod_lua_nginx.conf: -------------------------------------------------------------------------------- 1 | mod_lua_nginx on 2 | 3 | ####add it to tsar default output 4 | output_stdio_mod mod_lua_nginx 5 | 6 | ####add it to center db 7 | #output_db_mod mod_lua_nginx 8 | 9 | ####add it to nagios send 10 | ####set nagios threshold for alert 11 | #output_nagios_mod mod_lua_nginx 12 | 13 | #threshold lua_nginx.value1;N;N;N;N; 14 | #threshold lua_nginx.value2;N;N;N;N; 15 | #threshold lua_nginx.value3;N;N;N;N; 16 | -------------------------------------------------------------------------------- /examples/tsar-lua-nginx/mod_lua_nginx.lua: -------------------------------------------------------------------------------- 1 | local _M = { 2 | _VERSION = "0.1.0" 3 | } 4 | 5 | local cjson = require("cjson") 6 | local socket = require("socket") 7 | local http = require("socket.http") 8 | local ltn12 = require("ltn12") 9 | local DETAIL_BIT = tsar.DETAIL_BIT 10 | local SUMMARY_BIT = tsar.SUMMARY_BIT 11 | local HIDE_BIT = tsar.HIDE_BIT 12 | local STATS_NULL = tsar.STATS_NULL 13 | local STATS_SUB = tsar.STATS_SUB 14 | local STATS_SUB_INTER = tsar.STATS_SUB_INTER 15 | local string_format = string.format 16 | local string_match = string.match 17 | local string_find = string.find 18 | local concat = table.concat 19 | 20 | local info = { 21 | {hdr = "accept", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_SUB}, 22 | {hdr = "handle", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_SUB}, 23 | {hdr = " reqs", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_SUB}, 24 | {hdr = "active", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 25 | {hdr = " read", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 26 | {hdr = " write", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 27 | {hdr = " wait", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 28 | {hdr = " qps", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_SUB_INTER}, 29 | {hdr = " rt", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 30 | {hdr = "sslqps", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_SUB_INTER}, 31 | {hdr = "spdyps", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_SUB_INTER}, 32 | {hdr = "sslhst", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 33 | {hdr = "sslhsc", summary_bit = HIDE_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 34 | } 35 | 36 | function _M.read(mod, param) 37 | local naccept, nhandled, nrequest, nrstime 38 | local result = http.request("http://127.0.0.1/nginx_status") 39 | 40 | local nactive = string_match(result, [[Active connections: (%d+)]]) 41 | local nreading = string_match(result, [[Reading: (%d+)]]) 42 | local nwriting = string_match(result, [[Writing: (%d+)]]) 43 | local nwaiting = string_match(result, [[Waiting: (%d+)]]) 44 | if string_find(result, [[server accepts handled requests request_time]]) then 45 | naccept, nhandled, nrequest, nrstime = string.match(result, "(%d+) (%d+) (%d+) (%d+)") 46 | elseif string_find(result, [[server accepts handled requests]]) then 47 | naccept, nhandled, nrequest = string.match(result, "(%d+) (%d+) (%d+)") 48 | else 49 | naccept = string_match(result, "Server accepts: (%d+)") 50 | nhandled = string_match(result, "nhandled: (%d+)") 51 | nrequest = string_match(result, "requests: (%d+)") 52 | nrstime = string_match(result, "request_time: (%d+)") 53 | end 54 | 55 | local d = {} 56 | 57 | d[1] = naccept 58 | d[2] = nhandled 59 | d[3] = nrequest 60 | d[4] = nactive 61 | d[5] = nreading 62 | d[6] = nwriting 63 | d[7] = nwaiting 64 | d[8] = nrequest 65 | d[9] = nrstime 66 | d[10] = 0 67 | d[11] = 0 68 | d[12] = 0 69 | d[13] = 0 70 | 71 | return concat(d, ",") 72 | end 73 | 74 | function _M.set(mod, st_array, pre_array, cur_array, interval) 75 | for i = 1, 3 do 76 | if cur_array[i] >= pre_array[i] then 77 | st_array[i] = cur_array[i] - pre_array[i] 78 | else 79 | st_array[i] = 0 80 | end 81 | end 82 | 83 | for i = 4, 7 do 84 | st_array[i] = cur_array[i] 85 | end 86 | 87 | if cur_array[3] >= pre_array[3] then 88 | st_array[7] = (cur_array[3] - pre_array[3]) * 1.0 / interval 89 | else 90 | st_array[7] = 0 91 | end 92 | 93 | if cur_array[9] >= pre_array[9] then 94 | if cur_array[3] > pre_array[3] then 95 | st_array[9] = (cur_array[9] - pre_array[9]) * 1.0 / (cur_array[3] - pre_array[3]); 96 | else 97 | st_array[9] = 0 98 | end 99 | end 100 | 101 | for i = 10, 11 do 102 | if cur_array[i] >= pre_array[i] then 103 | st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / interval 104 | else 105 | st_array[i] = 0 106 | end 107 | end 108 | 109 | if cur_array[12] >= pre_array[12] then 110 | if cur_array[12] > pre_array[12] then 111 | st_array[12] = (cur_array[12] - pre_array[12]) * 1.0 / (cur_array[13] - pre_array[13]) 112 | else 113 | st_array[12] = 0 114 | end 115 | end 116 | 117 | return st_array, pre_array, cur_array 118 | end 119 | 120 | function _M.register() 121 | return { 122 | opt = "--lua_nginx", 123 | usage = "nginx statistics", 124 | info = info, 125 | } 126 | end 127 | 128 | return _M 129 | -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_COMMON_H 21 | #define TSAR_COMMON_H 22 | 23 | 24 | #define PRE_RECORD_FILE "/tmp/.tsar.tmp" 25 | 26 | /* 27 | * convert data to array 28 | */ 29 | int convert_record_to_array(U_64 *array, int l_array, const char *record); 30 | void get_mod_hdr(char hdr[], const struct module *mod); 31 | char* strtok_next_item(char *record, int *start); 32 | int merge_mult_item_to_array(U_64 *array, struct module *mod); 33 | int get_strtok_num(const char *str, const char *split); 34 | int get_st_array_from_file(int have_collect); 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /include/config.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_CONFIG_H 21 | #define TSAR_CONFIG_H 22 | 23 | 24 | #include "define.h" 25 | 26 | 27 | struct configure { 28 | 29 | /* from arg */ 30 | int running_mode; /* running mode */ 31 | char config_file[LEN_128]; 32 | int debug_level; 33 | 34 | char output_interface[LEN_128]; /* which interface will enable*/ 35 | 36 | /* output print */ 37 | char output_print_mod[LEN_512]; /* which mod will print throught argv */ 38 | char output_stdio_mod[LEN_512]; /* which mod will print throuhth conf file */ 39 | char output_nagios_mod[LEN_512]; /* which mod will output to nagios */ 40 | int print_interval; /* how many seconds will escape every print interval */ 41 | int print_nline_interval; /* how many lines will skip every print interval */ 42 | int print_mode; /* data type will print: summary or detail */ 43 | int print_merge; /* mult items is merge */ 44 | int print_detail; /* conver data to K/M/G */ 45 | int print_ndays; /* these days will print.default:1 */ 46 | int print_day; /* which day will print */ 47 | int print_start_time; /* the start of the print time */ 48 | int print_end_time; /* the end of the print time */ 49 | int print_tail; 50 | int print_file_number; /* which tsar.data file used */ 51 | int print_max_day; /* max day for history print */ 52 | int print_nminute; /* these minutes for history watch */ 53 | 54 | /* output db */ 55 | char output_db_mod[LEN_512]; /* which mod will output */ 56 | char output_db_addr[LEN_512]; /* db addr */ 57 | 58 | /* output tcp */ 59 | int output_tcp_addr_num; /*the number of tcp address indeed need to send data*/ 60 | char output_tcp_mod[LEN_512]; 61 | char output_tcp_addr[MAX_TCP_ADDR_NUM][LEN_256]; 62 | char output_tcp_merge[LEN_256]; 63 | 64 | /* output nagios */ 65 | char server_addr[LEN_512]; 66 | int server_port; 67 | int cycle_time; 68 | char send_nsca_cmd[LEN_512]; 69 | char send_nsca_conf[LEN_512]; 70 | 71 | char check_name[MAX_MOD_NUM][LEN_32]; 72 | float wmin[MAX_MOD_NUM]; 73 | float wmax[MAX_MOD_NUM]; 74 | float cmin[MAX_MOD_NUM]; 75 | float cmax[MAX_MOD_NUM]; 76 | int mod_num; 77 | 78 | /* output file */ 79 | char output_file_path[LEN_128]; 80 | 81 | /* lua package path */ 82 | char lua_path[LEN_512]; 83 | char lua_cpath[LEN_512]; 84 | }; 85 | 86 | 87 | void parse_config_file(const char *file_name); 88 | void get_include_conf(); 89 | void get_threshold(); 90 | void set_special_field(const char *spec_field); 91 | void set_special_item(const char *spec_field); 92 | 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /include/debug.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_DEBUG_H 21 | #define TSAR_DEBUG_H 22 | 23 | 24 | typedef enum 25 | { 26 | LOG_INFO, 27 | LOG_DEBUG, 28 | LOG_WARN, 29 | LOG_ERR, 30 | LOG_FATAL 31 | } log_level_t; 32 | 33 | 34 | #define do_debug(level, ...) \ 35 | _do_debug(level, __FILE__, __LINE__, __VA_ARGS__) 36 | 37 | void _do_debug(log_level_t level, const char *file, int line, const char *fmt, ...); 38 | 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/define.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_DEFINE_H 21 | #define TSAR_DEFINE_H 22 | 23 | 24 | //-check & --check function for old tsar amon usage 25 | #define OLDTSAR 26 | 27 | #define U_BIT 3 28 | 29 | #define U_64 unsigned long long 30 | 31 | #define LEN_32 32 32 | #define LEN_64 64 33 | #define LEN_128 128 34 | #define LEN_256 256 35 | #define LEN_512 512 36 | #define LEN_1024 1024 37 | #define LEN_4096 4096 38 | #define LEN_1M 1048576 39 | #define LEN_10M 10485760 40 | 41 | #define MAX_COL_NUM 64 42 | #define MAX_MOD_NUM 32 43 | #define MAX_TCP_ADDR_NUM 4 44 | 45 | #define SECTION_SPLIT "|" 46 | #define STRING_SPLIT ":" 47 | #define ITEM_SPLIT ";" 48 | #define ITEM_SPSTART "=" 49 | #define DATA_SPLIT "," 50 | #define PARAM_SPLIT ':' 51 | #define HDR_SPLIT "#" 52 | #define PRINT_DATA_SPLIT " " 53 | #define PRINT_SEC_SPLIT " " 54 | #define W_SPACE " \t\r\n" 55 | 56 | #define DEFAULT_PRINT_NUM 20 57 | #define DEFAULT_PRINT_INTERVAL 5 58 | 59 | #define MOD_INFO_SIZE sizeof(strcut mod_info) 60 | 61 | #define DEFAULT_MODULE_PATH "/usr/local/tsar/modules" 62 | #define DEFAULT_CONF_FILE_PATH "/etc/tsar/tsar.conf" 63 | #define DEFAULT_OUTPUT_FILE_PATH "/var/log/tsar.data" 64 | #define MIN_STRING "MIN: " 65 | #define MEAN_STRING "MEAN: " 66 | #define MAX_STRING "MAX: " 67 | 68 | #define TRUE 1 69 | #define FALSE 0 70 | 71 | #define VMSTAT "/proc/vmstat" 72 | #define STAT "/proc/stat" 73 | #define MEMINFO "/proc/meminfo" 74 | #define LOADAVG "/proc/loadavg" 75 | #define NET_DEV "/proc/net/dev" 76 | #define NET_SNMP "/proc/net/snmp" 77 | #define APACHERT "/tmp/apachert.mmap" 78 | #define TCP "/proc/net/tcp" 79 | #define NETSTAT "/proc/net/netstat" 80 | #define MOD_LUA_PREFIX "mod_lua_" 81 | 82 | 83 | enum { 84 | MERGE_NOT, 85 | MERGE_ITEM 86 | }; 87 | 88 | 89 | enum { 90 | RUN_NULL, 91 | RUN_LIST, 92 | RUN_CRON, 93 | #ifdef OLDTSAR 94 | RUN_CHECK, 95 | #endif 96 | RUN_CHECK_NEW, 97 | RUN_PRINT, 98 | RUN_PRINT_LIVE, 99 | RUN_WATCH 100 | }; 101 | 102 | 103 | enum { 104 | DATA_NULL, 105 | DATA_SUMMARY, 106 | DATA_DETAIL, 107 | DATA_ALL 108 | }; 109 | 110 | 111 | enum { 112 | TAIL_NULL, 113 | TAIL_MAX, 114 | TAIL_MEAN, 115 | TAIL_MIN 116 | }; 117 | 118 | 119 | enum { 120 | OUTPUT_NULL, 121 | OUTPUT_PRINT, 122 | OUTPUT_NAGIOS 123 | }; 124 | 125 | 126 | enum { 127 | HIDE_BIT, 128 | DETAIL_BIT, 129 | SUMMARY_BIT, 130 | SPEC_BIT 131 | }; 132 | 133 | 134 | enum { 135 | MERGE_NULL, 136 | MERGE_SUM, 137 | MERGE_AVG 138 | }; 139 | 140 | 141 | enum { 142 | STATS_NULL, 143 | STATS_SUB, 144 | STATS_SUB_INTER 145 | }; 146 | 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /include/framework.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_FRAMEWORK_H 21 | #define TSAR_FRAMEWORK_H 22 | 23 | 24 | #include "define.h" 25 | 26 | struct mod_info { 27 | char hdr[LEN_128]; 28 | int summary_bit; /* bit set indefi summary */ 29 | int merge_mode; 30 | int stats_opt; 31 | }; 32 | 33 | struct module { 34 | 35 | char name[LEN_32]; 36 | char opt_line[LEN_32]; 37 | char record[LEN_1M]; 38 | char usage[LEN_256]; 39 | char parameter[LEN_256]; 40 | char print_item[LEN_256]; 41 | 42 | struct mod_info *info; 43 | void *lib; 44 | int enable; 45 | int spec; 46 | int p_item; 47 | 48 | /* private data used by framework*/ 49 | int n_item; 50 | int n_col; 51 | long n_record; 52 | 53 | int pre_flag:4; 54 | int st_flag:4; 55 | 56 | U_64 *pre_array; 57 | U_64 *cur_array; 58 | double *st_array; 59 | double *max_array; 60 | double *mean_array; 61 | double *min_array; 62 | 63 | /* callback function of module */ 64 | void (*data_collect) (struct module *, char *); 65 | void (*set_st_record) (struct module *, double *, U_64 *, U_64 *, int); 66 | 67 | /* mod manage */ 68 | void (*mod_register) (struct module *); 69 | }; 70 | 71 | 72 | void register_mod_fields(struct module *mod, const char *opt, const char *usage, 73 | struct mod_info *info, int n_col, void *data_collect, void *set_st_record); 74 | void set_mod_record(struct module *mod, const char *record); 75 | void init_module_fields(); 76 | int reload_modules(const char *s_mod); 77 | #ifdef OLDTSAR 78 | void reload_check_modules(); 79 | #endif 80 | void load_modules(); 81 | void free_modules(); 82 | void collect_record(); 83 | time_t read_line_to_module_record(char *line); 84 | int collect_record_stat(); 85 | void disable_col_zero(); 86 | 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /include/output_db.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_OUTPUT_DB_H 21 | #define TSAR_OUTPUT_DB_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | void output_db(int have_collect); 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/output_file.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_OUTPUT_FILE_H 21 | #define TSAR_OUTPUT_FILE_H 22 | 23 | 24 | /* 25 | * output data to file 26 | */ 27 | 28 | struct buffer { 29 | char *data; 30 | int len; 31 | }; 32 | 33 | struct file_header { 34 | int version; 35 | time_t t_start; 36 | }; 37 | 38 | 39 | void output_file(); 40 | 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/output_nagios.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_OUTPUT_NAGIOS_H 21 | #define TSAR_OUTPUT_NAGIOS_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | void output_nagios(); 32 | 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/output_print.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_OUT_PRINT_H 21 | #define TSAR_OUT_PRINT_H 22 | 23 | 24 | /* 25 | * output data to std output (history or live mode) 26 | */ 27 | void running_print(); 28 | #ifdef OLDTSAR 29 | void running_current(); 30 | void running_check(int check_type); 31 | #endif 32 | void running_print_live(); 33 | 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /include/output_tcp.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_OUTPUT_TCP_H 21 | #define TSAR_OUTPUT_TCP_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | 30 | void output_multi_tcp(int have_collect); 31 | struct sockaddr_in * str2sa(char *); 32 | #endif 33 | -------------------------------------------------------------------------------- /include/public.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_PUBLIC_H 21 | #define TSAR_PUBLIC_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include "tsar.h" 28 | 29 | 30 | /* 31 | * /proc/files 32 | */ 33 | #define NET_DEV "/proc/net/dev" 34 | #define STAT "/proc/stat" 35 | #define MEMINFO "/proc/meminfo" 36 | #define LOADAVG "/proc/loadavg" 37 | #define INTERRUPT "/proc/interrupts" 38 | #define APACHERT "/tmp/apachert.mmap" 39 | #define VMSTAT "/proc/vmstat" 40 | #define DISKSTATS "/proc/diskstats" 41 | #define NET_SNMP "/proc/net/snmp" 42 | #define FDENTRY_STATE "/proc/sys/fs/dentry-state" 43 | #define FFILE_NR "/proc/sys/fs/file-nr" 44 | #define FINODE_STATE "/proc/sys/fs/inode-state" 45 | #define PTY_NR "/proc/sys/kernel/pty/nr" 46 | 47 | 48 | /* 49 | * ANSI Color setting segment 50 | * 51 | */ 52 | #define BLUE_FMT(s) "\033[40;34m"s"\033[0m" 53 | #define GREEN_FMT(s) "\033[40;32m"s"\033[0m" 54 | #define RED_FMT(s) "\033[40;31m"s"\033[0m" 55 | 56 | 57 | #define COLOR(val, fmt, str, ret, color) do \ 58 | { \ 59 | if ((val) > 100) \ 60 | ret = sprintf(str, \ 61 | color##_FMT(fmt), (val)); \ 62 | else \ 63 | ret = sprintf(str, fmt, (val)); \ 64 | } while(0) 65 | 66 | #define FALSE 0 67 | #define TRUE 1 68 | #define PRINT_STATISTICS FALSE 69 | 70 | #define CURR 0 71 | #define PAST 1 72 | 73 | 74 | /* 75 | * for statistics 76 | */ 77 | #define NR_ARRAY 3 78 | 79 | enum {MIN, MEAN, MAX}; 80 | 81 | 82 | /* 83 | * Macros used to display statistics values. 84 | * 85 | * NB: Define SP_VALUE() to normalize to %; 86 | * HZ is 1024 on IA64 and % should be normalized to 100. 87 | */ 88 | #define _S(a, b) (((b) == 0) ? 0 : ((a) / (b))) 89 | 90 | #define S_VALUE(m, n, p) (((double) ((n) - (m))) / (p) ) 91 | 92 | #define SP_VALUE(m, n, p) (((double) ((n) - (m))) / (p) * 100) 93 | 94 | #define SK(K, shift) (((unsigned long long)(K) << 10) >> shift) 95 | #define SB(B, shift) ((unsigned long long)(B) >> shift) 96 | #define KTOB(B) ((unsigned long long)(B) << 10) 97 | 98 | #define FMT_U64 "%lld" 99 | #define FMT_U32 "%ld" 100 | 101 | #define FMT_SP " %5.1f " 102 | #define FMT_S "%5.1f%c " 103 | #define FMT_NAGIOS "%.2f," 104 | 105 | /*1000 * 1024 * 1024 * 1024*/ 106 | #define TB 0xF424000000 107 | 108 | /* 1000 * 1024 * 1024*/ 109 | #define GB 0x3E800000 110 | 111 | /* 1000 * 1024 */ 112 | #define MB 0xFA000 113 | 114 | /* 1000 */ 115 | #define KB 0x3E8 116 | 117 | #define __INDENT(f, idx, ret) \ 118 | do { \ 119 | if((f/1024.0) > GB) { \ 120 | (ret) = (f) * 1.0/1024.0 / GB; \ 121 | (idx) = 3; \ 122 | } \ 123 | else if((f) > GB) { \ 124 | (ret) = (f) * 1.0 / GB; \ 125 | (idx) = 2; \ 126 | } \ 127 | else if ((f) > MB){ \ 128 | (ret) = (f) * 1.0 / MB; \ 129 | (idx) = 1; \ 130 | } \ 131 | else { \ 132 | (ret) = (f) * 1.0 / KB; \ 133 | (idx) = 0; \ 134 | } \ 135 | }while(0) 136 | 137 | 138 | #define __PRINT_S(buffer, val, ret) do { \ 139 | int _i; \ 140 | double _f; \ 141 | char u[] = {'K', 'M', 'G', 'T'}; \ 142 | __INDENT((val), _i, _f); \ 143 | (ret) += sprintf((buffer), FMT_S, _f, u[_i]); \ 144 | }while(0) 145 | 146 | #define __PRINT_SP(buffer, val, ret) do { \ 147 | (ret) += sprintf(buffer, FMT_SP, (val)); \ 148 | }while(0) 149 | 150 | #define __PRINT_NAGIOS(buffer, val, ret) do { \ 151 | (ret) += sprintf(buffer, FMT_NAGIOS, (val)); \ 152 | }while(0) 153 | 154 | #define PRINT(buffer, val, ret, type) do { \ 155 | if (type == OUTPUT_NAGIOS) { \ 156 | __PRINT_NAGIOS(buffer, val, ret); \ 157 | } \ 158 | else{ \ 159 | if ((val) < KB) { \ 160 | __PRINT_SP(buffer, val, ret); \ 161 | } \ 162 | else { \ 163 | __PRINT_S(buffer, val, ret); \ 164 | } \ 165 | } \ 166 | } while(0) 167 | 168 | #define myalloc(p, type, size) \ 169 | struct type * p = NULL; \ 170 | p = (struct type *)malloc(size); \ 171 | if(!p) { \ 172 | fprintf(stderr, "failed to alloc memory\n"); \ 173 | exit(EXIT_FAILURE); \ 174 | } \ 175 | memset(p, 0, size) \ 176 | 177 | #define BUFFER_ROTATE(mod, size) \ 178 | do { \ 179 | memcpy(&s_st_##mod[PAST], &s_st_##mod[CURR], (size)); \ 180 | memset(&s_st_##mod[CURR], '\0', (size)); \ 181 | }while(0) 182 | 183 | inline void func_mod_free(struct module *mod) 184 | { 185 | free(mod->detail); 186 | free(mod->summary); 187 | mod->detail = NULL; 188 | mod->summary = NULL; 189 | } 190 | 191 | #define INIT_STRING_P(s, nr, len) \ 192 | do { \ 193 | int i; \ 194 | s = (char **)malloc((nr) * sizeof(char *)); \ 195 | for(i = 0; i < (nr); i++) \ 196 | s[i] = (char *)malloc(len); \ 197 | } while(0) 198 | 199 | 200 | #define DECLARE_TMP_MOD_STATISTICS(mod) \ 201 | union mod##_statistics mod##_tmp_s; \ 202 | 203 | #define SET_CURRENT_VALUE(mod, type, member, ret) \ 204 | do { \ 205 | mod##_tmp_s.mod##_##type.ret = \ 206 | s_st_##mod[CURR].member; \ 207 | }while(0) 208 | 209 | #define __COMPUTE_MOD_VALUE(ret, ops, m1, m2, i) \ 210 | do { \ 211 | if (!(i)) { \ 212 | (ret) = 0; \ 213 | } \ 214 | else if ((m1) == (m2)) { \ 215 | (ret) = 0; \ 216 | } \ 217 | else { \ 218 | (ret) = ops((m1), (m2), (i)); \ 219 | } \ 220 | } while(0) 221 | 222 | 223 | #define COMPUTE_MOD_VALUE(mod, ops, type, member, i, ret) \ 224 | do { \ 225 | /*printf("i = %ld\n", (i));*/ \ 226 | __COMPUTE_MOD_VALUE( \ 227 | mod##_tmp_s.mod##_##type.ret, \ 228 | ops, \ 229 | s_st_##mod[1].member, \ 230 | s_st_##mod[0].member, \ 231 | (i)); \ 232 | } while(0) 233 | 234 | 235 | /* Fix me */ 236 | #define __SET_MOD_STATISTICS(val, mean, max, min, i) \ 237 | do{ \ 238 | static int sw = 0; \ 239 | if(!sw) { \ 240 | (max) = (val); \ 241 | (min) = (val); \ 242 | sw = 1; \ 243 | } else { \ 244 | if (((val) - (max)) > 0.00001) \ 245 | (max) = (val); \ 246 | else if (((min) - (val)) > 0.00001) { \ 247 | (min) = (val); \ 248 | } \ 249 | } \ 250 | (mean) += (val); \ 251 | } while(0) 252 | 253 | #define SET_MOD_STATISTICS(mod, member, i, type) \ 254 | __SET_MOD_STATISTICS \ 255 | ( \ 256 | mod##_tmp_s.mod##_##type.member, \ 257 | mod##_statis[MEAN].mod##_##type.member, \ 258 | mod##_statis[MAX].mod##_##type.member, \ 259 | mod##_statis[MIN].mod##_##type.member, \ 260 | i) 261 | 262 | #define __PRINT_AVG(buf, pos, val, member, idx, count, otype) do \ 263 | { \ 264 | if ((idx) == MEAN) \ 265 | val[(idx)].member = \ 266 | val[(idx)].member / (count); \ 267 | PRINT(buf[(idx)] + pos[(idx)], \ 268 | val[(idx)].member, \ 269 | pos[(idx)], (otype)); \ 270 | }while(0) 271 | 272 | #define __PRINT_AVG_SEP(buf, pos, val, member, sep, idx, count, otype) do \ 273 | { \ 274 | if((idx) == MEAN) \ 275 | val[(idx)].member = \ 276 | (val[(idx)].member / (count)); \ 277 | PRINT(buf[(idx)] + pos[(idx)], \ 278 | val[(idx)].member * (sep), \ 279 | pos[(idx)], (otype)); \ 280 | }while(0) 281 | 282 | inline char *getitem(char *r, char *mnt) 283 | { 284 | char *start, *end; 285 | if (r == NULL || *r == '\0') { 286 | return NULL; 287 | } else { 288 | start = strstr(r, "="); 289 | end = strstr(r, ";"); 290 | memcpy(mnt, start + 1, end - start -1); 291 | r = end + 1; 292 | mnt[end - start - 1] = '\0'; 293 | } 294 | 295 | return r; 296 | } 297 | 298 | #define CALITV(pt, ct, i) ((i) = ((pt) < (ct)) ? (ct) - (pt) : 1) 299 | 300 | 301 | #endif 302 | -------------------------------------------------------------------------------- /include/tsar.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_H 21 | #define TSAR_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | 41 | #include "framework.h" 42 | #include "debug.h" 43 | #include "config.h" 44 | 45 | #include "output_file.h" 46 | #include "output_print.h" 47 | #include "output_db.h" 48 | #include "output_tcp.h" 49 | #include "output_nagios.h" 50 | #include "common.h" 51 | #include "tsar_lua_util.h" 52 | 53 | 54 | struct statistic { 55 | int total_mod_num; 56 | time_t cur_time; 57 | }; 58 | 59 | 60 | extern struct configure conf; 61 | extern struct module *mods[MAX_MOD_NUM]; 62 | extern struct statistic statis; 63 | extern lua_State *L; 64 | 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /include/tsar_lua_util.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #ifndef TSAR_LUA_UTIL_H 21 | #define TSAR_LUA_UTIL_H 22 | 23 | 24 | #include "define.h" 25 | 26 | void close_luavm(lua_State *L); 27 | lua_State *load_luavm(); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /luadevel/Makefile.test: -------------------------------------------------------------------------------- 1 | install: 2 | mkdir -p /etc/tsar/conf.d/ 3 | cp ./mod_test.lua /usr/local/tsar/modules/ 4 | cp ./mod_test.conf /etc/tsar/conf.d/test.conf 5 | 6 | uninstall: 7 | rm /usr/local/tsar/modules/mod_test.lua 8 | rm /etc/tsar/conf.d/test.conf 9 | -------------------------------------------------------------------------------- /luadevel/mod_lua_test.conf: -------------------------------------------------------------------------------- 1 | mod_test on 2 | 3 | ####add it to tsar default output 4 | output_stdio_mod mod_test 5 | 6 | ####add it to center db 7 | #output_db_mod mod_test 8 | 9 | ####add it to nagios send 10 | ####set nagios threshold for alert 11 | #output_nagios_mod mod_test 12 | 13 | #threshold test.value1;N;N;N;N; 14 | #threshold test.value2;N;N;N;N; 15 | #threshold test.value3;N;N;N;N; 16 | -------------------------------------------------------------------------------- /luadevel/mod_lua_test.lua: -------------------------------------------------------------------------------- 1 | local _M = { 2 | _VERSION = "0.1.0" 3 | } 4 | 5 | local cjson = require("cjson") 6 | local socket = require("socket") 7 | local http = require("socket.http") 8 | local ltn12 = require("ltn12") 9 | local DETAIL_BIT = tsar.DETAIL_BIT 10 | local SUMMARY_BIT = tsar.SUMMARY_BIT 11 | local HIDE_BIT = tsar.HIDE_BIT 12 | local STATS_NULL = tsar.STATS_NULL 13 | local string_format = string.format 14 | 15 | local info = { 16 | {hdr = " value1", summary_bit = SUMMARY_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 17 | {hdr = " value2", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 18 | {hdr = " value3", summary_bit = DETAIL_BIT, merge_mode = 0, stats_opt = STATS_NULL}, 19 | } 20 | 21 | local value1 = 1 22 | local value2 = 2 23 | local value3 = 3 24 | function _M.read(mod, param) 25 | value1 = value1 + 3 26 | value2 = value2 + 3 27 | value3 = value3 + 3 28 | 29 | return string_format("%d,%d,%d", value1, value2, value3) 30 | end 31 | 32 | local totalvalue = 0 33 | function _M.set(mod, st_array, pre_array, cur_array, interval) 34 | totalvalue = totalvalue + cur_array[2] 35 | 36 | st_array[1] = cur_array[1] - pre_array[1] 37 | st_array[2] = (cur_array[1] - pre_array[1]) * 100.0 / totalvalue 38 | st_array[3] = cur_array[3] 39 | 40 | return st_array, pre_array, cur_array 41 | end 42 | 43 | function _M.register() 44 | return { 45 | opt = "--test", 46 | usage = "test information", 47 | info = info, 48 | } 49 | end 50 | 51 | return _M 52 | -------------------------------------------------------------------------------- /luadevel/tsarluadevel: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # check argc 4 | usage() 5 | { 6 | echo "Usage:" 7 | echo "tsarluadevel modname" 8 | exit 0 9 | } 10 | install() 11 | { 12 | echo "install:make install" 13 | echo "uninstall:make uninstall" 14 | echo "test:tsar --list or tsar --lua_$modname --live -i 1" 15 | } 16 | if [ $# -ne 1 ] 17 | then 18 | usage 19 | fi 20 | 21 | modname=$1 22 | install_path='/usr/local/tsar/luadevel' 23 | 24 | for file in mod_lua_test.lua mod_lua_test.conf Makefile.test 25 | do 26 | if [ ! -e "$install_path/$file" ] ;then 27 | echo "$install_path/$file not exist!" 28 | echo "make sure you have run 'make tsarluadevel' when install tsar." 29 | exit 1 30 | fi 31 | done 32 | 33 | 34 | # mk new mod_test 35 | mkdir -p $modname 36 | sed -e "s/test/lua_$modname/g" < $install_path/mod_lua_test.lua > ./$modname/mod_lua_$modname.lua 37 | sed -e "s/test/lua_$modname/g" < $install_path/mod_lua_test.conf > ./$modname/mod_lua_$modname.conf 38 | sed -e "s/test/lua_$modname/g" < $install_path/Makefile.test > ./$modname/Makefile 39 | if [ $? -eq 0 ] 40 | then 41 | install 42 | fi 43 | -------------------------------------------------------------------------------- /lualib/Makefile: -------------------------------------------------------------------------------- 1 | LUACJSON = lua-cjson-2.1.0 2 | LUASOCKET = luasocket-2.0.2 3 | DIRS = $(LUACJSON) $(LUASOCKET) 4 | 5 | INCLUDE_DIR ?= $(CURDIR)/../src/obj/include/luajit-2.0 6 | INSTALL_DIR ?= /usr/local/tsar/lualib 7 | 8 | all: 9 | for i in $(DIRS); do tar --no-same-owner -zxf $$i.tar.gz; done 10 | make -C $(LUACJSON) LUA_INCLUDE_DIR=$(INCLUDE_DIR) 11 | make -C $(LUASOCKET) LUAINC=-I$(INCLUDE_DIR) 12 | 13 | install: 14 | @make -C $(LUACJSON) LUA_CMODULE_DIR=$(INSTALL_DIR) LUA_MODULE_DIR=$(INSTALL_DIR) install 15 | @make -C $(LUASOCKET) INSTALL_TOP_SHARE=$(INSTALL_DIR) INSTALL_TOP_LIB=$(INSTALL_DIR) install 16 | 17 | clean: 18 | for i in $(DIRS); do make -C $$i clean; done 19 | -------------------------------------------------------------------------------- /lualib/lua-cjson-2.1.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/tsar/0224ccbf81982b46f600048311f87cb1b5bc8e8f/lualib/lua-cjson-2.1.0.tar.gz -------------------------------------------------------------------------------- /lualib/luasocket-2.0.2.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/tsar/0224ccbf81982b46f600048311f87cb1b5bc8e8f/lualib/luasocket-2.0.2.tar.gz -------------------------------------------------------------------------------- /modules/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -MD -Wall -fPIC --shared -g -O2 -Wno-strict-aliasing 2 | CC = gcc 3 | INCLUDE_DIR = ../include 4 | LINK = $(CC) -I$(INCLUDE_DIR) -I../src/obj/include $(CFLAGS) 5 | 6 | UNAME_S := $(shell uname -s) 7 | ifeq ($(UNAME_S),Darwin) 8 | LINK += -Wl,-undefined -Wl,dynamic_lookup 9 | 10 | OBJS = mod_apache.so mod_cpu.so mod_haproxy.so mod_load.so mod_swap.so\ 11 | mod_lvs.so mod_mem.so mod_ncpu.so mod_nginx.so \ 12 | mod_pcsw.so mod_percpu.so mod_pernic.so \ 13 | mod_proc.so mod_squid.so mod_tcp.so mod_tcpx.so mod_traffic.so mod_udp.so 14 | else 15 | OBJS = mod_apache.so mod_cpu.so mod_haproxy.so mod_io.so mod_load.so mod_swap.so \ 16 | mod_lvs.so mod_mem.so mod_ncpu.so mod_nginx.so \ 17 | mod_partition.so mod_pcsw.so mod_percpu.so mod_pernic.so \ 18 | mod_proc.so mod_squid.so mod_tcp.so mod_tcpx.so mod_traffic.so mod_udp.so 19 | endif 20 | 21 | all: $(OBJS) 22 | 23 | $(OBJS): %.so: %.c 24 | $(LINK) $< -o $@ 25 | clean: 26 | rm -f *.so; 27 | rm -f *.d; 28 | rm -rf *.dSYM; 29 | 30 | -include $(OBJS:.so=.d) 31 | -------------------------------------------------------------------------------- /modules/mod_apache.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "tsar.h" 7 | 8 | char *apache_usage = " --apache apache statistics"; 9 | 10 | struct stats_apache { 11 | unsigned int busy_proc; 12 | unsigned int idle_proc; 13 | unsigned long long query; 14 | unsigned long long response_time; 15 | unsigned long long kBytes_sent; 16 | }; 17 | 18 | #define STATS_APACHE_SIZE (sizeof(struct stats_apache)) 19 | 20 | 21 | struct hostinfo { 22 | char *host; 23 | int port; 24 | }; 25 | 26 | void 27 | init_host_info(struct hostinfo *p) 28 | { 29 | p->host = strdup("127.0.0.1"); 30 | p->port = 80; 31 | } 32 | 33 | void 34 | read_apache_stats(struct module *mod) 35 | { 36 | int fd, n, m, sockfd, send, pos; 37 | char buf[LEN_4096] = {0}, request[LEN_4096], line[LEN_4096], 38 | buff[LEN_4096]; 39 | memset(buf, 0, LEN_4096); 40 | struct sockaddr_in servaddr; 41 | FILE *stream = NULL; 42 | /* FIX me */ 43 | char *cmd = "server-status?auto"; 44 | struct stats_apache st_apache; 45 | memset(&st_apache, 0, sizeof(struct stats_apache)); 46 | struct hostinfo hinfo; 47 | memset(&hinfo, 0, sizeof(struct hostinfo)); 48 | 49 | if ((fd = open(APACHERT, O_RDONLY , 0644)) < 0 ){ 50 | return; 51 | } 52 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 53 | if (sockfd < 0) { 54 | goto last; 55 | } 56 | if ((n = read(fd, buff, 16)) != 16) { 57 | goto last; 58 | } 59 | st_apache.query = * (unsigned long long *)buff; 60 | st_apache.response_time = * (unsigned long long *)&buff[8]; 61 | /*fullfil another member int the structure*/ 62 | init_host_info(&hinfo); 63 | bzero(&servaddr, sizeof(servaddr)); 64 | servaddr.sin_family = AF_INET; 65 | servaddr.sin_port = htons(hinfo.port); 66 | inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr); 67 | sprintf(request, 68 | "GET /%s HTTP/1.0\r\n" 69 | "User-Agent: Wget/1.9\r\n" 70 | "Host: %s\r\n" 71 | "Accept:*/*\r\n" 72 | "Connection: Close\r\n\r\n", 73 | cmd, hinfo.host); 74 | 75 | if ((m = connect(sockfd, (struct sockaddr *) &servaddr, 76 | sizeof(servaddr))) == -1 ) { 77 | goto writebuf; 78 | } 79 | 80 | if ((send = write(sockfd, request, strlen(request))) == -1) { 81 | goto writebuf; 82 | } 83 | stream = fdopen(sockfd, "r"); 84 | if (!stream) { 85 | goto last; 86 | } 87 | while(fgets(line, LEN_4096, stream) != NULL) { 88 | if(!strncmp(line, "Total kBytes:", 13)) { 89 | sscanf(line + 14, "%llu", &st_apache.kBytes_sent); 90 | 91 | } else if (!strncmp(line, "BusyWorkers:", 12)) { 92 | sscanf(line + 13, "%d", &st_apache.busy_proc); 93 | 94 | } else if (!strncmp(line, "IdleWorkers:", 12)) { 95 | sscanf(line + 13, "%d", &st_apache.idle_proc); 96 | 97 | } else { 98 | ; 99 | } 100 | memset(line, 0, LEN_4096); 101 | } 102 | writebuf: 103 | pos = sprintf(buf, "%lld,%lld,%lld,%d,%d", 104 | st_apache.query, 105 | st_apache.response_time / 1000, 106 | st_apache.kBytes_sent, 107 | st_apache.busy_proc, 108 | st_apache.idle_proc); 109 | buf[pos] = '\0'; 110 | if (stream) { 111 | if (fclose(stream) < 0) { 112 | goto last; 113 | } 114 | } 115 | set_mod_record(mod, buf); 116 | last: 117 | close(fd); 118 | if (sockfd) { 119 | close(sockfd); 120 | } 121 | free(hinfo.host); 122 | } 123 | 124 | static void 125 | set_apache_record(struct module *mod, double st_array[], 126 | U_64 pre_array[], U_64 cur_array[], int inter) 127 | { 128 | int i; 129 | /* set st record */ 130 | if(cur_array[0] >= pre_array[0]) 131 | st_array[0] = (cur_array[0] - pre_array[0]) / (inter * 1.0); 132 | if((cur_array[1] >= pre_array[1]) && (cur_array[0] > pre_array[0])) 133 | st_array[1] = (cur_array[1] - pre_array[1]) / ((cur_array[0] - pre_array[0]) * 1.0); 134 | if(cur_array[2] >= pre_array[2]) 135 | st_array[2] = (cur_array[2] - pre_array[2]) / (inter * 1.0); 136 | for (i = 3; i <= 4; i++) st_array[i] = cur_array[i]; 137 | } 138 | 139 | static struct mod_info apache_info[] = { 140 | {" qps", SUMMARY_BIT, 0, STATS_SUB_INTER}, 141 | {" rt", SUMMARY_BIT, 0, STATS_SUB_INTER}, 142 | {" sent", DETAIL_BIT, 0, STATS_SUB_INTER}, 143 | {" busy", DETAIL_BIT, 0, STATS_NULL}, 144 | {" idle", DETAIL_BIT, 0, STATS_NULL}, 145 | }; 146 | 147 | void 148 | mod_register(struct module *mod) 149 | { 150 | register_mod_fields(mod, "--apache", apache_usage, apache_info, 5, read_apache_stats, set_apache_record); 151 | } 152 | -------------------------------------------------------------------------------- /modules/mod_cpu.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | /* 4 | * Structure for CPU infomation. 5 | */ 6 | struct stats_cpu { 7 | unsigned long long cpu_user; 8 | unsigned long long cpu_nice; 9 | unsigned long long cpu_sys; 10 | unsigned long long cpu_idle; 11 | unsigned long long cpu_iowait; 12 | unsigned long long cpu_steal; 13 | unsigned long long cpu_hardirq; 14 | unsigned long long cpu_softirq; 15 | unsigned long long cpu_guest; 16 | unsigned long long cpu_number; 17 | }; 18 | 19 | #define STATS_CPU_SIZE (sizeof(struct stats_cpu)) 20 | 21 | static char *cpu_usage = " --cpu CPU share (user, system, interrupt, nice, & idle)"; 22 | static int cpu_quota = 1; 23 | 24 | 25 | static void 26 | read_cpu_stats(struct module *mod) 27 | { 28 | FILE *fp, *ncpufp; 29 | char *max_cpu; 30 | char line[LEN_4096]; 31 | char buf[LEN_4096]; 32 | struct stats_cpu st_cpu; 33 | 34 | memset(buf, 0, LEN_4096); 35 | memset(&st_cpu, 0, sizeof(struct stats_cpu)); 36 | //get cpu number for cpushare 37 | max_cpu = getenv("SIGMA_MAX_CPU_QUOTA"); 38 | cpu_quota = max_cpu ? atoi(max_cpu) / 100 : 1; 39 | //unsigned long long cpu_util; 40 | if ((fp = fopen(STAT, "r")) == NULL) { 41 | return; 42 | } 43 | while (fgets(line, LEN_4096, fp) != NULL) { 44 | if (!strncmp(line, "cpu ", 4)) { 45 | /* 46 | * Read the number of jiffies spent in the different modes 47 | * (user, nice, etc.) among all proc. CPU usage is not reduced 48 | * to one processor to avoid rounding problems. 49 | */ 50 | sscanf(line + 5, "%llu %llu %llu %llu %llu %llu %llu %llu %llu", 51 | &st_cpu.cpu_user, 52 | &st_cpu.cpu_nice, 53 | &st_cpu.cpu_sys, 54 | &st_cpu.cpu_idle, 55 | &st_cpu.cpu_iowait, 56 | &st_cpu.cpu_hardirq, 57 | &st_cpu.cpu_softirq, 58 | &st_cpu.cpu_steal, 59 | &st_cpu.cpu_guest); 60 | } 61 | } 62 | 63 | /* get cpu number */ 64 | if ((ncpufp = fopen("/proc/cpuinfo", "r")) == NULL) { 65 | fclose(fp); 66 | return; 67 | } 68 | while (fgets(line, LEN_4096, ncpufp)) { 69 | if (!strncmp(line, "processor\t:", 11)) 70 | st_cpu.cpu_number++; 71 | } 72 | fclose(ncpufp); 73 | 74 | /* cpu_util = */ 75 | /* st_cpu.cpu_user + st_cpu.cpu_sys + */ 76 | /* st_cpu.cpu_hardirq + st_cpu.cpu_softirq; */ 77 | 78 | sprintf(buf, "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu", 79 | /* the store order is not same as read procedure */ 80 | st_cpu.cpu_user, 81 | st_cpu.cpu_sys, 82 | st_cpu.cpu_iowait, 83 | st_cpu.cpu_hardirq, 84 | st_cpu.cpu_softirq, 85 | st_cpu.cpu_idle, 86 | st_cpu.cpu_nice, 87 | st_cpu.cpu_steal, 88 | st_cpu.cpu_guest, 89 | st_cpu.cpu_number); 90 | 91 | set_mod_record(mod, buf); 92 | if (fclose(fp) < 0) { 93 | return; 94 | } 95 | } 96 | 97 | static void 98 | set_cpu_record(struct module *mod, double st_array[], 99 | U_64 pre_array[], U_64 cur_array[], int inter) 100 | { 101 | int i, j; 102 | char *max_cpu; 103 | U_64 pre_total, cur_total; 104 | 105 | //get cpu number for cpushare 106 | max_cpu = getenv("SIGMA_MAX_CPU_QUOTA"); 107 | cpu_quota = max_cpu ? atoi(max_cpu) / 100 : 1; 108 | 109 | pre_total = cur_total = 0; 110 | 111 | for (i = 0; i < 9; i++) { 112 | if(cur_array[i] < pre_array[i]){ 113 | for(j = 0; j < 9; j++) 114 | st_array[j] = -1; 115 | return; 116 | } 117 | pre_total += pre_array[i]; 118 | cur_total += cur_array[i]; 119 | } 120 | 121 | /* no tick changes, or tick overflows */ 122 | if (cur_total <= pre_total) { 123 | for(j = 0; j < 9; j++) 124 | st_array[j] = -1; 125 | return; 126 | } 127 | 128 | /* set st record */ 129 | for (i = 0; i < 9; i++) { 130 | /* st_array[5] is util, calculate it late */ 131 | if((i != 5) && (cur_array[i] >= pre_array[i])) 132 | st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total); 133 | } 134 | 135 | /* util = 100 - idle - iowait - steal */ 136 | if (cur_array[5] >= pre_array[5]) { 137 | st_array[5] = 100.0 - (cur_array[5] - pre_array[5]) * 100.0 / (cur_total - pre_total) - st_array[2] - st_array[7]; 138 | } 139 | if (cpu_quota > 1) { 140 | for (i = 0; i < 9; i++) { 141 | st_array[i] = st_array[i] * cur_array[9] / cpu_quota; 142 | } 143 | } 144 | 145 | st_array[9] = cur_array[9]; 146 | /* util = user + sys + hirq + sirq + nice */ 147 | //st_array[5] = st_array[0] + st_array[1] + st_array[3] + st_array[4] + st_array[6]; 148 | } 149 | 150 | static struct mod_info cpu_info[] = { 151 | {" user", DETAIL_BIT, 0, STATS_NULL}, 152 | {" sys", DETAIL_BIT, 0, STATS_NULL}, 153 | {" wait", DETAIL_BIT, 0, STATS_NULL}, 154 | {" hirq", DETAIL_BIT, 0, STATS_NULL}, 155 | {" sirq", DETAIL_BIT, 0, STATS_NULL}, 156 | {" util", SUMMARY_BIT, 0, STATS_NULL}, 157 | {" nice", HIDE_BIT, 0, STATS_NULL}, 158 | {" steal", HIDE_BIT, 0, STATS_NULL}, 159 | {" guest", HIDE_BIT, 0, STATS_NULL}, 160 | {" ncpu", HIDE_BIT, 0, STATS_NULL}, 161 | }; 162 | 163 | void 164 | mod_register(struct module *mod) 165 | { 166 | register_mod_fields(mod, "--cpu", cpu_usage, cpu_info, 10, read_cpu_stats, set_cpu_record); 167 | } 168 | -------------------------------------------------------------------------------- /modules/mod_load.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | #define LOAD_DETAIL_HDR(d) \ 4 | " runq"d" plist"d" min1"d \ 5 | " min5"d" min15" 6 | 7 | #define LOAD_STORE_FMT(d) \ 8 | "%ld"d"%d"d"%d"d"%d"d"%d" 9 | 10 | char *load_usage = " --load System Run Queue and load average"; 11 | 12 | /* Structure for queue and load statistics */ 13 | struct stats_load { 14 | unsigned long nr_running; 15 | unsigned int load_avg_1; 16 | unsigned int load_avg_5; 17 | unsigned int load_avg_15; 18 | unsigned int nr_threads; 19 | }; 20 | 21 | #define STATS_LOAD_SIZE (sizeof(struct stats_load)) 22 | 23 | void 24 | read_stat_load(struct module *mod) 25 | { 26 | int load_tmp[3]; 27 | FILE *fp; 28 | char buf[LEN_4096]; 29 | struct stats_load st_load; 30 | memset(buf, 0, LEN_4096); 31 | memset(&st_load, 0, sizeof(struct stats_load)); 32 | 33 | if ((fp = fopen(LOADAVG, "r")) == NULL) { 34 | return; 35 | } 36 | 37 | /* Read load averages and queue length */ 38 | if (fscanf(fp, "%d.%d %d.%d %d.%d %ld/%d %*d\n", 39 | &load_tmp[0], &st_load.load_avg_1, 40 | &load_tmp[1], &st_load.load_avg_5, 41 | &load_tmp[2], &st_load.load_avg_15, 42 | &st_load.nr_running, 43 | &st_load.nr_threads) != 8) 44 | { 45 | fclose(fp); 46 | return; 47 | } 48 | st_load.load_avg_1 += load_tmp[0] * 100; 49 | st_load.load_avg_5 += load_tmp[1] * 100; 50 | st_load.load_avg_15 += load_tmp[2] * 100; 51 | 52 | if (st_load.nr_running) { 53 | /* Do not take current process into account */ 54 | st_load.nr_running--; 55 | } 56 | 57 | sprintf(buf , "%u,%u,%u,%lu,%u", 58 | st_load.load_avg_1, 59 | st_load.load_avg_5, 60 | st_load.load_avg_15, 61 | st_load.nr_running, 62 | st_load.nr_threads); 63 | set_mod_record(mod, buf); 64 | fclose(fp); 65 | } 66 | 67 | static void 68 | set_load_record(struct module *mod, double st_array[], 69 | U_64 pre_array[], U_64 cur_array[], int inter) 70 | { 71 | int i; 72 | for (i = 0; i < 3; i++) { 73 | st_array[i] = cur_array[i] / 100.0; 74 | } 75 | st_array[3] = cur_array[3]; 76 | st_array[4] = cur_array[4]; 77 | } 78 | 79 | static struct mod_info load_info[] = { 80 | {" load1", SUMMARY_BIT, 0, STATS_NULL}, 81 | {" load5", DETAIL_BIT, 0, STATS_NULL}, 82 | {"load15", DETAIL_BIT, 0, STATS_NULL}, 83 | {" runq", DETAIL_BIT, 0, STATS_NULL}, 84 | {" plit", DETAIL_BIT, 0, STATS_NULL} 85 | }; 86 | 87 | void 88 | mod_register(struct module *mod) 89 | { 90 | register_mod_fields(mod, "--load", load_usage, load_info, 5, read_stat_load, set_load_record); 91 | } 92 | 93 | -------------------------------------------------------------------------------- /modules/mod_lvs.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include "tsar.h" 3 | 4 | #define LVS_PROC_STATS "/proc/net/ip_vs_stats" 5 | #define LVS_CONN_PROC_STATS "/proc/net/ip_vs_conn_stats" 6 | 7 | #define LVS_CMD "sudo /usr/local/sbin/slb_admin -ln --total --dump" 8 | #define LVS_CONN_CMD "sudo /usr/local/sbin/appctl -csa" 9 | 10 | #define LVS_CMD_PATH "/usr/local/sbin/slb_admin" 11 | #define LVS_STORE_FMT(d) \ 12 | "%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d\ 13 | "%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld"d"%lld" 14 | #define MAX_LINE_LEN 1024 15 | struct stats_lvs{ 16 | unsigned long long stat; 17 | unsigned long long conns; 18 | unsigned long long pktin; 19 | unsigned long long pktout; 20 | unsigned long long bytin; 21 | unsigned long long bytout; 22 | 23 | unsigned long long total_conns; /* total conns */ 24 | unsigned long long local_conns; /* local conns */ 25 | unsigned long long act_conns; /* active conns */ 26 | unsigned long long inact_conns; /* inactive conns */ 27 | unsigned long long sync_conns; /* sync conns */ 28 | unsigned long long sync_act_conns; /* sync active conns */ 29 | unsigned long long sync_inact_conns; /* sync inactive conns */ 30 | unsigned long long template_conns; /* template conns */ 31 | }; 32 | #define STATS_LVS_SIZE (sizeof(struct stats_lvs)) 33 | 34 | static struct mod_info info[] = { 35 | {" stat", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 36 | {" conns", SUMMARY_BIT, MERGE_NULL, STATS_SUB_INTER}, 37 | {" pktin", DETAIL_BIT, MERGE_NULL, STATS_SUB_INTER}, 38 | {"pktout", DETAIL_BIT, MERGE_NULL, STATS_SUB_INTER}, 39 | {" bytin", DETAIL_BIT, MERGE_NULL, STATS_SUB_INTER}, 40 | {"bytout", DETAIL_BIT, MERGE_NULL, STATS_SUB_INTER}, 41 | {" total", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 42 | {" local", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 43 | {" lact", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 44 | {"linact", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 45 | {" sync", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 46 | {" sact", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 47 | {"sinact", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 48 | {" templ", DETAIL_BIT, MERGE_NULL, STATS_NULL}, 49 | }; 50 | 51 | static char *lvs_usage = " --lvs lvs connections and packets and bytes in/out"; 52 | struct stats_lvs st_lvs; 53 | /* 54 | ******************************************************* 55 | * Read swapping statistics from ip_vs_stat 56 | ******************************************************* 57 | */ 58 | static void 59 | read_lvs_stat(int has_netframe) 60 | { 61 | int i = 0, use_popen = 0; 62 | char tmp[5][16]; 63 | FILE *fp = NULL; 64 | char line[MAX_LINE_LEN]; 65 | 66 | if (has_netframe) { 67 | fp = popen(LVS_CMD, "r"); 68 | use_popen = 1; 69 | } else if (!access(LVS_PROC_STATS, F_OK)) 70 | fp = fopen(LVS_PROC_STATS, "r"); 71 | 72 | if (!fp) 73 | return; 74 | 75 | st_lvs.stat = 1; 76 | while (fgets(line, MAX_LINE_LEN, fp) != NULL) { 77 | i++; 78 | if (i < 3) { 79 | continue; 80 | } 81 | if (!strncmp(line, "CPU", 3)) { 82 | /* CPU 0: 5462458943 44712664864 54084995692 8542115117674 41738811918899 */ 83 | int k = 0; 84 | k = strcspn(line, ":"); 85 | sscanf(line + k + 1, "%s %s %s %s %s", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]); 86 | st_lvs.conns += strtoll(tmp[0], NULL, 10); 87 | st_lvs.pktin += strtoll(tmp[1], NULL, 10); 88 | st_lvs.pktout += strtoll(tmp[2], NULL, 10); 89 | st_lvs.bytin += strtoll(tmp[3], NULL, 10); 90 | st_lvs.bytout += strtoll(tmp[4], NULL, 10); 91 | } else { 92 | /* 218EEA1A 1B3BA96D 0 163142140FA1F 0 */ 93 | sscanf(line, "%s %s %s %s %s", tmp[0], tmp[1], tmp[2], tmp[3], tmp[4]); 94 | st_lvs.conns += strtoll(tmp[0], NULL ,16); 95 | st_lvs.pktin += strtoll(tmp[1], NULL, 16); 96 | st_lvs.pktout += strtoll(tmp[2], NULL, 16); 97 | st_lvs.bytin += strtoll(tmp[3], NULL, 16); 98 | st_lvs.bytout += strtoll(tmp[4], NULL, 16); 99 | break; 100 | } 101 | } 102 | 103 | if (use_popen) 104 | pclose(fp); 105 | else 106 | fclose(fp); 107 | } 108 | 109 | static void 110 | read_lvs_conn_stat(int has_netframe) 111 | { 112 | int use_popen = 0; 113 | FILE *fp = NULL; 114 | char line[MAX_LINE_LEN]; 115 | 116 | if (has_netframe) { 117 | fp = popen(LVS_CONN_CMD, "r"); 118 | use_popen = 1; 119 | } else if (!access(LVS_CONN_PROC_STATS, F_OK)) 120 | fp = fopen(LVS_CONN_PROC_STATS, "r"); 121 | 122 | if (!fp) 123 | return; 124 | 125 | while (fgets(line, MAX_LINE_LEN, fp) != NULL) { 126 | 127 | if (has_netframe) { 128 | unsigned long long *item = NULL; 129 | 130 | /* Example: 131 | total_conns : 0 132 | local_conns : 0 133 | local_active_conns : 0 134 | local_inactive_conns : 0 135 | sync_conns : 0 136 | sync_active_conns : 0 137 | sync_inactive_conns : 0 138 | template_conns : 0 139 | */ 140 | if (!strncmp(line, "total_conns", 11)) 141 | item = &st_lvs.total_conns; 142 | else if (!strncmp(line, "local_conns", 11)) 143 | item = &st_lvs.local_conns; 144 | else if (!strncmp(line, "local_active_conns", 18)) 145 | item = &st_lvs.act_conns; 146 | else if (!strncmp(line, "local_inactive_conns", 20)) 147 | item = &st_lvs.inact_conns; 148 | else if (!strncmp(line, "sync_conns", 10)) 149 | item = &st_lvs.sync_conns; 150 | else if (!strncmp(line, "sync_active_conns", 16)) 151 | item = &st_lvs.sync_act_conns; 152 | else if (!strncmp(line, "sync_inactive_conns", 18)) 153 | item = &st_lvs.sync_inact_conns; 154 | else if (!strncmp(line, "template_conns", 10)) 155 | item = &st_lvs.template_conns; 156 | 157 | if (item) 158 | *item = strtoll(strchr(line, ':') + 1, NULL, 10); 159 | 160 | } else { 161 | /* Example: 162 | PersistConns: 17 163 | 164 | Total Local Sync LocAct SynAct LocInAct SynInAct Flush Flush 165 | Conns Conns Conns Conns Conns Conns Conns Threshold State 166 | CPU0 : 58094 14710 43384 9522 28133 5188 15251 0 N/A 167 | CPU11: 49888 12589 37299 7657 22498 4932 14801 0 N/A 168 | TOTAL: 603642 151514 452128 90610 269578 60904 182550 0 N/A 169 | */ 170 | if (!strncmp(line, "PersistConns", 12)) { 171 | st_lvs.template_conns = strtoll(strchr(line, ':') + 1, NULL, 10); 172 | } else if (!strncmp(line, "TOTAL", 5)) { 173 | char tmp[7][16]; 174 | 175 | sscanf(strchr(line, ':') + 1, "%s %s %s %s %s %s %s", 176 | tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6]); 177 | 178 | st_lvs.total_conns = strtoll(tmp[0], NULL, 10); 179 | st_lvs.local_conns = strtoll(tmp[1], NULL, 10); 180 | st_lvs.sync_conns = strtoll(tmp[2], NULL, 10); 181 | st_lvs.act_conns = strtoll(tmp[3], NULL, 10); 182 | st_lvs.sync_act_conns = strtoll(tmp[4], NULL, 10); 183 | st_lvs.inact_conns = strtoll(tmp[5], NULL, 10); 184 | st_lvs.sync_inact_conns = strtoll(tmp[6], NULL, 10); 185 | } 186 | } 187 | } 188 | 189 | if (use_popen) 190 | pclose(fp); 191 | else 192 | fclose(fp); 193 | } 194 | 195 | static void 196 | read_lvs(struct module *mod) 197 | { 198 | char buf[512] = { 0 }; 199 | int pos = 0, has_netframe = 0; 200 | 201 | memset(&st_lvs, 0, sizeof(struct stats_lvs)); 202 | 203 | if (!access(LVS_CMD_PATH, F_OK | X_OK)) 204 | has_netframe = 1; 205 | 206 | read_lvs_stat(has_netframe); 207 | 208 | read_lvs_conn_stat(has_netframe); 209 | 210 | if (st_lvs.stat == 1) { 211 | pos = sprintf(buf, LVS_STORE_FMT(DATA_SPLIT), 212 | st_lvs.stat, st_lvs.conns, 213 | st_lvs.pktin, st_lvs.pktout, st_lvs.bytin, st_lvs.bytout, 214 | st_lvs.total_conns, st_lvs.local_conns, st_lvs.act_conns, st_lvs.inact_conns, 215 | st_lvs.sync_conns, st_lvs.sync_act_conns, st_lvs.sync_inact_conns, 216 | st_lvs.template_conns); 217 | } else { 218 | return; 219 | } 220 | 221 | buf[pos] = '\0'; 222 | set_mod_record(mod, buf); 223 | return; 224 | } 225 | 226 | 227 | void 228 | mod_register(struct module *mod) 229 | { 230 | register_mod_fields(mod, "--lvs", lvs_usage, info, sizeof(info)/sizeof(struct mod_info), read_lvs, NULL); 231 | } 232 | -------------------------------------------------------------------------------- /modules/mod_mem.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | char *mem_usage = 4 | " --mem Physical memory share (active, inactive, cached, free, wired)"; 5 | 6 | /* Structure for memory and swap space utilization statistics */ 7 | struct stats_mem { 8 | unsigned long frmkb; 9 | unsigned long bufkb; 10 | unsigned long camkb; 11 | unsigned long tlmkb; 12 | unsigned long acmkb; 13 | unsigned long iamkb; 14 | unsigned long slmkb; 15 | unsigned long frskb; 16 | unsigned long tlskb; 17 | unsigned long caskb; 18 | unsigned long comkb; 19 | }; 20 | 21 | static void 22 | read_mem_stats(struct module *mod) 23 | { 24 | FILE *fp; 25 | char line[LEN_128]; 26 | char buf[LEN_4096]; 27 | struct stats_mem st_mem; 28 | 29 | memset(buf, 0, LEN_4096); 30 | memset(&st_mem, 0, sizeof(struct stats_mem)); 31 | if ((fp = fopen(MEMINFO, "r")) == NULL) { 32 | return; 33 | } 34 | 35 | while (fgets(line, 128, fp) != NULL) { 36 | 37 | if (!strncmp(line, "MemTotal:", 9)) { 38 | /* Read the total amount of memory in kB */ 39 | sscanf(line + 9, "%lu", &st_mem.tlmkb); 40 | } 41 | else if (!strncmp(line, "MemFree:", 8)) { 42 | /* Read the amount of free memory in kB */ 43 | sscanf(line + 8, "%lu", &st_mem.frmkb); 44 | } 45 | else if (!strncmp(line, "Buffers:", 8)) { 46 | /* Read the amount of buffered memory in kB */ 47 | sscanf(line + 8, "%lu", &st_mem.bufkb); 48 | } 49 | else if (!strncmp(line, "Cached:", 7)) { 50 | /* Read the amount of cached memory in kB */ 51 | sscanf(line + 7, "%lu", &st_mem.camkb); 52 | } 53 | else if (!strncmp(line, "Active:", 7)) { 54 | /* Read the amount of Active memory in kB */ 55 | sscanf(line + 7, "%lu", &st_mem.acmkb); 56 | } 57 | else if (!strncmp(line, "Inactive:", 9)) { 58 | /* Read the amount of Inactive memory in kB */ 59 | sscanf(line + 9, "%lu", &st_mem.iamkb); 60 | } 61 | else if (!strncmp(line, "Slab:", 5)) { 62 | /* Read the amount of Slab memory in kB */ 63 | sscanf(line + 5, "%lu", &st_mem.slmkb); 64 | } 65 | else if (!strncmp(line, "SwapCached:", 11)) { 66 | /* Read the amount of cached swap in kB */ 67 | sscanf(line + 11, "%lu", &st_mem.caskb); 68 | } 69 | else if (!strncmp(line, "SwapTotal:", 10)) { 70 | /* Read the total amount of swap memory in kB */ 71 | sscanf(line + 10, "%lu", &st_mem.tlskb); 72 | } 73 | else if (!strncmp(line, "SwapFree:", 9)) { 74 | /* Read the amount of free swap memory in kB */ 75 | sscanf(line + 9, "%lu", &st_mem.frskb); 76 | } 77 | else if (!strncmp(line, "Committed_AS:", 13)) { 78 | /* Read the amount of commited memory in kB */ 79 | sscanf(line + 13, "%lu", &st_mem.comkb); 80 | } 81 | } 82 | 83 | int pos = sprintf(buf, "%lu,%u,%lu,%lu,%lu,%u", 84 | st_mem.frmkb, 85 | 0, /* used */ 86 | st_mem.bufkb, 87 | st_mem.camkb, 88 | st_mem.tlmkb, 89 | 0 /* util */); 90 | buf[pos] = '\0'; 91 | set_mod_record(mod, buf); 92 | fclose(fp); 93 | return; 94 | } 95 | static void 96 | set_mem_record(struct module *mod, double st_array[], 97 | U_64 pre_array[], U_64 cur_array[], int inter) 98 | { 99 | int i; 100 | if ((cur_array[4] - cur_array[0] -cur_array[2] -cur_array[3]) < 0) { 101 | for (i = 0; i < 6; i++) 102 | st_array[i] = -1; 103 | return; 104 | } 105 | st_array[0] = cur_array[0]<<10; 106 | st_array[1] = (cur_array[4] - cur_array[0] -cur_array[2] -cur_array[3])<<10; 107 | st_array[2] = cur_array[2]<<10; 108 | st_array[3] = cur_array[3]<<10; 109 | st_array[4] = cur_array[4]<<10; 110 | st_array[5] = st_array[1] * 100.0 / (cur_array[4]<<10); 111 | } 112 | 113 | static struct mod_info mem_info[] = { 114 | {" free", DETAIL_BIT, 0, STATS_NULL}, 115 | {" used", DETAIL_BIT, 0, STATS_NULL}, 116 | {" buff", DETAIL_BIT, 0, STATS_NULL}, 117 | {" cach", DETAIL_BIT, 0, STATS_NULL}, 118 | {" total", DETAIL_BIT, 0, STATS_NULL}, 119 | {" util", SUMMARY_BIT, 0, STATS_NULL} 120 | }; 121 | 122 | void 123 | mod_register(struct module *mod) 124 | { 125 | register_mod_fields(mod, "--mem", mem_usage, mem_info, 6, read_mem_stats, set_mem_record); 126 | } 127 | -------------------------------------------------------------------------------- /modules/mod_ncpu.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | /* 4 | * Structure for CPU infomation. 5 | */ 6 | struct stats_cpu { 7 | unsigned long long cpu_user; 8 | unsigned long long cpu_nice; 9 | unsigned long long cpu_sys; 10 | unsigned long long cpu_idle; 11 | unsigned long long cpu_iowait; 12 | unsigned long long cpu_steal; 13 | unsigned long long cpu_hardirq; 14 | unsigned long long cpu_softirq; 15 | unsigned long long cpu_guest; 16 | }; 17 | 18 | #define STATS_CPU_SIZE (sizeof(struct stats_cpu)) 19 | 20 | static char *cpu_usage = " --ncpu CPU share (user, system, interrupt, nice, & idle)"; 21 | 22 | 23 | static void 24 | read_cpu_stats(struct module *mod) 25 | { 26 | int pos = 0; 27 | char line[LEN_1M]; 28 | char buf[LEN_1M]; 29 | char cpuname[16]; 30 | FILE *fp; 31 | struct stats_cpu st_cpu; 32 | 33 | memset(buf, 0, LEN_1M); 34 | memset(&st_cpu, 0, sizeof(struct stats_cpu)); 35 | if ((fp = fopen(STAT, "r")) == NULL) { 36 | return; 37 | } 38 | while (fgets(line, LEN_1M, fp) != NULL) { 39 | if (!strncmp(line, "cpu", 3)) { 40 | /* 41 | * Read the number of jiffies spent in the different modes 42 | * (user, nice, etc.) among all proc. CPU usage is not reduced 43 | * to one processor to avoid rounding problems. 44 | */ 45 | sscanf(line, "%s", cpuname); 46 | if(strcmp(cpuname, "cpu") == 0) 47 | continue; 48 | sscanf(line + strlen(cpuname), "%llu %llu %llu %llu %llu %llu %llu %llu %llu", 49 | &st_cpu.cpu_user, 50 | &st_cpu.cpu_nice, 51 | &st_cpu.cpu_sys, 52 | &st_cpu.cpu_idle, 53 | &st_cpu.cpu_iowait, 54 | &st_cpu.cpu_hardirq, 55 | &st_cpu.cpu_softirq, 56 | &st_cpu.cpu_steal, 57 | &st_cpu.cpu_guest); 58 | 59 | pos += snprintf(buf + pos, LEN_1M - pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu" ITEM_SPLIT, 60 | /* the store order is not same as read procedure */ 61 | cpuname, 62 | st_cpu.cpu_user, 63 | st_cpu.cpu_sys, 64 | st_cpu.cpu_iowait, 65 | st_cpu.cpu_hardirq, 66 | st_cpu.cpu_softirq, 67 | st_cpu.cpu_idle, 68 | st_cpu.cpu_nice, 69 | st_cpu.cpu_steal, 70 | st_cpu.cpu_guest); 71 | if (strlen(buf) == LEN_1M - 1) { 72 | fclose(fp); 73 | return; 74 | } 75 | } 76 | } 77 | set_mod_record(mod, buf); 78 | fclose(fp); 79 | return; 80 | } 81 | 82 | static void 83 | set_cpu_record(struct module *mod, double st_array[], 84 | U_64 pre_array[], U_64 cur_array[], int inter) 85 | { 86 | int i; 87 | U_64 pre_total, cur_total; 88 | pre_total = cur_total = 0; 89 | 90 | for (i = 0; i < mod->n_col; i++) { 91 | pre_total += pre_array[i]; 92 | cur_total += cur_array[i]; 93 | } 94 | /* set st record */ 95 | for (i = 0; i <= 4; i++) { 96 | if(cur_array[i] >= pre_array[i]) 97 | st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total); 98 | } 99 | if(cur_array[5] >= pre_array[5]) 100 | st_array[5] = 100.0 - (cur_array[5] - pre_array[5]) * 100.0 / (cur_total - pre_total); 101 | } 102 | 103 | static struct mod_info cpu_info[] = { 104 | {" user", DETAIL_BIT, 0, STATS_NULL}, 105 | {" sys", DETAIL_BIT, 0, STATS_NULL}, 106 | {" wait", DETAIL_BIT, 0, STATS_NULL}, 107 | {" hirq", DETAIL_BIT, 0, STATS_NULL}, 108 | {" sirq", DETAIL_BIT, 0, STATS_NULL}, 109 | {" util", SUMMARY_BIT, 0, STATS_NULL}, 110 | {" nice", HIDE_BIT, 0, STATS_NULL}, 111 | {" steal", HIDE_BIT, 0, STATS_NULL}, 112 | {" guest", HIDE_BIT, 0, STATS_NULL}, 113 | }; 114 | 115 | void 116 | mod_register(struct module *mod) 117 | { 118 | register_mod_fields(mod, "--ncpu", cpu_usage, cpu_info, 9, read_cpu_stats, set_cpu_record); 119 | } 120 | -------------------------------------------------------------------------------- /modules/mod_nginx.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "tsar.h" 7 | 8 | struct stats_nginx { 9 | unsigned long long naccept; /* accepted connections */ 10 | unsigned long long nhandled; /* handled connections */ 11 | unsigned long long nrequest; /* handled requests */ 12 | unsigned long long nactive; /* number of all open connections including connections to backends */ 13 | unsigned long long nreading; /* nginx reads request header */ 14 | unsigned long long nwriting; /* nginx reads request body, processes request, or writes response to a client */ 15 | unsigned long long nwaiting; /* keep-alive connections, actually it is active - (reading + writing) */ 16 | unsigned long long nrstime; /* reponse time of handled requests */ 17 | unsigned long long nspdy; /* spdy requests */ 18 | unsigned long long nsslhds; /* ssl handshake */ 19 | unsigned long long nssl; /* ssl requests */ 20 | unsigned long long nsslk; /* ssl keepalive requests */ 21 | unsigned long long nsslf; /* ssl failed request */ 22 | unsigned long long nsslv3f; /* sslv3 failed request */ 23 | unsigned long long nhttp2; /* http2 requests */ 24 | }; 25 | 26 | struct hostinfo { 27 | char *host; 28 | int port; 29 | char *server_name; 30 | char *uri; 31 | }; 32 | 33 | static char *nginx_usage = " --nginx nginx statistics"; 34 | 35 | static struct mod_info nginx_info[] = { 36 | {"accept", DETAIL_BIT, 0, STATS_SUB}, 37 | {"handle", DETAIL_BIT, 0, STATS_SUB}, 38 | {" reqs", DETAIL_BIT, 0, STATS_SUB}, 39 | {"active", DETAIL_BIT, 0, STATS_NULL}, 40 | {" read", DETAIL_BIT, 0, STATS_NULL}, 41 | {" write", DETAIL_BIT, 0, STATS_NULL}, 42 | {" wait", DETAIL_BIT, 0, STATS_NULL}, 43 | {" qps", SUMMARY_BIT, 0, STATS_SUB_INTER}, 44 | {" rt", SUMMARY_BIT, 0, STATS_NULL}, 45 | {"sslqps", SUMMARY_BIT, 0, STATS_SUB_INTER}, 46 | {"spdyps", SUMMARY_BIT, 0, STATS_SUB_INTER}, 47 | {" sslf", SUMMARY_BIT, 0, STATS_SUB_INTER}, 48 | {"sslv3f", SUMMARY_BIT, 0, STATS_SUB_INTER}, 49 | {" h2qps", SUMMARY_BIT, 0, STATS_SUB_INTER}, 50 | {"sslhds", SUMMARY_BIT, 0, STATS_SUB_INTER}, 51 | {" sslk", SUMMARY_BIT, 0, STATS_SUB_INTER}, 52 | }; 53 | 54 | 55 | static void 56 | set_nginx_record(struct module *mod, double st_array[], 57 | U_64 pre_array[], U_64 cur_array[], int inter) 58 | { 59 | int i; 60 | for (i = 0; i < 3; i++) { 61 | if (cur_array[i] >= pre_array[i]) { 62 | st_array[i] = cur_array[i] - pre_array[i]; 63 | } else { 64 | st_array[i] = 0; 65 | } 66 | } 67 | 68 | for (i = 3; i < 7; i++) { 69 | st_array[i] = cur_array[i]; 70 | } 71 | 72 | if (cur_array[2] >= pre_array[2]) { 73 | st_array[7] = (cur_array[2] - pre_array[2]) * 1.0 / inter; 74 | } else { 75 | st_array[7] = 0; 76 | } 77 | 78 | if (cur_array[8] >= pre_array[8]) { 79 | if (cur_array[2] > pre_array[2]) { 80 | st_array[8] = (cur_array[8] - pre_array[8]) * 1.0 / (cur_array[2] - pre_array[2]); 81 | } else { 82 | st_array[8] = 0; 83 | } 84 | } 85 | 86 | for (i = 9; i < 16; i++){ 87 | if (cur_array[i] >= pre_array[i]) { 88 | st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter; 89 | } else { 90 | st_array[i] = 0; 91 | } 92 | } 93 | } 94 | 95 | 96 | static void 97 | init_nginx_host_info(struct hostinfo *p) 98 | { 99 | char *port; 100 | 101 | p->host = getenv("NGX_TSAR_HOST"); 102 | p->host = p->host ? p->host : "127.0.0.1"; 103 | 104 | port = getenv("NGX_TSAR_PORT"); 105 | p->port = port ? atoi(port) : 80; 106 | 107 | p->uri = getenv("NGX_TSAR_URI"); 108 | p->uri = p->uri ? p->uri : "/nginx_status"; 109 | 110 | p->server_name = getenv("NGX_TSAR_SERVER_NAME"); 111 | p->server_name = p->server_name ? p->server_name : "status.taobao.com"; 112 | } 113 | 114 | 115 | static void 116 | read_nginx_stats(struct module *mod, char *parameter) 117 | { 118 | int write_flag = 0, addr_len, domain; 119 | int m, sockfd, send, pos; 120 | void *addr; 121 | char buf[LEN_4096], request[LEN_4096], line[LEN_4096]; 122 | FILE *stream = NULL; 123 | 124 | struct timeval timeout; 125 | struct hostinfo hinfo; 126 | struct sockaddr_in servaddr; 127 | struct sockaddr_un servaddr_un; 128 | 129 | 130 | init_nginx_host_info(&hinfo); 131 | if (atoi(parameter) != 0) { 132 | hinfo.port = atoi(parameter); 133 | } 134 | struct stats_nginx st_nginx; 135 | memset(&st_nginx, 0, sizeof(struct stats_nginx)); 136 | 137 | if (*hinfo.host == '/') { 138 | addr = &servaddr_un; 139 | addr_len = sizeof(servaddr_un); 140 | bzero(addr, addr_len); 141 | domain = AF_LOCAL; 142 | servaddr_un.sun_family = AF_LOCAL; 143 | strncpy(servaddr_un.sun_path, hinfo.host, sizeof(servaddr_un.sun_path) - 1); 144 | 145 | } else { 146 | addr = &servaddr; 147 | addr_len = sizeof(servaddr); 148 | bzero(addr, addr_len); 149 | domain = AF_INET; 150 | servaddr.sin_family = AF_INET; 151 | servaddr.sin_port = htons(hinfo.port); 152 | inet_pton(AF_INET, hinfo.host, &servaddr.sin_addr); 153 | } 154 | 155 | if ((sockfd = socket(domain, SOCK_STREAM, 0)) == -1) { 156 | goto writebuf; 157 | } 158 | 159 | sprintf(request, 160 | "GET %s HTTP/1.0\r\n" 161 | "User-Agent: taobot\r\n" 162 | "Host: %s\r\n" 163 | "Accept:*/*\r\n" 164 | "Connection: Close\r\n\r\n", 165 | hinfo.uri, hinfo.server_name); 166 | 167 | if ((m = connect(sockfd, (struct sockaddr *) addr, addr_len)) == -1 ) { 168 | goto writebuf; 169 | } 170 | 171 | timeout.tv_sec = 10; 172 | timeout.tv_usec = 0; 173 | setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(struct timeval)); 174 | setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)); 175 | 176 | if ((send = write(sockfd, request, strlen(request))) == -1) { 177 | goto writebuf; 178 | } 179 | 180 | if ((stream = fdopen(sockfd, "r")) == NULL) { 181 | goto writebuf; 182 | } 183 | 184 | while (fgets(line, LEN_4096, stream) != NULL) { 185 | if (!strncmp(line, "Active connections:", sizeof("Active connections:") - 1)) { 186 | sscanf(line + sizeof("Active connections:"), "%llu", &st_nginx.nactive); 187 | write_flag = 1; 188 | } else if (!strncmp(line, 189 | "server accepts handled requests request_time", 190 | sizeof("server accepts handled requests request_time") - 1) 191 | ) { 192 | /*for tengine*/ 193 | if (fgets(line, LEN_4096, stream) != NULL) { 194 | if (!strncmp(line, " ", 1)) { 195 | sscanf(line + 1, "%llu %llu %llu %llu", 196 | &st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest, &st_nginx.nrstime); 197 | write_flag = 1; 198 | } 199 | } 200 | } else if (!strncmp(line, 201 | "server accepts handled requests", 202 | sizeof("server accepts handled requests") - 1) 203 | ) { 204 | /*for nginx*/ 205 | if (fgets(line, LEN_4096, stream) != NULL) { 206 | if (!strncmp(line, " ", 1)) { 207 | sscanf(line + 1, "%llu %llu %llu", 208 | &st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest); 209 | write_flag = 1; 210 | } 211 | } 212 | } else if (!strncmp(line, "Server accepts:", sizeof("Server accepts:") - 1)) { 213 | sscanf(line , "Server accepts: %llu handled: %llu requests: %llu request_time: %llu", 214 | &st_nginx.naccept, &st_nginx.nhandled, &st_nginx.nrequest, &st_nginx.nrstime); 215 | write_flag = 1; 216 | 217 | } else if (!strncmp(line, "Reading:", sizeof("Reading:") - 1)) { 218 | sscanf(line, "Reading: %llu Writing: %llu Waiting: %llu", 219 | &st_nginx.nreading, &st_nginx.nwriting, &st_nginx.nwaiting); 220 | write_flag = 1; 221 | } else if (!strncmp(line, "SSL:", sizeof("SSL:") - 1)) { 222 | sscanf(line, "SSL: %llu SPDY: %llu", 223 | &st_nginx.nssl, &st_nginx.nspdy); 224 | write_flag = 1; 225 | } else if (!strncmp(line, "HTTP2:", sizeof("HTTP2:") - 1)) { 226 | sscanf(line, "HTTP2: %llu", 227 | &st_nginx.nhttp2); 228 | write_flag = 1; 229 | } else if (!strncmp(line, "SSL_failed:", sizeof("SSL_failed:") - 1)) { 230 | sscanf(line, "SSL_failed: %llu", 231 | &st_nginx.nsslf); 232 | write_flag = 1; 233 | } else if (!strncmp(line, "SSLv3_failed:", sizeof("SSLv3_failed:") - 1)) { 234 | sscanf(line, "SSLv3_failed: %llu", 235 | &st_nginx.nsslv3f); 236 | write_flag = 1; 237 | } else if (!strncmp(line, "SSL_handshake:", sizeof("SSL_handshake:") - 1)) { 238 | sscanf(line, "SSL_handshake: %llu", 239 | &st_nginx.nsslhds); 240 | write_flag = 1; 241 | } else if (!strncmp(line, "SSL_keepalive_reqs:", sizeof("SSL_keepalive_reqs:") - 1)) { 242 | sscanf(line, "SSL_keepalive_reqs: %llu", 243 | &st_nginx.nsslk); 244 | write_flag = 1; 245 | } else { 246 | ; 247 | } 248 | } 249 | if (st_nginx.nrequest == 0) { 250 | write_flag = 0; 251 | } 252 | 253 | writebuf: 254 | if (stream) { 255 | fclose(stream); 256 | } 257 | 258 | if (sockfd != -1) { 259 | close(sockfd); 260 | } 261 | 262 | if (write_flag) { 263 | pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld", 264 | st_nginx.naccept, 265 | st_nginx.nhandled, 266 | st_nginx.nrequest, 267 | st_nginx.nactive, 268 | st_nginx.nreading, 269 | st_nginx.nwriting, 270 | st_nginx.nwaiting, 271 | st_nginx.nrequest, 272 | st_nginx.nrstime, 273 | st_nginx.nssl, 274 | st_nginx.nspdy, 275 | st_nginx.nsslf, 276 | st_nginx.nsslv3f, 277 | st_nginx.nhttp2, 278 | st_nginx.nsslhds, 279 | st_nginx.nsslk 280 | ); 281 | buf[pos] = '\0'; 282 | set_mod_record(mod, buf); 283 | } 284 | } 285 | 286 | void 287 | mod_register(struct module *mod) 288 | { 289 | register_mod_fields(mod, "--nginx", nginx_usage, nginx_info, 16, read_nginx_stats, set_nginx_record); 290 | } 291 | -------------------------------------------------------------------------------- /modules/mod_partition.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "tsar.h" 4 | 5 | #define TRUE 1 6 | #define FALSE 0 7 | 8 | char *partition_usage = " --partition Disk and partition usage"; 9 | 10 | 11 | #define MAXPART 32 12 | 13 | struct stats_partition { 14 | int bsize; /* block size*/ 15 | unsigned long long blocks; /* total blocks*/ 16 | unsigned long long bfree; /* free for non root user*/ 17 | unsigned long long bavail; /* avail for root*/ 18 | unsigned long long itotal; 19 | unsigned long long ifree; 20 | }; 21 | #define STATS_PARTITION_SIZE (sizeof(struct stats_partition)) 22 | 23 | int 24 | __read_partition_stat(char *fsname, struct stats_partition *sp) 25 | { 26 | struct statfs fsbuf; 27 | if (!statfs(fsname, &fsbuf)) { 28 | sp->bsize = fsbuf.f_bsize; 29 | sp->blocks = fsbuf.f_blocks; 30 | sp->bfree = fsbuf.f_bfree; 31 | sp->bavail = fsbuf.f_bavail; 32 | sp->itotal = fsbuf.f_files; 33 | sp->ifree = fsbuf.f_ffree; 34 | } 35 | return 0; 36 | } 37 | 38 | int 39 | store_single_partition(char *buf, char *mntpath, struct stats_partition *sp, int size) 40 | { 41 | int len = 0; 42 | int k = 1; 43 | if (sp->bsize % 1024 != 0) { 44 | return len; 45 | } else { 46 | k = sp->bsize / 1024; 47 | } 48 | len += snprintf(buf + len, size, "%s=%d,%lld,%lld,%lld,%lld,%lld" ITEM_SPLIT, 49 | mntpath, 50 | sp->bsize / k, 51 | sp->bfree * k, 52 | sp->blocks * k, 53 | sp->bavail * k, 54 | sp->ifree, 55 | sp->itotal); 56 | return len; 57 | } 58 | 59 | 60 | void 61 | read_partition_stat(struct module *mod) 62 | { 63 | int part_nr, pos = 0; 64 | char buf[LEN_1M]; 65 | FILE *mntfile; 66 | struct mntent *mnt = NULL; 67 | struct stats_partition temp; 68 | 69 | memset(buf, 0, LEN_1M); 70 | memset(&temp, 0, sizeof(temp)); 71 | 72 | /* part_nr = count_partition_nr(NULL); */ 73 | 74 | mntfile = setmntent("/etc/mtab", "r"); 75 | 76 | /* init part_nr */ 77 | part_nr = 0; 78 | /* traverse the mount table */ 79 | while ((mnt = getmntent(mntfile)) != NULL) { 80 | /* only recore block filesystems */ 81 | if (! strncmp(mnt->mnt_fsname, "/", 1)) { 82 | /* we only read MAXPART partition */ 83 | if (part_nr >= MAXPART) break; 84 | /* read each partition infomation */ 85 | __read_partition_stat(mnt->mnt_dir, &temp); 86 | 87 | /* print log to the buffer */ 88 | pos += store_single_partition(buf + pos, mnt->mnt_dir, &temp, LEN_1M - pos); 89 | if (strlen(buf) == LEN_1M - 1) { 90 | return; 91 | } 92 | /* successful read */ 93 | part_nr++; 94 | /* move the pointer to the next structure */ 95 | } 96 | } 97 | endmntent(mntfile); 98 | set_mod_record(mod, buf); 99 | return; 100 | } 101 | 102 | static void 103 | set_part_record(struct module *mod, double st_array[], U_64 pre_array[], U_64 cur_array[], int inter) 104 | { 105 | st_array[0] = cur_array[3] * cur_array[0]; 106 | st_array[1] = (cur_array[2] - cur_array[1]) * cur_array[0]; 107 | st_array[2] = cur_array[2] * cur_array[0]; 108 | 109 | U_64 used = cur_array[2] - cur_array[1]; 110 | U_64 nonroot_total = cur_array[2] - cur_array[1] + cur_array[3]; 111 | 112 | if(nonroot_total != 0) { 113 | st_array[3]= (used * 100.0) / nonroot_total + ((used * 100) % nonroot_total != 0); 114 | } 115 | if (st_array[3] > 100) { 116 | st_array[3] = 100; 117 | } 118 | st_array[4] = cur_array[4]; 119 | st_array[5] = cur_array[5]; 120 | if (cur_array[5] >= cur_array[4] && cur_array[5] != 0) { 121 | st_array[6] = (cur_array[5] - cur_array[4]) * 100.0 / cur_array[5]; 122 | } 123 | } 124 | 125 | static struct mod_info part_info[] = { 126 | {" bfree", DETAIL_BIT, MERGE_AVG, STATS_NULL}, 127 | {" bused", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 128 | {" btotl", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 129 | {" util", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 130 | {" ifree", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 131 | {" itotl", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 132 | {" iutil", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 133 | }; 134 | 135 | void 136 | mod_register(struct module *mod) 137 | { 138 | register_mod_fields(mod, "--partition", partition_usage, part_info, 7, read_partition_stat, set_part_record); 139 | } 140 | -------------------------------------------------------------------------------- /modules/mod_pcsw.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | 4 | char *pcsw_usage = " --pcsw Process (task) creation and context switch"; 5 | 6 | struct stats_pcsw { 7 | unsigned long long context_switch; 8 | unsigned long processes; 9 | }; 10 | 11 | #define STATS_PCSW_SIZE sizeof(struct pcsw_stats) 12 | 13 | enum {PROC, CSWCH}; 14 | 15 | 16 | /* 17 | *************************************************************************** 18 | * Read processes (tasks) creation and context switches statistics from 19 | * /proc/stat 20 | * 21 | *************************************************************************** 22 | */ 23 | void 24 | read_stat_pcsw(struct module *mod) 25 | { 26 | FILE *fp; 27 | char line[LEN_4096]; 28 | char buf[LEN_4096]; 29 | struct stats_pcsw st_pcsw; 30 | 31 | memset(buf, 0, LEN_4096); 32 | memset(&st_pcsw, 0, sizeof(struct stats_pcsw)); 33 | 34 | if ((fp = fopen(STAT, "r")) == NULL) { 35 | return; 36 | } 37 | while (fgets(line, LEN_4096, fp) != NULL) { 38 | 39 | if (!strncmp(line, "ctxt ", 5)) { 40 | /* Read number of context switches */ 41 | sscanf(line + 5, "%llu", &st_pcsw.context_switch); 42 | } 43 | 44 | else if (!strncmp(line, "processes ", 10)) { 45 | /* Read number of processes created since system boot */ 46 | sscanf(line + 10, "%lu", &st_pcsw.processes); 47 | } 48 | } 49 | int pos = sprintf(buf, "%lld,%ld", 50 | st_pcsw.context_switch, 51 | st_pcsw.processes); 52 | buf[pos] = '\0'; 53 | set_mod_record(mod, buf); 54 | fclose(fp); 55 | } 56 | 57 | static struct mod_info pcsw_info[] = { 58 | {" cswch", DETAIL_BIT, 0, STATS_SUB_INTER}, 59 | {" proc", DETAIL_BIT, 0, STATS_SUB_INTER} 60 | }; 61 | 62 | void 63 | mod_register(struct module *mod) 64 | { 65 | register_mod_fields(mod, "--pcsw", pcsw_usage, pcsw_info, 2, read_stat_pcsw, NULL); 66 | } 67 | 68 | -------------------------------------------------------------------------------- /modules/mod_percpu.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | #define STAT_PATH "/proc/stat" 4 | 5 | static char *percpu_usage = " --percpu Per cpu share (user, system, interrupt, nice, & idle)"; 6 | 7 | struct stats_percpu { 8 | unsigned long long cpu_user; 9 | unsigned long long cpu_nice; 10 | unsigned long long cpu_sys; 11 | unsigned long long cpu_idle; 12 | unsigned long long cpu_iowait; 13 | unsigned long long cpu_steal; 14 | unsigned long long cpu_hardirq; 15 | unsigned long long cpu_softirq; 16 | unsigned long long cpu_guest; 17 | char cpu_name[10]; 18 | }; 19 | 20 | #define STATS_PERCPU_SIZE (sizeof(struct stats_percpu)) 21 | 22 | static void 23 | read_percpu_stats(struct module *mod) 24 | { 25 | int pos = 0, cpus = 0; 26 | FILE *fp; 27 | char line[LEN_1M]; 28 | char buf[LEN_1M]; 29 | struct stats_percpu st_percpu; 30 | 31 | memset(buf, 0, LEN_1M); 32 | memset(&st_percpu, 0, STATS_PERCPU_SIZE); 33 | if ((fp = fopen(STAT_PATH, "r")) == NULL) { 34 | return; 35 | } 36 | while (fgets(line, LEN_1M, fp) != NULL) { 37 | if (!strncmp(line, "cpu", 3)) { 38 | /* 39 | * Read the number of jiffies spent in the different modes 40 | * (user, nice, etc.) among all proc. CPU usage is not reduced 41 | * to one processor to avoid rounding problems. 42 | */ 43 | sscanf(line, "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu", 44 | st_percpu.cpu_name, 45 | &st_percpu.cpu_user, 46 | &st_percpu.cpu_nice, 47 | &st_percpu.cpu_sys, 48 | &st_percpu.cpu_idle, 49 | &st_percpu.cpu_iowait, 50 | &st_percpu.cpu_hardirq, 51 | &st_percpu.cpu_softirq, 52 | &st_percpu.cpu_steal, 53 | &st_percpu.cpu_guest); 54 | if (st_percpu.cpu_name[3] == '\0') //ignore cpu summary stat 55 | continue; 56 | 57 | pos += snprintf(buf + pos, LEN_1M - pos, "%s=%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu" ITEM_SPLIT, 58 | /* the store order is not same as read procedure */ 59 | st_percpu.cpu_name, 60 | st_percpu.cpu_user, 61 | st_percpu.cpu_sys, 62 | st_percpu.cpu_iowait, 63 | st_percpu.cpu_hardirq, 64 | st_percpu.cpu_softirq, 65 | st_percpu.cpu_idle, 66 | st_percpu.cpu_nice, 67 | st_percpu.cpu_steal, 68 | st_percpu.cpu_guest); 69 | if (strlen(buf) == LEN_1M - 1) { 70 | fclose(fp); 71 | return; 72 | } 73 | cpus++; 74 | } 75 | } 76 | set_mod_record(mod, buf); 77 | fclose(fp); 78 | return; 79 | } 80 | 81 | static void 82 | set_percpu_record(struct module *mod, double st_array[], 83 | U_64 pre_array[], U_64 cur_array[], int inter) 84 | { 85 | int i, j; 86 | U_64 pre_total, cur_total; 87 | pre_total = cur_total = 0; 88 | 89 | for (i = 0; i < mod->n_col; i++) { 90 | if(cur_array[i] < pre_array[i]){ 91 | for(j = 0; j < 9; j++) 92 | st_array[j] = -1; 93 | return; 94 | } 95 | pre_total += pre_array[i]; 96 | cur_total += cur_array[i]; 97 | } 98 | 99 | /* no tick changes, or tick overflows */ 100 | if (cur_total <= pre_total) 101 | return; 102 | /* set st record */ 103 | for (i = 0; i < 9; i++) { 104 | /* st_array[5] is util, calculate it late */ 105 | if((i != 5) && (cur_array[i] >= pre_array[i])) 106 | st_array[i] = (cur_array[i] - pre_array[i]) * 100.0 / (cur_total - pre_total); 107 | } 108 | 109 | /* util = user + sys + hirq + sirq + nice */ 110 | st_array[5] = st_array[0] + st_array[1] + st_array[3] + st_array[4] + st_array[6]; 111 | } 112 | 113 | static struct mod_info percpu_info[] = { 114 | {" user", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 115 | {" sys", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 116 | {" wait", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 117 | {" hirq", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 118 | {" sirq", DETAIL_BIT, MERGE_SUM, STATS_NULL}, 119 | {" util", SUMMARY_BIT, MERGE_SUM, STATS_NULL}, 120 | {" nice", HIDE_BIT, MERGE_SUM, STATS_NULL}, 121 | {" steal", HIDE_BIT, MERGE_SUM, STATS_NULL}, 122 | {" guest", HIDE_BIT, MERGE_SUM, STATS_NULL}, 123 | }; 124 | 125 | void 126 | mod_register(struct module *mod) 127 | { 128 | register_mod_fields(mod, "--percpu", percpu_usage, percpu_info, 9, read_percpu_stats, set_percpu_record); 129 | } 130 | -------------------------------------------------------------------------------- /modules/mod_pernic.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | char *pernic_usage = " --pernic Net pernic statistics"; 4 | 5 | #define MAX_NICS 8 6 | 7 | /* 8 | * Structure for pernic infomation. 9 | */ 10 | struct stats_pernic { 11 | unsigned long long bytein; 12 | unsigned long long byteout; 13 | unsigned long long pktin; 14 | unsigned long long pktout; 15 | char name[16]; 16 | }; 17 | 18 | #define STATS_TRAFFIC_SIZE (sizeof(struct stats_pernic)) 19 | 20 | 21 | /* 22 | * collect pernic infomation 23 | */ 24 | static void 25 | read_pernic_stats(struct module *mod) 26 | { 27 | int pos = 0, nics = 0; 28 | FILE *fp; 29 | char line[LEN_1M] = {0}; 30 | char buf[LEN_1M] = {0}; 31 | struct stats_pernic st_pernic; 32 | 33 | memset(buf, 0, LEN_1M); 34 | memset(&st_pernic, 0, sizeof(struct stats_pernic)); 35 | 36 | if ((fp = fopen(NET_DEV, "r")) == NULL) { 37 | return; 38 | } 39 | 40 | while (fgets(line, LEN_1M, fp) != NULL) { 41 | memset(&st_pernic, 0, sizeof(st_pernic)); 42 | if (!strstr(line, ":")) { 43 | continue; 44 | } 45 | sscanf(line, "%*[^a-z]%[^:]:%llu %llu %*u %*u %*u %*u %*u %*u " 46 | "%llu %llu %*u %*u %*u %*u %*u %*u", 47 | st_pernic.name, 48 | &st_pernic.bytein, 49 | &st_pernic.pktin, 50 | &st_pernic.byteout, 51 | &st_pernic.pktout); 52 | /* if nic not used, skip it */ 53 | if (st_pernic.bytein == 0) { 54 | continue; 55 | } 56 | 57 | pos += snprintf(buf + pos, LEN_1M - pos, "%s=%lld,%lld,%lld,%lld" ITEM_SPLIT, 58 | st_pernic.name, 59 | st_pernic.bytein, 60 | st_pernic.byteout, 61 | st_pernic.pktin, 62 | st_pernic.pktout); 63 | if (strlen(buf) == LEN_1M - 1) { 64 | fclose(fp); 65 | return; 66 | } 67 | 68 | nics++; 69 | if (nics > MAX_NICS) { 70 | break; 71 | } 72 | } 73 | 74 | set_mod_record(mod, buf); 75 | fclose(fp); 76 | return; 77 | } 78 | 79 | static struct mod_info pernic_info[] = { 80 | {" bytin", SUMMARY_BIT, MERGE_SUM, STATS_SUB_INTER}, 81 | {"bytout", SUMMARY_BIT, MERGE_SUM, STATS_SUB_INTER}, 82 | {" pktin", DETAIL_BIT, MERGE_SUM, STATS_SUB_INTER}, 83 | {"pktout", DETAIL_BIT, MERGE_SUM, STATS_SUB_INTER} 84 | }; 85 | 86 | void 87 | mod_register(struct module *mod) 88 | { 89 | register_mod_fields(mod, "--pernic", pernic_usage, pernic_info, 4, read_pernic_stats, NULL); 90 | } 91 | -------------------------------------------------------------------------------- /modules/mod_proc.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | /* 4 | * Structure for Proc infomation. 5 | */ 6 | struct stats_proc { 7 | unsigned long long user_cpu; 8 | unsigned long long sys_cpu; 9 | unsigned long long total_cpu; 10 | unsigned long long mem; 11 | unsigned long long total_mem; 12 | unsigned long long read_bytes; 13 | unsigned long long write_bytes; 14 | }; 15 | 16 | #define PID_IO "/proc/%u/io" 17 | #define PID_STAT "/proc/%u/stat" 18 | #define PID_STATUS "/proc/%u/status" 19 | #define STATS_PROC_SIZE (sizeof(struct stats_proc)) 20 | 21 | static char *proc_usage = " --proc PROC info (mem cpu usage & io/fd info)"; 22 | 23 | 24 | static void 25 | read_proc_stats(struct module *mod, char *parameter) 26 | { 27 | int nb = 0, pid[16]; 28 | char buf[LEN_4096]; 29 | char filename[128], line[256]; 30 | FILE *fp; 31 | struct stats_proc st_proc; 32 | 33 | memset(&st_proc, 0, sizeof(struct stats_proc)); 34 | 35 | /* get pid by proc name */ 36 | if (strlen(parameter) > 20) { 37 | return; 38 | } 39 | char cmd[32] = "pidof "; 40 | strncat(cmd, parameter, sizeof(cmd) - strlen(cmd) -1); 41 | char spid[256]; 42 | fp = popen(cmd, "r"); 43 | if (fp == NULL) { 44 | return; 45 | } 46 | if(fscanf(fp, "%s", spid) == EOF) { 47 | pclose(fp); 48 | return; 49 | } 50 | pclose(fp); 51 | /* split pidof into array pid */ 52 | char *p; 53 | p = strtok(spid, " "); 54 | while (p) { 55 | pid[nb] = atoi(p); 56 | if (pid[nb++] <= 0) { 57 | return; 58 | } 59 | if (nb >= 16) { 60 | return; 61 | } 62 | p = strtok(NULL, " "); 63 | } 64 | /* get all pid's info */ 65 | while (--nb >= 0) { 66 | unsigned long long data; 67 | /* read values from /proc/pid/stat */ 68 | sprintf(filename, PID_STAT, pid[nb]); 69 | if ((fp = fopen(filename, "r")) == NULL) { 70 | return; 71 | } 72 | unsigned long long cpudata[4]; 73 | if (fgets(line, 256, fp) == NULL) { 74 | fclose(fp); 75 | return; 76 | } 77 | 78 | if ((p = strstr(line, ")")) == NULL) { 79 | fclose(fp); 80 | return; 81 | } 82 | if (sscanf(p, "%*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu %llu %llu", 83 | &cpudata[0], &cpudata[1], &cpudata[2], &cpudata[3]) == EOF) { 84 | fclose(fp); 85 | return; 86 | } 87 | st_proc.user_cpu += cpudata[0]; 88 | st_proc.user_cpu += cpudata[2]; 89 | st_proc.sys_cpu += cpudata[1]; 90 | st_proc.sys_cpu += cpudata[3]; 91 | fclose(fp); 92 | /* get cpu&mem info from /proc/pid/status */ 93 | sprintf(filename, PID_STATUS, pid[nb]); 94 | if ((fp = fopen(filename, "r")) == NULL) { 95 | return; 96 | } 97 | while (fgets(line, 256, fp) != NULL) { 98 | if (!strncmp(line, "VmRSS:", 6)) { 99 | sscanf(line + 6, "%llu", &data); 100 | st_proc.mem += data * 1024; 101 | } 102 | } 103 | fclose(fp); 104 | /* get io info from /proc/pid/io */ 105 | sprintf(filename, PID_IO, pid[nb]); 106 | if ((fp = fopen(filename, "r")) == NULL) { 107 | return; 108 | } 109 | while (fgets(line, 256, fp) != NULL) { 110 | if (!strncmp(line, "read_bytes:", 11)) { 111 | sscanf(line + 11, "%llu", &data); 112 | st_proc.read_bytes += data; 113 | } 114 | else if (!strncmp(line, "write_bytes:", 12)) { 115 | sscanf(line + 12, "%llu", &data); 116 | st_proc.write_bytes += data; 117 | } 118 | } 119 | fclose(fp); 120 | } 121 | 122 | /* read+calc cpu total time from /proc/stat */ 123 | fp = fopen("/proc/stat", "r"); 124 | if (fp == NULL) { 125 | fclose(fp); 126 | return; 127 | } 128 | unsigned long long cpu_time[10]; 129 | bzero(cpu_time, sizeof(cpu_time)); 130 | if (fscanf(fp, "%*s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu", 131 | &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3], 132 | &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7], 133 | &cpu_time[8], &cpu_time[9]) == EOF) { 134 | fclose(fp); 135 | return; 136 | } 137 | fclose(fp); 138 | int i; 139 | for(i=0; i < 10;i++) { 140 | st_proc.total_cpu += cpu_time[i]; 141 | } 142 | /* read total mem from /proc/meminfo */ 143 | fp = fopen("/proc/meminfo", "r"); 144 | if (fp == NULL) { 145 | fclose(fp); 146 | return; 147 | } 148 | if (fscanf(fp, "MemTotal: %llu kB", &st_proc.total_mem) == EOF) { 149 | fclose(fp); 150 | return; 151 | } 152 | st_proc.total_mem *= 1024; 153 | fclose(fp); 154 | /* store data to tsar */ 155 | int pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld", 156 | st_proc.user_cpu, 157 | st_proc.sys_cpu, 158 | st_proc.total_cpu, 159 | st_proc.total_mem, 160 | st_proc.mem, 161 | st_proc.read_bytes, 162 | st_proc.write_bytes 163 | ); 164 | if (pos >= 0) buf[pos] = '\0'; 165 | set_mod_record(mod, buf); 166 | } 167 | 168 | static void 169 | set_proc_record(struct module *mod, double st_array[], 170 | U_64 pre_array[], U_64 cur_array[], int inter) 171 | { 172 | if (cur_array[2] > pre_array[2]) { 173 | st_array[2] = cur_array[2] - pre_array[2]; 174 | } else { 175 | st_array[2] = 0; 176 | return; 177 | } 178 | if (cur_array[0] >= pre_array[0]) { 179 | st_array[0] = (cur_array[0] - pre_array[0]) * 100.0 / st_array[2]; 180 | } else { 181 | st_array[0] = 0; 182 | } 183 | if (cur_array[1] >= pre_array[1]) { 184 | st_array[1] = (cur_array[1] - pre_array[1]) * 100.0 / st_array[2]; 185 | } else { 186 | st_array[1] = 0; 187 | } 188 | st_array[3] = cur_array[4] * 100.0 / cur_array[3]; 189 | st_array[4] = cur_array[4]; 190 | if (cur_array[5] >= pre_array[5]) { 191 | st_array[5] = (cur_array[5] - pre_array[5]) * 1.0 / inter; 192 | } else { 193 | st_array[5] = 0; 194 | } 195 | if (cur_array[6] >= pre_array[6]) { 196 | st_array[6] = (cur_array[6] - pre_array[6]) * 1.0 / inter; 197 | } else { 198 | st_array[5] = 0; 199 | } 200 | } 201 | 202 | static struct mod_info proc_info[] = { 203 | {" user", SUMMARY_BIT, 0, STATS_NULL}, 204 | {" sys", SUMMARY_BIT, 0, STATS_NULL}, 205 | {" total", HIDE_BIT, 0, STATS_NULL}, 206 | {" mem", SUMMARY_BIT, 0, STATS_NULL}, 207 | {" RSS", DETAIL_BIT, 0, STATS_NULL}, 208 | {" read", DETAIL_BIT, 0, STATS_NULL}, 209 | {" write", DETAIL_BIT, 0, STATS_NULL}, 210 | }; 211 | 212 | void 213 | mod_register(struct module *mod) 214 | { 215 | register_mod_fields(mod, "--proc", proc_usage, proc_info, 7, read_proc_stats, set_proc_record); 216 | } 217 | -------------------------------------------------------------------------------- /modules/mod_swap.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | struct stats_swap { 4 | unsigned long long pswpin; 5 | unsigned long long pswpout; 6 | unsigned long long swaptotal; 7 | unsigned long long swapfree; 8 | }; 9 | 10 | 11 | #define STATS_SWAP_SIZE (sizeof(struct stats_swap)) 12 | 13 | static char *swap_usage = " --swap swap usage"; 14 | 15 | /* 16 | ************************************************************* 17 | * Read swapping statistics from /proc/vmstat & /proc/meminfo. 18 | ************************************************************* 19 | */ 20 | static void 21 | read_vmstat_swap(struct module *mod) 22 | { 23 | FILE *fp; 24 | char line[LEN_4096], buf[LEN_4096]; 25 | struct stats_swap st_swap; 26 | 27 | memset(buf, 0, LEN_4096); 28 | memset(&st_swap, 0, sizeof(struct stats_swap)); 29 | /* read /proc/vmstat*/ 30 | if ((fp = fopen(VMSTAT, "r")) == NULL) { 31 | return ; 32 | } 33 | 34 | while (fgets(line, LEN_4096, fp) != NULL) { 35 | 36 | if (!strncmp(line, "pswpin ", 7)) { 37 | /* Read number of swap pages brought in */ 38 | sscanf(line + 7, "%llu", &st_swap.pswpin); 39 | 40 | } else if (!strncmp(line, "pswpout ", 8)) { 41 | /* Read number of swap pages brought out */ 42 | sscanf(line + 8, "%llu", &st_swap.pswpout); 43 | } 44 | } 45 | fclose(fp); 46 | /* read /proc/meminfo */ 47 | if ((fp = fopen(MEMINFO, "r")) == NULL) { 48 | return; 49 | } 50 | 51 | while (fgets(line, LEN_4096, fp) != NULL) { 52 | if (!strncmp(line, "SwapTotal:", 10)) { 53 | sscanf(line + 10, "%llu", &st_swap.swaptotal); 54 | 55 | } else if (!strncmp(line, "SwapFree:", 9)) { 56 | sscanf(line + 9, "%llu", &st_swap.swapfree); 57 | } 58 | } 59 | fclose(fp); 60 | 61 | sprintf(buf, "%lld,%lld,%lld,%lld", st_swap.pswpin, st_swap.pswpout, st_swap.swaptotal*1024, st_swap.swapfree*1024); 62 | set_mod_record(mod, buf); 63 | return; 64 | } 65 | 66 | static void 67 | set_swap_record(struct module *mod, double st_array[], 68 | U_64 pre_array[], U_64 cur_array[], int inter) 69 | { 70 | if (cur_array[0] >= pre_array[0]) { 71 | st_array[0] = (cur_array[0] - pre_array[0]) / inter; 72 | 73 | } else { 74 | st_array[0] = 0; 75 | } 76 | 77 | if (cur_array[1] >= pre_array[1]) { 78 | st_array[1] = (cur_array[1] - pre_array[1]) / inter; 79 | 80 | } else { 81 | st_array[1] = 0; 82 | } 83 | 84 | /* calc total swap and use util */ 85 | st_array[2] = cur_array[2]; 86 | st_array[3] = 100.0 - cur_array[3] * 100.0 / cur_array[2]; 87 | } 88 | 89 | static struct mod_info swap_info[] = { 90 | {" swpin", DETAIL_BIT, 0, STATS_NULL}, 91 | {"swpout", DETAIL_BIT, 0, STATS_NULL}, 92 | {" total", DETAIL_BIT, 0, STATS_NULL}, 93 | {" util", DETAIL_BIT, 0, STATS_NULL} 94 | }; 95 | 96 | void 97 | mod_register(struct module *mod) 98 | { 99 | register_mod_fields(mod, "--swap", swap_usage, swap_info, 4, read_vmstat_swap, set_swap_record); 100 | } 101 | -------------------------------------------------------------------------------- /modules/mod_tcp.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | 4 | char *tcp_usage = 5 | " --tcp TCP traffic (v4)"; 6 | 7 | /* Structure for TCP statistics */ 8 | struct stats_tcp { 9 | unsigned long long ActiveOpens; 10 | unsigned long long PassiveOpens; 11 | unsigned long long InSegs; 12 | unsigned long long OutSegs; 13 | unsigned long long AttemptFails; 14 | unsigned long long EstabResets; 15 | unsigned long long CurrEstab; 16 | unsigned long long RetransSegs; 17 | unsigned long long InErrs; 18 | unsigned long long OutRsts; 19 | }; 20 | 21 | #define STATS_TCP_SIZE (sizeof(struct stats_tcp)) 22 | 23 | void 24 | read_tcp_stats(struct module *mod) 25 | { 26 | int sw = FALSE; 27 | FILE *fp; 28 | char line[LEN_1024]; 29 | char buf[LEN_1024]; 30 | struct stats_tcp st_tcp; 31 | 32 | memset(buf, 0, LEN_1024); 33 | memset(&st_tcp, 0, sizeof(struct stats_tcp)); 34 | if ((fp = fopen(NET_SNMP, "r")) == NULL) { 35 | return; 36 | } 37 | 38 | while (fgets(line, LEN_1024, fp) != NULL) { 39 | if (!strncmp(line, "Tcp:", 4)) { 40 | if (sw) { 41 | sscanf(line + 4, "%*u %*u %*u %*d %llu %llu " 42 | "%llu %llu %llu %llu %llu %llu %llu %llu", 43 | &st_tcp.ActiveOpens, 44 | &st_tcp.PassiveOpens, 45 | &st_tcp.AttemptFails, 46 | &st_tcp.EstabResets, 47 | &st_tcp.CurrEstab, 48 | &st_tcp.InSegs, 49 | &st_tcp.OutSegs, 50 | &st_tcp.RetransSegs, 51 | &st_tcp.InErrs, 52 | &st_tcp.OutRsts); 53 | break; 54 | 55 | } else { 56 | sw = TRUE; 57 | } 58 | } 59 | } 60 | 61 | fclose(fp); 62 | 63 | int pos = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld,%lld,%lld", 64 | st_tcp.ActiveOpens, 65 | st_tcp.PassiveOpens, 66 | st_tcp.InSegs, 67 | st_tcp.OutSegs, 68 | st_tcp.EstabResets, 69 | st_tcp.AttemptFails, 70 | st_tcp.CurrEstab, 71 | st_tcp.RetransSegs); 72 | 73 | buf[pos] = '\0'; 74 | set_mod_record(mod, buf); 75 | } 76 | 77 | static void 78 | set_tcp_record(struct module *mod, double st_array[], 79 | U_64 pre_array[], U_64 cur_array[], int inter) 80 | { 81 | int i; 82 | for (i = 0; i < 6; i++) { 83 | if (cur_array[i] >= pre_array[i]) { 84 | st_array[i] = (cur_array[i] - pre_array[i]) * 1.0 / inter; 85 | } 86 | } 87 | /* 6 is for st_tcp.CurrEstab */ 88 | st_array[6] = cur_array[6]; 89 | /* as for st_tcp.RetransSegs, we calculate the retransfer radio. Retrans/outSegs */ 90 | if ((cur_array[7] >= pre_array[7]) && (cur_array[3] > pre_array[3])) { 91 | st_array[7] = (cur_array[7]- pre_array[7]) * 100.0 / (cur_array[3]- pre_array[3]); 92 | } 93 | if (st_array[7] > 100.0) { 94 | st_array[7] = 100.0; 95 | } 96 | } 97 | 98 | static struct mod_info tcp_info[] = { 99 | {"active", DETAIL_BIT, 0, STATS_SUB_INTER}, 100 | {"pasive", DETAIL_BIT, 0, STATS_SUB_INTER}, 101 | {" iseg", DETAIL_BIT, 0, STATS_SUB_INTER}, 102 | {"outseg", DETAIL_BIT, 0, STATS_SUB_INTER}, 103 | {"EstReset", DETAIL_BIT, 0, STATS_SUB_INTER}, 104 | {"AtmpFail", DETAIL_BIT, 0, STATS_SUB_INTER}, 105 | {"CurrEstab", DETAIL_BIT, 0, STATS_SUB_INTER}, 106 | {"retran", SUMMARY_BIT, 0, STATS_SUB_INTER} 107 | }; 108 | 109 | void 110 | mod_register(struct module *mod) 111 | { 112 | register_mod_fields(mod, "--tcp", tcp_usage, tcp_info, 8, read_tcp_stats, set_tcp_record); 113 | } 114 | -------------------------------------------------------------------------------- /modules/mod_tcpx.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | char * tcpx_usage=" --tcpx TCP connection data"; 4 | 5 | struct stats_tcpx{ 6 | unsigned long long tcprecvq; 7 | unsigned long long tcpsendq; 8 | unsigned long long tcpest; 9 | unsigned long long tcptimewait; 10 | unsigned long long tcpfinwait1; 11 | unsigned long long tcpfinwait2; 12 | unsigned long long tcplistenq; 13 | unsigned long long tcplistenincq; 14 | unsigned long long tcplistenover; 15 | unsigned long long tcpnconnest; 16 | unsigned long long tcpnconndrop; 17 | unsigned long long tcpembdrop; 18 | unsigned long long tcprexmitdrop; 19 | unsigned long long tcppersistdrop; 20 | unsigned long long tcpkadrop; 21 | }; 22 | 23 | static void 24 | read_stat_tcpx(struct module *mod) 25 | { 26 | int sw; 27 | FILE *fp_tcp; 28 | FILE *fp_snmp; 29 | FILE *fp_netstat; 30 | char buf[LEN_4096], line[LEN_4096]; 31 | struct stats_tcpx st_tcpx; 32 | 33 | memset(buf, 0, LEN_4096); 34 | memset(&st_tcpx, 0, sizeof(struct stats_tcpx)); 35 | 36 | fp_tcp = fopen(TCP, "r"); 37 | if (fp_tcp == NULL) { 38 | return; 39 | } 40 | 41 | fp_snmp = fopen(NET_SNMP, "r"); 42 | if (fp_snmp == NULL) { 43 | fclose(fp_tcp); 44 | return; 45 | } 46 | fp_netstat = fopen(NETSTAT, "r"); 47 | if (fp_netstat == NULL) { 48 | fclose(fp_snmp); 49 | fclose(fp_tcp); 50 | return; 51 | } 52 | st_tcpx.tcplistenq = 0; 53 | st_tcpx.tcplistenincq = 0; 54 | 55 | sw = 0; 56 | while (fgets(line, LEN_4096, fp_netstat) !=NULL) { 57 | if (!strncmp(line, "TcpExt:", 7)) { 58 | if (!sw) {sw = 1; continue;} 59 | sscanf(line + 7, 60 | "%*u %*u %*u %*u %*u %*u %*u %*u %*u " 61 | "%*u %*u %*u %*u %*u %*u %*u %*u %*u " 62 | "%*u %llu %*u %*u %*u %*u %*u %*u %*u " 63 | "%*u %*u %*u %*u %*u %*u %*u %*u %*u " 64 | "%*u %*u %*u %*u %*u %*u %*u %*u %*u " 65 | "%*u %*u %*u %*u %*u %*u %*u %*u %*u " 66 | "%*u %*u %*u %llu %*u %*u %*u %llu", 67 | &st_tcpx.tcplistenover, 68 | &st_tcpx.tcpembdrop, 69 | &st_tcpx.tcprexmitdrop); 70 | break; 71 | } 72 | } 73 | sw = 0; 74 | unsigned long activeopen, passiveopen; 75 | activeopen = 0; 76 | passiveopen = 0; 77 | while (fgets(line, LEN_4096, fp_snmp) !=NULL) { 78 | if (!strncmp(line, "Tcp:", 4)) { 79 | if (!sw) {sw = 1; continue;} 80 | sscanf(line + 4, "%*u %*u %*u %*d %lu %lu", 81 | &activeopen, &passiveopen); 82 | break; 83 | } 84 | } 85 | 86 | st_tcpx.tcpnconnest = activeopen + passiveopen; 87 | st_tcpx.tcpnconndrop = 0; 88 | st_tcpx.tcppersistdrop = 0; 89 | st_tcpx.tcpkadrop = 0; 90 | 91 | sprintf(buf, 92 | "%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu," 93 | "%llu,%llu,%llu,%llu,%llu,%llu,%llu", 94 | st_tcpx.tcprecvq, 95 | st_tcpx.tcpsendq, 96 | st_tcpx.tcpest, 97 | st_tcpx.tcptimewait, 98 | st_tcpx.tcpfinwait1, 99 | st_tcpx.tcpfinwait2, 100 | st_tcpx.tcplistenq, 101 | st_tcpx.tcplistenincq, 102 | st_tcpx.tcplistenover, 103 | st_tcpx.tcpnconnest, 104 | st_tcpx.tcpnconndrop, 105 | st_tcpx.tcpembdrop, 106 | st_tcpx.tcprexmitdrop, 107 | st_tcpx.tcppersistdrop, 108 | st_tcpx.tcpkadrop); 109 | set_mod_record(mod, buf); 110 | fclose(fp_tcp); 111 | fclose(fp_snmp); 112 | fclose(fp_netstat); 113 | } 114 | 115 | static struct mod_info tcpx_info[]={ 116 | {" recvq", DETAIL_BIT, 0, STATS_NULL}, 117 | {" sendq", DETAIL_BIT, 0, STATS_NULL}, 118 | {" est", DETAIL_BIT, 0, STATS_NULL}, 119 | {" twait", DETAIL_BIT, 0, STATS_NULL}, 120 | {"fwait1", DETAIL_BIT, 0, STATS_NULL}, 121 | {"fwait2", DETAIL_BIT, 0, STATS_NULL}, 122 | {" lisq", DETAIL_BIT, 0, STATS_NULL}, 123 | {"lising", DETAIL_BIT, 0, STATS_NULL}, 124 | {"lisove", DETAIL_BIT, 0, STATS_SUB_INTER}, 125 | {" cnest", DETAIL_BIT, 0, STATS_SUB_INTER}, 126 | {" ndrop", DETAIL_BIT, 0, STATS_SUB_INTER}, 127 | {" edrop", DETAIL_BIT, 0, STATS_SUB_INTER}, 128 | {" rdrop", DETAIL_BIT, 0, STATS_SUB_INTER}, 129 | {" pdrop", DETAIL_BIT, 0, STATS_SUB_INTER}, 130 | {" kdrop", DETAIL_BIT, 0, STATS_SUB_INTER}, 131 | }; 132 | 133 | void 134 | mod_register(struct module *mod) 135 | { 136 | register_mod_fields(mod, "--tcpx", tcpx_usage, tcpx_info, 15, read_stat_tcpx, NULL); 137 | } 138 | -------------------------------------------------------------------------------- /modules/mod_traffic.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | char *traffic_usage = " --traffic Net traffic statistics"; 4 | 5 | /* 6 | * Structure for traffic infomation. 7 | */ 8 | struct stats_traffic { 9 | unsigned long long bytein; 10 | unsigned long long byteout; 11 | unsigned long long pktin; 12 | unsigned long long pktout; 13 | unsigned long long pkterrin; 14 | unsigned long long pktdrpin; 15 | unsigned long long pkterrout; 16 | unsigned long long pktdrpout; 17 | } ; 18 | 19 | #define STATS_TRAFFIC_SIZE (sizeof(struct stats_traffic)) 20 | 21 | 22 | /* 23 | * collect traffic infomation 24 | */ 25 | static void 26 | read_traffic_stats(struct module *mod, char *parameter) 27 | { 28 | int len = 0, num = 0, n_prefix = 3, i; 29 | FILE *fp; 30 | char *p = NULL; 31 | char line[LEN_4096] = {0}; 32 | char buf[LEN_4096] = {0}; 33 | char mod_parameter[LEN_256], *token; 34 | char *prefixes[10] = {"eth", "em", "en"}; 35 | struct stats_traffic total_st, cur_st; 36 | 37 | memset(buf, 0, LEN_4096); 38 | memset(&total_st, 0, sizeof(struct stats_traffic)); 39 | memset(&cur_st, 0, sizeof(struct stats_traffic)); 40 | 41 | if ((fp = fopen(NET_DEV, "r")) == NULL) { 42 | return; 43 | } 44 | 45 | memset(&total_st, 0, sizeof(cur_st)); 46 | 47 | if (parameter != NULL) { 48 | strncpy(mod_parameter, parameter, LEN_256); 49 | token = strtok(mod_parameter, W_SPACE); 50 | while (token != NULL && n_prefix < 10) { 51 | prefixes[n_prefix++] = token; 52 | token = strtok(NULL, W_SPACE); 53 | } 54 | } 55 | 56 | while (fgets(line, LEN_4096, fp) != NULL) { 57 | for (i = 0; i < n_prefix; i++) { 58 | if (strstr(line, prefixes[i])) { 59 | memset(&cur_st, 0, sizeof(cur_st)); 60 | p = strchr(line, ':'); 61 | sscanf(p + 1, "%llu %llu %llu %llu %*u %*u %*u %*u " 62 | "%llu %llu %llu %llu %*u %*u %*u %*u", 63 | &cur_st.bytein, 64 | &cur_st.pktin, 65 | &cur_st.pkterrin, 66 | &cur_st.pktdrpin, 67 | &cur_st.byteout, 68 | &cur_st.pktout, 69 | &cur_st.pkterrout, 70 | &cur_st.pktdrpout); 71 | 72 | num++; 73 | total_st.bytein += cur_st.bytein; 74 | total_st.byteout += cur_st.byteout; 75 | total_st.pktin += cur_st.pktin; 76 | total_st.pktout += cur_st.pktout; 77 | total_st.pkterrin += cur_st.pkterrin; 78 | total_st.pktdrpin += cur_st.pktdrpin; 79 | total_st.pkterrout += cur_st.pkterrout; 80 | total_st.pktdrpout += cur_st.pktdrpout; 81 | 82 | break; 83 | } 84 | } 85 | } 86 | 87 | len = sprintf(buf, "%lld,%lld,%lld,%lld,%lld,%lld", 88 | total_st.bytein, 89 | total_st.byteout, 90 | total_st.pktin, 91 | total_st.pktout, 92 | total_st.pkterrin + total_st.pkterrout, 93 | total_st.pktdrpin + total_st.pktdrpout); 94 | buf[len] = '\0'; 95 | if(num > 0) { 96 | set_mod_record(mod, buf); 97 | } 98 | fclose(fp); 99 | } 100 | 101 | static struct mod_info traffic_info[] ={ 102 | {" bytin", SUMMARY_BIT, 0, STATS_SUB_INTER}, 103 | {"bytout", SUMMARY_BIT, 0, STATS_SUB_INTER}, 104 | {" pktin", DETAIL_BIT, 0, STATS_SUB_INTER}, 105 | {"pktout", DETAIL_BIT, 0, STATS_SUB_INTER}, 106 | {"pkterr", DETAIL_BIT, 0, STATS_SUB_INTER}, 107 | {"pktdrp", DETAIL_BIT, 0, STATS_SUB_INTER} 108 | }; 109 | 110 | void 111 | mod_register(struct module *mod) 112 | { 113 | register_mod_fields(mod, "--traffic", traffic_usage, traffic_info, 6, read_traffic_stats, NULL); 114 | } 115 | -------------------------------------------------------------------------------- /modules/mod_udp.c: -------------------------------------------------------------------------------- 1 | #include "tsar.h" 2 | 3 | #define UDP_DETAIL_HDR(d) \ 4 | " idgm"d" odgm"d"noport"d"idmerr" 5 | 6 | char *udp_usage = 7 | " --udp UDP traffic (v4)"; 8 | 9 | /* Structure for UDP statistics */ 10 | struct stats_udp { 11 | unsigned long long InDatagrams; 12 | unsigned long long OutDatagrams; 13 | unsigned long long NoPorts; 14 | unsigned long long InErrors; 15 | }; 16 | 17 | #define STATS_UDP_SIZE (sizeof(struct stats_udp)) 18 | 19 | void 20 | read_udp_stats(struct module *mod) 21 | { 22 | int sw = FALSE; 23 | FILE *fp; 24 | char line[LEN_1024]; 25 | char buf[LEN_1024]; 26 | struct stats_udp st_udp; 27 | 28 | memset(buf, 0, LEN_1024); 29 | memset(&st_udp, 0, sizeof(struct stats_udp)); 30 | if ((fp = fopen(NET_SNMP, "r")) == NULL) { 31 | return; 32 | } 33 | 34 | while (fgets(line, LEN_1024, fp) != NULL) { 35 | 36 | if (!strncmp(line, "Udp:", 4)) { 37 | if (sw) { 38 | sscanf(line + 4, "%llu %llu %llu %llu", 39 | &st_udp.InDatagrams, 40 | &st_udp.NoPorts, 41 | &st_udp.InErrors, 42 | &st_udp.OutDatagrams); 43 | break; 44 | 45 | } else { 46 | sw = TRUE; 47 | } 48 | } 49 | } 50 | 51 | fclose(fp); 52 | 53 | int pos = sprintf(buf, "%lld,%lld,%lld,%lld", 54 | st_udp.InDatagrams, 55 | st_udp.OutDatagrams, 56 | st_udp.NoPorts, 57 | st_udp.InErrors); 58 | buf[pos] = '\0'; 59 | set_mod_record(mod, buf); 60 | } 61 | 62 | static struct mod_info udp_info[] = { 63 | {" idgm", DETAIL_BIT, 0, STATS_SUB_INTER}, 64 | {" odgm", DETAIL_BIT, 0, STATS_SUB_INTER}, 65 | {"noport", DETAIL_BIT, 0, STATS_SUB_INTER}, 66 | {"idmerr", DETAIL_BIT, 0, STATS_SUB_INTER}, 67 | }; 68 | 69 | void 70 | mod_register(struct module *mod) 71 | { 72 | register_mod_fields(mod, "--udp", udp_usage, udp_info, 4, read_udp_stats, NULL); 73 | } 74 | -------------------------------------------------------------------------------- /rpm/scm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 集团 8 | 9 |
技术共享平台
10 | 核心系统研发 11 | 系统 12 |
13 | 14 |
核心系统
15 | Cache 16 |
17 | tsar 18 | C/C++ 19 | http://svn.simba.taobao.com/svn/cdn/trunk/tsar/ 20 |
21 |
22 |
23 | 24 | -------------------------------------------------------------------------------- /rpm/tsar-VER.txt: -------------------------------------------------------------------------------- 1 | 2.1.29 2 | -------------------------------------------------------------------------------- /rpm/tsar-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export temppath=$1 4 | cd $temppath/rpm 5 | export name=$2 6 | export version=$3 7 | export release=$4 8 | 9 | 10 | TOP_DIR="/tmp/.rpm_create_"$2"_"`whoami` 11 | 12 | LANG=C 13 | export LANG 14 | 15 | usage() 16 | { 17 | echo "Usage:" 18 | echo "build-squid rpmdir packagename version release" 19 | exit 0 20 | } 21 | 22 | git_path="Unknown_path" 23 | git_revision=$release 24 | git_info() 25 | { 26 | base=19000 27 | git_version=`git rev-list --all|wc -l` 28 | git_revision=`expr $git_version + $base` 29 | echo $git_revision 30 | } 31 | 32 | building_tag() 33 | { 34 | git_revision=$release.`git log --pretty=oneline -1 |cut -c1-7` 35 | echo "new subversion is:"$version 36 | } 37 | building_tag 38 | ##git_info 39 | 40 | echo "/etc/redhat-release:" 41 | cat /etc/redhat-release 42 | releasever=$(cut -d: -f5 /etc/system-release-cpe) 43 | if [[ -n "$releasever" ]] 44 | then 45 | release="$git_revision".el$releasever 46 | else 47 | release="$git_revision".el7 48 | fi 49 | 50 | RPM_MACROS=$HOME/.rpmmacros 51 | if [ -e $RPM_MACROS ]; then 52 | mv -f $RPM_MACROS $RPM_MACROS.bak 53 | fi 54 | 55 | 56 | echo "%_topdir $TOP_DIR" > $RPM_MACROS 57 | echo "%packager " `whoami` >> $RPM_MACROS 58 | echo "%vendor TaoBao Inc." >> $RPM_MACROS 59 | echo "%_git_path $git_path" >> $RPM_MACROS 60 | echo "%_git_revision $git_revision" >> $RPM_MACROS 61 | echo "%_release $release" >> $RPM_MACROS 62 | echo "%debug_package %{nil}" >> $RPM_MACROS 63 | 64 | cd .. 65 | rm -rf $TOP_DIR 66 | mkdir -p $TOP_DIR/RPMS 67 | mkdir -p $TOP_DIR/SRPMS 68 | mkdir -p $TOP_DIR/BUILD 69 | mkdir -p $TOP_DIR/SOURCES 70 | mkdir -p $TOP_DIR/SPECS 71 | 72 | export fullname=$name-$version 73 | 74 | ln -s . $fullname 75 | tar --exclude=$fullname/$fullname \ 76 | --exclude=$fullname/$fullname.tar.gz \ 77 | -cf - $fullname/* | gzip -c9 >$fullname.tar.gz 78 | cp $fullname.tar.gz $TOP_DIR/SOURCES 79 | 80 | ## remove temporary file or dir 81 | rm $fullname.tar.gz 82 | rm -rf $fullname 83 | 84 | ## create spec file from template 85 | sed -e "s/_VERSION_/$version/g" -e "s/_RELEASE_/$release/g" -e "s/SVN_REVISION/$git_revision/g" < rpm/$name.spec.in > $TOP_DIR/SPECS/$name.spec 86 | 87 | rpmbuild --ba $TOP_DIR/SPECS/$name.spec 88 | 89 | find $TOP_DIR/RPMS -name "*.rpm" -exec mv {} ./rpm \; 90 | echo "dir: $TOP_DIR" 91 | rm -rf $TOP_DIR $RPM_MACROS 92 | if [ -e $RPM_MACROS.bak ]; then 93 | mv -f $RPM_MACROS.bak $RPM_MACROS 94 | fi 95 | 96 | cd - 97 | -------------------------------------------------------------------------------- /rpm/tsar-devel.spec: -------------------------------------------------------------------------------- 1 | Name: tsar-devel 2 | Version: 2.1.1 3 | Release: %(echo $RELEASE)%{?dist} 4 | Summary: Taobao Tsar Devel 5 | Group: Taobao/Common 6 | License: Commercial 7 | 8 | %description 9 | devel package include tsar header files and module template for the development 10 | 11 | %install 12 | rm -rf $RPM_BUILD_ROOT 13 | mkdir -p $RPM_BUILD_ROOT/usr/bin 14 | cd $OLDPWD/../ 15 | make DESTDIR=$RPM_BUILD_ROOT tsardevel 16 | make DESTDIR=$RPM_BUILD_ROOT tsarluadevel 17 | 18 | %clean 19 | rm -rf $RPM_BUILD_ROOT 20 | 21 | %files 22 | %defattr(-,root,root) 23 | /usr/local/tsar/devel/tsar.h 24 | /usr/local/tsar/devel/Makefile.test 25 | /usr/local/tsar/devel/mod_test.c 26 | /usr/local/tsar/devel/mod_test.conf 27 | /usr/local/tsar/luadevel/Makefile.test 28 | /usr/local/tsar/luadevel/mod_lua_test.lua 29 | /usr/local/tsar/luadevel/mod_lua_test.conf 30 | %attr(755,root,root) 31 | /usr/bin/tsardevel 32 | /usr/bin/tsarluadevel 33 | 34 | %changelog 35 | 36 | -------------------------------------------------------------------------------- /rpm/tsar.spec: -------------------------------------------------------------------------------- 1 | Name: tsar 2 | Version: 2.1.1 3 | Release: 19200.aone 4 | Summary: Taobao System Activity Reporter 5 | URL: https://github.com/alibaba/tsar 6 | Group: Taobao/Common 7 | License: Commercial 8 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 9 | Source: tsar-%{version}.tar.gz 10 | 11 | %description 12 | tsar is Taobao monitor tool for collect system activity status, and report it. 13 | It have a plugin system that is easy for collect plugin development. and may 14 | setup different output target such as local logfile and remote nagios host. 15 | 16 | %prep 17 | %setup -q 18 | 19 | %build 20 | make clean;make 21 | 22 | %install 23 | 24 | rm -rf %{buildroot} 25 | mkdir -p %{buildroot}/usr/local/tsar/ 26 | mkdir -p %{buildroot}/usr/local/tsar/modules/ 27 | mkdir -p %{buildroot}/usr/local/tsar/conf/ 28 | mkdir -p %{buildroot}/usr/local/man/man8/ 29 | mkdir -p %{buildroot}/etc/logrotate.d/ 30 | mkdir -p %{buildroot}/etc/tsar/ 31 | mkdir -p %{buildroot}/etc/cron.d/ 32 | mkdir -p %{buildroot}/usr/bin 33 | 34 | install -p -D -m 0755 src/tsar %{buildroot}/usr/bin/tsar 35 | install -p -D -m 0644 conf/tsar.conf %{buildroot}/etc/tsar/tsar.conf 36 | install -p -D -m 0644 modules/*.so %{buildroot}/usr/local/tsar/modules/ 37 | install -p -D -m 0644 conf/tsar.cron %{buildroot}/etc/cron.d/tsar 38 | install -p -D -m 0644 conf/tsar.logrotate %{buildroot}/etc/logrotate.d/tsar 39 | install -p -D -m 0644 conf/tsar.8 %{buildroot}/usr/local/man/man8/tsar.8 40 | 41 | make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install 42 | 43 | make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install 44 | 45 | %clean 46 | [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} 47 | 48 | 49 | %files 50 | %defattr(-,root,root) 51 | /usr/local/tsar/modules/*.so 52 | /usr/local/tsar/lualib 53 | 54 | %attr(755,root,root) /usr/bin/tsar 55 | %config(noreplace) /etc/tsar/tsar.conf 56 | %attr(644,root,root) /etc/cron.d/tsar 57 | %attr(644,root,root) /etc/logrotate.d/tsar 58 | %attr(644,root,root) /usr/local/man/man8/tsar.8 59 | 60 | %changelog 61 | * Sun Jan 6 2013 Ke Li 62 | - merge inner and opensource tsar 63 | * Thu Dec 9 2010 Ke Li 64 | - add logrotate for tsar.data 65 | * Mon Apr 26 2010 Bin Chen 66 | - first create tsar rpm package 67 | -------------------------------------------------------------------------------- /rpm/tsar.spec.in: -------------------------------------------------------------------------------- 1 | Name: tsar 2 | Version: _VERSION_ 3 | Release: _RELEASE_ 4 | Summary: Taobao System Activity Reporter 5 | URL: https://github.com/alibaba/tsar 6 | Group: Taobao/Common 7 | License: Commercial 8 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 9 | Source: tsar-%{version}.tar.gz 10 | 11 | %description 12 | tsar is Taobao monitor tool for collect system activity status, and report it. 13 | It have a plugin system that is easy for collect plugin development. and may 14 | setup different output target such as local logfile and remote nagios host. 15 | 16 | %prep 17 | %setup -q 18 | 19 | %build 20 | make clean;make 21 | 22 | %install 23 | 24 | rm -rf %{buildroot} 25 | mkdir -p %{buildroot}/usr/local/tsar/ 26 | mkdir -p %{buildroot}/usr/local/tsar/modules/ 27 | mkdir -p %{buildroot}/usr/local/tsar/conf/ 28 | mkdir -p %{buildroot}/usr/local/man/man8/ 29 | mkdir -p %{buildroot}/etc/logrotate.d/ 30 | mkdir -p %{buildroot}/etc/tsar/ 31 | mkdir -p %{buildroot}/etc/cron.d/ 32 | mkdir -p %{buildroot}/usr/bin 33 | 34 | install -p -D -m 0755 src/tsar %{buildroot}/usr/bin/tsar 35 | install -p -D -m 0644 conf/tsar.conf %{buildroot}/etc/tsar/tsar.conf 36 | install -p -D -m 0644 modules/*.so %{buildroot}/usr/local/tsar/modules/ 37 | install -p -D -m 0644 conf/tsar.cron %{buildroot}/etc/cron.d/tsar 38 | install -p -D -m 0644 conf/tsar.logrotate %{buildroot}/etc/logrotate.d/tsar 39 | install -p -D -m 0644 conf/tsar.8 %{buildroot}/usr/local/man/man8/tsar.8 40 | 41 | make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install 42 | 43 | install -p -D -m 0755 luadevel/tsarluadevel %{buildroot}/usr/bin/tsarluadevel 44 | install -p -D -m 0644 luadevel/mod_lua_test.lua %{buildroot}/usr/local/tsar/luadevel/mod_lua_test.lua 45 | install -p -D -m 0644 luadevel/mod_lua_test.conf %{buildroot}/usr/local/tsar/luadevel/mod_lua_test.conf 46 | install -p -D -m 0644 luadevel/Makefile.test %{buildroot}/usr/local/tsar/luadevel/Makefile.test 47 | 48 | make -C lualib INSTALL_DIR=%{buildroot}/usr/local/tsar/lualib install 49 | 50 | %clean 51 | [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} 52 | 53 | 54 | %files 55 | %defattr(-,root,root) 56 | /usr/local/tsar/modules/*.so 57 | /usr/local/tsar/lualib 58 | 59 | %attr(755,root,root) /usr/bin/tsar 60 | %config(noreplace) /etc/tsar/tsar.conf 61 | %attr(644,root,root) /etc/cron.d/tsar 62 | %attr(644,root,root) /etc/logrotate.d/tsar 63 | %attr(644,root,root) /usr/local/man/man8/tsar.8 64 | 65 | %changelog 66 | * Sun Jan 6 2013 Ke Li 67 | - merge inner and opensource tsar 68 | * Thu Dec 9 2010 Ke Li 69 | - add logrotate for tsar.data 70 | * Mon Apr 26 2010 Bin Chen 71 | - first create tsar rpm package 72 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | SRC = tsar.c config.c debug.c framework.c output_file.c output_print.c output_db.c output_tcp.c output_nagios.c common.c tsar_lua_util.c 3 | OBJ = $(patsubst %.c, %.o,$(SRC)) 4 | DEPS_DIR = deps 5 | 6 | BIN = tsar 7 | LUAJIT = $(notdir $(patsubst %.tar.gz,%,$(wildcard deps/LuaJIT*.tar.gz))) 8 | 9 | ODIR = obj 10 | DEPS = $(ODIR)/lib/libluajit-5.1.a 11 | 12 | CFLAGS = -MD -g -O2 -Wall -I../include -I$(ODIR)/include 13 | LDFLAGS += -L$(ODIR)/lib -lluajit-5.1 -lm -ldl -rdynamic 14 | 15 | all: $(BIN) 16 | 17 | $(BIN): $(OBJ) 18 | @echo LINK $(BIN) 19 | $(CC) $^ -o tsar -I$(INCLUDE_DIR) $(CFLAGS) $(LDFLAGS) 20 | 21 | $(OBJ): $(DEPS) | $(ODIR) 22 | 23 | $(ODIR)/$(LUAJIT): $(DEPS_DIR)/$(LUAJIT).tar.gz | $(ODIR) 24 | @tar -C $(ODIR) -xf $< 25 | 26 | $(ODIR)/lib/libluajit-5.1.a: $(ODIR)/$(LUAJIT) | $(ODIR) 27 | @echo Building LuaJIT... 28 | @$(MAKE) -C $< PREFIX=$(abspath $(ODIR)) BUILDMODE=static install 29 | 30 | $(ODIR)/%.o : %.c 31 | @echo CC $< 32 | @$(CC) $(CFLAGS) -c -o $@ $< 33 | 34 | $(ODIR): 35 | @mkdir -p $@ 36 | 37 | clean: 38 | rm -rf *.o *.d $(BIN) $(ODIR); 39 | 40 | OBJS = *.o 41 | -include $(OBJS:.o=.d) 42 | -------------------------------------------------------------------------------- /src/common.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include "tsar.h" 21 | 22 | 23 | int 24 | is_digit(const char *str) 25 | { 26 | if (*str == '-') { 27 | str++; 28 | } 29 | /*dont handle minus value in tsar.data */ 30 | while (*str) { 31 | if (!isdigit(*str++)) { 32 | return 0; 33 | } 34 | } 35 | return 1; 36 | } 37 | 38 | 39 | /* 40 | * convert record to array 41 | */ 42 | int 43 | convert_record_to_array(U_64 *array, int l_array, const char *record) 44 | { 45 | int i = 0; 46 | char *ptr; 47 | U_64 num; 48 | 49 | if (l_array <= 0 || !record || !strlen(record)) { 50 | return 0; 51 | } 52 | 53 | do { 54 | num = strtoull(record, &ptr, 10); 55 | array[i++] = num; 56 | if (strpbrk(ptr, DATA_SPLIT) == NULL) break; 57 | record = ptr + 1; 58 | } while(i < l_array); 59 | 60 | return i; 61 | } 62 | 63 | 64 | int 65 | merge_one_string(U_64 *array, int l_array, char *string, struct module *mod, int n_item) 66 | { 67 | int i, len; 68 | U_64 array_2[MAX_COL_NUM] = {0}; 69 | struct mod_info *info = mod->info; 70 | 71 | if ((len = convert_record_to_array(array_2, l_array, string)) <= 0) { 72 | return 0; 73 | } 74 | 75 | for (i=0; i < len; i++) { 76 | switch (info[i].merge_mode) { 77 | case MERGE_SUM: 78 | array[i] += array_2[i]; 79 | break; 80 | case MERGE_AVG: 81 | array[i] = (array[i] * (n_item - 1) + array_2[i]) / n_item; 82 | break; 83 | default: 84 | ; 85 | } 86 | } 87 | return 1; 88 | } 89 | 90 | 91 | char* 92 | strtok_next_item(char *record, int *start) 93 | { 94 | char *s_token, *e_token, *n_record; 95 | 96 | if (!record || !strlen(record) || strlen(record) <= *start) { 97 | return NULL; 98 | } 99 | 100 | n_record = record + *start; 101 | e_token = strpbrk(n_record, ITEM_SPLIT); 102 | if (!e_token) { 103 | return NULL; 104 | } 105 | s_token = strpbrk(n_record, ITEM_SPSTART); 106 | if (!s_token) { 107 | return NULL; 108 | } 109 | if (e_token < s_token) { 110 | return NULL; 111 | } 112 | 113 | *start = e_token - record + 2; 114 | return s_token + 1; 115 | } 116 | 117 | 118 | int 119 | merge_mult_item_to_array(U_64 *array, struct module *mod) 120 | { 121 | int pos = 0; 122 | int n_item = 1; 123 | char *item; 124 | 125 | memset(array, 0, sizeof(U_64) * mod->n_col); 126 | while ((item = strtok_next_item(mod->record, &pos)) != NULL) { 127 | if (!merge_one_string(array, mod->n_col, item, mod, n_item)) { 128 | return 0; 129 | } 130 | n_item++; 131 | } 132 | return 1; 133 | } 134 | 135 | 136 | int 137 | get_strtok_num(const char *str, const char *split) 138 | { 139 | int num = 0; 140 | char *token, n_str[LEN_1M] = {0}; 141 | 142 | if (!str || !strlen(str)) { 143 | return 0; 144 | } 145 | 146 | memcpy(n_str, str, strlen(str)); 147 | /* set print opt line */ 148 | token = strtok(n_str, split); 149 | while (token) { 150 | num++; 151 | token = strtok(NULL, split); 152 | } 153 | 154 | return num; 155 | } 156 | 157 | 158 | /* 159 | * get__mod_hdr; hdr format:HDR_SPLIT"hdr1"HDR_SLIT"hdr2" 160 | */ 161 | void 162 | get_mod_hdr(char hdr[], const struct module *mod) 163 | { 164 | int i, pos = 0; 165 | struct mod_info *info = mod->info; 166 | 167 | for (i = 0; i < mod->n_col; i++) { 168 | if (mod->spec) { 169 | if (SPEC_BIT == info[i].summary_bit) { 170 | if (strlen(info[i].hdr) > 6) { 171 | info[i].hdr[6] = '\0'; 172 | } 173 | pos += sprintf(hdr + pos, "%s%s", info[i].hdr, PRINT_DATA_SPLIT); 174 | } 175 | 176 | } else { 177 | if (((DATA_SUMMARY == conf.print_mode) && (SUMMARY_BIT == info[i].summary_bit)) 178 | || ((DATA_DETAIL == conf.print_mode) && (HIDE_BIT != info[i].summary_bit))) 179 | { 180 | if (strlen(info[i].hdr) > 6) { 181 | info[i].hdr[6] = '\0'; 182 | } 183 | pos += sprintf(hdr + pos, "%s%s", info[i].hdr, PRINT_DATA_SPLIT); 184 | } 185 | } 186 | } 187 | } 188 | 189 | 190 | /* 191 | get data from tsar.data 192 | */ 193 | int 194 | get_st_array_from_file(int have_collect) 195 | { 196 | int i, ret = 0; 197 | char detail[LEN_1M] = {0}; 198 | char pre_time[32] = {0}; 199 | char *s_token; 200 | FILE *fp; 201 | struct module *mod; 202 | static char pre_line[LEN_10M] = {0}; 203 | static char line[LEN_10M] = {0}; 204 | 205 | if (!have_collect) { 206 | collect_record(0); 207 | } 208 | 209 | /* update module parameter */ 210 | conf.print_merge = MERGE_ITEM; 211 | 212 | sprintf(line, "%ld", statis.cur_time); 213 | for (i = 0; i < statis.total_mod_num; i++) { 214 | mod = mods[i]; 215 | if (mod->enable && strlen(mod->record)) { 216 | memset(&detail, 0, sizeof(detail)); 217 | /* save collect data to output_file */ 218 | sprintf(detail, "%s%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT, mod->record); 219 | strcat(line, detail); 220 | } 221 | } 222 | 223 | if (strlen(line)) { 224 | strcat(line, "\n"); 225 | } 226 | 227 | /* if fopen PRE_RECORD_FILE sucess then store data to pre_record */ 228 | if ((fp = fopen(PRE_RECORD_FILE, "r"))) { 229 | if (!fgets(pre_line, LEN_10M, fp)) { 230 | if (fclose(fp) < 0) { 231 | do_debug(LOG_FATAL, "fclose error:%s", strerror(errno)); 232 | } 233 | ret = -1; 234 | goto out; 235 | } else { 236 | if (fclose(fp) < 0) { 237 | do_debug(LOG_FATAL, "fclose error:%s", strerror(errno)); 238 | } 239 | } 240 | } else { 241 | ret = -1; 242 | goto out; 243 | } 244 | 245 | /* set print_interval */ 246 | s_token = strpbrk(pre_line, SECTION_SPLIT); 247 | if (!s_token) { 248 | ret = -1; 249 | goto out; 250 | } 251 | memcpy(pre_time, pre_line, s_token - pre_line); 252 | if (!(conf.print_interval = statis.cur_time - atol(pre_time))) { 253 | ret = -1; 254 | goto out; 255 | } 256 | 257 | /* read pre_line to mod->record and store to pre_array */ 258 | read_line_to_module_record(pre_line); 259 | init_module_fields(); 260 | collect_record_stat(); 261 | 262 | /* read cur_line and stats operation */ 263 | read_line_to_module_record(line); 264 | collect_record_stat(); 265 | ret = 0; 266 | 267 | out: 268 | /* store current record to PRE_RECORD_FILE */ 269 | if ((fp = fopen(PRE_RECORD_FILE, "w"))) { 270 | strcat(line, "\n"); 271 | if (fputs(line, fp) < 0) { 272 | do_debug(LOG_ERR, "fputs error:%s", strerror(errno)); 273 | } 274 | if (fclose(fp) < 0) { 275 | do_debug(LOG_FATAL, "fclose error:%s", strerror(errno)); 276 | } 277 | chmod(PRE_RECORD_FILE, 0666); 278 | } 279 | 280 | return ret; 281 | } 282 | -------------------------------------------------------------------------------- /src/debug.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include "tsar.h" 21 | 22 | 23 | void 24 | _do_debug(log_level_t level, const char *file, int line, const char *fmt, ...) 25 | { 26 | char *timestr; 27 | time_t timep; 28 | va_list argp; 29 | struct tm *local; 30 | 31 | /* FIXME */ 32 | if (level >= conf.debug_level) { 33 | 34 | time(&timep); 35 | local = localtime(&timep); 36 | timestr = asctime(local); 37 | 38 | fprintf(stderr, "[%.*s] %s:%d ", 39 | (int)(strlen(timestr) - 1), timestr, file, line); 40 | 41 | va_start(argp, fmt); 42 | vfprintf(stderr, fmt, argp); 43 | fflush(stderr); 44 | va_end(argp); 45 | } 46 | 47 | if (level == LOG_FATAL) { 48 | fprintf(stderr, "\n"); 49 | exit(1); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/deps/LuaJIT-2.0.4.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/tsar/0224ccbf81982b46f600048311f87cb1b5bc8e8f/src/deps/LuaJIT-2.0.4.tar.gz -------------------------------------------------------------------------------- /src/output_db.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include 21 | #include "tsar.h" 22 | 23 | 24 | /* 25 | * send sql to remote db 26 | */ 27 | void 28 | send_sql_txt(int fd, int have_collect) 29 | { 30 | int i = 0, j, len; 31 | char s_time[LEN_64] = {0}; 32 | char host_name[LEN_64] = {0}; 33 | struct module *mod; 34 | static char sqls[LEN_10M] = {0}; 35 | 36 | /* get hostname */ 37 | if (0 != gethostname(host_name, sizeof(host_name))) { 38 | do_debug(LOG_FATAL, "send_sql_txt: gethostname err, errno=%d", errno); 39 | } 40 | while (host_name[i]) { 41 | if (!isprint(host_name[i++])) { 42 | host_name[i-1] = '\0'; 43 | break; 44 | } 45 | } 46 | 47 | /* get st_array */ 48 | if (get_st_array_from_file(have_collect)) { 49 | return; 50 | } 51 | 52 | /* only output from output_db_mod */ 53 | reload_modules(conf.output_db_mod); 54 | 55 | sprintf(s_time, "%ld", time(NULL)); 56 | 57 | /* print summary data */ 58 | for (i = 0; i < statis.total_mod_num; i++) { 59 | mod = mods[i]; 60 | if (!mod->enable) { 61 | continue; 62 | 63 | } else { 64 | if (!mod->st_flag) { 65 | char sql_hdr[LEN_256] = {0}; 66 | /* set sql header */ 67 | memset(sql_hdr, '\0', sizeof(sql_hdr)); 68 | sprintf(sql_hdr, "insert into `%s` (host_name, time) VALUES ('%s', '%s');", 69 | mod->opt_line + 2, host_name, s_time); 70 | strcat(sqls, sql_hdr); 71 | 72 | } else { 73 | char str[LEN_32] = {0}; 74 | char sql_hdr[LEN_256] = {0}; 75 | struct mod_info *info = mod->info; 76 | 77 | /* set sql header */ 78 | memset(sql_hdr, '\0', sizeof(sql_hdr)); 79 | sprintf(sql_hdr, "insert into `%s` (host_name, time", mod->opt_line + 2); 80 | 81 | /* get value */ 82 | for (j = 0; j < mod->n_col; j++) { 83 | strcat(sql_hdr, ", `"); 84 | char *p = info[j].hdr; 85 | while (*p == ' ') { 86 | p++; 87 | } 88 | strncat(sql_hdr, p, LEN_128); 89 | strcat(sql_hdr, "`"); 90 | } 91 | strcat(sql_hdr, ") VALUES ('"); 92 | strcat(sql_hdr, host_name); 93 | strcat(sql_hdr, "', '"); 94 | strcat(sql_hdr, s_time); 95 | strcat(sql_hdr, "'"); 96 | strcat(sqls, sql_hdr); 97 | 98 | /* get value */ 99 | for (j = 0; j < mod->n_col; j++) { 100 | memset(str, 0, sizeof(str)); 101 | sprintf(str, ", '%.1f'", mod->st_array[j]); 102 | strcat(sqls, str); 103 | } 104 | strcat(sqls, ");"); 105 | } 106 | } 107 | } 108 | len = strlen(sqls); 109 | if (write(fd, sqls, len) != len) { 110 | do_debug(LOG_ERR, "output_db write error:%s", strerror(errno)); 111 | } 112 | } 113 | 114 | struct sockaddr_in * 115 | str2sa(char *str) 116 | { 117 | int port; 118 | char *c; 119 | static struct sockaddr_in sa; 120 | 121 | memset(&sa, 0, sizeof(sa)); 122 | str = strdup(str); 123 | if (str == NULL) { 124 | goto out_nofree; 125 | } 126 | 127 | if ((c = strrchr(str, ':')) != NULL) { 128 | *c++ = '\0'; 129 | port = atol(c); 130 | 131 | } else { 132 | port = 0; 133 | } 134 | 135 | if (*str == '*' || *str == '\0') { /* INADDR_ANY */ 136 | sa.sin_addr.s_addr = INADDR_ANY; 137 | 138 | } else { 139 | if (!inet_pton(AF_INET, str, &sa.sin_addr)) { 140 | struct hostent *he; 141 | 142 | if ((he = gethostbyname(str)) == NULL) { 143 | do_debug(LOG_FATAL, "str2sa: Invalid server name, '%s'", str); 144 | 145 | } else { 146 | sa.sin_addr = *(struct in_addr *) *(he->h_addr_list); 147 | } 148 | } 149 | } 150 | sa.sin_port = htons(port); 151 | sa.sin_family = AF_INET; 152 | 153 | free(str); 154 | out_nofree: 155 | return &sa; 156 | } 157 | 158 | void 159 | output_db(int have_collect) 160 | { 161 | int fd, flags, res; 162 | fd_set fdr, fdw; 163 | struct timeval timeout; 164 | struct sockaddr_in db_addr; 165 | 166 | fd = socket(AF_INET, SOCK_STREAM, 0); 167 | if (fd < 0) { 168 | do_debug(LOG_FATAL, "can't get socket"); 169 | } 170 | 171 | /* set socket fd noblock */ 172 | if ((flags = fcntl(fd, F_GETFL, 0)) < 0) { 173 | close(fd); 174 | return; 175 | } 176 | 177 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { 178 | close(fd); 179 | return; 180 | } 181 | 182 | /* get db server address */ 183 | db_addr = *str2sa(conf.output_db_addr); 184 | 185 | if (connect(fd, (struct sockaddr*)&db_addr, sizeof(db_addr)) != 0) { 186 | if (errno != EINPROGRESS) { // EINPROGRESS 187 | close(fd); 188 | return; 189 | 190 | } else { 191 | goto select; 192 | } 193 | 194 | } else { 195 | goto send; 196 | } 197 | 198 | select: 199 | FD_ZERO(&fdr); 200 | FD_ZERO(&fdw); 201 | FD_SET(fd, &fdr); 202 | FD_SET(fd, &fdw); 203 | 204 | timeout.tv_sec = 2; 205 | timeout.tv_usec = 0; 206 | 207 | res = select(fd + 1, &fdr, &fdw, NULL, &timeout); 208 | if (res <= 0) { 209 | close(fd); 210 | return; 211 | } 212 | 213 | send: 214 | send_sql_txt(fd, have_collect); 215 | close(fd); 216 | } 217 | -------------------------------------------------------------------------------- /src/output_file.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include "tsar.h" 21 | 22 | 23 | void 24 | output_file() 25 | { 26 | int i, ret = 0, n = 0; 27 | FILE *fp = NULL; 28 | char detail[LEN_1M] = {0}; 29 | char s_time[LEN_256] = {0}; 30 | struct module *mod; 31 | static char line[LEN_10M] = {0}; 32 | 33 | if (!(fp = fopen(conf.output_file_path, "a"))) { 34 | do_debug(LOG_FATAL, "output_file: can't open or create data file = %s err=%d\n", conf.output_file_path, errno); 35 | } 36 | setbuf(fp, NULL); 37 | 38 | sprintf(s_time, "%ld", statis.cur_time); 39 | strcat(line, s_time); 40 | 41 | for (i = 0; i < statis.total_mod_num; i++) { 42 | mod = mods[i]; 43 | if (mod->enable && strlen(mod->record)) { 44 | /* save collect data to output_file */ 45 | n = snprintf(detail, LEN_1M, "%s%s%s%s", SECTION_SPLIT, mod->opt_line, STRING_SPLIT, mod->record); 46 | if (n >= LEN_1M - 1) { 47 | do_debug(LOG_FATAL, "mod %s lenth is overflow %d\n", mod->name, n); 48 | } 49 | /* one for \n one for \0 */ 50 | if (strlen(line) + strlen(detail) >= LEN_10M - 2) { 51 | do_debug(LOG_FATAL, "tsar.data line lenth is overflow line %d detail %d\n", strlen(line), strlen(detail)); 52 | } 53 | strcat(line, detail); 54 | ret = 1; 55 | } 56 | } 57 | strcat(line, "\n"); 58 | 59 | if (ret) { 60 | if (fputs(line, fp) < 0) { 61 | do_debug(LOG_ERR, "write line error\n"); 62 | } 63 | } 64 | if (fclose(fp) < 0) { 65 | do_debug(LOG_FATAL, "fclose error:%s", strerror(errno)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/output_nagios.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include 21 | #include "tsar.h" 22 | 23 | 24 | #define PRE_RECORD_FILE "/tmp/.tsar.tmp" 25 | 26 | 27 | void 28 | output_nagios() 29 | { 30 | int i = 0, j = 0, k = 0, l = 0, result = 0, now_time; 31 | char s_time[LEN_64] = {0}; 32 | char host_name[LEN_64] = {0}; 33 | struct module *mod; 34 | static char output[LEN_10M] = {0}; 35 | static char output_err[LEN_10M] = {0}; 36 | 37 | /* if cycle time ok*/ 38 | now_time = statis.cur_time - statis.cur_time%60; 39 | if (conf.cycle_time == 0 || now_time%conf.cycle_time != 0) { 40 | return; 41 | } 42 | 43 | /* get hostname */ 44 | if (0 != gethostname(host_name, sizeof(host_name))) { 45 | do_debug(LOG_FATAL, "send to nagios: gethostname err, errno=%d \n", errno); 46 | } 47 | while (host_name[i]) { 48 | if (!isprint(host_name[i++])) { 49 | host_name[i-1] = '\0'; 50 | break; 51 | } 52 | } 53 | 54 | /* update module parameter */ 55 | conf.print_merge = MERGE_NOT; 56 | 57 | /* get st_array */ 58 | if (get_st_array_from_file(0)) { 59 | return; 60 | } 61 | 62 | /* only output from output_nagios_mod */ 63 | reload_modules(conf.output_nagios_mod); 64 | 65 | sprintf(s_time, "%ld", time(NULL)); 66 | 67 | /* print summary data */ 68 | for (i = 0; i < statis.total_mod_num; i++) { 69 | mod = mods[i]; 70 | if (!mod->enable) { 71 | continue; 72 | 73 | } else { 74 | if (!mod->st_flag) { 75 | printf("name %s\n", mod->name); 76 | printf("do nothing\n"); 77 | 78 | } else { 79 | char opt[LEN_32]; 80 | char check[LEN_64]; 81 | char *n_record = strdup(mod->record); 82 | char *token = strtok(n_record, ITEM_SPLIT); 83 | char *s_token; 84 | double *st_array; 85 | struct mod_info *info = mod->info; 86 | 87 | j = 0; 88 | /* get mod_name.(item_name).col_name value */ 89 | while (token) { 90 | memset(check, 0, sizeof(check)); 91 | strncat(check, mod->name + 4, LEN_32); 92 | strcat(check, "."); 93 | s_token = strpbrk(token, ITEM_SPSTART); 94 | /* multi item */ 95 | if (s_token){ 96 | memset(opt, 0, sizeof(opt)); 97 | strncat(opt, token, s_token - token); 98 | strcat(check, opt); 99 | strcat(check, "."); 100 | } 101 | /* get value */ 102 | st_array = &mod->st_array[j * mod->n_col]; 103 | token = strtok(NULL, ITEM_SPLIT); 104 | j++; 105 | for (k = 0; k < mod->n_col; k++) { 106 | char *p; 107 | char check_item[LEN_64]; 108 | 109 | memset(check_item, 0, LEN_64); 110 | memcpy(check_item, check, LEN_64); 111 | p = info[k].hdr; 112 | while (*p == ' ') { 113 | p++; 114 | } 115 | strncat(check_item, p, LEN_64); 116 | for (l = 0; l < conf.mod_num; l++){ 117 | /* cmp tsar item with naigos item*/ 118 | if (!strcmp(conf.check_name[l], check_item)) { 119 | char value[LEN_32]; 120 | memset(value, 0, sizeof(value)); 121 | sprintf(value, "%0.2f", st_array[k]); 122 | strncat(output, check_item, LEN_64); 123 | strcat(output, "="); 124 | strncat(output, value, LEN_32); 125 | strcat(output, " "); 126 | if (conf.cmin[l] != 0 && st_array[k] >= conf.cmin[l]) { 127 | if (conf.cmax[l] == 0 || (conf.cmax[l] != 0 && st_array[k] <= conf.cmax[l])) { 128 | result = 2; 129 | strncat(output_err, check_item, LEN_64); 130 | strcat(output_err, "="); 131 | strncat(output_err, value, LEN_32); 132 | strcat(output_err, " "); 133 | continue; 134 | } 135 | } 136 | if (conf.wmin[l] != 0 && st_array[k] >= conf.wmin[l]) { 137 | if (conf.wmax[l] == 0 || (conf.wmax[l] != 0 && st_array[k] <= conf.wmax[l]) ) { 138 | if (result != 2) { 139 | result = 1; 140 | } 141 | strncat(output_err, check_item, LEN_64); 142 | strcat(output_err, "="); 143 | strncat(output_err, value, LEN_32); 144 | strcat(output_err, " "); 145 | } 146 | } 147 | } 148 | } 149 | } 150 | } 151 | free(n_record); 152 | } 153 | } 154 | } 155 | if (!strcmp(output_err, "")) { 156 | strcat(output_err, "OK"); 157 | } 158 | /* send to nagios server*/ 159 | char nagios_cmd[LEN_1024]; 160 | sprintf(nagios_cmd, "echo \"%s;tsar;%d;%s|%s\"|%s -H %s -p %d -to 10 -d \";\" -c %s", host_name, result, output_err, output, conf.send_nsca_cmd, conf.server_addr, conf.server_port, conf.send_nsca_conf); 161 | do_debug(LOG_DEBUG, "send to naigos:%s\n", nagios_cmd); 162 | if (system(nagios_cmd) != 0) { 163 | do_debug(LOG_WARN, "nsca run error:%s\n", nagios_cmd); 164 | } 165 | printf("%s\n", nagios_cmd); 166 | } 167 | -------------------------------------------------------------------------------- /src/output_tcp.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include 21 | #include "tsar.h" 22 | 23 | void 24 | send_data_tcp(char *output_addr, char *data, int len) 25 | { 26 | int fd, flags, res; 27 | fd_set fdr, fdw; 28 | struct timeval timeout; 29 | struct sockaddr_in db_addr; 30 | 31 | fd = socket(AF_INET, SOCK_STREAM, 0); 32 | if (fd < 0) { 33 | do_debug(LOG_FATAL, "can't get socket"); 34 | } 35 | 36 | /* set socket fd noblock */ 37 | if ((flags = fcntl(fd, F_GETFL, 0)) < 0) { 38 | close(fd); 39 | return; 40 | } 41 | 42 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { 43 | close(fd); 44 | return; 45 | } 46 | 47 | /* get db server address */ 48 | db_addr = *str2sa(output_addr); 49 | 50 | if (connect(fd, (struct sockaddr*)&db_addr, sizeof(db_addr)) != 0) { 51 | if (errno != EINPROGRESS) { // EINPROGRESS 52 | close(fd); 53 | return; 54 | 55 | } else { 56 | goto select; 57 | } 58 | 59 | } else { 60 | goto send; 61 | } 62 | 63 | select: 64 | FD_ZERO(&fdr); 65 | FD_ZERO(&fdw); 66 | FD_SET(fd, &fdr); 67 | FD_SET(fd, &fdw); 68 | 69 | timeout.tv_sec = 2; 70 | timeout.tv_usec = 0; 71 | 72 | res = select(fd + 1, &fdr, &fdw, NULL, &timeout); 73 | if (res <= 0) { 74 | close(fd); 75 | return; 76 | } 77 | 78 | send: 79 | if (len > 0 && write(fd, data, len) != len) { 80 | do_debug(LOG_ERR, "output_db write error:dst:%s\terrno:%s\n",output_addr, strerror(errno)); 81 | } 82 | close(fd); 83 | } 84 | 85 | void 86 | output_multi_tcp(int have_collect) 87 | { 88 | int out_pipe[2]; 89 | int len; 90 | static char data[LEN_10M] = {0}; 91 | int i; 92 | /* only output from output_tcp_mod */ 93 | reload_modules(conf.output_tcp_mod); 94 | 95 | if (!strcasecmp(conf.output_tcp_merge, "on") || !strcasecmp(conf.output_tcp_merge, "enable")) { 96 | conf.print_merge = MERGE_ITEM; 97 | } else { 98 | conf.print_merge = MERGE_NOT; 99 | } 100 | 101 | if (pipe(out_pipe) != 0) { 102 | return; 103 | } 104 | 105 | dup2(out_pipe[1], STDOUT_FILENO); 106 | close(out_pipe[1]); 107 | 108 | running_check(RUN_CHECK_NEW); 109 | 110 | fflush(stdout); 111 | len = read(out_pipe[0], data, LEN_10M); 112 | close(out_pipe[0]); 113 | /*now ,the data to send is gotten*/ 114 | for(i = 0; i < conf.output_tcp_addr_num; i++){ 115 | send_data_tcp(conf.output_tcp_addr[i], data, len); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/tsar.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * (C) 2010-2011 Alibaba Group Holding Limited 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | 20 | #include "tsar.h" 21 | 22 | 23 | struct statistic statis; 24 | struct configure conf; 25 | struct module *mods[MAX_MOD_NUM]; 26 | lua_State *L = NULL; 27 | 28 | 29 | void 30 | usage() 31 | { 32 | int i; 33 | struct module *mod; 34 | 35 | fprintf(stderr, 36 | "Usage: tsar [options]\n" 37 | "Options:\n" 38 | #ifdef OLDTSAR 39 | /*used for check alert*/ 40 | " -check display last record for alert\n" 41 | /*end*/ 42 | #endif 43 | " --check/-C display last record for alert.example:tsar --check / tsar --check --cpu --io\n" 44 | " --watch/-w display last records in N mimutes. example:tsar --watch 30 / tsar --watch 30 --cpu --io\n" 45 | " --cron/-c run in cron mode, output data to file\n" 46 | " --interval/-i specify intervals numbers, in minutes if with --live, it is in seconds\n" 47 | " --list/-L list enabled modules\n" 48 | " --live/-l running print live mode, which module will print\n" 49 | " --file/-f specify a filepath as input\n" 50 | " --ndays/-n show the value for the past days (default: 1)\n" 51 | " --date/-d show the value for the specify day(n or YYYYMMDD)\n" 52 | " --merge/-m merge multiply item to one\n" 53 | " --detail/-D do not conver data to K/M/G\n" 54 | " --spec/-s show spec field data, tsar --cpu -s sys,util\n" 55 | " --item/-I show spec item data, tsar --io -I sda\n" 56 | " --help/-h help\n"); 57 | 58 | fprintf(stderr, 59 | "Modules Enabled:\n" 60 | ); 61 | 62 | for (i = 0; i < statis.total_mod_num; i++) { 63 | mod = mods[i]; 64 | fprintf(stderr, "%s\n", mod->usage); 65 | } 66 | 67 | exit(0); 68 | } 69 | 70 | 71 | struct option longopts[] = { 72 | { "cron", no_argument, NULL, 'c' }, 73 | { "check", no_argument, NULL, 'C' }, 74 | { "watch", required_argument, NULL, 'w' }, 75 | { "interval", required_argument, NULL, 'i' }, 76 | { "list", no_argument, NULL, 'L' }, 77 | { "live", no_argument, NULL, 'l' }, 78 | { "file", required_argument, NULL, 'f' }, 79 | { "ndays", required_argument, NULL, 'n' }, 80 | { "date", required_argument, NULL, 'd' }, 81 | { "merge", no_argument, NULL, 'm' }, 82 | { "detail", no_argument, NULL, 'D' }, 83 | { "spec", required_argument, NULL, 's' }, 84 | { "item", required_argument, NULL, 'I' }, 85 | { "help", no_argument, NULL, 'h' }, 86 | { 0, 0, 0, 0}, 87 | }; 88 | 89 | 90 | static void 91 | main_init(int argc, char **argv) 92 | { 93 | int opt, oind = 0; 94 | #ifdef OLDTSAR 95 | /* check option for tsar1.0 */ 96 | if (argc >= 2) { 97 | if (!strcmp(argv[1], "-check") && argc == 2) { 98 | conf.running_mode = RUN_CHECK; 99 | conf.print_mode = DATA_DETAIL; 100 | conf.print_interval = 60; 101 | conf.print_tail = 0; 102 | conf.print_nline_interval = conf.print_interval; 103 | return; 104 | } 105 | } 106 | /*end*/ 107 | #endif 108 | while ((opt = getopt_long(argc, argv, ":cCw:i:Llf:n:d:s:I:mhD", longopts, NULL)) != -1) { 109 | oind++; 110 | switch (opt) { 111 | case 'c': 112 | conf.running_mode = RUN_CRON; 113 | break; 114 | case 'C': 115 | conf.running_mode = RUN_CHECK_NEW; 116 | break; 117 | case 'w': 118 | conf.running_mode = RUN_WATCH; 119 | conf.print_nminute = atoi(optarg); 120 | oind++; 121 | break; 122 | case 'i': 123 | conf.print_interval = atoi(optarg); 124 | oind++; 125 | break; 126 | case 'L': 127 | conf.running_mode = RUN_LIST; 128 | break; 129 | case 'l': 130 | conf.running_mode = RUN_PRINT_LIVE; 131 | break; 132 | case 'f': 133 | strncpy(conf.output_file_path, optarg, LEN_128); 134 | break; 135 | case 's': 136 | set_special_field(optarg); 137 | break; 138 | case 'I': 139 | set_special_item(optarg); 140 | break; 141 | case 'n': 142 | conf.print_ndays = atoi(optarg); 143 | oind++; 144 | break; 145 | case 'd': 146 | conf.print_day = atoi(optarg); 147 | oind++; 148 | break; 149 | case 'm': 150 | conf.print_merge = MERGE_ITEM; 151 | break; 152 | case 'D': 153 | conf.print_detail = TRUE; 154 | break; 155 | case 'h': 156 | usage(); 157 | break; 158 | case ':': 159 | printf("must have parameter\n"); 160 | usage(); 161 | break; 162 | case '?': 163 | if (argv[oind] && strstr(argv[oind], "--")) { 164 | strncat(conf.output_print_mod, argv[oind], LEN_512 - sizeof(DATA_SPLIT)); 165 | strcat(conf.output_print_mod, DATA_SPLIT); 166 | 167 | } else { 168 | usage(); 169 | } 170 | } 171 | } 172 | /* set default parameter */ 173 | if (!conf.print_ndays) { 174 | conf.print_ndays = 1; 175 | } 176 | 177 | if (!conf.print_interval) { 178 | conf.print_interval = DEFAULT_PRINT_INTERVAL; 179 | } 180 | 181 | if (RUN_NULL == conf.running_mode) { 182 | conf.running_mode = RUN_PRINT; 183 | 184 | } else if (conf.running_mode == RUN_CHECK_NEW) { 185 | conf.print_interval = 60; 186 | conf.print_tail = 0; 187 | } 188 | 189 | if (!strlen(conf.output_print_mod)) { 190 | conf.print_mode = DATA_SUMMARY; 191 | 192 | } else { 193 | conf.print_mode = DATA_DETAIL; 194 | } 195 | 196 | strcpy(conf.config_file, DEFAULT_CONF_FILE_PATH); 197 | if (access(conf.config_file, F_OK)) { 198 | do_debug(LOG_FATAL, "main_init: can't find tsar.conf"); 199 | } 200 | } 201 | 202 | 203 | void 204 | shut_down() 205 | { 206 | close_luavm(L); 207 | free_modules(); 208 | 209 | /* 210 | memset(&conf, 0, sizeof(struct configure)); 211 | memset(mods, 0, sizeof(mods)); 212 | memset(&statis, 0, sizeof(struct statistic)); 213 | */ 214 | } 215 | 216 | 217 | void 218 | running_list() 219 | { 220 | int i; 221 | struct module *mod; 222 | 223 | printf("tsar enable follow modules:\n"); 224 | 225 | for (i = 0; i < statis.total_mod_num; i++) { 226 | mod = mods[i]; 227 | printf(" %s\n", mod->name + 4); 228 | } 229 | } 230 | 231 | 232 | void 233 | running_cron() 234 | { 235 | int have_collect = 0; 236 | /* output interface */ 237 | if (strstr(conf.output_interface, "file")) { 238 | /* output data */ 239 | collect_record(); 240 | output_file(); 241 | have_collect = 1; 242 | } 243 | 244 | if (strstr(conf.output_interface, "db")) { 245 | output_db(have_collect); 246 | } 247 | if (strstr(conf.output_interface, "nagios")) { 248 | output_nagios(); 249 | } 250 | if (strstr(conf.output_interface, "tcp")) { 251 | output_multi_tcp(have_collect); 252 | } 253 | } 254 | 255 | 256 | int 257 | main(int argc, char **argv) 258 | { 259 | 260 | parse_config_file(DEFAULT_CONF_FILE_PATH); 261 | 262 | L = load_luavm(); 263 | if (L == NULL) { 264 | do_debug(LOG_ERR, "load lua vm err"); 265 | return 1; 266 | } 267 | 268 | load_modules(); 269 | 270 | statis.cur_time = time(NULL); 271 | 272 | conf.print_day = -1; 273 | 274 | main_init(argc, argv); 275 | 276 | /* 277 | * enter running 278 | */ 279 | switch (conf.running_mode) { 280 | case RUN_LIST: 281 | running_list(); 282 | break; 283 | 284 | case RUN_CRON: 285 | conf.print_mode = DATA_DETAIL; 286 | running_cron(); 287 | break; 288 | #ifdef OLDTSAR 289 | /*for check option*/ 290 | case RUN_CHECK: 291 | reload_check_modules(); 292 | /* disable module when n_col is zero */ 293 | running_check(RUN_CHECK); 294 | break; 295 | /*end*/ 296 | #endif 297 | case RUN_CHECK_NEW: 298 | if (reload_modules(conf.output_print_mod)) { 299 | conf.print_mode = DATA_DETAIL; 300 | }; 301 | /* disable module when n_col is zero */ 302 | disable_col_zero(); 303 | running_check(RUN_CHECK_NEW); 304 | break; 305 | case RUN_PRINT: 306 | /* reload module by output_stdio_mod and output_print_mod*/ 307 | reload_modules(conf.output_stdio_mod); 308 | reload_modules(conf.output_print_mod); 309 | 310 | /* disable module when n_col is zero */ 311 | disable_col_zero(); 312 | 313 | /* set conf.print_nline_interval */ 314 | conf.print_nline_interval = conf.print_interval; 315 | 316 | running_print(); 317 | break; 318 | 319 | case RUN_PRINT_LIVE: 320 | /* reload module by output_stdio_mod and output_print_mod*/ 321 | reload_modules(conf.output_stdio_mod); 322 | reload_modules(conf.output_print_mod); 323 | 324 | /* disable module when n_col is zero */ 325 | disable_col_zero(); 326 | 327 | running_print_live(); 328 | break; 329 | case RUN_WATCH: 330 | /* reload module by output_stdio_mod and output_print_mod*/ 331 | reload_modules(conf.output_stdio_mod); 332 | reload_modules(conf.output_print_mod); 333 | 334 | /* disable module when n_col is zero */ 335 | disable_col_zero(); 336 | 337 | /* set conf.print_nline_interval */ 338 | conf.print_nline_interval = conf.print_interval; 339 | 340 | running_print(); 341 | break; 342 | 343 | default: 344 | break; 345 | } 346 | 347 | shut_down(); 348 | return 0; 349 | } 350 | -------------------------------------------------------------------------------- /tools/bytes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test $# -ne 2; then 4 | echo "Usage: `basename $0` tsarfile pngfile" 1>&2 5 | exit 1 6 | fi 7 | 8 | datafile=$1.tmp 9 | 10 | grep ":" $1 | awk 'function f(a) { if (index(a, "G") > 0) return a * 1000 * 1000; else if (index(a, "M") > 0) return a * 1000; else return a} {printf "%s %.2f %.2f\n", $1, f($2), f($3)}' > $datafile 11 | 12 | start=`head -n1 $datafile | awk '{print $1}'` 13 | end=`tail -n1 $datafile | awk '{print $1}'` 14 | duration="$start - $end" 15 | 16 | gnuplot << EOF 17 | set terminal png 18 | set output "$2" 19 | set title "bytes in/out ($duration)" 20 | set xlabel "time" 21 | set ylabel "K bytes" 22 | set xdata time 23 | set timefmt "%d/%m-%H:%M" 24 | set format x "%H:%M" 25 | plot "$datafile" using 1:2 title "bytes in" with lines, "$datafile" using 1:3 title "bytes out" with lines 26 | 27 | EOF 28 | 29 | rm $datafile 30 | -------------------------------------------------------------------------------- /tools/cpu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test $# -ne 2; then 4 | echo "Usage: `basename $0` tsarfile pngfile" 1>&2 5 | exit 1 6 | fi 7 | 8 | datafile=$1.tmp 9 | 10 | grep ":" $1 | grep -v '\-\-' | awk '{print $1 " " $2 " " $3 " " $4 " " $7}' > $datafile 11 | 12 | start=`head -n1 $datafile | awk '{print $1}'` 13 | end=`tail -n1 $datafile | awk '{print $1}'` 14 | duration="$start - $end" 15 | 16 | gnuplot << EOF 17 | set terminal png 18 | set output "$2" 19 | set title "CPU utilization ($duration)" 20 | set xlabel "time" 21 | set ylabel "percent (%)" 22 | set yrange [ 0 : 100 ] 23 | set xdata time 24 | set timefmt "%d/%m-%H:%M" 25 | set format x "%H:%M" 26 | plot "$datafile" using 1:2 title "user" with lines, "$datafile" using 1:3 title "sys" with lines, "$datafile" using 1:4 title "wait" with lines, "$datafile" using 1:5 title "util" with lines 27 | 28 | EOF 29 | 30 | rm $datafile 31 | -------------------------------------------------------------------------------- /tools/load.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test $# -ne 2; then 4 | echo "Usage: `basename $0` tsarfile pngfile" 1>&2 5 | exit 1 6 | fi 7 | 8 | datafile=$1.tmp 9 | 10 | grep ":" $1 | grep -v '\-\-' | awk '{print $1 " " $2 " " $3 " " $4}' > $datafile 11 | 12 | start=`head -n1 $datafile | awk '{print $1}'` 13 | end=`tail -n1 $datafile | awk '{print $1}'` 14 | duration="$start - $end" 15 | 16 | gnuplot << EOF 17 | set terminal png 18 | set output "$2" 19 | set title "load ($duration)" 20 | set xlabel "time" 21 | set xdata time 22 | set timefmt "%d/%m-%H:%M" 23 | set format x "%H:%M" 24 | plot "$datafile" using 1:2 title "load1" with lines, "$datafile" using 1:3 title "load5" with lines, "$datafile" using 1:4 title "load15" with lines 25 | EOF 26 | 27 | rm $datafile 28 | -------------------------------------------------------------------------------- /tools/mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test $# -ne 2; then 4 | echo "Usage: `basename $0` tsarfile pngfile" 1>&2 5 | exit 1 6 | fi 7 | 8 | datafile=$1.tmp 9 | 10 | grep ":" $1 | awk 'function f(a){if(index(a,"G")>0) return a*1000; else return a} {printf "%s %.2f %.2f %.2f %.2f %.2f\n", $1, f($2),f($3),f($4),f($5),f($6)}' > $datafile 11 | 12 | start=`head -n1 $datafile | awk '{print $1}'` 13 | end=`tail -n1 $datafile | awk '{print $1}'` 14 | duration="$start - $end" 15 | total=`head -n1 $datafile | awk '{print $6}'` 16 | 17 | gnuplot << EOF 18 | set terminal png 19 | set output "$2" 20 | set title "memory utilization, total = ${total}M ($duration)" 21 | set xlabel "time" 22 | set ylabel "M bytes" 23 | set yrange [ 0 : $total * 1.1 ] 24 | set xdata time 25 | set timefmt "%d/%m-%H:%M" 26 | set format x "%H:%M" 27 | plot "$datafile" using 1:2 title "free" with lines, "$datafile" using 1:3 title "used" with lines, "$datafile" using 1:4 title "buff" with lines, "$datafile" using 1:5 title "cache" with lines 28 | 29 | EOF 30 | 31 | rm $datafile 32 | -------------------------------------------------------------------------------- /tools/packets.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test $# -ne 2; then 4 | echo "Usage: `basename $0` tsarfile pngfile" 1>&2 5 | exit 1 6 | fi 7 | 8 | datafile=$1.tmp 9 | 10 | grep ":" $1 | awk 'function f(a) { if (index(a, "M") > 0) return a * 1000 * 1000; else if (index(a, "K") > 0) return a * 1000; else return a} {printf "%s %.2f %.2f\n", $1, f($4), f($5)}' > $datafile 11 | 12 | start=`head -n1 $datafile | awk '{print $1}'` 13 | end=`tail -n1 $datafile | awk '{print $1}'` 14 | duration="$start - $end" 15 | 16 | gnuplot << EOF 17 | set terminal png 18 | set output "$2" 19 | set title "packets in/out ($duration)" 20 | set xlabel "time" 21 | set xdata time 22 | set timefmt "%d/%m-%H:%M" 23 | set format x "%H:%M" 24 | plot "$datafile" using 1:2 title "packets in" with lines, "$datafile" using 1:3 title "packets out" with lines 25 | 26 | EOF 27 | 28 | rm $datafile 29 | -------------------------------------------------------------------------------- /tools/readme.txt: -------------------------------------------------------------------------------- 1 | 画图脚本使用方法 2 | 3 | 流程: 4 | 先用tsar生成分类数据,再用脚本处理数据文件生成png图片即可。 5 | 6 | 1、画CPU使用率的图 7 | tsar --cpu > cpu.txt 8 | ./cpu.sh cpu.txt cpu.png 9 | 2、内存使用率的图 10 | tsar --mem > mem.txt 11 | ./mem.sh mem.txt mem.png 12 | 3、画load图 13 | tsar --load > load.txt 14 | ./load.sh load.txt load.png 15 | 4、画TCP重传率 16 | tsar --tcp > retran.txt 17 | ./retran.sh retran.txt retran.png 18 | 5、画in和out的包 19 | tsar --traffic > traffic.txt 20 | ./packets.sh traffic.txt packets.png 21 | 6、画in和out的字节数 22 | tsar --traffic > traffic.txt 23 | ./bytes.sh traffic.txt bytes.png 24 | 25 | 26 | 若遇使用问题请联系叔度(shudu@taobao.com) 27 | -------------------------------------------------------------------------------- /tools/retran.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test $# -ne 2; then 4 | echo "Usage: `basename $0` tsarfile pngfile" 1>&2 5 | exit 1 6 | fi 7 | 8 | datafile=$1.tmp 9 | 10 | grep ":" $1 | grep -v '\-\-' | awk '{print $1 " " $6}' > $datafile 11 | 12 | start=`head -n1 $datafile | awk '{print $1}'` 13 | end=`tail -n1 $datafile | awk '{print $1}'` 14 | duration="$start - $end" 15 | 16 | gnuplot << EOF 17 | set terminal png 18 | set output "$2" 19 | set title "TCP retransmission rate ($duration)" 20 | set xlabel "time" 21 | set ylabel "percent (%)" 22 | set yrange [ 0 : 10 ] 23 | set xdata time 24 | set timefmt "%d/%m-%H:%M" 25 | set format x "%H:%M" 26 | plot "$datafile" using 1:2 title "rate" with lines 27 | EOF 28 | 29 | rm $datafile 30 | --------------------------------------------------------------------------------