diff options
| author | Qiuwen Lu <[email protected]> | 2018-03-10 14:44:03 +0800 |
|---|---|---|
| committer | Qiuwen Lu <[email protected]> | 2018-03-10 14:44:03 +0800 |
| commit | 12ea152a6d74da8353c4c04cae8cabc41f2ff443 (patch) | |
| tree | 827e7a878c5cbeaaaa633ded5f9d7288fcb2f1d3 | |
| parent | 2116050524d2cba9fac89844564645770d60e12f (diff) | |
增加pagstat功能,对接A3项目。v4.2.37-20180310
| -rw-r--r-- | tools/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | tools/pagstat/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | tools/pagstat/pagstat.py | 205 |
3 files changed, 220 insertions, 0 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index a14bd13..d1a3867 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(tcpdump) add_subdirectory(monit_device) add_subdirectory(monit_stream) +add_subdirectory(pagstat) add_subdirectory(dlogreader) add_subdirectory(devbind) add_subdirectory(systemd)
\ No newline at end of file diff --git a/tools/pagstat/CMakeLists.txt b/tools/pagstat/CMakeLists.txt new file mode 100644 index 0000000..1d1d72f --- /dev/null +++ b/tools/pagstat/CMakeLists.txt @@ -0,0 +1,14 @@ + +set(PI_DIST_PATH ${CMAKE_CURRENT_BINARY_DIR}/pi_dist) +set(PI_BUILD_PATH ${CMAKE_CURRENT_BINARY_DIR}/pi_build) +set(PI_SPEC_PATH ${CMAKE_CURRENT_BINARY_DIR}/pi_spec) + +add_custom_command(OUTPUT ${PI_DIST_PATH}/pagstat + COMMAND pyinstaller -F -y --distpath ${PI_DIST_PATH} + --workpath ${PI_BUILD_PATH} + --specpath ${PI_SPEC_PATH} + --noconsole ${CMAKE_CURRENT_SOURCE_DIR}/pagstat.py + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/pagstat.py) + +add_custom_target(pagstat ALL DEPENDS ${PI_DIST_PATH}/pagstat) +install(PROGRAMS ${PI_DIST_PATH}/pagstat DESTINATION bin COMPONENT Program)
\ No newline at end of file diff --git a/tools/pagstat/pagstat.py b/tools/pagstat/pagstat.py new file mode 100644 index 0000000..d0f2875 --- /dev/null +++ b/tools/pagstat/pagstat.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python2 + +import argparse +import json +import prettytable +import time +import sys +import signal +import os +import telegraf +import socket + +TBPS = (1 * 1000 * 1000 * 1000 * 1000) +GBPS = (1 * 1000 * 1000 * 1000) +MBPS = (1 * 1000 * 1000) +KBPS = (1 * 1000) + +G_JSON_PATH = '/var/run/mrzcpd/mrmonit.daemon' + +TITLE_VECTOR = ['PhyRXFrame','PhyRXBits','PhyRXMissed','PhyRXError', + 'PhyRXNoBUF','PhyTXFrame','PhyTXBits','PhyTXError', + 'UsrRXDrops', 'UsrTXDrops'] + +TITLE_MAP = { 'rx_total_packets' : 'ipackets', + 'rx_total_bytes' : 'ibytes', + 'rx_packets' : 'ipackets', + 'rx_bytes' : 'ibytes', + 'tx_packets' : 'opackets', + 'tx_bytes' : 'obytes', + 'port_dropped' : 'imissed', + 'rx_dropped' : '', + 'rx_errors' : 'ierrors' + } + +def locate_vector_by_symbol(vector, symbol): + return [s for s in vector if s['symbol'] == symbol] + +def list_all_phydev(json_fp): + return [ s['symbol'] for s in json_fp['device']] + +def phydev_value_read(json_fp, str_device, str_item): + phydevs = locate_vector_by_symbol(json_fp['device'], str_device) + return phydevs[0]['stats']['accumulative'][str_item] + +def phydev_speed_read(json_fp, str_device, str_item): + phydevs = locate_vector_by_symbol(json_fp['device'], str_device) + return phydevs[0]['stats']['speed'][str_item] + +def trans_to_human_readable(value): + if value > TBPS: + return value * 1.0 / TBPS, 'T' + if value > GBPS: + return value * 1.0 / GBPS, 'G' + if value > MBPS: + return value * 1.0 / MBPS, 'M' + if value > KBPS: + return value * 1.0 / KBPS, 'K' + + return value * 1.0, ' ' + +def dump_human_table(json_fp, devsym, is_human_number = 0): + + print("%16s %16s %16s %16s %16s %16s %16s %16s %16s %16s %16s" % + ("rx_total_packets", "rx_total_bytes", "rx_packets", "rx_bytes", + "tx_packets","tx_bytes", "port_dropped", "rx_dropped", + "rx_errors", "ring_tx_packets", "ring_tx_bytes")) + + print("%16u %16u %16u %16u %16u %16u %16u %16u %16u %16u %16u" % ( + phydev_value_read(json_fp, devsym, 'ipackets'), phydev_value_read(json_fp, devsym, 'ibytes') / 8, + phydev_value_read(json_fp, devsym, 'ipackets'), phydev_value_read(json_fp, devsym, 'ibytes') / 8, + phydev_value_read(json_fp, devsym, 'opackets'), phydev_value_read(json_fp, devsym, 'obytes') / 8, + phydev_value_read(json_fp, devsym, 'imissed'), 0, 0, 0, 0)) + +# APM sendlog format +def dump_apm_sendlog(json_fp, telegraf_client, devsym): + + __metric_dict_speed = {} + __metric_dict_value = {} + __tags = {'device' : devsym } + + for item in TITLE_VECTOR: + value = phydev_speed_read(json_fp, devsym, TITLE_MAP[item]) + __metric_dict_speed[item] = value + + for item in TITLE_VECTOR: + value = phydev_value_read(json_fp, devsym, TITLE_MAP[item]) + __metric_dict_value[item] = value + + telegraf_client.metric('mr4_device_rxtx_speed', __metric_dict_speed, tags = __tags) + telegraf_client.metric('mr4_device_rxtx_value', __metric_dict_value, tags = __tags) + return + +def setup_argv_parser(phydev_list): + + parser = argparse.ArgumentParser(description='Marsio ZeroCopy Tools -- Monitor NIC devices', + version = 'Marsio ZeroCopy Tools Suite 4.1') + + parser.add_argument('-t', '--time', help = 'interval, seconds to wait between updates', + type=int, default = 1) + parser.add_argument('-l', '--loop', help = 'print loop, exit when recv a signal', + action='store_true', default = 0) + parser.add_argument('-H', '--human-readable', help = 'print value in human readable format', + action = 'store_true', default = 0) + parser.add_argument('-i', '--interface', help = 'the name of network interface', + action = 'append', choices=phydev_list) + parser.add_argument('--clear-screen', help = 'clear screen at start of loop', + action='store_true', default = 0) + + # APM sendlog options + parser.add_argument('--sendlog-apm', help = 'send log to apm server', + action='store_true', default = 0) + parser.add_argument('--sendlog-apm-cfg', help = 'send log configure file', + type=str, default = '/opt/mrzcpd/etc/mrsendlog.conf') + + return parser.parse_args() + +def phydev_json_load(): + with open(G_JSON_PATH) as json_fp: + return json.load(json_fp) + + +def sendlog_hostname(test_hostname, test_port): + import socket + + hostname = socket.gethostname() + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect((test_hostname, int(test_port))) + local_ip_addr = s.getsockname()[0] + except: + local_ip_addr = '127.0.0.1' + finally: + s.close() + + return hostname, local_ip_addr + +def sendlog_apm_init(r_option): + import ConfigParser + import urllib + + config = ConfigParser.ConfigParser() + config.read(r_option.sendlog_apm_cfg) + + apm_server_url = config.get('sendlog_apm', 'apm_device_server') + url_proto, rest = urllib.splittype(apm_server_url) + url_host, rest = urllib.splithost(rest) + url_host, url_port = urllib.splitport(url_host) + + hostname, local_ip_addr = sendlog_hostname(url_host, url_port) + sendlog_tags = {'host' : hostname, 'local_ip_addr': local_ip_addr} + + if url_proto == 'udp': + telegraf_client = telegraf.TelegrafClient(host = url_host, + port = int(url_port), tags = sendlog_tags) + elif url_proto == 'http': + telegraf_client = telegraf.HttpClient(host = url_host, + port = int(url_port), tags = sendlog_tags) + + return telegraf_client + +def sigint_handler(handler, frame): + sys.exit(0) + +def main(): + signal.signal(signal.SIGINT, sigint_handler) + + try: + json_fp = phydev_json_load() + phydev_list = list_all_phydev(json_fp) + r_option = setup_argv_parser(phydev_list) + + if r_option.sendlog_apm: + telegraf_client = sendlog_apm_init(r_option) + + phydev_user_list = phydev_list if r_option.interface is None else r_option.interface + + while True: + if r_option.clear_screen: + os.system('clear') + + json_fp = phydev_json_load() + + if r_option.sendlog_apm: + for devsym in phydev_user_list: + dump_apm_sendlog(json_fp, telegraf_client, devsym) + else: + for devsym in phydev_user_list: + dump_human_table(json_fp, devsym, r_option.human_readable) + + if not r_option.loop: + break + + time.sleep(r_option.time) + + except KeyboardInterrupt: + pass + except ValueError as err: + print(("%s, perhaps mrzcpd program is not running.") % str(err)) + except IOError as err: + print(("%s, perhaps mrzcpd program is not running.") % str(err)) + + return 0 + +if __name__ == '__main__': + main()
\ No newline at end of file |
