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 terminal, browser or native, runs the respective frontend.

When config, runs command to interact with configuration.

When password, runs command to set permon’s password.

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 edit, opens your preferred editor to edit the config.json file.

When show, prints your current configuriation file and directory.

When reset, resets configuration to the defaults.

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, type nvidia-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.