monitor.parsers

Metric parsers — convert raw command output (CommandStatus.output) to numeric values.

Built-in parsers cover the most common Linux host metrics. To add support for a custom command, subclass MetricParser and override parse():

class MyAppParser(MetricParser):
    chart   = 'Connections'
    unit    = ''
    command = 'ss -s | grep estab'

    def parse(self, output: str) -> float | None:
        # output is the raw stdout/stderr string from the command
        for line in output.splitlines():
            if 'estab' in line.lower():
                return float(line.split()[0])
        return None

To associate custom parsers with a specific host, call register_host_parsers() from an init module listed in .otto/settings.toml:

from otto.monitor.parsers import DEFAULT_PARSERS, TopCpuParser, register_host_parsers
from my_repo.parsers import NvidiaGpuParser

register_host_parsers('gpu-01', {
    **DEFAULT_PARSERS,
    'nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits': NvidiaGpuParser(),
})

Hosts with no registered parsers fall back to DEFAULT_PARSERS.

class otto.monitor.parsers.MetricDataPoint(value: float, meta: dict[str, Any] | None = None)

Bases: NamedTuple

A single data point returned by MetricParser.parse().

value : --is-rst--:py:class:`float`

The numeric measurement for this tick.

meta : --is-rst--:py:class:`dict`\ \[:py:class:`str`, :py:data:`~typing.Any`] | :py:obj:`None`

Optional supplementary data forwarded to the dashboard as hover text (e.g. {'used': '4.2 GB', 'total': '16 GB'} for memory).

otto.monitor.parsers.human_readable(value, precision=1)

Format a byte count as a human-readable string using binary prefixes (df -h style).

Parameters:
  • value – The value in bytes.

  • precision – Maximum number of decimal places in the output (trailing zeros are stripped).

Return type:

str

>>> human_readable(0)
'0 B'
>>> human_readable(1024)
'1 K'
>>> human_readable(1536)
'1.5 K'
>>> human_readable(1073741824)
'1 G'
class otto.monitor.parsers.MetricParser

Bases: ABC

Base class for metric parsers.

Subclass this and set the class attributes, then override parse() to extract a single numeric value from the raw command output string.

y_title : --is-rst--:py:class:`str`

Y-axis title shown to the left of the chart, e.g. ‘CPU’.

unit : --is-rst--:py:class:`str`

Unit suffix for chart annotations, e.g. ‘%’, ‘MB’, ‘GB’. Empty string for dimensionless values.

command : --is-rst--:py:class:`str`

The exact shell command whose output this parser handles.

tab : --is-rst--:py:class:`str` = 'metrics'

Dashboard tab id this metric belongs to, e.g. ‘cpu’. Defaults to ‘metrics’.

tab_label : --is-rst--:py:class:`str` = 'Metrics'

Human-readable label for the tab button, e.g. ‘CPU’. Defaults to ‘Metrics’.

chart : --is-rst--:py:class:`str`

Chart group id. Series with the same chart value share one Plotly chart. Single-series parsers set this to their series label; multi-series parsers set it to a shared group name (e.g. 'Load').

core_count : --is-rst--:py:class:`int` = 1

Number of CPU cores on the target host. Set per-host by MetricCollector before the first tick. Most parsers ignore this; TopCpuParser uses it to normalize per-process CPU%.

abstract parse(output)

Convert raw command output into one or more labelled data points.

Parameters:

output – The full stdout+stderr string returned by the remote command.

Return type:

dict[str, MetricDataPoint]

Returns:

A dict mapping series label → MetricDataPoint for each data point produced this tick. Return an empty dict if parsing fails. Single-series parsers return {self.chart: MetricDataPoint(value)}. Multi-series parsers may return multiple entries in the dict.

class otto.monitor.parsers.TopCpuParser(top_n=5, delay=0.5)

Bases: MetricParser

Parse overall and per-process CPU usage from top -d{delay} -bn2 output.

Runs two top iterations separated by delay seconds so that per-process %CPU values reflect activity during that interval (the first iteration has no baseline and is discarded). Overall CPU usage and per-process traces share one chart.

Parameters:
  • top_n – Maximum number of processes to include per collection tick.

  • delay – Seconds between top iterations (controls accuracy vs latency trade-off).

y_title : --is-rst--:py:class:`str` = 'Usage %'

Y-axis title shown to the left of the chart, e.g. ‘CPU’.

unit : --is-rst--:py:class:`str` = '%'

Unit suffix for chart annotations, e.g. ‘%’, ‘MB’, ‘GB’. Empty string for dimensionless values.

tab : --is-rst--:py:class:`str` = 'cpu'

Dashboard tab id this metric belongs to, e.g. ‘cpu’. Defaults to ‘metrics’.

tab_label : --is-rst--:py:class:`str` = 'CPU'

Human-readable label for the tab button, e.g. ‘CPU’. Defaults to ‘Metrics’.

chart : --is-rst--:py:class:`str` = 'CPU'

Chart group id. Series with the same chart value share one Plotly chart. Single-series parsers set this to their series label; multi-series parsers set it to a shared group name (e.g. 'Load').

property command : str
parse(output)

Convert raw command output into one or more labelled data points.

Parameters:

output – The full stdout+stderr string returned by the remote command.

Return type:

dict[str, MetricDataPoint]

Returns:

A dict mapping series label → MetricDataPoint for each data point produced this tick. Return an empty dict if parsing fails. Single-series parsers return {self.chart: MetricDataPoint(value)}. Multi-series parsers may return multiple entries in the dict.

