之前前辈用 java 写的收集 jvm 脚本, 不太方便组内小伙伴维护, 遂用 python 重写了

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: jvm_monitor
# Description: collect jvm info
# Author: quke
# Date: 2018/8/22 import base64
import datetime
import json
import logging.handlers
import os
import random
import re
import socket
import time
from subprocess import Popen, PIPE import MySQLdb
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry logging.basicConfig(level=logging.INFO,
format='%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
)
console_handler = logging.StreamHandler()
file_handler = logging.handlers.RotatingFileHandler('jvm_monitor.log', maxBytes=10485760, backupCount=5) logger = logging.getLogger(__name__)
logger.addHandler(file_handler) hostname = socket.gethostname() def run_command(cmd):
process = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
if stderr:
logger.error('Excepiton with run %s:%s' % (cmd, stderr))
raise SystemExit
else:
return stdout.strip('\n').split('\n') def requests_retry(
retries=3,
backoff_factor=0.3,
status_forcelist=(500, 502, 504),
session=None,
):
session = session or requests.Session()
retry = Retry(
total=retries,
read=retries,
connect=retries,
backoff_factor=backoff_factor,
status_forcelist=status_forcelist,
)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
return session def execute_sql(sql, host='192.168.1.1', user='user', password='password', db='db'):
db = MySQLdb.connect(host, user, password, db)
cursor = db.cursor()
cursor.execute(sql)
if 'insert' in sql or 'update' in sql:
db.commit()
ret = cursor.fetchall()
cursor.close()
db.close()
return ret def get_all_mixed_info():
sql = 'select mixhost,module,alias from cmdb_mixed_relation'
db_detail = execute_sql(sql, host='192.168.1.1', user='user', password='password', db='db')
ret = {}
for obj in db_detail:
hostname, modulename, alias = obj
ret.setdefault(hostname, {}).update({modulename: alias}) return ret def get_java_module(args):
cur_dir = '/apps'
for d in os.listdir(cur_dir):
if os.path.isdir(os.path.join(cur_dir, d)):
if 'java' in d or 'boot' in d or 'tomcat' in d or 'mycat' in d:
if d in args:
return d def get_alias(module_name):
all_alias = get_all_mixed_info()
alias = all_alias.get(hostname, {}).get(module_name)
alias = alias if alias else 'null'
return alias def get_gc_collector_name(line):
for gc in ['UseParNewGC', 'UseG1GC', 'UseSerialGC', 'UseParallelGC']:
if gc in line:
ygc = gc
break
else:
ygc = 'ParNew' for gc in ['UseConcMarkSweepGC', 'UseG1GC', 'UseParallelOldGC', 'UseSerialGC']:
if gc in line:
ogc = gc
break
else:
ogc = 'CMS' return ygc, ogc def get_start_time(pid):
ret = run_command('ps -o lstart -p %s' % pid)
start_time = time.strftime('%Y-%m-%d %H:%M:%S', time.strptime(ret[1], '%a %b %d %H:%M:%S %Y'))
return start_time def get_jstat_info(pid):
ret = run_command('jstat -gc %s' % pid)
rc = re.compile(
r'(?P<s0c>[0-9.]+)\s+(?P<s1c>[0-9.]+)\s+(?P<s0u>[0-9.]+)\s+(?P<s1u>[0-9.]+)\s+(?P<ec>[0-9.]+)\s+(?P<eu>[0-9.]+)\s+(?P<oc>[0-9.]+)\s+(?P<ou>[0-9.]+)\s+(?P<pc>[0-9.]+)\s+(?P<pu>[0-9.]+)\s+(?P<jvmYgc>[0-9.]+)\s+(?P<jvmYgct>[0-9.]+)\s+(?P<jvmFgc>[0-9.]+)\s+(?P<jvmFgct>[0-9.]+)\s+(?P<jvmGct>[0-9.]+)')
gc_statistics = rc.match(ret[1]).groupdict()
return gc_statistics def get_thread_count(pid):
ret = run_command('jstat -snap %s' % pid)
active_thread_count = ret[-3].split('=')[1]
total_thread_count = ret[-1].split('=')[1]
return active_thread_count, total_thread_count def get_jvm_info():
instances = []
ret = run_command('jps -mlv')
for line in ret:
if line and 'sun.tools.jps.Jps' not in line and 'com.lagou.jmonitor.AgentWatcher' not in line:
module = get_java_module(line)
alias = hostname if module in hostname else get_alias(module) if 'null' == alias:
logger.error('[%s] can not get mixed module alias name , continue' % module)
continue ygc, ogc = get_gc_collector_name(line)
instances_list = line.split(' ')
pid = instances_list[0]
start_time = get_start_time(pid)
gc_statistics = get_jstat_info(pid)
active_thread_count, total_thread_count = get_thread_count(pid)
main_function = instances_list[1]
main_args = ' '.join(instances_list[2:])
instances.append(
dict(
pid=pid,
module=module,
alias=alias,
start_time=start_time,
gc_statistics=gc_statistics,
active_thread_count=active_thread_count,
total_thread_count=total_thread_count,
ygc=ygc,
ogc=ogc,
main_function=main_function,
main_args=main_args
)
)
return instances def push_to_oss(jvm):
modulename = jvm.get('module')
hostname = jvm.get('alias')
pid = jvm.get('pid')
mainclassname = jvm.get('main_function')
vmparam = jvm.get('main_args')
updated = jvm.get('start_time') gclist = json.dumps(
[dict(useTime=jvm['gc_statistics']['jvmYgct'], name=jvm['ygc'], times=jvm['gc_statistics']['jvmYgc']),
dict(useTime=jvm['gc_statistics']['jvmFgct'], name=jvm['ogc'], times=jvm['gc_statistics']['jvmFgc'])]) fgcygc = json.dumps(dict(jvmFgc=jvm['gc_statistics']['jvmFgc'],
jvmYgc=jvm['gc_statistics']['jvmYgc'],
jvmFgct=jvm['gc_statistics']['jvmFgct'],
jvmYgct=jvm['gc_statistics']['jvmYgct'], )) get_hostnames_sql = 'select hostname,modulename from jvmmonitordata where modulename="%s"' % modulename
ignore_hostname_ne_modulename = 'select hostname from jvmmonitordata where hostname="%s"' % hostname
logger.info('execute sql :%s' % get_hostnames_sql) is_existing = False
for obj in execute_sql(get_hostnames_sql):
if hostname in obj:
is_existing = True for obj in execute_sql(ignore_hostname_ne_modulename):
if hostname in obj:
is_existing = True if is_existing:
update_jvmmonitordata_sql = "update jvmmonitordata set pid=%d,gclist='%s',fgcygc='%s' where hostname='%s'" % (
int(pid), gclist, fgcygc, hostname)
logger.info('execute sql :%s' % update_jvmmonitordata_sql)
execute_sql(update_jvmmonitordata_sql)
else:
insert_jvmmonitordata_sql = "insert into jvmmonitordata(hostname,modulename,mainclassname,pid,vmparam,gclist,updated,fgcygc) values ('%s','%s','%s',%d,'%s','%s','%s','%s')" % (
hostname, modulename, mainclassname, int(pid), vmparam, gclist, updated, fgcygc)
logger.info('execute sql :%s' % insert_jvmmonitordata_sql)
execute_sql(insert_jvmmonitordata_sql) def get_hbase_svr():
hbase_list = ["http://192.168.100.1:8080", "http://192.168.100.2:8080", "http://192.168.100.3:8080"]
hbase_url = None
retry = 10
while retry > 0:
hbase_url = random.choice(hbase_list)
try:
r = requests.head(hbase_url, timeout=2)
except:
logger.info("connect" + hbase_url + "error, try another")
else:
if r.status_code == 200:
break
retry -= 1
if retry == 0:
logger.error("connect hbase failed with 10 times")
return hbase_url def build_hbase_data(jvm):
hostName = jvm['alias']
jvmEc = float(jvm['gc_statistics']['ec']) * 1000
jvmEu = float(jvm['gc_statistics']['eu']) * 1000
jvmOc = float(jvm['gc_statistics']['oc']) * 1000
jvmOu = float(jvm['gc_statistics']['ou']) * 1000
jvmPc = float(jvm['gc_statistics']['pc']) * 1000
jvmPu = float(jvm['gc_statistics']['pu']) * 1000
jvmSc = (float(jvm['gc_statistics']['s0c']) + float(jvm['gc_statistics']['s1c'])) * 1000
jvmSu = (float(jvm['gc_statistics']['s0u']) + float(jvm['gc_statistics']['s1u'])) * 1000
totalThreadCount = int(jvm['total_thread_count'])
activeThreadCount = int(jvm['active_thread_count']) return dict(
hostName=hostName,
jvmEc=int(jvmEc),
jvmEu=int(jvmEu),
jvmOc=int(jvmOc),
jvmOu=int(jvmOu),
jvmPc=int(jvmPc),
jvmPu=int(jvmPu),
jvmSc=int(jvmSc),
jvmSu=int(jvmSu),
totalThreadCount=totalThreadCount,
activeThreadCount=activeThreadCount,
) def jvm_hbase_constructor(jvm):
"""jvm hbase 数据构造器"""
data = build_hbase_data(jvm)
rows = []
json_rows = {"Row": rows}
row_key = base64.b64encode(data['hostName'] + ":" + datetime.datetime.now().strftime('%Y%m%d%H%M'))
cell = []
for column in ['jvmEc', 'jvmEu', 'jvmOc', 'jvmOu', 'jvmPc', 'jvmPu', 'jvmSc', 'jvmSu',
'totalThreadCount', 'activeThreadCount']:
cell.append({"column": base64.b64encode('jvm' + ":" + column), "$": base64.b64encode(str(data[column]))})
rows.append({'key': row_key, 'Cell': cell})
return row_key, json_rows def push_to_hbase(jvm):
table_name = 'jvm'
try:
row_key, json_rows = jvm_hbase_constructor(jvm)
except Exception as e:
logger.error("construct hbase data error %s" % str(e))
else:
for i in range(10):
hbase_url = get_hbase_svr()
try:
response = requests.post(hbase_url + '/' + table_name + '/' + row_key, data=json.dumps(json_rows),
headers={"Content-Type": "application/json", "Accept": "application/json"},
timeout=60)
if response.status_code == 200:
break
except:
pass
if i == 9:
logger.error("try to save hbase failed with 10 times,exit") def push_data(jvm_infos):
for jvm in jvm_infos:
push_to_oss(jvm)
push_to_hbase(jvm) if __name__ == '__main__':
jvm_infos = get_jvm_info()
push_data(jvm_infos)

