def CheckStats(self): """Checks if the last transmission of client stats is too long ago.""" if self.last_stats_sent_time is None: self.last_stats_sent_time = rdfvalue.RDFDatetime().Now() stats.STATS.SetGaugeValue( "grr_client_last_stats_sent_time", self.last_stats_sent_time.AsSecondsFromEpoch()) time_since_last_check = (rdfvalue.RDFDatetime().Now() - self.last_stats_sent_time) # No matter what, we don't want to send stats more often than # once per STATS_MIN_SEND_INTERVAL. if time_since_last_check < self.STATS_MIN_SEND_INTERVAL: return if (time_since_last_check > self.STATS_MAX_SEND_INTERVAL or self._is_active or self._send_stats_on_check): self._send_stats_on_check = False logging.info("Sending back client statistics to the server.") action_cls = actions.ActionPlugin.classes.get( "GetClientStatsAuto", actions.ActionPlugin) action = action_cls(grr_worker=self) action.Run( rdf_client.GetClientStatsRequest( start_time=self.last_stats_sent_time)) self.last_stats_sent_time = rdfvalue.RDFDatetime().Now() stats.STATS.SetGaugeValue( "grr_client_last_stats_sent_time", self.last_stats_sent_time.AsSecondsFromEpoch())
def Run(self, arg): """Returns the client stats.""" if arg is None: arg = rdf_client.GetClientStatsRequest() proc = psutil.Process(os.getpid()) meminfo = proc.memory_info() response = rdf_client.ClientStats( RSS_size=meminfo.rss, VMS_size=meminfo.vms, memory_percent=proc.memory_percent(), bytes_received=stats.STATS.GetMetricValue( "grr_client_received_bytes"), bytes_sent=stats.STATS.GetMetricValue("grr_client_sent_bytes"), create_time=long(proc.create_time() * 1e6), boot_time=long(psutil.boot_time() * 1e6)) samples = self.grr_worker.stats_collector.cpu_samples for (timestamp, user, system, percent) in samples: if arg.start_time < timestamp < arg.end_time: sample = rdf_client.CpuSample(timestamp=timestamp, user_cpu_time=user, system_cpu_time=system, cpu_percent=percent) response.cpu_samples.Append(sample) samples = self.grr_worker.stats_collector.io_samples for (timestamp, read_bytes, write_bytes) in samples: if arg.start_time < timestamp < arg.end_time: sample = rdf_client.IOSample(timestamp=timestamp, read_bytes=read_bytes, write_bytes=write_bytes) response.io_samples.Append(sample) self.Send(response)
def Run(self, arg): """Returns the client stats.""" if arg is None: arg = rdf_client.GetClientStatsRequest() proc = psutil.Process(os.getpid()) meminfo = proc.memory_info() boot_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch( psutil.boot_time()) create_time = rdfvalue.RDFDatetime.FromSecondsSinceEpoch( proc.create_time()) response = rdf_client.ClientStats( RSS_size=meminfo.rss, VMS_size=meminfo.vms, memory_percent=proc.memory_percent(), bytes_received=stats.STATS.GetMetricValue( "grr_client_received_bytes"), bytes_sent=stats.STATS.GetMetricValue("grr_client_sent_bytes"), create_time=create_time, boot_time=boot_time) response.cpu_samples = self.grr_worker.stats_collector.CpuSamplesBetween( start_time=arg.start_time, end_time=arg.end_time) response.io_samples = self.grr_worker.stats_collector.IOSamplesBetween( start_time=arg.start_time, end_time=arg.end_time) self.Send(response)
def testReturnsAllDataByDefault(self): """Checks that stats collection works.""" stats.STATS.RegisterCounterMetric("grr_client_received_bytes") stats.STATS.IncrementCounter("grr_client_received_bytes", 1566) stats.STATS.RegisterCounterMetric("grr_client_sent_bytes") stats.STATS.IncrementCounter("grr_client_sent_bytes", 2000) results = self.RunAction( admin.GetClientStats, grr_worker=MockClientWorker(), arg=rdf_client.GetClientStatsRequest()) response = results[0] self.assertEqual(response.bytes_received, 1566) self.assertEqual(response.bytes_sent, 2000) self.assertEqual(len(response.cpu_samples), 3) for i in range(3): self.assertEqual(response.cpu_samples[i].timestamp, rdfvalue.RDFDatetime.FromSecondsSinceEpoch(100 + i * 10)) self.assertAlmostEqual(response.cpu_samples[i].user_cpu_time, 0.1) self.assertAlmostEqual(response.cpu_samples[i].system_cpu_time, 0.1 * (i + 1)) self.assertAlmostEqual(response.cpu_samples[i].cpu_percent, 10.0 + 5 * i) self.assertEqual(len(response.io_samples), 3) for i in range(3): self.assertEqual(response.io_samples[i].timestamp, rdfvalue.RDFDatetime.FromSecondsSinceEpoch(100 + i * 10)) self.assertEqual(response.io_samples[i].read_bytes, 100 * (i + 1)) self.assertEqual(response.io_samples[i].write_bytes, 100 * (i + 1)) self.assertEqual(response.boot_time, long(100 * 1e6))
def testFiltersDataPointsByEndTime(self): end_time = rdfvalue.RDFDatetime().FromSecondsFromEpoch(102) results = self.RunAction( "GetClientStats", grr_worker=MockClientWorker(), arg=rdf_client.GetClientStatsRequest(end_time=end_time)) response = results[0] self.assertEqual(len(response.cpu_samples), 1) self.assertEqual(response.cpu_samples[0].timestamp, rdfvalue.RDFDatetime().FromSecondsFromEpoch(100)) self.assertEqual(len(response.io_samples), 1) self.assertEqual(response.io_samples[0].timestamp, rdfvalue.RDFDatetime().FromSecondsFromEpoch(100))
def testFiltersDataPointsByStartTime(self): start_time = rdfvalue.RDFDatetime().FromSecondsFromEpoch(117) results = self.RunAction( admin.GetClientStats, grr_worker=MockClientWorker(), arg=rdf_client.GetClientStatsRequest(start_time=start_time)) response = results[0] self.assertEqual(len(response.cpu_samples), 1) self.assertEqual(response.cpu_samples[0].timestamp, rdfvalue.RDFDatetime().FromSecondsFromEpoch(120)) self.assertEqual(len(response.io_samples), 1) self.assertEqual(response.io_samples[0].timestamp, rdfvalue.RDFDatetime().FromSecondsFromEpoch(120))
def _Send(self): if not self._ShouldSend(): return # TODO(hanuszczak): We shouldn't manually create action instances. Instead, # we should refactor action code to some other function and make the action # class use that function. Then here we should use that function as well. # # Also, it looks like there is a very weird dependency triangle: the worker # creates stat collector (which requires a worker), then the stats action # requires a worker and uses stat collector internally. But this action is # spawned by the stat collector. What...? action = admin.GetClientStatsAuto(grr_worker=self._worker) request = rdf_client.GetClientStatsRequest( start_time=self._last_send_time) action.Run(request) self._should_send = False self._last_send_time = rdfvalue.RDFDatetime.Now() stats.STATS.SetGaugeValue("grr_client_last_stats_sent_time", self._last_send_time.AsSecondsSinceEpoch())