Skip to content

Commit

Permalink
Merge "Adding stats for UVE GET/POST in Opserver" into R2.22-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Sep 7, 2015
2 parents d51e835 + bd0d3a6 commit ea82b86
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 13 deletions.
13 changes: 13 additions & 0 deletions src/analytics/analytics.sandesh
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,16 @@ uve sandesh QueryPerfInfoTrace {
1: QueryPerfInfo data
}

struct AnalyticsApiSample {
1: string operation_type // (GET, POST)
3: string remote_ip
5: string object_type
6: string request_url
8: u64 response_time_in_usec
9: u64 response_size
10: string node (key="ObjectCollectorInfo")
}

objectlog sandesh AnalyticsApiStats {
1: AnalyticsApiSample api_stats (tags=".operation_type,.remote_ip,.object_type")
}
17 changes: 16 additions & 1 deletion src/analytics/viz.sandesh
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,22 @@ const list<stat_table> _STAT_TABLES = [
{ 'name' : 'if_stats.in_bw_usage', 'datatype' : 'int', 'index' : false },
{ 'name' : 'if_stats.out_bw_usage', 'datatype' : 'int', 'index' : false }
]
}
},
{
'display_name' : 'Analytics API Statistics',
'stat_type' : 'AnalyticsApiStats',
'stat_attr' : 'api_stats',
'obj_table' : 'NONE',
'attributes' : [
{ 'name' : 'api_stats.operation_type', 'datatype' : 'string', 'index' : true },
{ 'name' : 'api_stats.remote_ip', 'datatype' : 'string', 'index' : true },
{ 'name' : 'api_stats.object_type', 'datatype' : 'string', 'index' : true },
{ 'name' : 'api_stats.request_url', 'datatype' : 'string', 'index' : false },
{ 'name' : 'api_stats.response_time_in_usec', 'datatype' : 'int', 'index' : false },
{ 'name' : 'api_stats.response_size', 'datatype' : 'int', 'index' : false },
{ 'name' : 'api_stats.node', 'datatype' : 'string', 'index' : false },
]
},
{
'display_name' : 'Api Server Statistics',
'stat_type' : 'VncApiStatsLog',
Expand Down
60 changes: 50 additions & 10 deletions src/opserver/opserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,31 @@ def redis_publish(self, msg_type, destination, msg):

# end class OpStateServer

class AnalyticsApiStatistics(object):
def __init__(self, sandesh, obj_type):
self.obj_type = obj_type
self.time_start = UTCTimestampUsec()
self.api_stats = None
self.sandesh = sandesh

def collect(self, resp_size):
time_finish = UTCTimestampUsec()

# Create api stats object
self.api_stats = AnalyticsApiSample(
operation_type=bottle.request.method,
remote_ip=bottle.request.headers.get('Host'),
request_url=bottle.request.url,
object_type=self.obj_type,
response_time_in_usec=(time_finish - self.time_start),
response_size=resp_size,
node=self.sandesh.source_id())

def sendwith(self):
stats_log = AnalyticsApiStats(api_stats=self.api_stats,
sandesh=self.sandesh)
stats_log.send(sandesh=self.sandesh)

class OpServer(object):

"""
Expand Down Expand Up @@ -408,6 +433,7 @@ def __init__(self):
file=self._args.log_file,
enable_syslog=self._args.use_syslog,
syslog_facility=self._args.syslog_facility)
self._sandesh = sandesh_global
ConnectionState.init(sandesh_global, self._hostname, self._moduleid,
self._instance_id,
staticmethod(ConnectionState.get_process_state_cb),
Expand Down Expand Up @@ -1288,20 +1314,21 @@ def _uve_alarm_http_post(self, is_alarm):
(code, msg) = result
abort(code, msg)
uve_type = bottle.request.url.rsplit('/', 1)[1]
try:
uve_tbl = uve_type
if uve_type in UVE_MAP:
uve_tbl = UVE_MAP[uve_type]
except Exception as e:
yield bottle.HTTPError(_ERRORS[errno.EINVAL],
'Invalid table name')

try:
req = bottle.request.json
filters = OpServer._uve_http_post_filter_set(req)
except Exception as err:
yield bottle.HTTPError(_ERRORS[errno.EBADMSG], err)
else:
try:
req = bottle.request.json
filters = OpServer._uve_http_post_filter_set(req)
except Exception as err:
yield bottle.HTTPError(_ERRORS[errno.EBADMSG], err)
stats = AnalyticsApiStatistics(self._sandesh, uve_type)
bottle.response.set_header('Content-Type', 'application/json')
yield u'{"value": ['
first = True
num = 0
for key in filters['kfilt']:
if key.find('*') != -1:
for gen in self._uve_server.multi_uve_get(uve_tbl, True,
Expand All @@ -1312,20 +1339,26 @@ def _uve_alarm_http_post(self, is_alarm):
first = False
else:
yield u', ' + json.dumps(gen)
num += 1
stats.collect(num)
stats.sendwith()
yield u']}'
return
first = True
for key in filters['kfilt']:
uve_name = uve_tbl + ':' + key
_, rsp = self._uve_server.get_uve(uve_name, True, filters,
is_alarm=is_alarm)
num += 1
if rsp != {}:
data = {'name': key, 'value': rsp}
if first:
yield u'' + json.dumps(data)
first = False
else:
yield u', ' + json.dumps(data)
stats.collect(num)
stats.sendwith()
yield u']}'
# end _uve_alarm_http_post

Expand All @@ -1346,29 +1379,36 @@ def _uve_alarm_http_get(self, uve_type, name, is_alarm):
filters = OpServer._uve_filter_set(req)
except Exception as e:
yield bottle.HTTPError(_ERRORS[errno.EBADMSG], e)

flat = False
if 'flat' in req.keys() or any(filters.values()):
flat = True

stats = AnalyticsApiStatistics(self._sandesh, uve_type)

uve_name = uve_tbl + ':' + name
if name.find('*') != -1:
flat = True
yield u'{"value": ['
first = True
if filters['kfilt'] is None:
filters['kfilt'] = [name]
num = 0
for gen in self._uve_server.multi_uve_get(uve_tbl, flat,
filters, is_alarm):
if first:
yield u'' + json.dumps(gen)
first = False
else:
yield u', ' + json.dumps(gen)
num += 1
stats.collect(num)
stats.sendwith()
yield u']}'
else:
_, rsp = self._uve_server.get_uve(uve_name, flat, filters,
is_alarm=is_alarm)
stats.collect(1)
stats.sendwith()
yield json.dumps(rsp)
# end _uve_alarm_http_get

Expand Down
2 changes: 1 addition & 1 deletion src/opserver/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def parse_args(self):
'start_time': 'now-10m',
'end_time': 'now',
'select' : [],
'where' : [],
'where' : ['Source=*'],
'sort': []
}

Expand Down
6 changes: 5 additions & 1 deletion src/opserver/test/utils/analytics_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -2321,6 +2321,7 @@ def get_free_udp_port():

def process_stop(self, name, instance, log_file, del_log = True):
self.logger.info('Shutting down %s' % name)
bad_term = False
if instance.poll() == None:
instance.terminate()
cnt = 1
Expand All @@ -2329,12 +2330,15 @@ def process_stop(self, name, instance, log_file, del_log = True):
break
cnt += 1
gevent.sleep(1)
else:
bad_term = True
if instance.poll() == None:
self.logger.info('%s FAILED to terminate; will be killed' % name)
instance.kill()
bad_term = True
(p_out, p_err) = instance.communicate()
rcode = instance.returncode
if rcode != 0:
if rcode != 0 or bad_term:
self.logger.info('%s returned %d' % (name,rcode))
self.logger.info('%s terminated stdout: %s' % (name, p_out))
self.logger.info('%s terminated stderr: %s' % (name, p_err))
Expand Down

0 comments on commit ea82b86

Please sign in to comment.