__init__.py 4.94 KB
Newer Older
Mario Hock's avatar
Mario Hock committed
1
2
3
4
5
#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import psutil
import time
Mario Hock's avatar
Mario Hock committed
6
7
import sys
import traceback
Mario Hock's avatar
Mario Hock committed
8

9
10
11
from collections import namedtuple

import helpers
Mario Hock's avatar
Mario Hock committed
12
import curses_display as ui
13
14
15
16
17

def get_time():
    """ Unified/comparable clock access """
    return time.time()

Mario Hock's avatar
Mario Hock committed
18
19
20
21
22
23
24
25
26
27

## XXX for interactive debugging only
def RELOAD():
    print ("import importlib")
    print ("importlib.reload(cpunetlog)")


MEASUREMENT_INTERVAL = 0.2


28
29

class Reading:
Mario Hock's avatar
Mario Hock committed
30
31
    """ A single reading of various CPU, NET, ... values. --> Building block for the »Measurement« class."""

Mario Hock's avatar
Mario Hock committed
32
33
    def __init__(self):
        ## * measurements *
34
        self.timestamp = get_time()
Mario Hock's avatar
Mario Hock committed
35
36
        #self.cpu_util = psutil.cpu_percent(interval=0, percpu=True)                      ## XXX
        #self.cpu_times_percent = psutil.cpu_times_percent(interval=0, percpu=True)       ## XXX
37
        self.cpu_times = psutil.cpu_times(percpu=True)
Mario Hock's avatar
Mario Hock committed
38
39
        self.memory = psutil.virtual_memory()
        self.net_io = psutil.net_io_counters(pernic=True)
Mario Hock's avatar
Mario Hock committed
40
41

    def __str__(self):
Mario Hock's avatar
Mario Hock committed
42
43
44
45
46
47
        ## •‣∘⁕∗◘☉☀★◾☞☛⦿
        return "◘ Timespan: " + str(self.timespan) +              \
                "\n◘ CPU utilization: " + str(self.cpu_util) +    \
                "\n◘ CPU times: " + str(self.cpu_times) +         \
                "\n◘ RAM: " + str(self.memory) +                  \
                "\n◘ NET: " + str(self.net_io)
Mario Hock's avatar
Mario Hock committed
48
49


50
51

class NetworkTraffic:
Mario Hock's avatar
Mario Hock committed
52
53
    """ Utility class for calculating and storing network traffic: Total amount (during a timespan) and ratio. """

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
    def __init__(self, older_counters, younger_counters, timespan):
        self.total = dict()
        self.ratio = dict()

        for field in older_counters._fields:
            field_delta = getattr(younger_counters, field) - getattr(older_counters, field)

            self.total[field] = field_delta
            self.ratio[field] = field_delta / timespan

    def __str__(self):
        return "Total (bytes):" + str(self.total) + "; Ratio (bytes/s)" + str(self.ratio)



class Measurement:
Mario Hock's avatar
Mario Hock committed
70
71
    """ Calculates and stores CPU utilization, network traffic, ... during a timespan. Based two »Readings«. """

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    def __init__(self, reading1, reading2):
        self.r1 = reading1
        self.r2 = reading2

        ## calculate differences
        self.timespan = self.r2.timestamp - self.r1.timestamp
        self.cpu_times_percent = helpers.calculate_cpu_times_percent(self.r1.cpu_times, self.r2.cpu_times, percpu=True)
        self.net_io = self._calculate_net_io()


    def _calculate_net_io(self):
        ret = dict()

        for nic in self.r1.net_io.keys():
            ret[nic] = NetworkTraffic(self.r1.net_io[nic], self.r2.net_io[nic], self.timespan)

        return ret



def measure(interval = MEASUREMENT_INTERVAL):
Mario Hock's avatar
Mario Hock committed
93
94
    """ Convenience function to perform one »Measurement« """

