11from __future__ import absolute_import
22
33import os
4- import time
54import logging
5+
6+ from time import time
67from types import FunctionType
78
8- from raven .utils .compat import iteritems , get_code , text_type , string_types
99from raven .utils import once
10+ from raven .utils .encoding import to_unicode
11+ from raven .utils .compat import iteritems , get_code , text_type , string_types
12+
13+ CATEGORY_MAX_LENGTH = 128
1014
15+ LEVEL_MAX_LENGTH = 16
1116
1217special_logging_handlers = []
1318special_logger_handlers = {}
1419
15-
1620logger = logging .getLogger ('raven' )
1721
1822
@@ -28,40 +32,59 @@ def event_payload_considered_equal(a, b):
2832
2933class BreadcrumbBuffer (object ):
3034
31- def __init__ (self , limit = 100 ):
35+ def __init__ (self , limit = 100 , message_max_length = 1024 ):
3236 self .buffer = []
3337 self .limit = limit
38+ self .message_max_length = message_max_length
3439
3540 def record (self , timestamp = None , level = None , message = None ,
3641 category = None , data = None , type = None , processor = None ):
3742 if not (message or data or processor ):
3843 raise ValueError ('You must pass either `message`, `data`, '
3944 'or `processor`' )
4045 if timestamp is None :
41- timestamp = time .time ()
42- self .buffer .append (({
46+ timestamp = time ()
47+
48+ # we format here to ensure we dont bloat memory due to message size
49+ result = (self .format ({
4350 'type' : type or 'default' ,
44- 'timestamp' : timestamp ,
51+ 'timestamp' : float ( timestamp ) ,
4552 'level' : level ,
53+ # hardcode message length to prevent huge crumbs
4654 'message' : message ,
4755 'category' : category ,
56+ # TODO(dcramer): we should trim data
4857 'data' : data ,
49- }, processor ))
58+ }), processor )
59+ self .buffer .append (result )
5060 del self .buffer [:- self .limit ]
5161
5262 def clear (self ):
5363 del self .buffer [:]
5464
65+ def format (self , result ):
66+ result ['message' ] = to_unicode (result ['message' ])[:self .message_max_length ] if result ['message' ] else None
67+ result ['category' ] = to_unicode (result ['category' ])[:CATEGORY_MAX_LENGTH ] if result ['category' ] else None
68+ result ['level' ] = to_unicode (result ['level' ])[:LEVEL_MAX_LENGTH ].lower () if result ['level' ] else None
69+ return result
70+
5571 def get_buffer (self ):
5672 rv = []
5773 for idx , (payload , processor ) in enumerate (self .buffer ):
5874 if processor is not None :
5975 try :
6076 processor (payload )
6177 except Exception :
78+ raise
6279 logger .exception ('Failed to process breadcrumbs. Ignored' )
6380 payload = None
81+ else :
82+ # we format here to ensure we dont bloat memory due to message size
83+ payload = self .format (payload ) if payload else None
6484 self .buffer [idx ] = (payload , None )
85+ elif payload is not None :
86+ payload = self .format (payload )
87+
6588 if payload is not None and \
6689 (not rv or not event_payload_considered_equal (rv [- 1 ], payload )):
6790 rv .append (payload )
@@ -92,7 +115,7 @@ def record(message=None, timestamp=None, level=None, category=None,
92115 on a specific client.
93116 """
94117 if timestamp is None :
95- timestamp = time . time ()
118+ timestamp = time ()
96119 for ctx in raven .context .get_active_contexts ():
97120 ctx .breadcrumbs .record (timestamp , level , message , category ,
98121 data , type , processor )
0 commit comments