2016-11-27 3 views
0

Ich würde meine Flask Anwendung mag, wie viel CPU und Speicher berichten es derzeit als Prozentsatz mit:psutil des cpu_percent immer wieder 0.0

import psutil 
from flask import Flask, request, jsonify 

app = Flask(__name__) 

@app.route("/test", methods=["GET"]) 
def healthz(): 
    return jsonify(msg="OK"), 200 

@app.route("/stats", methods=["GET"]) 
def stats(): 
    p = psutil.Process() 
    json_body = { 
     "cpu_percent": p.cpu_percent(interval=None), 
     "cpu_times": p.cpu_times(), 
     "mem_info": p.memory_info(), 
     "mem_percent": p.memory_percent() 
    } 
    return jsonify(json_body), 200 


def main(): 
    app.run(host="0.0.0.0", port=8000, debug=False) 

if __name__ == '__main__': 
    main() 

Während viele Anfragen an/Test Senden/Statistiken werden immer cpu_percent liefert 0.0 für:

$ while true; do curl http://127.0.0.1:8000/test &>/dev/null; done & 
$ curl http://127.0.0.1:8000/stats 
{ 
    "cpu_percent": 0.0, 
    "cpu_times": [ 
    4.97, 
    1.28, 
    0.0, 
    0.0 
    ], 
    "mem_info": [ 
    19652608, 
    243068928, 
    4292608, 
    4096, 
    0, 
    14675968, 
    0 
    ], 
    "mem_percent": 1.8873787935409003 
} 

wenn ich jedoch ipython mit manuell überprüfen:

import psutil 
p = psutil.Process(10993) 
p.cpu_percent() 

Dies gibt korrekt einen Wert größer als 0.0 zurück.

+0

Dies ist eine Art von selbstreferenziellen; Die Anwendung wird zusätzliche Zyklen und Speicher verbrauchen, nur um zu berichten, wie viele Zyklen und Speicher sie bereits verbraucht. Dies kann mit anderen Prozessüberwachungsanwendungen und -diensten erreicht werden; Warum willst du das in deiner App? – Makoto

Antwort

1

Definieren Sie einfach "p = psutil.Process()" global (außerhalb der Funktion stat()). cpu_percent() verfolgt die CPU-Zeiten seit dem letzten Aufruf und kann so den Prozentsatz bestimmen.

Der erste Aufruf ist immer 0.0, da der Berechnungsprozentsatz das Vergleichen zweier Werte im Zeitverlauf erfordert und daher einige Zeit vergehen muss.

1

Wie Giampaolo darauf hingewiesen hat, muss die Instanz der Process im globalen Gültigkeitsbereich sein, da die Instanz den Status verfolgt, um sie basierend auf dem vorherigen Aufruf auszuarbeiten.

Beachten Sie jedoch, dass der CPU-Prozentsatz von einem Moment zum nächsten ziemlich viel springen kann und vor allem, wenn der Zeitraum, über den er berechnet wird, sich ständig ändert, kann ziemlich verwirrend sein. Es ist vielleicht besser, einen Hintergrund-Thread zu verwenden, der den durchschnittlichen CPU-Prozentsatz über festgelegte Zeitbereiche ermittelt.

Einiger Code Ich war zufällig zur Hand haben kann von Interesse sein:

from __future__ import print_function 

import os 
import time 
import atexit 

import threading 

try: 
    import Queue as queue 
except ImportError: 
    import queue 

import psutil 

_running = False 
_queue = queue.Queue() 
_lock = threading.Lock() 

_cpu_percentage = 1800 * [0.0] 
_processes = {} 

def _monitor(): 
    global _cpu_percentage 
    global _processes 

    while True: 
     marker = time.time() 

     total = 0.0 
     pids = psutil.pids() 

     processes = {} 

     for pid in pids: 
      process = _processes.get(pid) 
      if process is None: 
       process = psutil.Process(pid) 
      processes[pid] = process 
      total += process.cpu_percent() 

     _processes = processes 

     _cpu_percentage.insert(0, total) 

     _cpu_percentage = _cpu_percentage[:1800] 

     duration = max(0.0, 1.0 - (time.time() - marker)) 

     try: 
      return _queue.get(timeout=duration) 

     except queue.Empty: 
      pass 

_thread = threading.Thread(target=_monitor) 
_thread.setDaemon(True) 

def _exiting(): 
    try: 
     _queue.put(True) 
    except Exception: 
     pass 
    _thread.join() 

def track_changes(path): 
    if not path in _files: 
     _files.append(path) 

def start_monitor(): 
    global _running 
    _lock.acquire() 
    if not _running: 
     prefix = 'monitor (pid=%d):' % os.getpid() 
     print('%s Starting CPU monitor.' % prefix) 
     _running = True 
     _thread.start() 
     atexit.register(_exiting) 
    _lock.release() 

def cpu_averages(): 
    values = _cpu_percentage[:60] 

    averages = {} 

    def average(secs): 
     return min(100.0, sum(values[:secs])/secs) 

    averages['cpu.average.1s'] = average(1) 
    averages['cpu.average.5s'] = average(5) 
    averages['cpu.average.15s'] = average(15) 
    averages['cpu.average.30s'] = average(30) 
    averages['cpu.average.1m'] = average(60) 
    averages['cpu.average.5m'] = average(300) 
    averages['cpu.average.15m'] = average(900) 
    averages['cpu.average.30m'] = average(1800) 

    return averages 

ich andere Sachen in dieser hatte die ich gelöscht, so hoffnungsvoll, was bleibt, ist immer noch in einem brauchbaren Zustand.

Um es zu verwenden, fügen Sie zu Datei monitor.py hinzu und importieren Sie dann das Modul in Ihrem Haupt und starten Sie die Überwachungsschleife.

import monitor 
monitor.start_monitor() 

dann auf jede Anfrage Aufruf:

monitor.cpu_averages() 

und Extraktwert für einen Zeitraum denken Sie macht Sinn.

Verwandte Themen