def Run(self): # We have to include all server metadata in the test context since server # code that uses the metrics runs within the context. non_test_metadata = list( itervalues(stats_collector_instance.Get().GetAllMetricsMetadata())) test_metadata = non_test_metadata + [ stats_utils.CreateCounterMetadata( _TEST_COUNTER, docstring="Sample counter metric."), stats_utils.CreateGaugeMetadata( _TEST_GAUGE_METRIC, str, docstring="Sample gauge metric."), stats_utils.CreateEventMetadata( _TEST_EVENT_METRIC, docstring="Sample event metric."), ] stats_collector = default_stats_collector.DefaultStatsCollector( test_metadata) with stats_test_utils.FakeStatsContext(stats_collector): with aff4.FACTORY.Create( None, aff4_stats_store.StatsStore, mode="w", token=self.token) as stats_store: stats_store.WriteStats(process_id="worker_1") # We use mixins to run the same tests against multiple APIs. # Result-filtering is only needed for HTTP API tests. if isinstance(self, api_regression_http.HttpApiRegressionTestMixinBase): api_post_process_fn = self._PostProcessApiResult else: api_post_process_fn = None self.Check( "ListStatsStoreMetricsMetadata", args=stats_plugin.ApiListStatsStoreMetricsMetadataArgs( component="WORKER"), api_post_process_fn=api_post_process_fn)
def testMetricCanBeRegisteredAfterStatsCollectorHasBeenSetUp(self): with mock.patch.multiple( stats_collector_instance, _metadatas=[], _stats_singleton=None): stats_collector_instance.Set( default_stats_collector.DefaultStatsCollector()) counter = metrics.Counter("cfoo") counter.Increment(1)
def testGetValue(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): counter = metrics.Counter("cfoo", fields=[("bar", str)]) self.assertEqual(counter.GetValue(["baz"]), 0) counter.Increment(fields=["baz"]) self.assertEqual(counter.GetValue(["baz"]), 1)
def setUp(self): super(StatsStoreTest, self).setUp() self.process_id = "some_pid" self.stats_store = aff4.FACTORY.Create(None, stats_store.StatsStore, mode="w", token=self.token) fake_stats_collector = default_stats_collector.DefaultStatsCollector([ stats_utils.CreateCounterMetadata("counter"), stats_utils.CreateCounterMetadata("counter_with_fields", fields=[("source", str)]), stats_utils.CreateEventMetadata("events"), stats_utils.CreateEventMetadata("events_with_fields", fields=[("source", str)]), stats_utils.CreateGaugeMetadata("int_gauge", int), stats_utils.CreateGaugeMetadata("str_gauge", str), stats_utils.CreateGaugeMetadata("str_gauge_with_fields", str, fields=[("task", int)]) ]) fake_stats_context = stats_test_utils.FakeStatsContext( fake_stats_collector) fake_stats_context.start() self.addCleanup(fake_stats_context.stop)
def testGetFields(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): counter = metrics.Counter("cfoo", fields=[("bar", str)]) self.assertEmpty(counter.GetFields()) counter.Increment(fields=["baz"]) counter.Increment(fields=["bazz"]) self.assertCountEqual(counter.GetFields(), [("baz",), ("bazz",)])
def _SetupFakeStatsContext(self): """Creates a stats context for running tests based on defined metrics.""" metrics_metadata = list( itervalues(stats_collector_instance.Get().GetAllMetricsMetadata())) fake_stats_collector = default_stats_collector.DefaultStatsCollector( metrics_metadata) fake_stats_context = stats_test_utils.FakeStatsContext(fake_stats_collector) fake_stats_context.start() self.addCleanup(fake_stats_context.stop)
def testPurgeServerStats(self): if not data_store.RelationalDBReadEnabled(): self.skipTest("Test is only for the relational DB. Skipping...") fake_stats_collector = default_stats_collector.DefaultStatsCollector([ stats_utils.CreateCounterMetadata("fake_counter"), ]) timestamp0 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1) timestamp1 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(2) timestamp2 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(3600) timestamp3 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(4800) config_overrides = { "Database.useForReads.stats": True, "StatsStore.stats_ttl_hours": 1 } with test_lib.ConfigOverrider(config_overrides), \ stats_test_utils.FakeStatsContext(fake_stats_collector), \ mock.patch.object(system, "_STATS_DELETION_BATCH_SIZE", 1): with test_lib.FakeTime(rdfvalue.RDFDatetime(timestamp0)): stats_store._WriteStats(process_id="fake_process_id") with test_lib.FakeTime(rdfvalue.RDFDatetime(timestamp1)): stats_collector_instance.Get().IncrementCounter("fake_counter") stats_store._WriteStats(process_id="fake_process_id") expected_results = { "fake_process_id": { "fake_counter": [(0, timestamp0), (1, timestamp1)] } } self.assertDictEqual( stats_store.ReadStats("f", "fake_counter"), expected_results) with test_lib.FakeTime(timestamp2): stats_store._WriteStats(process_id="fake_process_id") expected_results = { "fake_process_id": { "fake_counter": [(0, timestamp0), (1, timestamp1), (1, timestamp2)] } } self.assertDictEqual( stats_store.ReadStats("f", "fake_counter"), expected_results) with test_lib.FakeTime(timestamp3): cron = system.PurgeServerStatsCronJob( rdf_cronjobs.CronJobRun(), rdf_cronjobs.CronJob()) cron.Run() # timestamp0 and timestamp1 are older than 1h, so they should get # deleted. expected_results = { "fake_process_id": { "fake_counter": [(1, timestamp2)] } } self.assertDictEqual( stats_store.ReadStats("f", "fake_counter"), expected_results) self.assertIn("Deleted 2 stats entries.", cron.run_state.log_message)
def TestInit(): """Only used in tests and will rerun all the hooks to create a clean state.""" global INIT_RAN metric_metadata = server_metrics.GetMetadata() metric_metadata.extend(client_metrics.GetMetadata()) metric_metadata.extend(communicator.GetMetricMetadata()) stats_collector = default_stats_collector.DefaultStatsCollector( metric_metadata) stats_collector_instance.Set(stats_collector) # Tests use both the server template grr_server.yaml as a primary config file # (this file does not contain all required options, e.g. private keys), and # additional configuration in test_data/grr_test.yaml which contains typical # values for a complete installation. flags.FLAGS.config = package.ResourcePath( "grr-response-core", "install_data/etc/grr-server.yaml") flags.FLAGS.secondary_configs.append( package.ResourcePath("grr-response-test", "grr_response_test/test_data/grr_test.yaml")) # This config contains non-public settings that should be applied during # tests. extra_test_config = config.CONFIG["Test.additional_test_config"] if os.path.exists(extra_test_config): flags.FLAGS.secondary_configs.append(extra_test_config) # Tests additionally add a test configuration file. config_lib.SetPlatformArchContext() config_lib.ParseConfigCommandLine() # We are running a test so let the config system know that. config.CONFIG.AddContext(contexts.TEST_CONTEXT, "Context applied when we run tests.") test_ds = flags.FLAGS.test_data_store if test_ds is None: test_ds = compatibility.GetName(fake_data_store.FakeDataStore) config.CONFIG.Set("Datastore.implementation", test_ds) if not INIT_RAN: server_logging.ServerLoggingStartupInit() server_logging.SetTestVerbosity() blob_store_test_lib.UseTestBlobStore() registry.TestInit() db = data_store.DB.SetupTestDB() if db: data_store.DB = db data_store.DB.Initialize() aff4.AFF4InitHook().Run() INIT_RAN = True
def testTimedDecorator(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): event = metrics.Event("efoo", fields=[("bar", str)]) @event.Timed(fields=["baz"]) def Foo(): pass with self.assertStatsCounterDelta(1, event, fields=["baz"]): Foo()
def _CreateFakeStatsCollector(): """Returns a stats-collector for use by tests in this file.""" return default_stats_collector.DefaultStatsCollector([ stats_utils.CreateCounterMetadata(_SINGLE_DIM_COUNTER), stats_utils.CreateCounterMetadata(_COUNTER_WITH_ONE_FIELD, fields=[("field1", str)]), stats_utils.CreateCounterMetadata(_COUNTER_WITH_TWO_FIELDS, fields=[("field1", str), ("field2", int)]), stats_utils.CreateEventMetadata(_EVENT_METRIC), ])
def testSuccessesCountedDecoratorIncrement(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): counter = metrics.Counter("cfoo", fields=[("bar", str)]) @counter.SuccessesCounted(fields=["baz"]) def Foo(): pass with self.assertStatsCounterDelta(1, counter, fields=["baz"]): Foo()
def testErrorsCountedDecoratorIncrement(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): counter = metrics.Counter("cfoo", fields=[("bar", str)]) @counter.ErrorsCounted(fields=["baz"]) def Foo(): raise ValueError() with self.assertStatsCounterDelta(1, counter, fields=["baz"]): with self.assertRaises(ValueError): Foo()
def testPurgeServerStats(self): if not data_store.RelationalDBReadEnabled(): self.skipTest("Test is only for the relational DB. Skipping...") fake_stats_collector = default_stats_collector.DefaultStatsCollector([ stats_utils.CreateCounterMetadata("fake_counter"), ]) timestamp1 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(1) timestamp2 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(3600) timestamp3 = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(4800) config_overrides = { "Database.useForReads.stats": True, "StatsStore.stats_ttl_hours": 1 } with test_lib.ConfigOverrider(config_overrides): with stats_test_utils.FakeStatsContext(fake_stats_collector): with test_lib.FakeTime(rdfvalue.RDFDatetime(timestamp1)): stats_collector_instance.Get().IncrementCounter( "fake_counter") stats_store._WriteStats(process_id="fake_process_id") expected_results = { "fake_process_id": { "fake_counter": [(1, timestamp1)] } } self.assertDictEqual( stats_store.ReadStats("f", "fake_counter"), expected_results) with test_lib.FakeTime(timestamp2): stats_store._WriteStats(process_id="fake_process_id") expected_results = { "fake_process_id": { "fake_counter": [(1, timestamp1), (1, timestamp2)] } } self.assertDictEqual( stats_store.ReadStats("f", "fake_counter"), expected_results) with test_lib.FakeTime(timestamp3): system.PurgeServerStatsCronJob( rdf_cronjobs.CronJobRun(), rdf_cronjobs.CronJob()).Run() # timestamp1 is older than 1h, so it should get deleted. expected_results = { "fake_process_id": { "fake_counter": [(1, timestamp2)] } } self.assertDictEqual( stats_store.ReadStats("f", "fake_counter"), expected_results)
def _CreateFakeStatsCollector(): """Returns a stats-collector for use by tests in this file.""" return default_stats_collector.DefaultStatsCollector([ stats_utils.CreateCounterMetadata("counter"), stats_utils.CreateCounterMetadata( "counter_with_fields", fields=[("source", str)]), stats_utils.CreateEventMetadata("events"), stats_utils.CreateEventMetadata( "events_with_fields", fields=[("source", str)]), stats_utils.CreateGaugeMetadata("int_gauge", int), stats_utils.CreateGaugeMetadata("str_gauge", str), stats_utils.CreateGaugeMetadata( "str_gauge_with_fields", str, fields=[("task", int)]) ])
def ClientInit(): """Run all startup routines for the client.""" registry_init.RegisterClientActions() stats_collector_instance.Set(default_stats_collector.DefaultStatsCollector()) config_lib.SetPlatformArchContext() config_lib.ParseConfigCommandLine() client_logging.LogInit() all_parsers.Register() if not config.CONFIG.ContextApplied(contexts.CLIENT_BUILD_CONTEXT): config.CONFIG.Persist("Client.labels") config.CONFIG.Persist("Client.proxy_servers") config.CONFIG.Persist("Client.tempdir_roots")
def testEventMetricGetsRendered(self): stats_collector = default_stats_collector.DefaultStatsCollector([ stats_utils.CreateEventMetadata("api_method_latency"), ]) with stats_test_utils.FakeStatsContext(stats_collector): stats_collector_instance.Get().RecordEvent("api_method_latency", 15) varz_json = json.loads(stats_server.BuildVarzJsonString()) self.assertEqual(varz_json["api_method_latency"]["info"], { "metric_type": "EVENT", "value_type": "DISTRIBUTION" }) self.assertCountEqual( iterkeys(varz_json["api_method_latency"]["value"]), ["sum", "bins_heights", "counter"])
def Init(): """Run all required startup routines and initialization hooks.""" global INIT_RAN if INIT_RAN: return # Set up a temporary syslog handler so we have somewhere to log problems # with ConfigInit() which needs to happen before we can start our create our # proper logging setup. syslog_logger = logging.getLogger("TempLogger") if os.path.exists("/dev/log"): handler = logging.handlers.SysLogHandler(address="/dev/log") else: handler = logging.handlers.SysLogHandler() syslog_logger.addHandler(handler) try: config_lib.SetPlatformArchContext() config_lib.ParseConfigCommandLine() except config_lib.Error: syslog_logger.exception("Died during config initialization") raise metric_metadata = server_metrics.GetMetadata() metric_metadata.extend(communicator.GetMetricMetadata()) stats_collector = default_stats_collector.DefaultStatsCollector( metric_metadata) stats_collector_instance.Set(stats_collector) server_logging.ServerLoggingStartupInit() bs_registry_init.RegisterBlobStores() all_decoders.Register() all_parsers.Register() registry.Init() # Exempt config updater from this check because it is the one responsible for # setting the variable. if not config.CONFIG.ContextApplied("ConfigUpdater Context"): if not config.CONFIG.Get("Server.initialized"): raise RuntimeError( "Config not initialized, run \"grr_config_updater" " initialize\". If the server is already configured," " add \"Server.initialized: True\" to your config.") INIT_RAN = True
def _SetUpFakeStatsContext(self): """Registers stats metrics used by tests in this class.""" # DB implementations might interact with real metrics (not defined in this # test), so we make sure that they get registered. real_metrics = list( stats_collector_instance.Get().GetAllMetricsMetadata().values()) test_metrics = [ stats_utils.CreateCounterMetadata(_SINGLE_DIM_COUNTER), stats_utils.CreateCounterMetadata(_MULTI_DIM_COUNTER, fields=[("str_field1", str), ("str_field2", str)]), ] fake_stats_context = stats_test_utils.FakeStatsContext( default_stats_collector.DefaultStatsCollector(real_metrics + test_metrics)) fake_stats_context.start() self.addCleanup(fake_stats_context.stop)
def ClientInit(): """Run all startup routines for the client.""" metric_metadata = client_metrics.GetMetadata() metric_metadata.extend(communicator.GetMetricMetadata()) stats_collector_instance.Set( default_stats_collector.DefaultStatsCollector(metric_metadata)) config_lib.SetPlatformArchContext() config_lib.ParseConfigCommandLine() client_logging.LogInit() all_parsers.Register() if not config.CONFIG.ContextApplied(contexts.CLIENT_BUILD_CONTEXT): config.CONFIG.Persist("Client.labels") config.CONFIG.Persist("Client.proxy_servers") config.CONFIG.Persist("Client.tempdir_roots")
def _CreateStatsCollector(self, metadata_list): return default_stats_collector.DefaultStatsCollector(metadata_list)
def Run(self): real_metric_metadata = list( itervalues(stats_collector_instance.Get().GetAllMetricsMetadata())) test_metadata = real_metric_metadata + [ stats_utils.CreateCounterMetadata( _TEST_COUNTER, docstring="Sample counter metric."), stats_utils.CreateGaugeMetadata( _TEST_GAUGE_METRIC, float, docstring="Sample gauge metric."), stats_utils.CreateEventMetadata( _TEST_EVENT_METRIC, docstring="Sample event metric."), ] stats_collector = default_stats_collector.DefaultStatsCollector( test_metadata) with stats_test_utils.FakeStatsContext(stats_collector): for i in range(10): with test_lib.FakeTime(42 + i * 60): stats_collector.IncrementCounter(_TEST_COUNTER) stats_collector.SetGaugeValue(_TEST_GAUGE_METRIC, i * 0.5) stats_collector.RecordEvent(_TEST_EVENT_METRIC, 0.42 + 0.5 * i) with aff4.FACTORY.Create( None, aff4_stats_store.StatsStore, mode="w", token=self.token) as stats_store: stats_store.WriteStats(process_id="worker_1") range_start = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(42) range_end = rdfvalue.RDFDatetime.FromSecondsSinceEpoch(3600) self.Check( "GetStatsStoreMetric", args=stats_plugin.ApiGetStatsStoreMetricArgs( component="WORKER", metric_name=_TEST_COUNTER, start=range_start, end=range_end)) self.Check( "GetStatsStoreMetric", args=stats_plugin.ApiGetStatsStoreMetricArgs( component="WORKER", metric_name=_TEST_COUNTER, start=range_start, end=range_end, rate="1m")) self.Check( "GetStatsStoreMetric", args=stats_plugin.ApiGetStatsStoreMetricArgs( component="WORKER", metric_name=_TEST_GAUGE_METRIC, start=range_start, end=range_end)) self.Check( "GetStatsStoreMetric", args=stats_plugin.ApiGetStatsStoreMetricArgs( component="WORKER", metric_name=_TEST_EVENT_METRIC, start=range_start, end=range_end)) self.Check( "GetStatsStoreMetric", args=stats_plugin.ApiGetStatsStoreMetricArgs( component="WORKER", metric_name=_TEST_EVENT_METRIC, start=range_start, end=range_end, distribution_handling_mode="DH_COUNT"))
def testSetGaugeValue(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): gauge = metrics.Gauge("gfoo", int, fields=[("bar", str)]) with self.assertStatsCounterDelta(42, gauge, fields=["baz"]): gauge.SetValue(42, fields=["baz"])
def _CreateStatsCollector(self): return default_stats_collector.DefaultStatsCollector()
def testRecordEvent(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): event = metrics.Event("efoo", fields=[("bar", str)]) with self.assertStatsCounterDelta(1, event, fields=["baz"]): event.RecordEvent(42, fields=["baz"])
def testGaugeRegistration(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): metrics.Gauge("gfoo", int) self.assertIsNotNone(self.collector.GetMetricMetadata("gfoo"))
def testCounterIncrement(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): counter = metrics.Counter("cfoo", fields=[("bar", str)]) with self.assertStatsCounterDelta(1, counter, fields=["baz"]): counter.Increment(fields=["baz"])
def testEventRegistration(self): with self.SetUpStatsCollector( default_stats_collector.DefaultStatsCollector()): metrics.Event("efoo") self.assertIsNotNone(self.collector.GetMetricMetadata("efoo"))