def test_initialized(self): def callback(): # pragma: no cover pass callback_mock = mock.Mock(callback, set_auto=True) interface.register_global_metrics_callback('cb', callback_mock) request = webapp2.Request.blank('/internal/cron/ts_mon/send') request.headers['X-Appengine-Cron'] = 'true' self.mock_state.global_monitor = mock.Mock() response = request.get_response(handlers.app) self.assertEqual(response.status_int, 200) callback_mock.assert_called_once_with()
def test_register_global_metrics_callback(self): interface.register_global_metrics_callback('test', 'callback') self.assertEqual(['test'], list(interface.state.global_metrics_callbacks)) interface.register_global_metrics_callback('nonexistent', None) self.assertEqual(['test'], list(interface.state.global_metrics_callbacks)) interface.register_global_metrics_callback('test', None) self.assertEqual([], list(interface.state.global_metrics_callbacks))
def test_callbacks_not_called_if_disabled(self): interface.state.invoke_global_callbacks_on_flush = False cb = mock.Mock() interface.register_global_metrics_callback('test', cb) interface.flush() self.assertFalse(cb.called)
def test_flush_continues_after_exception(self): cb = mock.Mock(side_effect=[Exception, None]) interface.register_global_metrics_callback('cb1', cb) interface.register_global_metrics_callback('cb2', cb) interface.flush() self.assertEqual(2, cb.call_count)
def test_callbacks_called_on_flush(self): cb = mock.Mock() interface.register_global_metrics_callback('test', cb) interface.flush() cb.assert_called_once_with()
def initialize(app=None, is_enabled_fn=None, cron_module='default', is_local_unittest=None): """Instruments webapp2 `app` with gae_ts_mon metrics. Instruments all the endpoints in `app` with basic metrics. Args: app (webapp2 app): the app to instrument. is_enabled_fn (function or None): a function returning bool if ts_mon should send the actual metrics. None (default) is equivalent to lambda: True. This allows apps to turn monitoring on or off dynamically, per app. cron_module (str): the name of the module handling the /internal/cron/ts_mon/send endpoint. This allows moving the cron job to any module the user wants. is_local_unittest (bool or None): whether we are running in a unittest. """ if is_local_unittest is None: # pragma: no cover # Since gae_ts_mon.initialize is called at module-scope by appengine apps, # AppengineTestCase.setUp() won't have run yet and none of the appengine # stubs will be initialized, so accessing Datastore or even getting the # application ID will fail. is_local_unittest = ('expect_tests' in sys.argv[0]) if is_enabled_fn is not None: interface.state.flush_enabled_fn = is_enabled_fn if app is not None: instrument_wsgi_application(app) if is_local_unittest or modules.get_current_module_name( ) == cron_module: instrument_wsgi_application(handlers.app) # Use the application ID as the service name and the module name as the job # name. if is_local_unittest: # pragma: no cover service_name = 'unittest' job_name = 'unittest' hostname = 'unittest' else: service_name = app_identity.get_application_id() job_name = modules.get_current_module_name() hostname = modules.get_current_version_name() runtime.set_shutdown_hook(_shutdown_hook) interface.state.target = targets.TaskTarget(service_name, job_name, shared.REGION, hostname, task_num=-1) interface.state.flush_mode = 'manual' interface.state.last_flushed = datetime.datetime.utcnow() # Don't send metrics when running on the dev appserver. if (is_local_unittest or os.environ.get('SERVER_SOFTWARE', '').startswith('Development')): logging.info('Using debug monitor') interface.state.global_monitor = monitors.DebugMonitor() else: logging.info('Using https monitor %s with %s', shared.PRODXMON_ENDPOINT, shared.PRODXMON_SERVICE_ACCOUNT_EMAIL) interface.state.global_monitor = monitors.HttpsMonitor( shared.PRODXMON_ENDPOINT, monitors.DelegateServiceAccountCredentials( shared.PRODXMON_SERVICE_ACCOUNT_EMAIL, monitors.AppengineCredentials())) interface.state.use_new_proto = True interface.register_global_metrics([shared.appengine_default_version]) interface.register_global_metrics_callback(shared.INTERNAL_CALLBACK_NAME, _internal_callback) # We invoke global callbacks once for the whole application in the cron # handler. Leaving this set to True would invoke them once per task. interface.state.invoke_global_callbacks_on_flush = False standard_metrics.init() logging.info( 'Initialized ts_mon with service_name=%s, job_name=%s, ' 'hostname=%s', service_name, job_name, hostname)
def initialize(app=None, is_enabled_fn=None, cron_module='default', is_local_unittest=None): """Instruments webapp2 `app` with gae_ts_mon metrics. Instruments all the endpoints in `app` with basic metrics. Args: app (webapp2 app): the app to instrument. is_enabled_fn (function or None): a function returning bool if ts_mon should send the actual metrics. None (default) is equivalent to lambda: True. This allows apps to turn monitoring on or off dynamically, per app. cron_module (str): the name of the module handling the /internal/cron/ts_mon/send endpoint. This allows moving the cron job to any module the user wants. is_local_unittest (bool or None): whether we are running in a unittest. """ if is_local_unittest is None: # pragma: no cover # Since gae_ts_mon.initialize is called at module-scope by appengine apps, # AppengineTestCase.setUp() won't have run yet and none of the appengine # stubs will be initialized, so accessing Datastore or even getting the # application ID will fail. is_local_unittest = ('expect_tests' in sys.argv[0]) if is_enabled_fn is not None: interface.state.flush_enabled_fn = is_enabled_fn if app is not None: instrument_wsgi_application(app) if is_local_unittest or modules.get_current_module_name() == cron_module: instrument_wsgi_application(handlers.app) # Use the application ID as the service name and the module name as the job # name. if is_local_unittest: # pragma: no cover service_name = 'unittest' job_name = 'unittest' hostname = 'unittest' else: service_name = app_identity.get_application_id() job_name = modules.get_current_module_name() hostname = modules.get_current_version_name() runtime.set_shutdown_hook(_shutdown_hook) interface.state.target = targets.TaskTarget( service_name, job_name, shared.REGION, hostname, task_num=-1) interface.state.flush_mode = 'manual' interface.state.last_flushed = datetime.datetime.utcnow() # Don't send metrics when running on the dev appserver. if (is_local_unittest or os.environ.get('SERVER_SOFTWARE', '').startswith('Development')): logging.info('Using debug monitor') interface.state.global_monitor = monitors.DebugMonitor() else: logging.info('Using https monitor %s with %s', shared.PRODXMON_ENDPOINT, shared.PRODXMON_SERVICE_ACCOUNT_EMAIL) interface.state.global_monitor = monitors.HttpsMonitor( shared.PRODXMON_ENDPOINT, monitors.DelegateServiceAccountCredentials( shared.PRODXMON_SERVICE_ACCOUNT_EMAIL, monitors.AppengineCredentials())) interface.state.use_new_proto = True interface.register_global_metrics([shared.appengine_default_version]) interface.register_global_metrics_callback( shared.INTERNAL_CALLBACK_NAME, _internal_callback) # We invoke global callbacks once for the whole application in the cron # handler. Leaving this set to True would invoke them once per task. interface.state.invoke_global_callbacks_on_flush = False standard_metrics.init() logging.info('Initialized ts_mon with service_name=%s, job_name=%s, ' 'hostname=%s', service_name, job_name, hostname)