class KronosLoggingMiddleware(object): FORWARDED_IP_FIELDS = {'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_HOST', 'HTTP_X_FORWARDED_SERVER'} def __init__(self): from django.conf import settings from django.core.exceptions import ImproperlyConfigured if not hasattr(settings, 'KRONOS_MIDDLEWARE'): raise ImproperlyConfigured kronos_config = settings.KRONOS_MIDDLEWARE if not isinstance(kronos_config, dict): raise ImproperlyConfigured if 'host' not in kronos_config: raise ImproperlyConfigured if 'stream' not in kronos_config: raise ImproperlyConfigured self.client = KronosClient( kronos_config['host'], blocking=kronos_config.get('blocking', False), sleep_block=kronos_config.get('sleep_block', 0.1)) self.stream = kronos_config['stream'] self.namespace = kronos_config.get('namespace') self.log_exception_stack_trace = kronos_config.get( 'log_exception_stack_trace', False) self.fail_silently = kronos_config.get('fail_silently', True) def _get_ip(self, request): if not KronosLoggingMiddleware.FORWARDED_IP_FIELDS & set(request.META): return request.META.get('REMOTE_ADDR', '').strip() for field in KronosLoggingMiddleware.FORWARDED_IP_FIELDS: if field in request.META: return request.META[field].split(',')[-1].strip() def process_request(self, request): request._kronos_event = { 'start_time': time.time(), '@time': kronos_time_now(), 'method': request.method.upper(), 'path': request.path, 'client_ip': self._get_ip(request) } get_dict = request.GET.dict() if get_dict: request._kronos_event['get_params'] = get_dict try: if not request.body: return except: # The following exception is thrown if the body could not be read. # Exception("You cannot access body after reading from request's data # stream") return post_dict = request.POST.dict() if (len(post_dict) == 1 and post_dict.values()[0] == '' and post_dict.keys()[0] == request.body): # There is no real *form* POST. try: request._kronos_event['body'] = json.loads(request.body) except ValueError: request._kronos_event['body'] = request.body else: request._kronos_event['post_params'] = post_dict def process_exception(self, request, exception): self.client._log_exception( request._kronos_event, exception, sys.exc_info()[2] if self.log_exception_stack_trace else None) def process_response(self, request, response): start_time = request._kronos_event.pop('start_time') request._kronos_event['duration'] = time.time() - start_time try: self.client.put({self.stream: [request._kronos_event]}, namespace=self.namespace) except: if self.fail_silently: log.error('Failed to log event to Kronos.', exc_info=True) else: raise return response
to the server. If the process running the client crashes before flushing events, those events will be lost. """ nonblocking = KronosClient('http://localhost:8151', namespace='demo', blocking=False) # Inserting data """ Insert data with the `put` command. The argument is a dictionary of stream names (e.g., `yourproduct.website.pageviews`) to a list of JSON-encodable dictionaries to insert to each stream. """ kc.put({'yourproduct.website.pageviews': [ {'source': 'http://test.com', 'browser': {'name': 'Firefox', 'version': 26}, 'pages': ['page1.html', 'page2.html']}], 'yourproduct.website.clicks': [ {'user': 40, 'num_clicks': 7}, {'user': 42, 'num_clicks': 2}]}) ## Optionally add a timestamp """ By default, each event will be timestamped on the client. If you add a `TIMESTAMP_FIELD` argument, you can specify the time at which each event ocurred. """ optional_time = datetime_to_kronos_time(start + timedelta(seconds=5)) kc.put({'yourproduct.website.clicks': [ {'user': 35, 'num_clicks': 10, TIMESTAMP_FIELD: optional_time}]})
class KronosLoggingMiddleware(object): FORWARDED_IP_FIELDS = { 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED_HOST', 'HTTP_X_FORWARDED_SERVER' } def __init__(self): from django.conf import settings from django.core.exceptions import ImproperlyConfigured if not hasattr(settings, 'KRONOS_MIDDLEWARE'): raise ImproperlyConfigured kronos_config = settings.KRONOS_MIDDLEWARE if not isinstance(kronos_config, dict): raise ImproperlyConfigured if 'host' not in kronos_config: raise ImproperlyConfigured if 'stream' not in kronos_config: raise ImproperlyConfigured self.client = KronosClient( kronos_config['host'], blocking=kronos_config.get('blocking', False), sleep_block=kronos_config.get('sleep_block', 0.1)) self.stream = kronos_config['stream'] self.namespace = kronos_config.get('namespace') self.log_exception_stack_trace = kronos_config.get( 'log_exception_stack_trace', False) self.fail_silently = kronos_config.get('fail_silently', True) def _get_ip(self, request): if not KronosLoggingMiddleware.FORWARDED_IP_FIELDS & set(request.META): return request.META.get('REMOTE_ADDR', '').strip() for field in KronosLoggingMiddleware.FORWARDED_IP_FIELDS: if field in request.META: return request.META[field].split(',')[-1].strip() def process_request(self, request): request._kronos_event = { 'start_time': time.time(), '@time': kronos_time_now(), 'method': request.method.upper(), 'path': request.path, 'client_ip': self._get_ip(request) } get_dict = request.GET.dict() if get_dict: request._kronos_event['get_params'] = get_dict try: if not request.body: return except: # The following exception is thrown if the body could not be read. # Exception("You cannot access body after reading from request's data # stream") return post_dict = request.POST.dict() if (len(post_dict) == 1 and post_dict.values()[0] == '' and post_dict.keys()[0] == request.body): # There is no real *form* POST. try: request._kronos_event['body'] = json.loads(request.body) except ValueError: request._kronos_event['body'] = request.body else: request._kronos_event['post_params'] = post_dict def process_exception(self, request, exception): self.client._log_exception( request._kronos_event, exception, sys.exc_info()[2] if self.log_exception_stack_trace else None) def process_response(self, request, response): start_time = request._kronos_event.pop('start_time') request._kronos_event['duration'] = time.time() - start_time try: self.client.put({self.stream: [request._kronos_event]}, namespace=self.namespace) except: if self.fail_silently: log.error('Failed to log event to Kronos.', exc_info=True) else: raise return response
""" nonblocking = KronosClient('http://localhost:8151', namespace='kronos', blocking=False) """ ## Inserting Events Insert events with the `put` command. The argument is a dictionary of stream names (e.g., `yourproduct.website.pageviews`) to a list of JSON-encodable dictionaries to insert to each stream. """ kc.put( {'yourproduct.website.pageviews': [ {'source': 'http://test.com', 'browser': {'name': 'Firefox', 'version': 26}, 'pages': ['page1.html', 'page2.html']}], 'yourproduct.website.clicks': [ {'user': 40, 'num_clicks': 7}, {'user': 42, 'num_clicks': 2}] }) """ ### Optionally Add A Timestamp By default, each event will be timestamped on the client. If you add a `TIMESTAMP_FIELD` argument, you can specify the time at which each event ocurred. """ optional_time = datetime_to_kronos_time(start + timedelta(seconds=5)) kc.put({'yourproduct.website.clicks': [ {'user': 35, 'num_clicks': 10, TIMESTAMP_FIELD: optional_time}]})