##// 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 import time
38 import time
39
39
40 import datetime
40 import datetime
41 import requests
42 import psutil
41 import psutil
43
42
44 import logging
43 import logging
45 import socket
44 import socket
46 logging.basicConfig(level=logging.DEBUG)
47
48
45
49 def profile():
46 from webhelpers.number import format_byte_size
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)
56
47
57 while True:
48 logging.basicConfig(level=logging.DEBUG)
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)
66
49
67
50
68 def parse_options():
51 def parse_options():
@@ -72,6 +55,9 b' def parse_options():'
72 '--pid', required=True, type=int,
55 '--pid', required=True, type=int,
73 help="Process ID to monitor.")
56 help="Process ID to monitor.")
74 parser.add_argument(
57 parser.add_argument(
58 '--human', action='store_true',
59 help="Show Human numbers")
60 parser.add_argument(
75 '--interval', '-i', type=float, default=5,
61 '--interval', '-i', type=float, default=5,
76 help="Interval in secods.")
62 help="Interval in secods.")
77 parser.add_argument(
63 parser.add_argument(
@@ -87,28 +73,78 b' def parse_options():'
87 return parser.parse_args()
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 mem = process.memory_info()
99 mem = process.memory_info()
92 iso_now = datetime.datetime.utcnow().isoformat()
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 stats = [
109 stats = [
94 {'message': 'Memory stats of process {pid}'.format(pid=process.pid),
110 {'message': 'Memory stats of process {pid}'.format(pid=process.pid),
95 'namespace': 'process.{pid}'.format(pid=process.pid),
111 'namespace': 'process.{pid}'.format(pid=process.pid),
96 'server': socket.getfqdn(socket.gethostname()),
112 'server': socket.getfqdn(socket.gethostname()),
97 'tags': [
113 'tags': [
98 ['rss', mem.rss],
114 ['rss', cur_rss],
99 ['vms', mem.vms]],
115 ['vms', cur_vms]
116 ],
117 'diff': [
118 ['rss', prev_rss_diff],
119 ['vms', prev_vms_diff]
120 ],
100 'date': iso_now,
121 'date': iso_now,
101 },
122 },
102 ]
123 ]
103 return stats
124 return stats
104
125
105
126
106 def dump_stats(stats):
127 def dump_stats(stats, human=False):
107 for sample in stats:
128 for sample in stats:
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:
108 print(json.dumps(sample))
144 print(json.dumps(sample))
109
145
110
146
111 class AppenlightClient():
147 class AppenlightClient(object):
112
148
113 url_template = '{url}?protocol_version=0.5'
149 url_template = '{url}?protocol_version=0.5'
114
150
@@ -117,6 +153,7 b' class AppenlightClient():'
117 self.api_key = api_key
153 self.api_key = api_key
118
154
119 def dump_stats(self, stats):
155 def dump_stats(self, stats):
156 import requests
120 response = requests.post(
157 response = requests.post(
121 self.url,
158 self.url,
122 headers={
159 headers={
General Comments 0
You need to be logged in to leave comments. Login now