def test_send_http_failure(self, _load_creds):
        mon = monitors.HttpsMonitor('endpoint', '/path/to/creds.p8.json')
        mon._http.request = mock.MagicMock(side_effect=ValueError())

        metric1 = metrics_pb2.MetricsData(name='m1')
        mon.send(metric1)

        mon._http.request.assert_called_once_with('endpoint',
                                                  method='POST',
                                                  body=self.message(metric1))
    def test_send_resp_failure(self, _load_creds):
        mon = monitors.HttpsMonitor('endpoint', '/path/to/creds.p8.json')
        resp = mock.MagicMock(spec=httplib2.Response, status=400)
        mon._http.request = mock.MagicMock(return_value=[resp, ""])

        metric1 = metrics_pb2.MetricsData(name='m1')
        mon.send(metric1)

        mon._http.request.assert_called_once_with('endpoint',
                                                  method='POST',
                                                  body=self.message(metric1))
Beispiel #3
0
  def test_send_http_failure(self, _load_creds):
    mon = monitors.HttpsMonitor('endpoint',
        monitors.CredentialFactory.from_string('/path/to/creds.p8.json'))
    mon._http.request = mock.MagicMock(side_effect=ValueError())

    metric1 = metrics_pb2.MetricsPayload()
    metric1.metrics_collection.add().metrics_data_set.add().metric_name = 'a'
    mon.send(metric1)

    mon._http.request.assert_called_once_with(
        'endpoint',
        method='POST',
        body=self.message(metric1),
        headers={'Content-Type': 'application/json'})
Beispiel #4
0
  def _test_send(self, http):
    mon = monitors.HttpsMonitor('endpoint',
        monitors.CredentialFactory.from_string(':gce'), http=http)
    resp = mock.MagicMock(spec=httplib2.Response, status=200)
    mon._http.request = mock.MagicMock(return_value=[resp, ""])

    payload = metrics_pb2.MetricsPayload()
    payload.metrics_collection.add().metrics_data_set.add().metric_name = 'a'
    mon.send(payload)

    mon._http.request.assert_has_calls([
      mock.call('endpoint', method='POST', body=self.message(payload),
                headers={'Content-Type': 'application/json'}),
    ])
Beispiel #5
0
  def test_send_resp_failure(self, _load_creds):
    mon = monitors.HttpsMonitor('endpoint',
        monitors.CredentialFactory.from_string('/path/to/creds.p8.json'))
    resp = mock.MagicMock(spec=httplib2.Response, status=400)
    mon._http.request = mock.MagicMock(return_value=[resp, ""])

    metric1 = metrics_pb2.MetricsPayload()
    metric1.metrics_collection.add().metrics_data_set.add().metric_name = 'a'
    mon.send(metric1)

    mon._http.request.assert_called_once_with(
        'endpoint',
        method='POST',
        body=self.message(metric1),
        headers={'Content-Type': 'application/json'})
    def _test_send(self, http):
        mon = monitors.HttpsMonitor('endpoint', ':gce', http=http)
        resp = mock.MagicMock(spec=httplib2.Response, status=200)
        mon._http.request = mock.MagicMock(return_value=[resp, ""])

        metric1 = metrics_pb2.MetricsData(name='m1')
        mon.send(metric1)
        metric2 = metrics_pb2.MetricsData(name='m2')
        mon.send([metric1, metric2])
        collection = metrics_pb2.MetricsCollection(data=[metric1, metric2])
        mon.send(collection)

        mon._http.request.assert_has_calls([
            mock.call('endpoint', method='POST', body=self.message(metric1)),
            mock.call('endpoint',
                      method='POST',
                      body=self.message([metric1, metric2])),
            mock.call('endpoint', method='POST',
                      body=self.message(collection)),
        ])
def process_argparse_options(args):
    """Process command line arguments to initialize the global monitor.

  Also initializes the default target.

  Starts a background thread to automatically flush monitoring metrics if not
  disabled by command line arguments.

  Args:
    args (argparse.Namespace): the result of parsing the command line arguments
  """
    # Parse the config file if it exists.
    config = load_machine_config(args.ts_mon_config_file)
    endpoint = config.get('endpoint', '')
    credentials = config.get('credentials', '')
    autogen_hostname = config.get('autogen_hostname', False)

    # Command-line args override the values in the config file.
    if args.ts_mon_endpoint is not None:
        endpoint = args.ts_mon_endpoint
    if args.ts_mon_credentials is not None:
        credentials = args.ts_mon_credentials

    if args.ts_mon_target_type == 'device':
        hostname = args.ts_mon_device_hostname
        if args.ts_mon_autogen_hostname or autogen_hostname:
            hostname = 'autogen:' + hostname
        interface.state.target = targets.DeviceTarget(
            args.ts_mon_device_region, args.ts_mon_device_role,
            args.ts_mon_device_network, hostname)
    if args.ts_mon_target_type == 'task':
        # Reimplement ArgumentParser.error, since we don't have access to the parser
        if not args.ts_mon_task_service_name:
            print >> sys.stderr, (
                'Argument --ts-mon-task-service-name must be '
                'provided when the target type is "task".')
            sys.exit(2)
        if not args.ts_mon_task_job_name:
            print >> sys.stderr, (
                'Argument --ts-mon-task-job-name must be provided '
                'when the target type is "task".')
            sys.exit(2)
        hostname = args.ts_mon_task_hostname
        if args.ts_mon_autogen_hostname or autogen_hostname:
            hostname = 'autogen:' + hostname
        interface.state.target = targets.TaskTarget(
            args.ts_mon_task_service_name, args.ts_mon_task_job_name,
            args.ts_mon_task_region, hostname, args.ts_mon_task_number)

    interface.state.metric_name_prefix = args.ts_mon_metric_name_prefix
    interface.state.global_monitor = monitors.NullMonitor()

    if endpoint.startswith('file://'):
        interface.state.global_monitor = monitors.DebugMonitor(
            endpoint[len('file://'):])
    elif endpoint.startswith('https://'):
        interface.state.global_monitor = monitors.HttpsMonitor(
            endpoint,
            monitors.CredentialFactory.from_string(credentials),
            ca_certs=args.ts_mon_ca_certs)
    elif endpoint.lower() == 'none' or not endpoint:
        logging.info('ts_mon monitoring has been explicitly disabled')
    else:
        logging.error(
            'ts_mon monitoring is disabled because the endpoint provided'
            ' is invalid or not supported: %s', endpoint)

    interface.state.flush_mode = args.ts_mon_flush

    if args.ts_mon_flush == 'auto':
        interface.state.flush_thread = interface._FlushThread(
            args.ts_mon_flush_interval_secs)
        interface.state.flush_thread.start()

    standard_metrics.init()
Beispiel #8
0
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)