├── .gitignore ├── LICENSE ├── MANIFEST ├── README.rst ├── example.py ├── linux_metrics ├── __init__.py ├── cpu_stat.py ├── disk_stat.py ├── mem_stat.py ├── net_stat.py ├── test_cpu_stat.py ├── test_disk_stat.py ├── test_mem_stat.py └── test_net_stat.py ├── setup.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | _build 3 | build 4 | dist 5 | .tox 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | license for linux-metrics distribution 2 | 3 | Copyright (c) 2010-2012 Corey Goldberg (http://goldb.org) 4 | 5 | License :: OSI Approved :: MIT License 6 | 7 | -------------------------------------------------------------------------------- 8 | The MIT License 9 | 10 | http://www.opensource.org/licenses/mit-license 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in 20 | all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | THE SOFTWARE. 29 | -------------------------------------------------------------------------------- 30 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | setup.py 2 | example.py 3 | LICENSE 4 | MANIFEST 5 | README.rst 6 | linux_metrics/__init__.py 7 | linux_metrics/cpu_stat.py 8 | linux_metrics/disk_stat.py 9 | linux_metrics/mem_stat.py 10 | linux_metrics/net_stat.py 11 | linux_metrics/test_cpu_stat.py 12 | linux_metrics/test_disk_stat.py 13 | linux_metrics/test_mem_stat.py 14 | linux_metrics/test_net_stat.py 15 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | linux-metrics 3 | ============= 4 | 5 | *System Metrics/Stats Library for Linux* 6 | 7 | * 2010-2013 `Corey Goldberg `_ 8 | * Dev Home: https://github.com/cgoldberg/linux-metrics 9 | * PyPI: http://pypi.python.org/pypi/linux-metrics 10 | * Free Open Source : `MIT License `_ 11 | 12 | ---- 13 | 14 | ----------- 15 | Description 16 | ----------- 17 | 18 | `linux-metrics` is a Python package containing modules for getting OS metrics on systems running the Linux kernel. It is a pure python library with no external dependencies. 19 | 20 | Basic stats for major subsystems are provided (Processor/CPU, Disk, Memory, Network). 21 | 22 | ----------------- 23 | Install from PyPI 24 | ----------------- 25 | 26 | * `pip install linux-metrics` 27 | 28 | ------------ 29 | Requirements 30 | ------------ 31 | 32 | * Python 2.6/2.7/3.1/3.2/3.3/PyPy 33 | * Linux 2.6+ 34 | 35 | ------------- 36 | Example Usage 37 | ------------- 38 | 39 | print number of processes running:: 40 | 41 | from linux_metrics import cpu_stat 42 | 43 | print cpu_stat.procs_running() 44 | 45 | print CPU utilization every 5 secs:: 46 | 47 | >>> from linux_metrics import cpu_stat 48 | >>> 49 | >>> while True: 50 | ... cpu_pcts = cpu_stat.cpu_percents(5) 51 | ... print 'cpu utilization: %.2f%%' % (100 - cpu_pcts['idle']) 52 | ... 53 | cpu utilization: 0.70% 54 | cpu utilization: 0.50% 55 | cpu utilization: 24.80% 56 | cpu utilization: 20.89% 57 | cpu utilization: 40.04% 58 | 59 | --- 60 | API 61 | --- 62 | 63 | :: 64 | 65 | * linux_metrics 66 | * cpu_stat 67 | * cpu_times() 68 | * cpu_percents(sample_duration=1) 69 | * procs_running() 70 | * procs_blocked() 71 | * load_avg() 72 | * cpu_info() 73 | * disk_stat 74 | * disk_busy(device, sample_duration=1) 75 | * disk_reads_writes(device) 76 | * disk_usage(path) 77 | * disk_reads_writes_persec(device, sample_duration=1) 78 | * mem_stat 79 | * mem_stats() 80 | * net_stat 81 | * rx_tx_bytes(interface) 82 | * rx_tx_bits(interface) 83 | * rx_tx_dump(interface) 84 | 85 | ------- 86 | Example 87 | ------- 88 | 89 | `linux-metrics` package contains an example script: 90 | 91 | * `example.py `_ 92 | 93 | ---------- 94 | Unit Tests 95 | ---------- 96 | 97 | You can run the included unit tests and verify all cases pass in your environment: 98 | 99 | :: 100 | 101 | $ nosetests 102 | 103 | Note: you may need to adjust the configuration of the unit tests to match your environment. They are set by default to use: 104 | 105 | :: 106 | 107 | DISK_DEVICE = 'sda1' 108 | 109 | NETWORK_INTERFACE = 'eth0' 110 | 111 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2011-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | """ example usage of linux-metrics """ 23 | 24 | 25 | import linux_metrics as lm 26 | 27 | 28 | 29 | def main(): 30 | 31 | # cpu 32 | print 'procs running: %d' % lm.cpu_stat.procs_running() 33 | cpu_pcts = lm.cpu_stat.cpu_percents(sample_duration=1) 34 | print 'cpu utilization: %.2f%%' % (100 - cpu_pcts['idle']) 35 | 36 | # disk 37 | print 'disk busy: %s%%' % lm.disk_stat.disk_busy('sda', sample_duration=1) 38 | r, w = lm.disk_stat.disk_reads_writes('sda1') 39 | print 'disk reads: %s' % r 40 | print 'disk writes: %s' % w 41 | 42 | # memory 43 | used, total, _, _, _, _ = lm.mem_stat.mem_stats() 44 | print 'mem used: %s' % used 45 | print 'mem total: %s' % total 46 | 47 | # network 48 | rx_bits, tx_bits = lm.net_stat.rx_tx_bits('enp4s0') 49 | print 'net bits received: %s' % rx_bits 50 | print 'net bits sent: %s' % tx_bits 51 | 52 | 53 | 54 | if __name__ == '__main__': 55 | main() 56 | -------------------------------------------------------------------------------- /linux_metrics/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | 23 | from .cpu_stat import * 24 | from .disk_stat import * 25 | from .mem_stat import * 26 | from .net_stat import * 27 | 28 | 29 | __version__ = '0.1.5dev' 30 | -------------------------------------------------------------------------------- /linux_metrics/cpu_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | """ 23 | cpu_stat - Python Module for CPU Stats on Linux 24 | 25 | 26 | requires: 27 | - Python 2.6+ 28 | - Linux 2.6+ 29 | 30 | """ 31 | 32 | 33 | import time 34 | 35 | 36 | 37 | def cpu_times(): 38 | """Return a sequence of cpu times. 39 | 40 | each number in the sequence is the amount of time, measured in units 41 | of USER_HZ (1/100ths of a second on most architectures), that the system 42 | spent in each cpu mode: 43 | (user, nice, system, idle, iowait, irq, softirq, [steal], [guest]). 44 | 45 | on SMP systems, these are aggregates of all processors/cores. 46 | """ 47 | 48 | with open('/proc/stat') as f: 49 | line = f.readline() 50 | 51 | cpu_times = [int(x) for x in line.split()[1:]] 52 | 53 | return cpu_times 54 | 55 | 56 | 57 | def cpu_percents(sample_duration=1): 58 | """Return a dictionary of usage percentages and cpu modes. 59 | 60 | elapsed cpu time samples taken at 'sample_time (seconds)' apart. 61 | 62 | cpu modes: 'user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq' 63 | 64 | on SMP systems, these are aggregates of all processors/cores. 65 | """ 66 | 67 | deltas = __cpu_time_deltas(sample_duration) 68 | total = sum(deltas) 69 | percents = [100 - (100 * (float(total - x) / total)) for x in deltas] 70 | 71 | return { 72 | 'user': percents[0], 73 | 'nice': percents[1], 74 | 'system': percents[2], 75 | 'idle': percents[3], 76 | 'iowait': percents[4], 77 | 'irq': percents[5], 78 | 'softirq': percents[6], 79 | } 80 | 81 | 82 | 83 | def procs_running(): 84 | """Return number of processes in runnable state.""" 85 | 86 | return __proc_stat('procs_running') 87 | 88 | 89 | 90 | def procs_blocked(): 91 | """Return number of processes blocked waiting for I/O to complete.""" 92 | 93 | return __proc_stat('procs_blocked') 94 | 95 | 96 | 97 | def file_desc(): 98 | """Return tuple with the number of allocated file descriptors, 99 | allocated free file descriptors, and max allowed open file descriptors. 100 | 101 | The number of file descriptors in use can be calculated as follows: 102 | 103 | fd = file_desc() 104 | in_use = fd[0] - fd[1] 105 | """ 106 | 107 | with open('/proc/sys/fs/file-nr') as f: 108 | line = f.readline() 109 | 110 | fd = [int(x) for x in line.split()] 111 | 112 | return fd 113 | 114 | 115 | 116 | def load_avg(): 117 | """Return a sequence of system load averages (1min, 5min, 15min).""" 118 | 119 | with open('/proc/loadavg') as f: 120 | line = f.readline() 121 | 122 | load_avgs = [float(x) for x in line.split()[:3]] 123 | 124 | return load_avgs 125 | 126 | 127 | 128 | def cpu_info(): 129 | """Return the logical cpu info. On SMP systems, the values are 130 | representing a single processor. The key processor_count has the number 131 | of processors. 132 | """ 133 | 134 | with open('/proc/cpuinfo') as f: 135 | cpuinfo = {'processor_count': 0} 136 | for line in f: 137 | if ':' in line: 138 | fields = line.replace('\t', '').strip().split(': ') 139 | # count processores and filter out core specific items 140 | if fields[0] == 'processor': 141 | cpuinfo['processor_count'] += 1 142 | elif fields[0] != 'core id': 143 | try: 144 | cpuinfo[fields[0]] = fields[1] 145 | except IndexError: 146 | pass 147 | return cpuinfo 148 | 149 | 150 | 151 | def __cpu_time_deltas(sample_duration): 152 | """Return a sequence of cpu time deltas for a sample period. 153 | 154 | elapsed cpu time samples taken at 'sample_time (seconds)' apart. 155 | 156 | each value in the sequence is the amount of time, measured in units 157 | of USER_HZ (1/100ths of a second on most architectures), that the system 158 | spent in each cpu mode: (user, nice, system, idle, iowait, irq, softirq, [steal], [guest]). 159 | 160 | on SMP systems, these are aggregates of all processors/cores. 161 | """ 162 | 163 | with open('/proc/stat') as f1: 164 | with open('/proc/stat') as f2: 165 | line1 = f1.readline() 166 | time.sleep(sample_duration) 167 | line2 = f2.readline() 168 | 169 | deltas = [int(b) - int(a) for a, b in zip(line1.split()[1:], line2.split()[1:])] 170 | 171 | return deltas 172 | 173 | 174 | 175 | def __proc_stat(stat): 176 | with open('/proc/stat') as f: 177 | for line in f: 178 | if line.startswith(stat): 179 | return int(line.split()[1]) 180 | -------------------------------------------------------------------------------- /linux_metrics/disk_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | """ 23 | disk_stat - Python Module for Disk Stats on Linux 24 | 25 | 26 | requires: 27 | - Python 2.6+ 28 | - Linux 2.6+ 29 | 30 | """ 31 | 32 | 33 | import time 34 | from subprocess import Popen, PIPE 35 | 36 | 37 | def disk_busy(device, sample_duration=1): 38 | """Return disk busy percent.""" 39 | with open('/proc/diskstats') as f1: 40 | with open('/proc/diskstats') as f2: 41 | content1 = f1.read() 42 | time.sleep(sample_duration) 43 | content2 = f2.read() 44 | sep = '%s ' % device 45 | found = False 46 | for line in content1.splitlines(): 47 | if sep in line: 48 | found = True 49 | io_ms1 = line.strip().split(sep)[1].split()[9] 50 | break 51 | if not found: 52 | raise DiskError('device not found: %r' % device) 53 | for line in content2.splitlines(): 54 | if sep in line: 55 | io_ms2 = line.strip().split(sep)[1].split()[9] 56 | break 57 | delta = int(io_ms2) - int(io_ms1) 58 | total = sample_duration * 1000 59 | return 100 * (float(delta) / total) 60 | 61 | def disk_reads_writes(device): 62 | """Return number of disk (reads, writes).""" 63 | with open('/proc/diskstats') as f: 64 | content = f.read() 65 | sep = '%s ' % device 66 | found = False 67 | for line in content.splitlines(): 68 | if sep in line: 69 | found = True 70 | fields = line.strip().split(sep)[1].split() 71 | num_reads = int(fields[0]) 72 | num_writes = int(fields[4]) 73 | break 74 | if not found: 75 | raise DiskError('device not found: %r' % device) 76 | return (num_reads, num_writes) 77 | 78 | 79 | def disk_usage(path): 80 | """Return disk usage statistics about the given path.""" 81 | output = Popen(['df', '-k', path], stdout=PIPE).communicate()[0] 82 | try: 83 | df = output.splitlines()[2].split() 84 | device = output.splitlines()[1] 85 | (size, used, free, percent, mountpoint) = df 86 | except IndexError: 87 | df = output.splitlines()[1].split() 88 | (device, size, used, free, percent, mountpoint) = df 89 | return (device, int(size), int(used), int(free), percent, mountpoint) 90 | 91 | 92 | def disk_reads_writes_persec(device, sample_duration=1): 93 | """Return number of disk (reads, writes) per sec during the sample_duration.""" 94 | with open('/proc/diskstats') as f1: 95 | with open('/proc/diskstats') as f2: 96 | content1 = f1.read() 97 | time.sleep(sample_duration) 98 | content2 = f2.read() 99 | sep = '%s ' % device 100 | found = False 101 | for line in content1.splitlines(): 102 | if sep in line: 103 | found = True 104 | fields = line.strip().split(sep)[1].split() 105 | num_reads1 = int(fields[0]) 106 | num_writes1 = int(fields[4]) 107 | break 108 | if not found: 109 | raise DiskError('device not found: %r' % device) 110 | for line in content2.splitlines(): 111 | if sep in line: 112 | fields = line.strip().split(sep)[1].split() 113 | num_reads2 = int(fields[0]) 114 | num_writes2 = int(fields[4]) 115 | break 116 | reads_per_sec = (num_reads2 - num_reads1) / float(sample_duration) 117 | writes_per_sec = (num_writes2 - num_writes1) / float(sample_duration) 118 | return (reads_per_sec, writes_per_sec) 119 | 120 | 121 | 122 | class DiskError(Exception): 123 | pass 124 | -------------------------------------------------------------------------------- /linux_metrics/mem_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | """ 23 | mem_stat - Python Module for Memory Stats on Linux 24 | 25 | requires: 26 | - Python 2.6+ 27 | - Linux 2.6+ 28 | 29 | """ 30 | 31 | 32 | 33 | def mem_stats(): 34 | with open('/proc/meminfo') as f: 35 | for line in f: 36 | if line.startswith('MemTotal:'): 37 | mem_total = int(line.split()[1]) * 1024 38 | elif line.startswith('Active: '): 39 | mem_active = int(line.split()[1]) * 1024 40 | elif line.startswith('MemFree:'): 41 | mem_free = (int(line.split()[1]) * 1024) 42 | elif line.startswith('Cached:'): 43 | mem_cached = (int(line.split()[1]) * 1024) 44 | elif line.startswith('SwapTotal: '): 45 | swap_total = (int(line.split()[1]) * 1024) 46 | elif line.startswith('SwapFree: '): 47 | swap_free = (int(line.split()[1]) * 1024) 48 | return (mem_active, mem_total, mem_cached, mem_free, swap_total, swap_free) 49 | -------------------------------------------------------------------------------- /linux_metrics/net_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | """ 23 | net_stat - Python Module for Network Stats on Linux 24 | 25 | 26 | requires: 27 | - Python 2.6+ 28 | - Linux 2.6+ 29 | 30 | """ 31 | 32 | 33 | 34 | import re 35 | import subprocess 36 | 37 | 38 | 39 | def rx_tx_bytes(interface): # by reading /proc 40 | with open('/proc/net/dev') as f: 41 | for line in f.readlines(): 42 | if interface in line: 43 | data = line.split('%s:' % interface)[1].split() 44 | rx_bytes, tx_bytes = (int(data[0]), int(data[8])) 45 | return (rx_bytes, tx_bytes) 46 | raise NetError('interface not found: %r' % interface) 47 | 48 | 49 | def rx_tx_bits(interface): # by reading /proc 50 | rx_bytes, tx_bytes = rx_tx_bytes(interface) 51 | rx_bits = rx_bytes * 8 52 | tx_bits = tx_bytes * 8 53 | return (rx_bits, tx_bits) 54 | 55 | def rx_tx_dump(interface): #get all info 56 | with open('/proc/net/dev') as f: 57 | for line in f.readlines(): 58 | if interface in line: 59 | data = line.split('%s:' % interface)[1].split() 60 | rx, tx = [int(x) for x in data[0:8]], [int(x) for x in data[8:]] 61 | return (rx, tx) 62 | 63 | def net_stats_ifconfig(interface): # by parsing ifconfig output 64 | output = subprocess.Popen(['ifconfig', interface], stdout=subprocess.PIPE).communicate()[0] 65 | rx_bytes = int(re.findall('RX bytes:([0-9]*) ', output)[0]) 66 | tx_bytes = int(re.findall('TX bytes:([0-9]*) ', output)[0]) 67 | return (rx_bytes, tx_bytes) 68 | 69 | 70 | class NetError(Exception): 71 | pass 72 | 73 | 74 | -------------------------------------------------------------------------------- /linux_metrics/test_cpu_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | import unittest 23 | 24 | from . import cpu_stat 25 | 26 | 27 | class TestCPUStats(unittest.TestCase): 28 | 29 | def setUp(self): 30 | self.sample_duration = .1 # secs 31 | 32 | def test_cpu_info(self): 33 | values = cpu_stat.cpu_info() 34 | self.assertTrue(len(values) > 0, values) 35 | 36 | def test_cpu_percent_idle(self): 37 | value = cpu_stat.cpu_percents(self.sample_duration)['idle'] 38 | self.assertTrue(0.0 <= value <= 100.0, value) 39 | 40 | def test_cpu_percent_iowait(self): 41 | value = cpu_stat.cpu_percents(self.sample_duration)['iowait'] 42 | self.assertTrue(0.0 <= value <= 100.0, value) 43 | 44 | def test_cpu_percent_irq(self): 45 | value = cpu_stat.cpu_percents(self.sample_duration)['irq'] 46 | self.assertTrue(0.0 <= value <= 100.0, value) 47 | 48 | def test_cpu_percent_nice(self): 49 | value = cpu_stat.cpu_percents(self.sample_duration)['nice'] 50 | self.assertTrue(0.0 <= value <= 100.0, value) 51 | 52 | def test_cpu_percent_softirq(self): 53 | value = cpu_stat.cpu_percents(self.sample_duration)['softirq'] 54 | self.assertTrue(0.0 <= value <= 100.0, value) 55 | 56 | def test_cpu_percent_system(self): 57 | value = cpu_stat.cpu_percents(self.sample_duration)['system'] 58 | self.assertTrue(0.0 <= value <= 100.0, value) 59 | 60 | def test_cpu_percent_user(self): 61 | value = cpu_stat.cpu_percents(self.sample_duration)['user'] 62 | self.assertTrue(0.0 <= value <= 100.0, value) 63 | 64 | def test_cpu_percents(self): 65 | values = cpu_stat.cpu_percents(self.sample_duration) 66 | self.assertTrue(len(values) == 7, values) 67 | 68 | def test_cpu_times(self): 69 | values = cpu_stat.cpu_times() 70 | self.assertTrue(len(values) >= 7, values) 71 | 72 | def test_procs_blocked(self): 73 | value = cpu_stat.procs_blocked() 74 | self.assertTrue(value >= 0, value) 75 | 76 | def test_procs_running(self): 77 | value = cpu_stat.procs_running() 78 | self.assertTrue(value >= 0, value) 79 | 80 | def test_load_avg(self): 81 | values = cpu_stat.load_avg() 82 | self.assertTrue(len(values) == 3, values) 83 | 84 | 85 | 86 | if __name__ == '__main__': 87 | test_suite = unittest.TestLoader().loadTestsFromTestCase(TestCPUStats) 88 | unittest.TextTestRunner(verbosity=2).run(test_suite) 89 | -------------------------------------------------------------------------------- /linux_metrics/test_disk_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | from . import disk_stat 23 | 24 | import unittest 25 | 26 | 27 | # configuration 28 | DISK_DEVICE = 'sda1' 29 | 30 | 31 | class TestDiskStats(unittest.TestCase): 32 | 33 | def setUp(self): 34 | self.device = DISK_DEVICE 35 | self.sample_duration = .1 # secs 36 | 37 | def test_disk_busy(self): 38 | value = disk_stat.disk_busy( 39 | self.device, 40 | self.sample_duration 41 | ) 42 | self.assertTrue(0.0 <= value <= 100.0, value) 43 | 44 | def test_disk_reads(self): 45 | value, _ = disk_stat.disk_reads_writes( 46 | self.device 47 | ) 48 | self.assertTrue(value >= 0, value) 49 | 50 | def test_disk_reads_persec(self): 51 | value, _ = disk_stat.disk_reads_writes_persec( 52 | self.device, 53 | self.sample_duration 54 | ) 55 | self.assertTrue(value >= 0.0, value) 56 | 57 | def test_disk_writes(self): 58 | _, value = disk_stat.disk_reads_writes( 59 | self.device 60 | ) 61 | self.assertTrue(value >= 0, value) 62 | 63 | def test_disk_writes_persec(self): 64 | _, value = disk_stat.disk_reads_writes_persec( 65 | self.device, 66 | self.sample_duration 67 | ) 68 | self.assertTrue(value >= 0.0, value) 69 | 70 | def test_invalid_disk_interface(self): 71 | self.assertRaises( 72 | disk_stat.DiskError, 73 | disk_stat.disk_busy, 74 | 'invalid_device', 75 | 0 76 | ) 77 | 78 | 79 | 80 | if __name__ == '__main__': 81 | test_suite = unittest.TestLoader().loadTestsFromTestCase(TestDiskStats) 82 | unittest.TextTestRunner(verbosity=2).run(test_suite) 83 | -------------------------------------------------------------------------------- /linux_metrics/test_mem_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | from . import mem_stat 23 | 24 | import unittest 25 | 26 | 27 | class TestMemoryStats(unittest.TestCase): 28 | 29 | def setUp(self): 30 | (self.mem_active, 31 | self.mem_total, 32 | self.mem_cached, 33 | self.mem_free, 34 | self.swap_total, 35 | self.swap_free) = mem_stat.mem_stats() 36 | 37 | def test_mem_active(self): 38 | self.assertTrue(self.mem_active > 0) 39 | 40 | def test_mem_total(self): 41 | self.assertTrue(self.mem_total > 0) 42 | 43 | def test_mem_cached(self): 44 | self.assertTrue(self.mem_cached > 0) 45 | 46 | def test_mem_free(self): 47 | self.assertTrue(self.mem_free > 0) 48 | 49 | def test_swap_total(self): 50 | self.assertTrue(self.swap_total > 0) 51 | 52 | def test_swap_free(self): 53 | self.assertTrue(self.swap_free > 0) 54 | 55 | 56 | if __name__ == '__main__': 57 | test_suite = unittest.TestLoader().loadTestsFromTestCase(TestMemoryStats) 58 | unittest.TextTestRunner(verbosity=2).run(test_suite) 59 | -------------------------------------------------------------------------------- /linux_metrics/test_net_stat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2010-2013 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | from . import net_stat 23 | 24 | import unittest 25 | 26 | 27 | # configuration 28 | NETWORK_INTERFACE = 'enp4s0' 29 | 30 | 31 | class TestNetworkStats(unittest.TestCase): 32 | 33 | def setUp(self): 34 | self.interface = NETWORK_INTERFACE 35 | 36 | def test_rx_tx_bytes(self): 37 | rx, tx = net_stat.rx_tx_bytes( 38 | self.interface 39 | ) 40 | self.assertTrue(rx >= 0, rx) 41 | self.assertTrue(tx >= 0, tx) 42 | 43 | def test_rx_tx_bits(self): 44 | rx, tx = net_stat.rx_tx_bits( 45 | self.interface 46 | ) 47 | self.assertTrue(rx >= 0, rx) 48 | self.assertTrue(tx >= 0, tx) 49 | 50 | def test_rx_tx_dump(self): 51 | rx, tx = net_stat.rx_tx_bits( 52 | self.interface 53 | ) 54 | rx, tx = map(int, (rx, tx)) 55 | self.assertTrue(rx >= 0, rx) 56 | self.assertTrue(tx >= 0, tx) 57 | 58 | def test_invalid_net_interface(self): 59 | self.assertRaises( 60 | net_stat.NetError, 61 | net_stat.rx_tx_bytes, 62 | 'eth-BAD' 63 | ) 64 | 65 | 66 | 67 | if __name__ == '__main__': 68 | test_suite = unittest.TestLoader().loadTestsFromTestCase(TestNetworkStats) 69 | unittest.TextTestRunner(verbosity=2).run(test_suite) 70 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Copyright (c) 2011-2012 Corey Goldberg (http://goldb.org) 4 | # 5 | # This file is part of linux-metrics 6 | # 7 | # License :: OSI Approved :: MIT License: 8 | # http://www.opensource.org/licenses/mit-license 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy 11 | # of this software and associated documentation files (the "Software"), to deal 12 | # in the Software without restriction, including without limitation the rights 13 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | # copies of the Software, and to permit persons to whom the Software is 15 | # furnished to do so, subject to the following conditions: 16 | # 17 | # The above copyright notice and this permission notice shall be included in 18 | # all copies or substantial portions of the Software. 19 | # 20 | 21 | 22 | """ setup/install script for linux-metrics """ 23 | 24 | 25 | 26 | from distutils.core import setup 27 | 28 | from linux_metrics import __version__ 29 | 30 | with open('README.rst') as f: 31 | LONG_DESCRIPTION = f.read() 32 | 33 | 34 | setup( 35 | name = 'linux-metrics', 36 | version = __version__, 37 | packages = ['linux_metrics'], 38 | 39 | author = 'Corey Goldberg', 40 | author_email = 'corey@goldb.org', 41 | description = 'linux-metrics - System Metrics/Stats Library for Linux', 42 | long_description = LONG_DESCRIPTION, 43 | url = 'https://github.com/cgoldberg/linux-metrics', 44 | download_url = 'http://pypi.python.org/pypi/linux-metrics', 45 | platforms = ['Linux'], 46 | license = 'MIT', 47 | classifiers = [ 48 | 'Intended Audience :: Developers', 49 | 'Intended Audience :: System Administrators', 50 | 'License :: OSI Approved :: MIT License', 51 | 'Operating System :: POSIX :: Linux', 52 | 'Programming Language :: Python :: 2.7', 53 | 'Programming Language :: Python :: 3.4', 54 | 'Programming Language :: Python :: 3.5', 55 | 'Programming Language :: Python :: 3.6', 56 | 'Topic :: Software Development :: Libraries :: Python Modules', 57 | 'Topic :: System :: Monitoring', 58 | ] 59 | ) 60 | 61 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | 2 | [tox] 3 | envlist = py27, py34, py35, py36 4 | 5 | [testenv] 6 | commands = {envpython} -m unittest discover 7 | --------------------------------------------------------------------------------