User documentation¶
What is Permon?¶
Permon is a tool to display live line charts in a clear, uncluttered way. Permon comes prepackaged with a lot of useful stats for monitoring the performance of your PC. It is developed with a focus on only showing you things you care about, not everything you can monitor in your system.
Permon is developed in Python 3. There is a good chance you already have Python on your system. If
not, install it (recommended: Miniconda. Run pip
install permon
in your preferred command line to install permon. Permon can then be started from the command line.
Synopsis¶
usage: permon [-h] [--version] {terminal,native,browser,config,password} ...
Positional Arguments¶
subcommand | Possible choices: terminal, native, browser, config, password the subcommand to launch. When When When |
Named Arguments¶
--version | show permon’s version and exit Default: False |
Sub-commands:¶
terminal¶
Starts permon’s terminal frontend.
permon terminal [-h] [--fps FPS] [--verbose] [--buffer-size BUFFER_SIZE]
[stats [stats ...]]
Positional Arguments¶
stats | which stats to display If none are given, take those from the config file (core.cpu_usage, core.ram_usage, core.read_speed, core.write_speed, core.vram_usage) Default: [‘core.cpu_usage’, ‘core.ram_usage’, ‘core.read_speed’, ‘core.write_speed’, ‘core.vram_usage’] |
Named Arguments¶
--fps | the frames per second the display moves with |
--verbose | whether to enable verbose logging Default: True |
--buffer-size | the number of points displayed on the screen at any time |
native¶
Starts permon’s native frontend.
permon native [-h] [--fps FPS] [--verbose] [--buffer-size BUFFER_SIZE]
[stats [stats ...]]
Positional Arguments¶
stats | which stats to display If none are given, take those from the config file (core.cpu_usage, core.ram_usage, core.read_speed, core.write_speed, core.vram_usage) Default: [‘core.cpu_usage’, ‘core.ram_usage’, ‘core.read_speed’, ‘core.write_speed’, ‘core.vram_usage’] |
Named Arguments¶
--fps | the frames per second the display moves with |
--verbose | whether to enable verbose logging Default: True |
--buffer-size | the number of points displayed on the screen at any time |
browser¶
Starts permon’s browser frontend.
permon browser [-h] [--port PORT] [--ip IP] [--no-browser]
[--certfile CERTFILE] [--keyfile KEYFILE] [--fps FPS]
[--verbose] [--buffer-size BUFFER_SIZE]
[stats [stats ...]]
Positional Arguments¶
stats | which stats to display If none are given, take those from the config file (core.cpu_usage, core.ram_usage, core.read_speed, core.write_speed, core.vram_usage) Default: [‘core.cpu_usage’, ‘core.ram_usage’, ‘core.read_speed’, ‘core.write_speed’, ‘core.vram_usage’] |
Named Arguments¶
--port | the port permon will listen on Default: 1234 |
--ip | the IP address permon will listen on Default: “localhost” |
--no-browser | don’t open permon in a browser after startup Default: False |
--certfile | the path to an SSL/TLS certificate file |
--keyfile | the path to a private key file for usage with SSL/TLS |
--fps | the frames per second the display moves with |
--verbose | whether to enable verbose logging Default: True |
--buffer-size | the number of points displayed on the screen at any time |
config¶
Command to interact with the configuration of permon. Default configuration:
{
"stats": [
"core.cpu_usage",
"core.ram_usage",
"core.read_speed",
"core.write_speed"
],
"colors": [
"#ed5565",
"#ffce54",
"#48cfad",
"#sd9cec",
"#ec87c0",
"#fc6e51",
"#a0d468",
"#4fc1e9",
"#ac92ec"
],
"verbose": true,
"password": null
}
Stats can either be specified by their tag name like in the default config or
by a dictionary with keys tag
and settings
where settings
is a
dictionary consisting of keys and values specifying the value of settings
for the respective stat e. g.
...
"stats": [
{
"tag": "jupyter.ram_usage",
"settings": {
"connection info": "",
"query interval [s]": 1
}
}
]
...
permon config [-h] {edit,show,reset}
Positional Arguments¶
command | Possible choices: edit, show, reset Which command to run. When When When |
password¶
Open dialog to set permon’s password. The password is currently only used for authentication in the browser frontend.
permon password [-h]
Stats¶
Permon comes prepackaged with some useful stats to monitor the performance of your PC. You can also add custom stats to Permon. See Extending permon with custom stats to see how to do that. The following stats are always part of Permon:
-
class
permon.backend.stats.core.
CPUStat
¶ tag:
core.cpu_usage
settings: none
Tracks the CPU usage of the user. Also returns the top contributors to the CPU usage.
-
class
permon.backend.stats.core.
RAMStat
¶ tag:
core.ram_usage
settings: none
Tracks the RAM usage of the user. Also returns the top contributors to the RAM usage.
-
class
permon.backend.stats.core.
GPUStat
¶ tag:
core.vram_usage
settings: none
Tracks the current vRAM usage of the user. Currently only works for NVIDIA GPUs and
nvidia-smi
must be installed. To check if it is installed, typenvidia-smi
in your command line and see if the command was found.
-
class
permon.backend.stats.core.
ReadStat
¶ tag:
core.read_speed
settings: none
Tracks the disk read speed of the user.
-
class
permon.backend.stats.core.
WriteStat
¶ tag:
core.write_speed
settings: none
Tracks the disk write speed of the user.
-
class
permon.backend.stats.core.
CPUTempStat
¶ tag:
core.cpu_temp
settings: none
Tracks the CPU temperature of the user.
-
class
permon.backend.stats.jupyter.
JupyterRAMUsage
¶ tag:
jupyter.ram_usage
settings:
{ "connection info": "", "query interval [s]": 1 }
Tracks the RAM usage of all variables in a user-specified jupyter notebook. If no connection info is given in the settings, take the kernel with the latest start date.
connection info
must be a string containing the info displayed when running%connect_info
in a jupyter notebook (you can directly copy-paste it).query interval [s]
specifies how often the thread running in the jupyter notebook should read the variables. The lower this is, the higher the resolution of the stat but it might start affecting the speed of your notebook when too low.Note that RAM tracked in this way is not equal to the actual RAM the OS needs because some further optimization is done by e. g. numpy to reduce the OS memory usage.
Extending permon with custom stats¶
Permon can be extended by adding custom stats. Custom stats have to be put in the stats
subdirectory of the user
config directory. You can find your user config directory by executing permon config show
and looking for Config directory.
Hint
On Linux, execute cd `permon config show | grep -o "\S*/permon$"`
to directly change your directory to permon’s config directory.
In the config directory, make a subdirectory stats
and create a file called <name>.permon.py
in the subdirectory where <name>
is the name for
your suite of stats e. g. custom.permon.py
.
The tag of your stat will then be <name>.<base_tag>
where <base_tag>
is the static base_tag
attribute
of your stat class.
You can now start creating stats in this file. They will automatically be discovered by permon. A simple custom stat could look like this:
import math
from permon.backend import Stat
class SineStat(Stat):
name = 'Sine'
base_tag = 'sine'
def __init__(self, fps):
self.t = 0
super(SineStat, self).__init__(fps)
def get_stat(self):
# get_stat is called once per frame to fetch the latest value for the stat
self.t += 1 / self.fps
return math.sin(self.t)
@property
def maximum(self):
# sets the maximum value for the stat
# if the stat has no fixed maximum, make it return None
return 1
@property
def minimum(self):
# sets the minimum value for the stat
# if the stat has no fixed minimum, make it return None
return -1
All stats must inherit from the permon.backend.Stat
base class. Also, the parent constructor should be called at the end of __init__
to make sure get_stat
can run successfully (the parent constructor needs to call it once to check whether the stat has a contributor breakdown).
View your first custom stat by running permon native custom.sine
(or, of course, use another frontend).
Adding settings to a stat¶
Stats can have settings to conventienly change some aspects of the stat. Extending the example from above:
import math
from permon.backend import Stat
class SineStat(Stat):
name = 'Sine'
base_tag = 'sine'
default_settings = {
'speed': 1.
}
def __init__(self, fps):
self.t = 0
super(SineStat, self).__init__(fps)
def get_stat(self):
self.t += 1 / self.fps * self.settings['speed']
return math.sin(self.t)
@property
def maximum(self):
return 1
@property
def minimum(self):
return -1
Note that default_settings
only stores the default settings. In the calculation, self.settings
is used because it stores the settings that
are entered in the UI.
Every setting must have a default value. Every value should be a basic python data type (string, float, integer, …) because
permon will automatically cast the user-entered string to the type specified in the default_settings
.
If you need more advanced data types like JSON, make the default value a string and manually convert it to the needed data type afterwards.
Making a stat conditionally available¶
Some stats are not always available, like permon.backend.stats.JupyterRAMUsage()
which needs nvidia-smi
installed.
To add some logic to check whether your stat is available or not, implement the Stat.check_availability()
method.
This method must raise a permon.exceptions.StatNotAvailableError()
if the stat is not available. cls.settings
can also be used
in Stat.check_availability()
to e. g. disallow some settings. Further expanding the example from above:
import math
from permon.backend import Stat
from permon import exceptions
class SineStat(Stat):
name = 'Sine'
base_tag = 'sine'
default_settings = {
'speed': 1.
}
@classmethod
def check_availability(cls):
if cls.settings['speed'] <= 0:
raise exceptions.StatNotAvailableError(
'Speed must be greater than zero.')
def __init__(self, fps):
self.t = 0
super(SineStat, self).__init__(fps)
def get_stat(self):
self.t += 1 / self.fps * self.settings['speed']
return math.sin(self.t)
@property
def maximum(self):
return 1
@property
def minimum(self):
return -1
Adding a contributor breakdown to a stat¶
Stats can have a contributor breakdown. A contributor breakdown shows what contributes to the stat, e. g. how much of the CPU different
processes need for permon.backend.stats.CPUUsage()
.
import math
from permon.backend import Stat
class SineModulationStat(Stat):
name = 'Sine Modulation'
base_tag = 'sine_modulation'
def __init__(self, fps):
self.t = 0
super(SineModulationStat, self).__init__(fps)
def get_stat(self):
self.t += 1 / self.fps
sine1 = 1 + math.sin(self.t)
sine2 = 1 + math.sin(self.t * 10)
return sine1 + sine2, [
('sine1', sine1),
('sine2', sine2)
]
@property
def maximum(self):
# both sines have a maximum of 2 because they are offset by +1
return 4
@property
def minimum(self):
return 0
Stats with a contributor breakdown must return the stat value and a list containing tuples of (name, value)
for every contributor (sine1 and sine2 in the above example).
Permon will automatically handle the rest.
Warning
The contributor breakdown of stats with a minimum of less than zero might have unexpected behaviour because the range of contributors is not well-defined in that case.
Negative contributors are also not handled well at the moment.
That already covers the full functionality of any stat. To see how the prepackaged stats are implemented, see the source on github.