95
96
97
98
99
100
101
102
103
104
    r1 = Reading()
    time.sleep(interval)
    r2 = Reading()

    m = Measurement(r1, r2)

    return m



Mario Hock's avatar
Mario Hock committed
105
## XXX TESTING
Mario Hock's avatar
Mario Hock committed
106
107
108
109
110
111
def display_cpu(measurement):
    num = 1
    for cpu in measurement.cpu_times_percent:
        print( "CPU" + str(num) + " util: " + str(100-cpu.idle) + "% (" + str(cpu.user) + "% user, " + str(cpu.system) + "% system)")
        num += 1

Mario Hock's avatar
Mario Hock committed
112
## XXX TESTING
Mario Hock's avatar
Mario Hock committed
113
def desplay_network_traffic(measurement, nics = None):
Mario Hock's avatar
Mario Hock committed
114
115
116
117
    divisor = 1000
    rounding_digits = 2
    unit = "KBytes"

Mario Hock's avatar
Mario Hock committed
118
119
120
121
122
123
    if not nics:
        nics = measurement.net_io.keys()

    for nic in nics:
        values = measurement.net_io[nic]

Mario Hock's avatar
Mario Hock committed
124
125
126
127
128
        sending = str( round(values.ratio["bytes_sent"] / divisor, rounding_digits) )
        receiving = str( round(values.ratio["bytes_recv"] / divisor, rounding_digits) )

        print( "[" + nic + "] Sending (" + unit + "/s): " + sending +
              ", Receiving (" + unit + "/s): " + receiving )
Mario Hock's avatar
Mario Hock committed
129
130


Mario Hock's avatar
Mario Hock committed
131
## XXX TESTING
Mario Hock's avatar
Mario Hock committed
132
def display(measurement):
Mario Hock's avatar
Mario Hock committed
133
134
    #nics = ("eth0", "wlan0", "lo")
    nics = ("eth0", "wlan0")
Mario Hock's avatar
Mario Hock committed
135
136
137
138
139

    display_cpu(measurement)
    desplay_network_traffic( measurement, nics )


Mario Hock's avatar
Mario Hock committed
140
## XXX TESTING
Mario Hock's avatar
Mario Hock committed
141
def displayX(measurement):
Mario Hock's avatar
Mario Hock committed
142
    nic = "eth0"
Mario Hock's avatar
Mario Hock committed
143

144
145
146
147
148
    for cpu in measurement.cpu_times_percent:
        print( ", ".join([str(x) + "%" for x in cpu]))
        print( str(100-cpu.idle) + "%, " + str(cpu.user) + "%. " + str(cpu.system) + "%")
    for nic in measurement.net_io.keys():
        print( "[" + nic + "] " + str(measurement.net_io[nic]) )
Mario Hock's avatar
Mario Hock committed
149
150

    print
Mario Hock's avatar
Mario Hock committed
151
152


Mario Hock's avatar
Mario Hock committed
153
154


Mario Hock's avatar
Mario Hock committed
155
## XXX TESTING -- NOTE: takes unnecessary Readings!!
156
def test_loop():
Mario Hock's avatar
Mario Hock committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
    err = None

    try:
        ui.init()
        ui.nics = ("eth0", "wlan0")

        while ui.display( measure(1.0) ):
            pass

    except KeyboardInterrupt:
        pass
    except Exception as e:
        err = e
        exc_type, exc_value, exc_traceback = sys.exc_info()
    finally:
        ui.close()

    ## On error: Print error message *after* curses has quit.
    if ( err ):
        print( "Unexpected exception happened: '" + str(err) + "'" )
Mario Hock's avatar
Mario Hock committed
177
        print
178

Mario Hock's avatar
Mario Hock committed
179
180
181
182
183
        traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stdout)

        print
        print( "QUIT." )

184
185

## XXX TESTING
Mario Hock's avatar
Mario Hock committed
186
187
#display( measure() )
test_loop()
Mario Hock's avatar
Mario Hock committed
188