Metric_info does not render nanoseconds

CMK version:
2.1.0
OS version:
ubuntu 20.04

I am using the checkmk built_in metrics_info to render time values in seconds and it correctly displays a time series graph in my custom plugin.
However, values smaller than 500 ns are rendered to 0 sec. The smallest value it displays in the graph is 1 microsecond.

I noticed in the built in NTP plugin checkmk renders nanosecond values. Does checkmk uses there a different method to render the values?

Here is an example of my my_metric.py file in

local/share/check_mk/web/plugins/metrics/

#!/usr/bin/env python3

from cmk.gui.i18n import _
from cmk.gui.plugins.metrics import (
    metric_info,
    graph_info,
)

metric_info["master_offset"] = {
    "title": _("Master Offset"),
    "unit": "s",
    "color": "#ff8020",
}

It does not seem so. The NTP Time check uses the metric names “offset” and “jitter” which also use “s” as unit in their metric_info.

As the value is stored as a float with the base unit seconds it could be that the precision of the RRD storing it is not high enough. But that’s just a guess.

Checking the render.py file, there are even smaller time units defined.
I am using the render.timespan() function.

/omd/sites/dev/lib/python3/cmk/base/api/agent_based/render.py


"""Render functions for check development
These are meant to be exposed in the API
"""

import math
import time
from typing import Iterable, Optional, Tuple

_DATE_FORMAT = "%b %d %Y"

_TIME_UNITS = [
    ("years", 31536000),
    ("days", 86400),
    ("hours", 3600),
    ("minutes", 60),
    ("seconds", 1),
    ("milliseconds", 1e-3),
    ("microseconds", 1e-6),
    ("nanoseconds", 1e-9),
    ("picoseconds", 1e-12),
    ("femtoseconds", 1e-15),
    # and while we're at it:
    ("attoseconds", 1e-18),
    ("zeptoseconds", 1e-21),
    ("yoctoseconds", 1e-24),
]



def _gen_timespan_chunks(seconds: float, nchunks: int) -> Iterable[str]:
    if seconds < 0:
        raise ValueError("Cannot render negative timespan")

    try:
        start = next(i for i, (_, v) in enumerate(_TIME_UNITS) if seconds >= v)
    except StopIteration:
        start = len(_TIME_UNITS) - 1

    for unit, scale in _TIME_UNITS[start : start + nchunks]:
        last_chunk = unit.endswith("seconds")
        value = (round if last_chunk else int)(seconds / scale)  # type: ignore[operator]
        yield "%.0f %s" % (value, unit if value != 1 else unit[:-1])
        if last_chunk:
            break
        seconds %= scale


def timespan(seconds: float) -> str:
    """Render a time span in seconds

    Example:
        >>> timespan(1606721)
        '18 days 14 hours'
        >>> timespan(0.0001)
        '100 microseconds'

    """
    ts = " ".join(_gen_timespan_chunks(float(seconds), nchunks=2))
    if ts == "0 %s" % _TIME_UNITS[-1][0]:
        ts = "0 seconds"
    return ts



Ok , the render.timespan() function seems to work as expected.

>>> import cmk.base.api.agent_based.render as render
>>> render.timespan(1e-9)
'1 nanosecond'
>>> render.timespan(1e-6)
'1 microsecond'
>>> render.timespan(1e-12)
'1 picosecond'
>>> render.timespan(1e-24)
'1 yoctosecond'
>>> 

Dear Developers,
I also experience the same, It doesn’t seem to be a render issue, but instead the result of this conversion:

2.1.0: cmk/base/agent_based/checking/_submit_to_core.py

def _serialize_value(x: Optional[float]) -> str:
    return "" if x is None else ("%.6f" % x).rstrip("0").rstrip(".")

Older 1.5.0: cmk_base/checking.py

def _convert_perf_value(x):
    if x is None:
        return ""
    elif isinstance(x, six.string_types):
        return x
    elif isinstance(x, float):
        return ("%.6f" % x).rstrip("0").rstrip(".")
    return str(x)

All CheckMK versions I’ve checked so far contains this conversion before submitting data to core. Most likely it might have been a design decision in the past. Does it still make sense to keep it?

Thank you for your reply in advance.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed. Contact an admin if you think this should be re-opened.