##// END OF EJS Templates
api: support permanent logs in sentry api
ergo -
Show More
@@ -53,116 +53,6 b' class TestMigration(object):'
53 53 assert 1 == 1
54 54
55 55
56 class TestAPIReports_0_4_Validation(object):
57 @pytest.mark.parametrize('dummy_json', ['', {}, [], None])
58 def test_no_payload(self, dummy_json):
59 import colander
60 from appenlight.validators import ReportListSchema_0_4
61 utcnow = datetime.utcnow()
62 schema = ReportListSchema_0_4().bind(utcnow=utcnow)
63 with pytest.raises(colander.Invalid):
64 schema.deserialize(dummy_json)
65
66 def test_minimal_payload(self, report_04_schema):
67 dummy_json = [{}]
68 import colander
69 from appenlight.validators import ReportListSchema_0_4
70 utcnow = datetime.utcnow()
71 schema = ReportListSchema_0_4().bind(utcnow=utcnow)
72 with pytest.raises(colander.Invalid):
73 schema.deserialize(dummy_json)
74
75 def test_minimal_payload(self):
76 from appenlight.validators import ReportListSchema_0_4
77 dummy_json = [{'report_details': [{}]}]
78 utcnow = datetime.utcnow()
79 schema = ReportListSchema_0_4().bind(utcnow=utcnow)
80 deserialized = schema.deserialize(dummy_json)
81
82 expected_deserialization = [
83 {'error_type': '',
84 'language': 'unknown',
85 'report_details': [
86 {'username': '',
87 'traceback': None,
88 'extra': None,
89 'frameinfo': None,
90 'url': '',
91 'ip': None,
92 'start_time': utcnow,
93 'group_string': None,
94 'request': {},
95 'request_stats': None,
96 'end_time': None,
97 'request_id': '',
98 'message': '',
99 'slow_calls': [],
100 'user_agent': ''}],
101 'server': 'unknown',
102 'occurences': 1,
103 'priority': 5,
104 'view_name': '',
105 'client': 'unknown',
106 'http_status': 200,
107 'error': '',
108 'tags': None}
109 ]
110 assert deserialized == expected_deserialization
111
112 def test_full_payload(self):
113 import appenlight.tests.payload_examples as payload_examples
114 from appenlight.validators import ReportListSchema_0_4
115 utcnow = datetime.utcnow()
116 schema = ReportListSchema_0_4().bind(utcnow=utcnow)
117 PYTHON_PAYLOAD = copy.deepcopy(payload_examples.PYTHON_PAYLOAD_0_4)
118 utcnow = datetime.utcnow()
119 PYTHON_PAYLOAD["tags"] = [("foo", 1), ("action", "test"), ("baz", 1.1),
120 ("date",
121 utcnow.strftime('%Y-%m-%dT%H:%M:%S.0'))]
122 dummy_json = [PYTHON_PAYLOAD]
123
124 deserialized = schema.deserialize(dummy_json)
125 assert deserialized[0]['error'] == PYTHON_PAYLOAD['error']
126 assert deserialized[0]['language'] == PYTHON_PAYLOAD['language']
127 assert deserialized[0]['server'] == PYTHON_PAYLOAD['server']
128 assert deserialized[0]['priority'] == PYTHON_PAYLOAD['priority']
129 assert deserialized[0]['view_name'] == PYTHON_PAYLOAD['view_name']
130 assert deserialized[0]['client'] == PYTHON_PAYLOAD['client']
131 assert deserialized[0]['http_status'] == PYTHON_PAYLOAD['http_status']
132 assert deserialized[0]['error'] == PYTHON_PAYLOAD['error']
133 assert deserialized[0]['occurences'] == PYTHON_PAYLOAD['occurences']
134 first_detail = deserialized[0]['report_details'][0]
135 payload_detail = PYTHON_PAYLOAD['report_details'][0]
136 assert first_detail['username'] == payload_detail['username']
137 assert first_detail['traceback'] == payload_detail['traceback']
138 assert first_detail['url'] == payload_detail['url']
139 assert first_detail['ip'] == payload_detail['ip']
140 assert first_detail['start_time'].strftime('%Y-%m-%dT%H:%M:%S.0') == \
141 payload_detail['start_time']
142 assert first_detail['ip'] == payload_detail['ip']
143 assert first_detail['group_string'] is None
144 assert first_detail['request_stats'] == payload_detail['request_stats']
145 assert first_detail['end_time'].strftime('%Y-%m-%dT%H:%M:%S.0') == \
146 payload_detail['end_time']
147 assert first_detail['request_id'] == payload_detail['request_id']
148 assert first_detail['message'] == payload_detail['message']
149 assert first_detail['user_agent'] == payload_detail['user_agent']
150 slow_call = first_detail['slow_calls'][0]
151 expected_slow_call = payload_detail['slow_calls'][0]
152 assert slow_call['start'].strftime('%Y-%m-%dT%H:%M:%S.0') == \
153 expected_slow_call['start']
154 assert slow_call['end'].strftime('%Y-%m-%dT%H:%M:%S.0') == \
155 expected_slow_call['end']
156 assert slow_call['statement'] == expected_slow_call['statement']
157 assert slow_call['parameters'] == expected_slow_call['parameters']
158 assert slow_call['type'] == expected_slow_call['type']
159 assert slow_call['subtype'] == expected_slow_call['subtype']
160 assert slow_call['location'] == ''
161 assert deserialized[0]['tags'] == [
162 ('foo', 1), ('action', 'test'),
163 ('baz', 1.1), ('date', utcnow.strftime('%Y-%m-%dT%H:%M:%S.0'))]
164
165
166 56 class TestSentryProto_7(object):
167 57 def test_log_payload(self):
168 58 import appenlight.tests.payload_examples as payload_examples
@@ -461,11 +351,11 b' class TestAPIGeneralMetricsValidation(object):'
461 351 general_metrics_schema.deserialize(dummy_json)
462 352
463 353 def test_minimal_payload(self, general_metrics_schema):
464 dummy_json = [{}]
354 dummy_json = [{'tags': [['counter_a', 15.5], ['counter_b', 63]]}]
465 355 deserialized = general_metrics_schema.deserialize(dummy_json)[0]
466 356 expected = {'namespace': '',
467 357 'server_name': 'unknown',
468 'tags': None,
358 'tags': [('counter_a', 15.5), ('counter_b', 63)],
469 359 'timestamp': datetime.utcnow()}
470 360 assert deserialized['namespace'] == expected['namespace']
471 361 assert deserialized['server_name'] == expected['server_name']
@@ -192,17 +192,20 b' class SlowCallSchema(colander.MappingSchema):'
192 192
193 193 def limited_date(node, value):
194 194 """ checks to make sure that the value is not older/newer than 2h """
195 hours = 2
196 min_time = datetime.datetime.utcnow() - datetime.timedelta(hours=72)
197 max_time = datetime.datetime.utcnow() + datetime.timedelta(hours=2)
195 past_hours = 72
196 future_hours = 2
197 min_time = datetime.datetime.utcnow() - datetime.timedelta(
198 hours=past_hours)
199 max_time = datetime.datetime.utcnow() + datetime.timedelta(
200 hours=future_hours)
198 201 if min_time > value:
199 msg = '%r is older from current UTC time by ' + str(hours) + ' hours.'
200 msg += ' Ask administrator to enable permanent logging for ' \
202 msg = '%r is older from current UTC time by ' + str(past_hours)
203 msg += ' hours. Ask administrator to enable permanent logging for ' \
201 204 'your application to store logs with dates in past.'
202 205 raise colander.Invalid(node, msg % value)
203 206 if max_time < value:
204 msg = '%r is newer from current UTC time by ' + str(hours) + ' hours'
205 msg += ' Ask administrator to enable permanent logging for ' \
207 msg = '%r is newer from current UTC time by ' + str(future_hours)
208 msg += ' hours. Ask administrator to enable permanent logging for ' \
206 209 'your application to store logs with dates in future.'
207 210 raise colander.Invalid(node, msg % value)
208 211
@@ -311,20 +314,13 b' class ReportDetailBaseSchema(colander.MappingSchema):'
311 314 extra = ExtraSchemaList()
312 315
313 316
314 class ReportDetailSchema_0_4(ReportDetailBaseSchema):
315 frameinfo = FrameInfoListSchema(missing=None)
316
317
318 317 class ReportDetailSchema_0_5(ReportDetailBaseSchema):
319 318 pass
320 319
321 320
322 class ReportDetailListSchema(colander.SequenceSchema):
323 """
324 Validates format of list of reports
325 """
326 report_detail = ReportDetailSchema_0_4()
327 validator = colander.Length(1)
321 class ReportDetailSchemaPermissiveDate_0_5(ReportDetailSchema_0_5):
322 start_time = colander.SchemaNode(NonTZDate(), missing=deferred_utcnow)
323 end_time = colander.SchemaNode(NonTZDate(), missing=None)
328 324
329 325
330 326 class ReportSchemaBase(colander.MappingSchema):
@@ -364,6 +360,11 b' class ReportSchema_0_5(ReportSchemaBase, ReportDetailSchema_0_5):'
364 360 pass
365 361
366 362
363 class ReportSchemaPermissiveDate_0_5(ReportSchemaBase,
364 ReportDetailSchemaPermissiveDate_0_5):
365 pass
366
367
367 368 class ReportListSchema_0_5(colander.SequenceSchema):
368 369 """
369 370 Validates format of list of report groups
@@ -372,6 +373,14 b' class ReportListSchema_0_5(colander.SequenceSchema):'
372 373 validator = colander.Length(1)
373 374
374 375
376 class ReportListPermissiveDateSchema_0_5(colander.SequenceSchema):
377 """
378 Validates format of list of report groups
379 """
380 report = ReportSchemaPermissiveDate_0_5()
381 validator = colander.Length(1)
382
383
375 384 class LogSchema(colander.MappingSchema):
376 385 """
377 386 Validates format if individual log entry
@@ -405,7 +405,12 b' def sentry_compat(request):'
405 405 event, event_type = parse_sentry_event(json_body)
406 406
407 407 if event_type == ParsedSentryEventType.LOG:
408 schema = LogSchema().bind(utcnow=datetime.datetime.utcnow())
408 if application.allow_permanent_storage:
409 schema = LogSchemaPermanent().bind(
410 utcnow=datetime.datetime.utcnow())
411 else:
412 schema = LogSchema().bind(
413 utcnow=datetime.datetime.utcnow())
409 414 deserialized_logs = schema.deserialize(event)
410 415 non_pkey_logs = [deserialized_logs]
411 416 log.debug('%s non-pkey logs received: %s' % (application,
General Comments 0
You need to be logged in to leave comments. Login now