Merge pull request #306 from AlanCoding/new_perf_logging

[3.2.2] new method of performance logging
This commit is contained in:
Alan Rominger
2017-09-29 10:14:44 -04:00
committed by Matthew Jones
4 changed files with 45 additions and 2 deletions

View File

@@ -139,7 +139,6 @@ class APIView(views.APIView):
response['X-API-Query-Count'] = len(q_times) response['X-API-Query-Count'] = len(q_times)
response['X-API-Query-Time'] = '%0.3fs' % sum(q_times) response['X-API-Query-Time'] = '%0.3fs' % sum(q_times)
analytics_logger.info("api response", extra=dict(python_objects=dict(request=request, response=response)))
return response return response
def get_authenticate_header(self, request): def get_authenticate_header(self, request):

View File

@@ -5,6 +5,10 @@ import logging
import threading import threading
import uuid import uuid
import six import six
import time
import cProfile
import pstats
import os
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
@@ -23,6 +27,38 @@ from awx.conf import fields, register
logger = logging.getLogger('awx.main.middleware') logger = logging.getLogger('awx.main.middleware')
analytics_logger = logging.getLogger('awx.analytics.activity_stream') analytics_logger = logging.getLogger('awx.analytics.activity_stream')
perf_logger = logging.getLogger('awx.analytics.performance')
class TimingMiddleware(threading.local):
dest = '/var/lib/awx/profile'
def process_request(self, request):
self.start_time = time.time()
if settings.AWX_REQUEST_PROFILE:
self.prof = cProfile.Profile()
self.prof.enable()
def process_response(self, request, response):
total_time = time.time() - self.start_time
response['X-API-Total-Time'] = '%0.3fs' % total_time
if settings.AWX_REQUEST_PROFILE:
self.prof.disable()
cprofile_file = self.save_profile_file(request)
response['cprofile_file'] = cprofile_file
perf_logger.info('api response times', extra=dict(python_objects=dict(request=request, response=response)))
return response
def save_profile_file(self, request):
if not os.path.isdir(self.dest):
os.makedirs(self.dest)
filename = '%.3fs-%s' % (pstats.Stats(self.prof).total_tt, uuid.uuid4())
filepath = os.path.join(self.dest, filename)
with open(filepath, 'w') as f:
f.write('%s %s\n' % (request.method, request.get_full_path()))
pstats.Stats(self.prof, stream=f).sort_stats('cumulative').print_stats()
return filepath
class ActivityStreamMiddleware(threading.local): class ActivityStreamMiddleware(threading.local):

View File

@@ -120,6 +120,7 @@ class LogstashFormatter(LogstashFormatterVersion1):
# exist if SQL_DEBUG is turned on in settings. # exist if SQL_DEBUG is turned on in settings.
headers = [ headers = [
(float, 'X-API-Time'), # may end with an 's' "0.33s" (float, 'X-API-Time'), # may end with an 's' "0.33s"
(float, 'X-API-Total-Time'),
(int, 'X-API-Query-Count'), (int, 'X-API-Query-Count'),
(float, 'X-API-Query-Time'), # may also end with an 's' (float, 'X-API-Query-Time'), # may also end with an 's'
(str, 'X-API-Node'), (str, 'X-API-Node'),
@@ -131,9 +132,11 @@ class LogstashFormatter(LogstashFormatterVersion1):
'path': request.path, 'path': request.path,
'path_info': request.path_info, 'path_info': request.path_info,
'query_string': request.META['QUERY_STRING'], 'query_string': request.META['QUERY_STRING'],
'data': request.data,
} }
if hasattr(request, 'data'):
data_for_log['request']['data'] = request.data
return data_for_log return data_for_log
def get_extra_fields(self, record): def get_extra_fields(self, record):

View File

@@ -211,6 +211,7 @@ TEMPLATE_CONTEXT_PROCESSORS = ( # NOQA
) )
MIDDLEWARE_CLASSES = ( # NOQA MIDDLEWARE_CLASSES = ( # NOQA
'awx.main.middleware.TimingMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
@@ -1134,4 +1135,8 @@ LOGGING = {
}, },
} }
} }
# Apply coloring to messages logged to the console
COLOR_LOGS = False COLOR_LOGS = False
# Use middleware to get request statistics
AWX_REQUEST_PROFILE = False