Ejemplo n.º 1
0
def _resources_via_ps(pid):
    """
  Fetches resource usage information about a given process via ps. This returns
  a tuple of the form...

    (total_cpu_time, uptime, memory_in_bytes, memory_in_percent)

  :param int pid: process to be queried

  :returns: **tuple** with the resource usage information

  :raises: **IOError** if unsuccessful
  """

    # ps results are of the form...
    #
    #     TIME     ELAPSED   RSS %MEM
    # 3-08:06:32 21-00:00:12 121844 23.5
    #
    # ... or if Tor has only recently been started...
    #
    #     TIME      ELAPSED    RSS %MEM
    #  0:04.40        37:57  18772  0.9

    try:
        ps_call = system.call(
            'ps -p {pid} -o cputime,etime,rss,%mem'.format(pid=pid))
    except OSError as exc:
        raise IOError(exc)

    if ps_call and len(ps_call) >= 2:
        stats = ps_call[1].strip().split()

        if len(stats) == 4:
            try:
                total_cpu_time = str_tools.parse_short_time_label(stats[0])
                uptime = str_tools.parse_short_time_label(stats[1])
                memory_bytes = int(stats[2]) * 1024  # ps size is in kb
                memory_percent = float(stats[3]) / 100.0

                return (total_cpu_time, uptime, memory_bytes, memory_percent)
            except ValueError:
                pass

    raise IOError('unrecognized output from ps: %s' % ps_call)
Ejemplo n.º 2
0
def _resources_via_ps(pid):
  """
  Fetches resource usage information about a given process via ps. This returns
  a tuple of the form...

    (total_cpu_time, uptime, memory_in_bytes, memory_in_percent)

  :param int pid: process to be queried

  :returns: **tuple** with the resource usage information

  :raises: **IOError** if unsuccessful
  """

  # ps results are of the form...
  #
  #     TIME     ELAPSED   RSS %MEM
  # 3-08:06:32 21-00:00:12 121844 23.5
  #
  # ... or if Tor has only recently been started...
  #
  #     TIME      ELAPSED    RSS %MEM
  #  0:04.40        37:57  18772  0.9

  try:
    ps_call = system.call('ps -p {pid} -o cputime,etime,rss,%mem'.format(pid = pid))
  except OSError as exc:
    raise IOError(exc)

  if ps_call and len(ps_call) >= 2:
    stats = ps_call[1].strip().split()

    if len(stats) == 4:
      try:
        total_cpu_time = str_tools.parse_short_time_label(stats[0])
        uptime = str_tools.parse_short_time_label(stats[1])
        memory_bytes = int(stats[2]) * 1024  # ps size is in kb
        memory_percent = float(stats[3]) / 100.0

        return (total_cpu_time, uptime, memory_bytes, memory_percent)
      except ValueError:
        pass

  raise IOError('unrecognized output from ps: %s' % ps_call)
Ejemplo n.º 3
0
    def test_parse_short_time_label(self):
        """
    Checks the parse_short_time_label() function.
    """

        # test the pydoc examples
        self.assertEqual(111, str_tools.parse_short_time_label('01:51'))
        self.assertEqual(544100,
                         str_tools.parse_short_time_label('6-07:08:20'))

        self.assertEqual(110, str_tools.parse_short_time_label('01:50.62'))
        self.assertEqual(0, str_tools.parse_short_time_label('00:00'))

        # these aren't technically valid, but might as well allow unnecessary
        # digits to be dropped

        self.assertEqual(300, str_tools.parse_short_time_label('05:0'))
        self.assertEqual(300, str_tools.parse_short_time_label('5:00'))

        self.assertRaises(TypeError, str_tools.parse_short_time_label, None)
        self.assertRaises(TypeError, str_tools.parse_short_time_label, 100)

        self.assertRaises(ValueError, str_tools.parse_short_time_label,
                          'blarg')
        self.assertRaises(ValueError, str_tools.parse_short_time_label, '00')
        self.assertRaises(ValueError, str_tools.parse_short_time_label, '05:')
        self.assertRaises(ValueError, str_tools.parse_short_time_label,
                          '05a:00')
        self.assertRaises(ValueError, str_tools.parse_short_time_label,
                          '-05:00')
Ejemplo n.º 4
0
  def test_parse_short_time_label(self):
    """
    Checks the parse_short_time_label() function.
    """

    # test the pydoc examples
    self.assertEqual(111, str_tools.parse_short_time_label('01:51'))
    self.assertEqual(544100, str_tools.parse_short_time_label('6-07:08:20'))

    self.assertEqual(110, str_tools.parse_short_time_label('01:50.62'))
    self.assertEqual(0, str_tools.parse_short_time_label('00:00'))

    # these aren't technically valid, but might as well allow unnecessary
    # digits to be dropped

    self.assertEqual(300, str_tools.parse_short_time_label('05:0'))
    self.assertEqual(300, str_tools.parse_short_time_label('5:00'))

    self.assertRaises(TypeError, str_tools.parse_short_time_label, None)
    self.assertRaises(TypeError, str_tools.parse_short_time_label, 100)

    self.assertRaises(ValueError, str_tools.parse_short_time_label, 'blarg')
    self.assertRaises(ValueError, str_tools.parse_short_time_label, '00')
    self.assertRaises(ValueError, str_tools.parse_short_time_label, '05:')
    self.assertRaises(ValueError, str_tools.parse_short_time_label, '05a:00')
    self.assertRaises(ValueError, str_tools.parse_short_time_label, '-05:00')
