Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: appengine_module/gae_ts_mon/test/config_test.py

Issue 1797103003: gae_ts_mon: instrument Cloud Endpoint methods (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Removed unnecessary 'no cover' Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import copy 5 import copy
6 import datetime 6 import datetime
7 import os 7 import os
8 import time 8 import time
9 import unittest 9 import unittest
10 10
11 import endpoints
11 import gae_ts_mon 12 import gae_ts_mon
12 import mock 13 import mock
13 import webapp2 14 import webapp2
14 15
15 from infra_libs.ts_mon import config 16 from infra_libs.ts_mon import config
16 from infra_libs.ts_mon import shared 17 from infra_libs.ts_mon import shared
17 from infra_libs.ts_mon.common import http_metrics 18 from infra_libs.ts_mon.common import http_metrics
18 from infra_libs.ts_mon.common import interface 19 from infra_libs.ts_mon.common import interface
19 from infra_libs.ts_mon.common import monitors 20 from infra_libs.ts_mon.common import monitors
20 from infra_libs.ts_mon.common import targets 21 from infra_libs.ts_mon.common import targets
21 from infra_libs.ts_mon.common.test import stubs 22 from infra_libs.ts_mon.common.test import stubs
23 from protorpc import message_types
24 from protorpc import remote
22 from testing_utils import testing 25 from testing_utils import testing
23 26
24 27
25 class InitializeTest(testing.AppengineTestCase): 28 class InitializeTest(testing.AppengineTestCase):
26 def setUp(self): 29 def setUp(self):
27 super(InitializeTest, self).setUp() 30 super(InitializeTest, self).setUp()
28 31
29 config.reset_for_unittest() 32 config.reset_for_unittest()
30 target = targets.TaskTarget('test_service', 'test_job', 33 target = targets.TaskTarget('test_service', 'test_job',
31 'test_region', 'test_host') 34 'test_region', 'test_host')
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 counter.increment() 114 counter.increment()
112 self.assertEqual(5, gauge.get()) 115 self.assertEqual(5, gauge.get())
113 self.assertEqual(1, counter.get()) 116 self.assertEqual(1, counter.get())
114 117
115 config._reset_cumulative_metrics() 118 config._reset_cumulative_metrics()
116 self.assertEqual(5, gauge.get()) 119 self.assertEqual(5, gauge.get())
117 self.assertIsNone(counter.get()) 120 self.assertIsNone(counter.get())
118 121
119 def test_flush_metrics_no_task_num(self): 122 def test_flush_metrics_no_task_num(self):
120 # We are not assigned task_num yet; cannot send metrics. 123 # We are not assigned task_num yet; cannot send metrics.
121 time_now = datetime.datetime(2016, 2, 8, 1, 0) 124 time_now = 10000
122 more_than_min_ago = time_now - datetime.timedelta(seconds=61) 125 datetime_now = datetime.datetime.utcfromtimestamp(time_now)
126 more_than_min_ago = datetime_now - datetime.timedelta(seconds=61)
123 interface.state.last_flushed = more_than_min_ago 127 interface.state.last_flushed = more_than_min_ago
124 entity = shared.get_instance_entity() 128 entity = shared.get_instance_entity()
125 entity.task_num = -1 129 entity.task_num = -1
126 interface.state.target.task_num = -1 130 interface.state.target.task_num = -1
127 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now)) 131 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now))
128 132
129 def test_flush_metrics_no_task_num_too_long(self): 133 def test_flush_metrics_no_task_num_too_long(self):
130 # We are not assigned task_num for too long; cannot send metrics. 134 # We are not assigned task_num for too long; cannot send metrics.
131 time_now = datetime.datetime(2016, 2, 8, 1, 0) 135 time_now = 10000
132 too_long_ago = time_now - datetime.timedelta( 136 datetime_now = datetime.datetime.utcfromtimestamp(time_now)
137 too_long_ago = datetime_now - datetime.timedelta(
133 seconds=shared.INSTANCE_EXPECTED_TO_HAVE_TASK_NUM_SEC+1) 138 seconds=shared.INSTANCE_EXPECTED_TO_HAVE_TASK_NUM_SEC+1)
134 interface.state.last_flushed = too_long_ago 139 interface.state.last_flushed = too_long_ago
135 entity = shared.get_instance_entity() 140 entity = shared.get_instance_entity()
136 entity.task_num = -1 141 entity.task_num = -1
137 entity.last_updated = too_long_ago 142 entity.last_updated = too_long_ago
138 interface.state.target.task_num = -1 143 interface.state.target.task_num = -1
139 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now)) 144 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now))
140 145
141 def test_flush_metrics_purged(self): 146 def test_flush_metrics_purged(self):
142 # We lost our task_num; cannot send metrics. 147 # We lost our task_num; cannot send metrics.
143 time_now = datetime.datetime(2016, 2, 8, 1, 0) 148 time_now = 10000
144 more_than_min_ago = time_now - datetime.timedelta(seconds=61) 149 datetime_now = datetime.datetime.utcfromtimestamp(time_now)
150 more_than_min_ago = datetime_now - datetime.timedelta(seconds=61)
145 interface.state.last_flushed = more_than_min_ago 151 interface.state.last_flushed = more_than_min_ago
146 entity = shared.get_instance_entity() 152 entity = shared.get_instance_entity()
147 entity.task_num = -1 153 entity.task_num = -1
148 interface.state.target.task_num = 2 154 interface.state.target.task_num = 2
149 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now)) 155 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now))
150 156
151 def test_flush_metrics_too_early(self): 157 def test_flush_metrics_too_early(self):
152 # Too early to send metrics. 158 # Too early to send metrics.
153 time_now = datetime.datetime(2016, 2, 8, 1, 0) 159 time_now = 10000
154 less_than_min_ago = time_now - datetime.timedelta(seconds=59) 160 datetime_now = datetime.datetime.utcfromtimestamp(time_now)
161 less_than_min_ago = datetime_now - datetime.timedelta(seconds=59)
155 interface.state.last_flushed = less_than_min_ago 162 interface.state.last_flushed = less_than_min_ago
156 entity = shared.get_instance_entity() 163 entity = shared.get_instance_entity()
157 entity.task_num = 2 164 entity.task_num = 2
158 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now)) 165 self.assertFalse(config.flush_metrics_if_needed(time_fn=lambda: time_now))
159 166
160 @mock.patch('infra_libs.ts_mon.common.interface.flush', autospec=True) 167 @mock.patch('infra_libs.ts_mon.common.interface.flush', autospec=True)
161 def test_flush_metrics_successfully(self, mock_flush): 168 def test_flush_metrics_successfully(self, mock_flush):
162 # We have task_num and due for sending metrics. 169 # We have task_num and due for sending metrics.
163 time_now = datetime.datetime(2016, 2, 8, 1, 0) 170 time_now = 10000
164 more_than_min_ago = time_now - datetime.timedelta(seconds=61) 171 datetime_now = datetime.datetime.utcfromtimestamp(time_now)
172 more_than_min_ago = datetime_now - datetime.timedelta(seconds=61)
165 interface.state.last_flushed = more_than_min_ago 173 interface.state.last_flushed = more_than_min_ago
166 entity = shared.get_instance_entity() 174 entity = shared.get_instance_entity()
167 entity.task_num = 2 175 entity.task_num = 2
168 # Global metrics must be erased after flush. 176 # Global metrics must be erased after flush.
169 test_global_metric = gae_ts_mon.GaugeMetric('test') 177 test_global_metric = gae_ts_mon.GaugeMetric('test')
170 test_global_metric.set(42) 178 test_global_metric.set(42)
171 shared.register_global_metrics([test_global_metric]) 179 shared.register_global_metrics([test_global_metric])
172 self.assertEqual(42, test_global_metric.get()) 180 self.assertEqual(42, test_global_metric.get())
173 self.assertTrue(config.flush_metrics_if_needed(time_fn=lambda: time_now)) 181 self.assertTrue(config.flush_metrics_if_needed(time_fn=lambda: time_now))
174 self.assertEqual(None, test_global_metric.get()) 182 self.assertEqual(None, test_global_metric.get())
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 def get(self): 226 def get(self):
219 self.response.write('success!') 227 self.response.write('success!')
220 228
221 app = webapp2.WSGIApplication([('/', Handler)]) 229 app = webapp2.WSGIApplication([('/', Handler)])
222 config.instrument_wsgi_application(app, time_fn=self.fake_time) 230 config.instrument_wsgi_application(app, time_fn=self.fake_time)
223 231
224 app.get_response('/') 232 app.get_response('/')
225 233
226 fields = {'name': '^/$', 'status': 200, 'is_robot': False} 234 fields = {'name': '^/$', 'status': 200, 'is_robot': False}
227 self.assertEqual(1, http_metrics.server_response_status.get(fields)) 235 self.assertEqual(1, http_metrics.server_response_status.get(fields))
228 self.assertEqual(3000, http_metrics.server_durations.get(fields).sum) 236 self.assertLessEqual(3000, http_metrics.server_durations.get(fields).sum)
229 self.assertEqual( 237 self.assertEqual(
230 len('success!'), http_metrics.server_response_bytes.get(fields).sum) 238 len('success!'), http_metrics.server_response_bytes.get(fields).sum)
231 239
232 def test_abort(self): 240 def test_abort(self):
233 class Handler(webapp2.RequestHandler): 241 class Handler(webapp2.RequestHandler):
234 def get(self): 242 def get(self):
235 self.abort(417) 243 self.abort(417)
236 244
237 app = webapp2.WSGIApplication([('/', Handler)]) 245 app = webapp2.WSGIApplication([('/', Handler)])
238 config.instrument_wsgi_application(app) 246 config.instrument_wsgi_application(app)
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 349
342 app = webapp2.WSGIApplication([('/', Handler)]) 350 app = webapp2.WSGIApplication([('/', Handler)])
343 config.instrument_wsgi_application(app) 351 config.instrument_wsgi_application(app)
344 352
345 app.get_response('/', POST='foo') 353 app.get_response('/', POST='foo')
346 354
347 fields = {'name': '^/$', 'status': 200, 'is_robot': False} 355 fields = {'name': '^/$', 'status': 200, 'is_robot': False}
348 self.assertEqual(1, http_metrics.server_response_status.get(fields)) 356 self.assertEqual(1, http_metrics.server_response_status.get(fields))
349 self.assertEqual( 357 self.assertEqual(
350 len('foo'), http_metrics.server_request_bytes.get(fields).sum) 358 len('foo'), http_metrics.server_request_bytes.get(fields).sum)
359
360
361 class FakeTime(object):
362 def __init__(self):
363 self.timestamp_now = 1000.0
364
365 def time_fn(self):
366 self.timestamp_now += 0.2
367 return self.timestamp_now
368
369
370 @endpoints.api(name='testapi', version='v1')
371 class TestEndpoint(remote.Service):
372
373 @gae_ts_mon.instrument_endpoint(time_fn=FakeTime().time_fn)
374 @endpoints.method(message_types.VoidMessage, message_types.VoidMessage,
375 name='method_good')
376 def do_good(self, request):
377 return request
378
379 @gae_ts_mon.instrument_endpoint(time_fn=FakeTime().time_fn)
380 @endpoints.method(message_types.VoidMessage, message_types.VoidMessage,
381 name='method_bad')
382 def do_bad(self, request):
383 raise Exception
384
385 @gae_ts_mon.instrument_endpoint(time_fn=FakeTime().time_fn)
386 @endpoints.method(message_types.VoidMessage, message_types.VoidMessage,
387 name='method_400')
388 def do_400(self, request):
389 raise endpoints.BadRequestException('Bad request')
390
391
392 class InstrumentEndpointTest(testing.EndpointsTestCase):
393 api_service_cls = TestEndpoint
394
395 def setUp(self):
396 super(InstrumentEndpointTest, self).setUp()
397
398 config.reset_for_unittest()
399 target = targets.TaskTarget('test_service', 'test_job',
400 'test_region', 'test_host')
401 self.mock_state = interface.State(target=target)
402 self.mock_state.metrics = copy.copy(interface.state.metrics)
403 self.endpoint_name = '/_ah/spi/TestEndpoint.%s'
404 mock.patch('infra_libs.ts_mon.common.interface.state',
405 new=self.mock_state).start()
406
407 mock.patch('infra_libs.ts_mon.common.monitors.PubSubMonitor',
408 autospec=True).start()
409
410 def tearDown(self):
411 config.reset_for_unittest()
412 self.assertEqual([], list(shared.global_metrics_callbacks))
413 mock.patch.stopall()
414 super(InstrumentEndpointTest, self).tearDown()
415
416 def test_good(self):
417 self.call_api('do_good')
418 fields = {'name': self.endpoint_name % 'method_good',
419 'status': 200, 'is_robot': False}
420 self.assertEqual(1, http_metrics.server_response_status.get(fields))
421 self.assertLessEqual(200, http_metrics.server_durations.get(fields).sum)
422
423 def test_bad(self):
424 with self.call_should_fail('500 Internal Server Error'):
425 self.call_api('do_bad')
426 fields = {'name': self.endpoint_name % 'method_bad',
427 'status': 500, 'is_robot': False}
428 self.assertEqual(1, http_metrics.server_response_status.get(fields))
429 self.assertLessEqual(200, http_metrics.server_durations.get(fields).sum)
430
431 def test_400(self):
432 with self.call_should_fail('400 Bad Request'):
433 self.call_api('do_400')
434 fields = {'name': self.endpoint_name % 'method_400',
435 'status': 400, 'is_robot': False}
436 self.assertEqual(1, http_metrics.server_response_status.get(fields))
437 self.assertLessEqual(200, http_metrics.server_durations.get(fields).sum)
438
439 @mock.patch('gae_ts_mon.config.need_to_flush_metrics', autospec=True,
440 return_value=False)
441 def test_no_flush(self, _fake):
442 # For branch coverage.
443 self.call_api('do_good')
444 fields = {'name': self.endpoint_name % 'method_good',
445 'status': 200, 'is_robot': False}
446 self.assertEqual(1, http_metrics.server_response_status.get(fields))
447 self.assertLessEqual(200, http_metrics.server_durations.get(fields).sum)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698