add response_time histgram for web_log
Signed-off-by: Wing924 <weihe924stephen@gmail.com>
Wing924 committed
Mar 19, 2018 at 11:53 UTC
78f2feee95f01429615a0027ab1efa0345a8f1ed
2 files changed
+66
-5
conf.d/python.d/web_log.conf
+1
@@ -85,6 +85,7 @@
85
# custom_log_format: # define a custom log format
86
# pattern: '(?P<address>[\da-f.:]+) -.*?"(?P<method>[A-Z]+) (?P<url>.*?)" (?P<code>[1-9]\d{2}) (?P<bytes_sent>\d+) (?P<resp_length>\d+) (?P<resp_time>\d+\.\d+) '
87
# time_multiplier: 1000000 # type <int> - convert time to microseconds
88
+# histgram: [1,3,10,30,100, ...] # type list of int - Cumulative histogram of response time in milli seconds
89
90
# ----------------------------------------------------------------------
91
# WEB SERVER CONFIGURATION
python.d/web_log.chart.py
+65
-5
@@ -5,6 +5,7 @@
5
import bisect
6
import re
7
import os
8
+import sys
9
10
from collections import namedtuple, defaultdict
11
from copy import deepcopy
@@ -21,7 +22,8 @@ from bases.FrameworkServices.LogService import LogService
22
23
ORDER_APACHE_CACHE = ['apache_cache']
24
24
-ORDER_WEB = ['response_statuses', 'response_codes', 'bandwidth', 'response_time', 'response_time_upstream',
25
+ORDER_WEB = ['response_statuses', 'response_codes', 'bandwidth',
26
+ 'response_time', 'response_time_hist', 'response_time_upstream', 'response_time_upstream_hist',
27
'requests_per_url', 'requests_per_user_defined', 'http_method', 'http_version',
28
'requests_per_ipproto', 'clients', 'clients_all']
29
@@ -55,6 +57,10 @@ CHARTS_WEB = {
57
['resp_time_max', 'max', 'incremental', 1, 1000],
58
['resp_time_avg', 'avg', 'incremental', 1, 1000]
59
]},
60
+ 'response_time_hist': {
61
+ 'options': [None, 'Processing Time Histgram', 'requests/s', 'timings', 'web_log.response_time_hist', 'line'],
62
+ 'lines': [
63
+ ]},
64
'response_time_upstream': {
65
'options': [None, 'Processing Time Upstream', 'milliseconds', 'timings',
66
'web_log.response_time_upstream', 'area'],
@@ -63,6 +69,11 @@ CHARTS_WEB = {
69
['resp_time_upstream_max', 'max', 'incremental', 1, 1000],
70
['resp_time_upstream_avg', 'avg', 'incremental', 1, 1000]
71
]},
72
+ 'response_time_upstream_hist': {
73
+ 'options': [None, 'Processing Time Histgram', 'requests/s', 'timings',
74
+ 'web_log.response_time_upstream_hist', 'line'],
75
+ 'lines': [
76
+ ]},
77
'clients': {
78
'options': [None, 'Current Poll Unique Client IPs', 'unique ips', 'clients', 'web_log.clients', 'stacked'],
79
'lines': [
@@ -347,8 +358,30 @@ class Web:
358
"""
359
if 'resp_time' not in match_dict:
360
self.order.remove('response_time')
361
+ self.order.remove('response_time_hist')
362
if 'resp_time_upstream' not in match_dict:
363
self.order.remove('response_time_upstream')
364
+ self.order.remove('response_time_upstream_hist')
365
+
366
+ # Add 'response_time_hist' and 'response_time_upstream_hist' charts if is specified in the configuration
367
+ histgram = self.configuration.get('histgram', None)
368
+ if type(histgram) is list:
369
+ self.storage['bucket_index'] = histgram[:]
370
+ self.storage['bucket_index'].append(sys.maxint)
371
+ self.storage['buckets'] = [0] * (len(histgram) + 1)
372
+ self.storage['upstream_buckets'] = [0] * (len(histgram) + 1)
373
+ hist_lines = self.definitions['response_time_hist']['lines']
374
+ upstream_hist_lines = self.definitions['response_time_upstream_hist']['lines']
375
+ for i, le in enumerate(histgram):
376
+ hist_key = "response_time_hist_%d" % i
377
+ upstream_hist_key = "response_time_upstream_hist_%d" % i
378
+ hist_lines.append([hist_key, str(le), 'incremental', 1, 1])
379
+ upstream_hist_lines.append([upstream_hist_key, str(le), 'incremental', 1, 1])
380
+
381
+ hist_lines.append(["response_time_hist_%d" % len(histgram), '+Inf', 'incremental', 1, 1])
382
+ upstream_hist_lines.append(["response_time_upstream_hist_%d" % len(histgram), '+Inf', 'incremental', 1, 1])
383
+ elif histgram is not None:
384
+ self.error("expect histgram list, but was {}".format(type(histgram)))
385
386
if not self.configuration.get('all_time', True):
387
self.order.remove('clients_all')
@@ -431,11 +464,15 @@ class Web:
464
resp_length = match_dict['resp_length'] if '-' not in match_dict['resp_length'] else 0
465
self.data['resp_length'] += int(resp_length)
466
if 'resp_time' in match_dict:
434
- get_timings(timings=timings['resp_time'],
435
- time=self.storage['func_resp_time'](float(match_dict['resp_time'])))
467
+ resp_time = self.storage['func_resp_time'](float(match_dict['resp_time']))
468
+ get_timings(timings=timings['resp_time'], time=resp_time)
469
+ if 'bucket_index' in self.storage:
470
+ get_hist(self.storage['bucket_index'], self.storage['buckets'], resp_time / 1000)
471
if 'resp_time_upstream' in match_dict and match_dict['resp_time_upstream'] != '-':
437
- get_timings(timings=timings['resp_time_upstream'],
438
- time=self.storage['func_resp_time'](float(match_dict['resp_time_upstream'])))
472
+ resp_time_upstream = self.storage['func_resp_time'](float(match_dict['resp_time_upstream']))
473
+ get_timings(timings=timings['resp_time_upstream'], time=resp_time_upstream)
474
+ if 'bucket_index' in self.storage:
475
+ get_hist(self.storage['bucket_index'], self.storage['upstream_buckets'], resp_time / 1000)
476
# requests per ip proto
477
proto = 'ipv6' if ':' in match_dict['address'] else 'ipv4'
478
self.data['req_' + proto] += 1
@@ -456,6 +493,17 @@ class Web:
493
self.data[elem + '_min'] += timings[elem]['minimum']
494
self.data[elem + '_avg'] += timings[elem]['summary'] / timings[elem]['count']
495
self.data[elem + '_max'] += timings[elem]['maximum']
496
+
497
+ # histgram
498
+ if 'bucket_index' in self.storage:
499
+ buckets = self.storage['buckets']
500
+ upstream_buckets = self.storage['upstream_buckets']
501
+ for i, le in enumerate(self.storage['bucket_index']):
502
+ hist_key = "response_time_hist_%d" % i
503
+ upstream_hist_key = "response_time_upstream_hist_%d" % i
504
+ self.data[hist_key] = buckets[i]
505
+ self.data[upstream_hist_key] = upstream_buckets[i]
506
+
507
return self.data
508
509
def find_regex(self, last_line):
@@ -903,6 +951,18 @@ def get_timings(timings, time):
951
timings['summary'] += time
952
timings['count'] += 1
953
954
+def get_hist(index, buckets, time):
955
+ """
956
+ :param index: histgram index (Ex. [10, 50, 100, 150, ...])
957
+ :param buckets: histgram buckets
958
+ :param time: time
959
+ :return: None
960
+ """
961
+ for i in xrange(len(index)-1, -1, -1):
962
+ if time <= index[i]:
963
+ buckets[i] += 1
964
+ else:
965
+ break
966
967
def address_not_in_pool(pool, address, pool_size):
968
"""