Ejemplo n.º 5
0
    def run(self):
        while not self._halt:
            timeSinceReset = time.time() - self.lastLookup

            if self.resolveRate == 0:
                self._cond.acquire()
                if not self._halt: self._cond.wait(0.2)
                self._cond.release()

                continue
            elif timeSinceReset < self.resolveRate:
                sleepTime = max(0.2, self.resolveRate - timeSinceReset)

                self._cond.acquire()
                if not self._halt: self._cond.wait(sleepTime)
                self._cond.release()

                continue  # done waiting, try again

            newValues = {}
            try:
                if self._useProc:
                    utime, stime, startTime = proc.get_stats(
                        self.processPid, proc.Stat.CPU_UTIME,
                        proc.Stat.CPU_STIME, proc.Stat.START_TIME)
                    totalCpuTime = float(utime) + float(stime)
                    cpuDelta = totalCpuTime - self._lastCpuTotal
                    newValues["cpuSampling"] = cpuDelta / timeSinceReset
                    newValues["cpuAvg"] = totalCpuTime / (time.time() -
                                                          float(startTime))
                    newValues["_lastCpuTotal"] = totalCpuTime

                    memUsage = int(proc.get_memory_usage(self.processPid)[0])
                    totalMemory = proc.get_physical_memory()
                    newValues["memUsage"] = memUsage
                    newValues["memUsagePercentage"] = float(
                        memUsage) / totalMemory
                else:
                    # the ps call formats results as:
                    #
                    #     TIME     ELAPSED   RSS %MEM
                    # 3-08:06:32 21-00:00:12 121844 23.5
                    #
                    # or if Tor has only recently been started:
                    #
                    #     TIME      ELAPSED    RSS %MEM
                    #  0:04.40        37:57  18772  0.9

                    psCall = system.call(
                        "ps -p %s -o cputime,etime,rss,%%mem" %
                        self.processPid)

                    isSuccessful = False
                    if psCall and len(psCall) >= 2:
                        stats = psCall[1].strip().split()

                        if len(stats) == 4:
                            try:
                                totalCpuTime = str_tools.parse_short_time_label(
                                    stats[0])
                                uptime = str_tools.parse_short_time_label(
                                    stats[1])
                                cpuDelta = totalCpuTime - self._lastCpuTotal
                                newValues[
                                    "cpuSampling"] = cpuDelta / timeSinceReset
                                newValues["cpuAvg"] = totalCpuTime / uptime
                                newValues["_lastCpuTotal"] = totalCpuTime

                                newValues["memUsage"] = int(
                                    stats[2]) * 1024  # ps size is in kb
                                newValues["memUsagePercentage"] = float(
                                    stats[3]) / 100.0
                                isSuccessful = True
                            except ValueError, exc:
                                pass

                    if not isSuccessful:
                        raise IOError("unrecognized output from ps: %s" %
                                      psCall)
            except IOError, exc:
                newValues = {}
                self._failureCount += 1

                if self._useProc:
                    if self._failureCount >= 3:
                        # We've failed three times resolving via proc. Warn, and fall back
                        # to ps resolutions.
                        log.info(
                            "Failed three attempts to get process resource usage from proc, falling back to ps (%s)"
                            % exc)

                        self._useProc = False
                        self._failureCount = 1  # prevents lastQueryFailed() from thinking that we succeeded
                    else:
                        # wait a bit and try again
                        log.debug(
                            "Unable to query process resource usage from proc (%s)"
                            % exc)
                        self._cond.acquire()
                        if not self._halt: self._cond.wait(0.5)
                        self._cond.release()
                else:
                    # exponential backoff on making failed ps calls
                    sleepTime = 0.01 * (
                        2**self._failureCount) + self._failureCount
                    log.debug(
                        "Unable to query process resource usage from ps, waiting %0.2f seconds (%s)"
                        % (sleepTime, exc))
                    self._cond.acquire()
                    if not self._halt: self._cond.wait(sleepTime)
                    self._cond.release()

            # sets the new values
            if newValues:
                # If this is the first run then the cpuSampling stat is meaningless
                # (there isn't a previous tick to sample from so it's zero at this
                # point). Setting it to the average, which is a fairer estimate.
                if self.lastLookup == -1:
                    newValues["cpuSampling"] = newValues["cpuAvg"]

                self._valLock.acquire()
                self.cpuSampling = newValues["cpuSampling"]
                self.cpuAvg = newValues["cpuAvg"]
                self.memUsage = newValues["memUsage"]
                self.memUsagePercentage = newValues["memUsagePercentage"]
                self._lastCpuTotal = newValues["_lastCpuTotal"]
                self.lastLookup = time.time()
                self._runCount += 1
                self._failureCount = 0
                self._valLock.release()