python收集jvm数据的更多相关文章

  1. nGrinder对监控机器收集自定义数据及源码分析

    转载:https://blog.csdn.net/neven7/article/details/50782451 0.背景 性能测试工具nGrinder支持在无需修改源码的情况下,对目标服务器收集自定 ...

  2. 通过Python将监控数据由influxdb写入到MySQL

    一.项目背景 我们知道InfluxDB是最受欢迎的时序数据库(TSDB).InfluxDB具有 持续高并发写入.无更新:数据压缩存储:低查询延时 的特点.从下面这个权威的统计图中,就可以看出Influ ...

  3. Python收集这些视频只是单纯的想做做壁纸,大家不要误会

    首先澄清一下,我用Python收集这些视频,绝不是想做别的什么,真的只是用来做动态壁纸,大家不要误会!我不是那样的人~ 这样的不过份吧 (这个动图看不看的到就看有没有缘分了 ) 阅读本文你需要准备 1 ...

  4. 使用Python解析JSON数据的基本方法

    这篇文章主要介绍了使用Python解析JSON数据的基本方法,是Python入门学习中的基础知识,需要的朋友可以参考下:     ----------------------------------- ...

  5. python matplotlib plot 数据中的中文无法正常显示的解决办法

    转发自:http://blog.csdn.net/laoyaotask/article/details/22117745?utm_source=tuicool python matplotlib pl ...

  6. Python/Numpy大数据编程经验

    Python/Numpy大数据编程经验 1.边处理边保存数据,不要处理完了一次性保存.不然程序跑了几小时甚至几天后挂了,就啥也没有了.即使部分结果不能实用,也可以分析程序流程的问题或者数据的特点.   ...

  7. Windows下Python读取GRIB数据

    之前写了一篇<基于Python的GRIB数据可视化>的文章,好多博友在评论里问我Windows系统下如何读取GRIB数据,在这里我做一下说明. 一.在Windows下Python为什么无法 ...

  8. 为什么说Python 是大数据全栈式开发语言

    欢迎大家访问我的个人网站<刘江的博客和教程>:www.liujiangblog.com 主要分享Python 及Django教程以及相关的博客 交流QQ群:453131687 原文链接 h ...

  9. 用Python浅析股票数据

    用Python浅析股票数据 本文将使用Python来可视化股票数据,比如绘制K线图,并且探究各项指标的含义和关系,最后使用移动平均线方法初探投资策略. 数据导入 这里将股票数据存储在stockData ...

