之前前辈用 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. linux下导入导出数据库

    导入导出数据库用mysqldump命令,使用方法与mysql命令类似. 导出 导出sql(包含数据和表结构):mysqldump -uroot -p dbname > dbname.sql 导出 ...

  2. css的基础用法之标签选择

    一.css的4种引入方式 #.内联式 <p style="color: red;font-size: 50px;text-align: center">Egon是一个非 ...

  3. mysql 表锁进程非常多的情况

    今天要说的是mysql 的 MYISAM引擎下的表锁问题. 通常来说,在MyISAM里读写操作是串行的,但当对同一个表进行查询和插入操作时,为了降低锁竞争的频率,根据concurrent_insert ...

  4. Opencv(3):基本数据类型

    1.比较简单的原子类型 结构 成员 意义 CvPoint int x,y 图像中的点 CvPoint2D32f float x,y 二维空间中的点 CvPoint3D32f float x,y,z 三 ...

  5. IE与非IE window.onload调用

    IEwin.attachEvent('onload', function(){ });非IEwin.onload=function(){}; if(navigator.appName == " ...

  6. 2014年的最后一个程序,却成为了2015年的第一个bug

    这个点不睡觉的程序员,要么就是在努力学技术,要么就是代码出bug了.而我,是后者.呵呵,2015了,觉还是要睡的

  7. 学以致用十八-----shell脚本之基础概念及变量

    1.脚本脚本,说了很多年的脚本,一直都没怎么弄明白为什么叫脚本,还仅仅是script翻译过来的?今天再查看翻译,查阅了资料,对脚本有了个新的认识. script也叫剧本,脚本---剧本,像剧本一样,让 ...

  8. js 匿名函数 用法

    JS执行顺序为从上到下 先声明存储匿名函数的变量放在JS文件中 <script src="/Scripts/niming.js" type="text/javasc ...

  9. c++ cout、<< 、cin、>> 、endl 详解

    std::cout是在#include<iostream>库中的ostream类型中的对象 std::表示命名空间,标准库定义的所有名字都在命名空间std中 std::cout是在#inc ...

  10. mysql问题处理记录

    1.使用 navicate 导出 csv 文件用 excel 打开乱码 由于excel默认编码是gbk,而navicate导出数据默认编码是utf-8,因此... 解决办法: 使用WPS打开文件,然后 ...