Ejemplo n.º 6
0
 def run(self):
   while not self._halt:
     timeSinceReset = time.time() - self.lastLookup
     
     if self.resolveRate == 0:
       self._cond.acquire()
       if not self._halt: self._cond.wait(0.2)
       self._cond.release()
       
       continue
     elif timeSinceReset < self.resolveRate:
       sleepTime = max(0.2, self.resolveRate - timeSinceReset)
       
       self._cond.acquire()
       if not self._halt: self._cond.wait(sleepTime)
       self._cond.release()
       
       continue # done waiting, try again
     
     newValues = {}
     try:
       if self._useProc:
         utime, stime, startTime = proc.get_stats(self.processPid, proc.Stat.CPU_UTIME, proc.Stat.CPU_STIME, proc.Stat.START_TIME)
         totalCpuTime = float(utime) + float(stime)
         cpuDelta = totalCpuTime - self._lastCpuTotal
         newValues["cpuSampling"] = cpuDelta / timeSinceReset
         newValues["cpuAvg"] = totalCpuTime / (time.time() - float(startTime))
         newValues["_lastCpuTotal"] = totalCpuTime
         
         memUsage = int(proc.get_memory_usage(self.processPid)[0])
         totalMemory = proc.get_physical_memory()
         newValues["memUsage"] = memUsage
         newValues["memUsagePercentage"] = float(memUsage) / totalMemory
       else:
         # the ps call formats results as:
         # 
         #     TIME     ELAPSED   RSS %MEM
         # 3-08:06:32 21-00:00:12 121844 23.5
         # 
         # or if Tor has only recently been started:
         # 
         #     TIME      ELAPSED    RSS %MEM
         #  0:04.40        37:57  18772  0.9
         
         psCall = system.call("ps -p %s -o cputime,etime,rss,%%mem" % self.processPid)
         
         isSuccessful = False
         if psCall and len(psCall) >= 2:
           stats = psCall[1].strip().split()
           
           if len(stats) == 4:
             try:
               totalCpuTime = str_tools.parse_short_time_label(stats[0])
               uptime = str_tools.parse_short_time_label(stats[1])
               cpuDelta = totalCpuTime - self._lastCpuTotal
               newValues["cpuSampling"] = cpuDelta / timeSinceReset
               newValues["cpuAvg"] = totalCpuTime / uptime
               newValues["_lastCpuTotal"] = totalCpuTime
               
               newValues["memUsage"] = int(stats[2]) * 1024 # ps size is in kb
               newValues["memUsagePercentage"] = float(stats[3]) / 100.0
               isSuccessful = True
             except ValueError, exc: pass
         
         if not isSuccessful:
           raise IOError("unrecognized output from ps: %s" % psCall)
     except IOError, exc:
       newValues = {}
       self._failureCount += 1
       
       if self._useProc:
         if self._failureCount >= 3:
           # We've failed three times resolving via proc. Warn, and fall back
           # to ps resolutions.
           log.info("Failed three attempts to get process resource usage from proc, falling back to ps (%s)" % exc)
           
           self._useProc = False
           self._failureCount = 1 # prevents lastQueryFailed() from thinking that we succeeded
         else:
           # wait a bit and try again
           log.debug("Unable to query process resource usage from proc (%s)" % exc)
           self._cond.acquire()
           if not self._halt: self._cond.wait(0.5)
           self._cond.release()
       else:
         # exponential backoff on making failed ps calls
         sleepTime = 0.01 * (2 ** self._failureCount) + self._failureCount
         log.debug("Unable to query process resource usage from ps, waiting %0.2f seconds (%s)" % (sleepTime, exc))
         self._cond.acquire()
         if not self._halt: self._cond.wait(sleepTime)
         self._cond.release()
     
     # sets the new values
     if newValues:
       # If this is the first run then the cpuSampling stat is meaningless
       # (there isn't a previous tick to sample from so it's zero at this
       # point). Setting it to the average, which is a fairer estimate.
       if self.lastLookup == -1:
         newValues["cpuSampling"] = newValues["cpuAvg"]
       
       self._valLock.acquire()
       self.cpuSampling = newValues["cpuSampling"]
       self.cpuAvg = newValues["cpuAvg"]
       self.memUsage = newValues["memUsage"]
       self.memUsagePercentage = newValues["memUsagePercentage"]
       self._lastCpuTotal = newValues["_lastCpuTotal"]
       self.lastLookup = time.time()
       self._runCount += 1
       self._failureCount = 0
       self._valLock.release()