随机推荐

  1. python学习 day7 (3月8日)

    read()读出来了之后文件里就从之后开始  光标不知道在哪 编码的进阶: 背景: ASCII:英文字母,数字,特殊符号,------------>二进制的对应关系 str: 一个字符 ---- ...

  2. 再读c++primer plus 002

    1.读取char值时,与读取其它基本类型一样,cin将忽略空格和换行符,函数cin.get(ch)读取输入的下一个字符(即使是空格),并将其赋给变量ch. 2.指针和const:(1)让指针指向一个常 ...

  3. 一窥kbmmw中的 smart service

    在kbmmw 的新版中(还没有发布),将会有一个叫做smart service 的服务.这种服务的属性基于服务器端,并且可以自动注册服务名,下面就是一个简单例子代码.这个服务里面有有三个发布的函数:e ...

  4. 一道区间DP的水题 -- luogu P2858 [USACO06FEB]奶牛零食Treats for the Cows

    https://www.luogu.org/problemnew/show/P2858 方程很好想,关键我多枚举了一次(不过也没多大关系) #include <bits/stdc++.h> ...

  5. 爬虫之mongodb数据库

    一 mongodb的介绍 1.易用性:mongodb是一款强大.灵活并且易扩展的数据库.他面向于文档的数据库,而不是关系性数据库.不采用关系型主要是为了获得更好的扩展性.还有一个好处就是面向文档的数据 ...

  6. Oracle启动两个监听

    接上篇:Oracle服务器修改IP后 Oracle服务器更换IP后,办公网络里面可以正常访问了,外地的同事,连了vpn 也可以访问,以为可以收工回家,突然又有同事过来说,机房的服务器ping不通新的i ...

  7. docker 安装私服

    官方的docker hub 提供了一个公共镜像服务器,但是有时候不希望自己 的镜像放到公网上,这个时候就需要创建自己的私服,用来存储管理自己的镜像. 1.安装私服 docker run -d -v $ ...

  8. WebVTT 及 HTML5 <track> 元素简介

    https://dev.opera.com/articles/zh-cn/an-introduction-to-webvtt-and-track/ 简介 网络视频文本轨道,简称为 WebVTT, 是一 ...

  9. excel2007vba绘图1

    参考:http://club.excelhome.net/thread-480025-1-1.html '----------------------------------------------- ...

  10. UVa 11542 Square (高斯消元)

    题意:给定 n 个数,从中选出一个,或者是多个,使得选出的整数的乘积是完全平方数,求一共有多少种选法,整数的素因子不大于 500. 析:从题目素因子不超过 500,就知道要把每个数进行分解.因为结果要 ...