class otto.monitor.parsers.MemParser

Bases: MetricParser

Parse memory usage % from free -b output.

Reads the ‘Mem:’ line and computes used/total as a percentage.

y_title : --is-rst--:py:class:`str` = 'Memory'

Y-axis title shown to the left of the chart, e.g. ‘CPU’.

unit : --is-rst--:py:class:`str` = '%'

Unit suffix for chart annotations, e.g. ‘%’, ‘MB’, ‘GB’. Empty string for dimensionless values.

command : --is-rst--:py:class:`str` = 'free -b'

The exact shell command whose output this parser handles.

tab : --is-rst--:py:class:`str` = 'memory'

Dashboard tab id this metric belongs to, e.g. ‘cpu’. Defaults to ‘metrics’.

tab_label : --is-rst--:py:class:`str` = 'Memory'

Human-readable label for the tab button, e.g. ‘CPU’. Defaults to ‘Metrics’.

chart : --is-rst--:py:class:`str` = 'Memory Usage'

Chart group id. Series with the same chart value share one Plotly chart. Single-series parsers set this to their series label; multi-series parsers set it to a shared group name (e.g. 'Load').

parse(output)

Convert raw command output into one or more labelled data points.

Parameters:

output – The full stdout+stderr string returned by the remote command.

Return type:

dict[str, MetricDataPoint]

Returns:

A dict mapping series label → MetricDataPoint for each data point produced this tick. Return an empty dict if parsing fails. Single-series parsers return {self.chart: MetricDataPoint(value)}. Multi-series parsers may return multiple entries in the dict.

class otto.monitor.parsers.DiskParser

Bases: MetricParser

Parse root filesystem usage % from df -h / output.

Reads the data row (second line) and extracts the Use% column. parse_meta() returns the already human-readable Size/Used strings from df -h.

y_title : --is-rst--:py:class:`str` = 'Disk'

Y-axis title shown to the left of the chart, e.g. ‘CPU’.

unit : --is-rst--:py:class:`str` = '%'

Unit suffix for chart annotations, e.g. ‘%’, ‘MB’, ‘GB’. Empty string for dimensionless values.

command : --is-rst--:py:class:`str` = 'df -h'

The exact shell command whose output this parser handles.

tab : --is-rst--:py:class:`str` = 'disk'

Dashboard tab id this metric belongs to, e.g. ‘cpu’. Defaults to ‘metrics’.

tab_label : --is-rst--:py:class:`str` = 'Disk'

Human-readable label for the tab button, e.g. ‘CPU’. Defaults to ‘Metrics’.

chart : --is-rst--:py:class:`str` = 'Disk Usage'

Chart group id. Series with the same chart value share one Plotly chart. Single-series parsers set this to their series label; multi-series parsers set it to a shared group name (e.g. 'Load').

parse(output)

Convert raw command output into one or more labelled data points.

Parameters:

output – The full stdout+stderr string returned by the remote command.

Return type:

dict[str, MetricDataPoint]

Returns:

A dict mapping series label → MetricDataPoint for each data point produced this tick. Return an empty dict if parsing fails. Single-series parsers return {self.chart: MetricDataPoint(value)}. Multi-series parsers may return multiple entries in the dict.

class otto.monitor.parsers.LoadParser

Bases: MetricParser

Parse all three load averages from cat /proc/loadavg.

Output format: ‘0.52 0.58 0.59 1/432 12345’ Returns 1-minute, 5-minute, and 15-minute load averages as separate series.

y_title : --is-rst--:py:class:`str` = 'Load'

Y-axis title shown to the left of the chart, e.g. ‘CPU’.

unit : --is-rst--:py:class:`str` = ''

Unit suffix for chart annotations, e.g. ‘%’, ‘MB’, ‘GB’. Empty string for dimensionless values.

command : --is-rst--:py:class:`str` = 'cat /proc/loadavg'

The exact shell command whose output this parser handles.

tab : --is-rst--:py:class:`str` = 'cpu'

Dashboard tab id this metric belongs to, e.g. ‘cpu’. Defaults to ‘metrics’.

tab_label : --is-rst--:py:class:`str` = 'CPU'

Human-readable label for the tab button, e.g. ‘CPU’. Defaults to ‘Metrics’.

chart : --is-rst--:py:class:`str` = 'Load'

Chart group id. Series with the same chart value share one Plotly chart. Single-series parsers set this to their series label; multi-series parsers set it to a shared group name (e.g. 'Load').

parse(output)

Convert raw command output into one or more labelled data points.

Parameters:

output – The full stdout+stderr string returned by the remote command.

Return type:

dict[str, MetricDataPoint]

Returns:

A dict mapping series label → MetricDataPoint for each data point produced this tick. Return an empty dict if parsing fails. Single-series parsers return {self.chart: MetricDataPoint(value)}. Multi-series parsers may return multiple entries in the dict.

otto.monitor.parsers.register_host_parsers(host_id, parsers)

Associate a custom parser dict with a host ID.

Call this from an init module (listed in .otto/settings.toml) to override or extend the default parsers for a specific host. The host_id string must match the ID used to look up the host (i.e. the key in lab.hosts).

Hosts with no registered parsers automatically fall back to DEFAULT_PARSERS.

Return type:

None

otto.monitor.parsers.get_host_parsers(host_id)

Return the parser dict registered for host_id, or a copy of DEFAULT_PARSERS.

Return type:

dict[str, MetricParser]