##// END OF EJS Templates
profiling: updated profile-memory script to be more human friendly.
marcink -
r3857:73e6cefb default
parent child Browse files
Show More
@@ -38,31 +38,14 b' import sys'
38 38 import time
39 39
40 40 import datetime
41 import requests
42 41 import psutil
43 42
44 43 import logging
45 44 import socket
46 logging.basicConfig(level=logging.DEBUG)
47
48 45
49 def profile():
50 config = parse_options()
51 try:
52 process = psutil.Process(config.pid)
53 except psutil.NoSuchProcess:
54 print("Process {pid} does not exist!".format(pid=config.pid))
55 sys.exit(1)
46 from webhelpers.number import format_byte_size
56 47
57 while True:
58 stats = process_stats(process)
59 dump_stats(stats)
60 if config.appenlight:
61 client = AppenlightClient(
62 url=config.appenlight_url,
63 api_key=config.appenlight_api_key)
64 client.dump_stats(stats)
65 time.sleep(config.interval)
48 logging.basicConfig(level=logging.DEBUG)
66 49
67 50
68 51 def parse_options():
@@ -72,6 +55,9 b' def parse_options():'
72 55 '--pid', required=True, type=int,
73 56 help="Process ID to monitor.")
74 57 parser.add_argument(
58 '--human', action='store_true',
59 help="Show Human numbers")
60 parser.add_argument(
75 61 '--interval', '-i', type=float, default=5,
76 62 help="Interval in secods.")
77 63 parser.add_argument(
@@ -87,28 +73,78 b' def parse_options():'
87 73 return parser.parse_args()
88 74
89 75
90 def process_stats(process):
76 def profile():
77 config = parse_options()
78 try:
79 process = psutil.Process(config.pid)
80 except psutil.NoSuchProcess:
81 print("Process {pid} does not exist!".format(pid=config.pid))
82 sys.exit(1)
83
84 prev_stats = None
85 while True:
86 stats = process_stats(process, prev_stats)
87 prev_stats = stats
88 dump_stats(stats, human=config.human)
89
90 if config.appenlight:
91 client = AppenlightClient(
92 url=config.appenlight_url,
93 api_key=config.appenlight_api_key)
94 client.dump_stats(stats)
95 time.sleep(config.interval)
96
97
98 def process_stats(process, prev_stats):
91 99 mem = process.memory_info()
92 100 iso_now = datetime.datetime.utcnow().isoformat()
101 prev_rss_diff, prev_vms_diff = 0, 0
102 cur_rss = mem.rss
103 cur_vms = mem.vms
104
105 if prev_stats:
106 prev_rss_diff = cur_rss - prev_stats[0]['tags'][0][1]
107 prev_vms_diff = cur_vms - prev_stats[0]['tags'][1][1]
108
93 109 stats = [
94 110 {'message': 'Memory stats of process {pid}'.format(pid=process.pid),
95 111 'namespace': 'process.{pid}'.format(pid=process.pid),
96 112 'server': socket.getfqdn(socket.gethostname()),
97 113 'tags': [
98 ['rss', mem.rss],
99 ['vms', mem.vms]],
114 ['rss', cur_rss],
115 ['vms', cur_vms]
116 ],
117 'diff': [
118 ['rss', prev_rss_diff],
119 ['vms', prev_vms_diff]
120 ],
100 121 'date': iso_now,
101 122 },
102 123 ]
103 124 return stats
104 125
105 126
106 def dump_stats(stats):
127 def dump_stats(stats, human=False):
107 128 for sample in stats:
108 print(json.dumps(sample))
129 if human:
130 diff = stats[0]['diff'][0][1]
131 if diff < 0:
132 diff = '-' + format_byte_size(abs(diff), binary=True)
133 elif diff > 0:
134 diff = '+' + format_byte_size(diff, binary=True)
135 else:
136 diff = ' ' + format_byte_size(diff, binary=True)
137
138 print('Sample:{message} RSS:{rss} RSS_DIFF:{rss_diff}'.format(
139 message=stats[0]['message'],
140 rss=format_byte_size(stats[0]['tags'][0][1], binary=True),
141 rss_diff=diff,
142 ))
143 else:
144 print(json.dumps(sample))
109 145
110 146
111 class AppenlightClient():
147 class AppenlightClient(object):
112 148
113 149 url_template = '{url}?protocol_version=0.5'
114 150
@@ -117,6 +153,7 b' class AppenlightClient():'
117 153 self.api_key = api_key
118 154
119 155 def dump_stats(self, stats):
156 import requests
120 157 response = requests.post(
121 158 self.url,
122 159 headers={
General Comments 0
You need to be logged in to leave comments. Login now