Perfometer oder ein andere Namen für Wahnsinn?

Hi Zusammen,

ich versuche ein Perfometer für einen Check zu erstellen soweit so gut:
cmk.graphing.v1.perfometers — Checkmk’s Plug-in APIs documentation

oder

checkmk/doc/treasures/cisco_meraki/graphing/packages.py at master · Checkmk/checkmk · GitHub

als Vorlage und los geht`s … leider nein hier mal alle Varianten ohne Erfolg:

# ------------------------------------------------------------
# Kombinierter Perf-O-Meter: [APs total] + [Clients total]
# ------------------------------------------------------------
#perfometer_xiq_summary = Perfometer(
#    name="xiq_summary",  # <== identisch zum CheckPlugin.name
#    focus_range=RANGE_SUMMARY,
#    segments=[
#        "xiq_aps_total",
#        "xiq_clients_total",
#    ],
#)

#perfometer_xiq_summary = Stacked(
#    name="xiq_summary",
#    lower=Perfometer(
#        name="xiq_aps_total",
#        focus_range=RANGE_APS,
#        segments=["xiq_aps_total"],
#    ),
#    upper=Perfometer(
#        name="xiq_clients_total",
#        focus_range=RANGE_CLIENTS,
#        segments=[
##            "xiq_clients_24",
##            "xiq_clients_5",
##            "xiq_clients_6",
#            "xiq_clients_total",
#        ],
#    ),
#)
#perfometer_xiq_summary = Perfometer(
#    name="xiq_summary",                       # ← Matcht Check-Plugin-Name
#    focus_range=FocusRange(Closed(0), Open(1000)),
#    segments=Stacked([
#        "xiq_aps_total",
#        "xiq_clients_total",
#    ]),
#)
perfometer_xiq_summary = Perfometer(
    name="XIQ Summary",                       
    focus_range=FocusRange(Closed(0), Open(1000)),
    segments=Stacked([
        "xiq_aps_total",
        "xiq_clients_total",
    ]),
)

Die Metriken sind da, die Graphen gehen nur nicht das Perfometer was mach ich bitte falsch ???

lG Bernd

hier nochmal die Komplette Datei:

perfometer.py

`

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Perfometers for ExtremeCloudIQ Summary (CMK 2.4 compatible)

from cmk.graphing.v1 import Title, Color
from cmk.graphing.v1.metrics import MetricDefinition, Unit, DecimalNotation, StrictPrecision
from cmk.graphing.v1.perfometers import (
    Perfometer,
    FocusRange,
    Closed,
    Open,
    Stacked,
)

# Fokusbereich: 0..100
RANGE = FocusRange(Closed(0), Closed(100))
RANGE_SUMMARY = FocusRange(Closed(0), Closed(600))  # z.B. Clients bis 600
RANGE_APS = FocusRange(
    Closed(0),
    Closed(100)
)

RANGE_CLIENTS = FocusRange(
    Closed(0),
    Closed(600)
)

# ------------------------------------------------------------
# Perf-O-Meter: AP total
# ------------------------------------------------------------
perfometer_xiq_summary_aps = Perfometer(
    name="perfometer_xiq_summary_aps",
    focus_range=RANGE,
    segments=["xiq_aps_total"],
)

# ------------------------------------------------------------
# Perf-O-Meter: Clients (stacked)
# ------------------------------------------------------------
perfometer_xiq_summary_clients = Stacked(
    name="perfometer_xiq_summary_clients",
    focus_range=RANGE,
    lower=Perfometer(
        name="perfometer_xiq_summary_clients_24",
        focus_range=RANGE,
        segments=["xiq_clients_24"],
    ),
    upper=Stacked(
        name="perfometer_xiq_summary_clients_5_6",
        focus_range=RANGE,
        lower=Perfometer(
            name="perfometer_xiq_summary_clients_5",
            focus_range=RANGE,
            segments=["xiq_clients_5"],
        ),
        upper=Perfometer(
            name="perfometer_xiq_summary_clients_6",
            focus_range=RANGE,
            segments=["xiq_clients_6"],
        ),
    ),
)

# ------------------------------------------------------------
# Kombinierter Perf-O-Meter: [APs total] + [Clients total]
# ------------------------------------------------------------
#perfometer_xiq_summary = Perfometer(
#    name="xiq_summary",  # <== identisch zum CheckPlugin.name
#    focus_range=RANGE_SUMMARY,
#    segments=[
#        "xiq_aps_total",
#        "xiq_clients_total",
#    ],
#)

#perfometer_xiq_summary = Stacked(
#    name="xiq_summary",
#    lower=Perfometer(
#        name="xiq_aps_total",
#        focus_range=RANGE_APS,
#        segments=["xiq_aps_total"],
#    ),
#    upper=Perfometer(
#        name="xiq_clients_total",
#        focus_range=RANGE_CLIENTS,
#        segments=[
##            "xiq_clients_24",
##            "xiq_clients_5",
##            "xiq_clients_6",
#            "xiq_clients_total",
#        ],
#    ),
#)
#perfometer_xiq_summary = Perfometer(
#    name="xiq_summary",                       # ← Matcht Check-Plugin-Name
#    focus_range=FocusRange(Closed(0), Open(1000)),
#    segments=Stacked([
#        "xiq_aps_total",
#        "xiq_clients_total",
#    ]),
#)
perfometer_xiq_summary = Perfometer(
    name="XIQ Summary",                       
    focus_range=FocusRange(Closed(0), Open(1000)),
    segments=Stacked([
        "xiq_aps_total",
        "xiq_clients_total",
    ]),
)

`

Hallo Bernd,

für dein gestacktes Perfometer mit den Metriken “APs total” und “Clients total” könnte es so aussehen:

perfometer_xiq_summary = Stacked(
    name='xiq_summary',
    upper=Perfometer(
        name='xiq_aps_total',
        segments=['xiq_aps_total'],
        focus_range=FocusRange(lower=Closed(0), upper=Open(1000)),
    ),
    lower=Perfometer(
        name='xiq_clients_total,
        segments=['xiq_clients_total'],
        focus_range=FocusRange(lower=Closed(0), upper=Open(1000)),
    ),
)

In diesem Fall sollte dein Check Plugin die beiden Metriken xiq_aps_total und xiq_clients_total erzeugen.

LG Alex

1 Like

leider auch nicht…

hier mal etwas output:
Service performance data (source code) xiq_aps_total=12;;;; xiq_clients_total=0;;;; xiq_clients_24=0;;;; xiq_clients_5=0;;;; xiq_clients_6=0;;;;

und die metric.yp

Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from cmk.graphing.v1 import Title, Color
from cmk.graphing.v1.metrics import Metric, Unit, DecimalNotation, AutoPrecision

# Einheit für reine Zaehlwerte (Anzahl) – sauber und wiederverwendbar
COUNT = Unit(DecimalNotation(""), AutoPrecision(0))  # oder einfach StrictPrecision(0) wenn du keine Auto-Skalierung willst

# ────────────────────────────────────────────────────────────────────────────────
# Metriken-Definitionen
# ────────────────────────────────────────────────────────────────────────────────

metric_xiq_aps_total = Metric(
    name="xiq_aps_total",
    title=Title("Access Points total"),
    unit=COUNT,
    color=Color.BLUE,
)

metric_xiq_clients_total = Metric(
    name="xiq_clients_total",
    title=Title("Clients total"),
    unit=COUNT,
    color=Color.GREEN,
)

metric_xiq_clients_24 = Metric(
    name="xiq_clients_24",
    title=Title("Clients 2.4 GHz"),
    unit=COUNT,
    color=Color.LIGHT_GREEN,
)

metric_xiq_clients_5 = Metric(
    name="xiq_clients_5",
    title=Title("Clients 5 GHz"),
    unit=COUNT,
    color=Color.ORANGE,
)

metric_xiq_clients_6 = Metric(
    name="xiq_clients_6",
    title=Title("Clients 6 GHz"),
    unit=COUNT,
    color=Color.RED,
)

metric_xiq_api_remaining = Metric(
    name="xiq_api_remaining",
    title=Title("API Calls remaining"),
    unit=COUNT,
    color=Color.CYAN,
)
XIQ Summary          12 APs, 0 Clients
+ EXECUTING INVENTORY PLUGINS
 xiq_inventory_devices: ok
 xiq_inventory_neighbors: ok
[special_xiq] Success, [piggyback] Success (but no data found for this host), execution time 97.1 sec | execution_time=97.120 user_time=0.060 system_time=0.010 children_user_time=4.100 children_system_time=0.100 cmk_time_ds=92.840 cmk_time_agent=0.000
OMD[test]:~$ cmk -n -I Extreme

Beispiel aus meiner Redfish Integration was ordentlich tut.

from cmk.graphing.v1 import metrics, Title, perfometers

metric_input_power = metrics.Metric(
    name="input_power",
    title=Title("Electrical input power"),
    unit=metrics.Unit(metrics.DecimalNotation("Watt")),
    color=metrics.Color.BROWN,
)

metric_output_power = metrics.Metric(
    name="output_power",
    title=Title("Electrical output power"),
    unit=metrics.Unit(metrics.DecimalNotation("Watt")),
    color=metrics.Color.BLUE,
)

perfometer_input_output_power = perfometers.Stacked(
    name="power_summary",
    lower=perfometers.Perfometer(
        name="input_power",
        focus_range=perfometers.FocusRange(perfometers.Closed(0), perfometers.Open(500.0)),
        segments=["input_power"],
    ),
    upper=perfometers.Perfometer(
        name="output_power",
        focus_range=perfometers.FocusRange(perfometers.Closed(0), perfometers.Open(500.0)),
        segments=["output_power"],
    ),
)

Ergebnis

1 Like

Hi Andreas,

und wo machst du die Verknüpfung auf den Check oder ist die Verknüpfung immer die Metric ?

Im Endeffekt ist es nur die Metric - die Datei hier selber liegt innerhalb des Ordners –> redfish/graphing und die Checks dazu unter redfish/agent_based.

Der Check selbst gibt mehr noch aus

Service performance data (source code)	input_power=544;;;; output_power=508;;;; input_voltage=232;;;;

So schaut im Check der Output aus.

hmmm bei mir kommt aus dem Check:

# Perfdata
yield Metric("xiq_aps_total", aps)
yield Metric("xiq_clients_total", tcl)
yield Metric("xiq_clients_24", c24)
yield Metric("xiq_clients_5", c5)
yield Metric("xiq_clients_6", c6)

Service performance data (source code)
xiq_aps_total=12;;;; xiq_clients_total=0;;;; xiq_clients_24=0;;;; xiq_clients_5=0;;;; xiq_clients_6=0;;;;

und hier noch das Perfometer

from cmk.graphing.v1.perfometers import (
    Perfometer,
    FocusRange,
    Closed,
)

# --------------------------------------------------------------------
# Fokusbereiche (bitte auf eure Umgebung anpassen)
# --------------------------------------------------------------------
# Beispielwerte: bis ~150 APs und ~600 Clients
RANGE_SUMMARY = FocusRange(Closed(0), Closed(600))    # für APs + Clients gesamt
RANGE_BANDS   = FocusRange(Closed(0), Closed(600))    # für Band-Clients (2.4/5/6)

# --------------------------------------------------------------------
# 1) Kombi-Balken: Summe APs + Summe Clients
#    - Segments muessen exakt den Metrik-Namen entsprechen (siehe xiq_metrics.py)
#    - Variablenname muss mit "perfometer_" beginnen (Discovery)
# --------------------------------------------------------------------
perfometer_xiq_summary_total = Perfometer(
    name="xiq_summary_total",
    focus_range=RANGE_SUMMARY,
    segments=[
        "xiq_aps_total",
        "xiq_clients_total",
    ],
)

und alles (Metriken, Graphen, Perfometer) liegen unter:

~/local/lib/python3/cmk_addons/plugins/xiq/graphing/

und trotzdem will der Mist nicht … werde noch Wahnsinnig

was für ein Krampf nun geht es:

metric.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
XIQ Metrics (Checkmk 2.4, Graphing API v1)

Diese Datei definiert alle Metriken, die in den XIQ-Checks und Graphs/Perf-O-Metern
verwendet werden. Farben/Titel sind konsistent fuer NOC-Dashboards.

Pfad: ~/local/lib/check_mk/graphing/xiq_summary/metrics.py
"""
from cmk.graphing.v1 import metrics

# --------------------------------------------------------------------
# Einheit: Ganzzahl (count) ohne Nachkommastellen
# --------------------------------------------------------------------
UNIT_COUNTER = metrics.Unit(metrics.DecimalNotation(""), metrics.AutoPrecision(0))

# --------------------------------------------------------------------
# Access Points (gesamt / optional: connected / disconnected)
# --------------------------------------------------------------------
metric_xiq_aps_total = metrics.Metric(
    name="xiq_aps_total",
    title=metrics.Title("Access Points gesamt"),
    unit=UNIT_COUNTER,
    color=metrics.Color.BLUE,
)

# Optional, falls dein Check diese Metriken liefert:
metric_xiq_aps_connected = metrics.Metric(
    name="xiq_aps_connected",
    title=metrics.Title("Access Points verbunden"),
    unit=UNIT_COUNTER,
    color=metrics.Color.LIGHT_GREEN,
)

metric_xiq_aps_disconnected = metrics.Metric(
    name="xiq_aps_disconnected",
    title=metrics.Title("Access Points getrennt"),
    unit=UNIT_COUNTER,
    color=metrics.Color.LIGHT_RED,
)

# --------------------------------------------------------------------
# Clients (gesamt und je Band)
# --------------------------------------------------------------------
metric_xiq_clients_total = metrics.Metric(
    name="xiq_clients_total",
    title=metrics.Title("Clients gesamt"),
    unit=UNIT_COUNTER,
    color=metrics.Color.GREEN,
)

metric_xiq_clients_24 = metrics.Metric(
    name="xiq_clients_24",
    title=metrics.Title("Clients (2.4 GHz)"),
    unit=UNIT_COUNTER,
    color=metrics.Color.LIGHT_GREEN,   # konsistent mit Band-Farbschema
)

metric_xiq_clients_5 = metrics.Metric(
    name="xiq_clients_5",
    title=metrics.Title("Clients (5 GHz)"),
    unit=UNIT_COUNTER,
    color=metrics.Color.ORANGE,
)

metric_xiq_clients_6 = metrics.Metric(
    name="xiq_clients_6",
    title=metrics.Title("Clients (6 GHz)"),
    unit=UNIT_COUNTER,
    color=metrics.Color.RED,
)

# --------------------------------------------------------------------
# API-Quota / Remaining (optional)
# --------------------------------------------------------------------
metric_xiq_api_remaining = metrics.Metric(
    name="xiq_api_remaining",
    title=metrics.Title("API Requests verbleibend"),
    unit=UNIT_COUNTER,
    color=metrics.Color.DARK_BLUE,
)
perfometer.py
# -*- coding: utf-8 -*-
# Perfometers for ExtremeCloudIQ Summary

from cmk.graphing.v1 import perfometers

# ------------------------------------------------------------
# Focus Ranges
# ------------------------------------------------------------
# Define the display ranges for our metrics
# Closed() means the range has hard boundaries
RANGE_APS = perfometers.FocusRange(
    perfometers.Closed(0),
    perfometers.Closed(100)
)

RANGE_CLIENTS = perfometers.FocusRange(
    perfometers.Closed(0),
    perfometers.Closed(600)
)

# ------------------------------------------------------------
# Haupt-Perfometer: Stacked (APs unten, Clients oben)
# ------------------------------------------------------------
# Dieser Perfometer wird automatisch fuer den Check "xiq_summary" 
# verwendet, wenn alle benoetigten Metriken verfuegbar sind.
# Der Name muss NICHT zwingend dem Check-Namen entsprechen,
# aber es ist Best Practice.
perfometer_xiq_summary = perfometers.Stacked(
    name="xiq_summary",
    lower=perfometers.Perfometer(
        name="xiq_summary_lower",
        focus_range=RANGE_APS,
        segments=["xiq_aps_total"],
    ),
    upper=perfometers.Perfometer(
        name="xiq_summary_upper",
        focus_range=RANGE_CLIENTS,
        segments=[
            "xiq_clients_24",  # Wird als gestackte Segmente angezeigt
            "xiq_clients_5",   # in verschiedenen Farben
            "xiq_clients_6",
        ],
    ),
)

# ------------------------------------------------------------
# Alternative Perfometer (werden automatisch gewaehlt wenn
# nur ein Teil der Metriken verfuegbar ist)
# ------------------------------------------------------------

# Nur APs anzeigen
perfometer_xiq_aps_only = perfometers.Perfometer(
    name="xiq_aps_only",
    focus_range=RANGE_APS,
    segments=["xiq_aps_total"],
)

# Nur Clients gesamt
perfometer_xiq_clients_only = perfometers.Perfometer(
    name="xiq_clients_only",
    focus_range=RANGE_CLIENTS,
    segments=["xiq_clients_total"],
)

# Clients aufgeteilt nach Frequenz
perfometer_xiq_clients_by_frequency = perfometers.Perfometer(
    name="xiq_clients_by_frequency",
    focus_range=RANGE_CLIENTS,
    segments=[
        "xiq_clients_24",
        "xiq_clients_5",
        "xiq_clients_6",
    ],
)

und der vollständigkeitshalber

graphs.py
# -*- coding: utf-8 -*-
# Graphs for ExtremeCloudIQ Summary

from cmk.graphing.v1 import graphs, metrics

# ------------------------------------------------------------
# Graph 1: Access Points
# ------------------------------------------------------------
graph_xiq_aps = graphs.Graph(
    name="xiq_aps",
    title=metrics.Title("XIQ: Access Points"),
    minimal_range=graphs.MinimalRange(0, 10),
    simple_lines=["xiq_aps_total"],
)

# ------------------------------------------------------------
# Graph 2: Clients nach Frequenz (gestacked)
# ------------------------------------------------------------
#graph_xiq_clients_by_frequency = graphs.Graph(
#    name="xiq_clients_by_frequency",
#    title=metrics.Title("XIQ: Clients nach Frequenz"),
#    minimal_range=graphs.MinimalRange(0, 10),
#    compound_lines=[
#        "xiq_clients_24",
#        "xiq_clients_5",
#        "xiq_clients_6",
#    ],
#)

# ------------------------------------------------------------
# Graph 3: Clients gesamt
# ------------------------------------------------------------
#graph_xiq_clients_total = graphs.Graph(
#    name="xiq_clients_total",
#    title=metrics.Title("XIQ: Clients gesamt"),
#    minimal_range=graphs.MinimalRange(0, 10),
#    simple_lines=["xiq_clients_total"],
#)

# ------------------------------------------------------------
# Graph 4: Kombinierte Uebersicht APs + Clients
# ------------------------------------------------------------
#graph_xiq_overview = graphs.Graph(
#    name="xiq_overview",
#    title=metrics.Title("XIQ: Overview APs & Clients"),
#    minimal_range=graphs.MinimalRange(0, 10),
#    simple_lines=[
#        "xiq_aps_total",
#        "xiq_clients_total",
#    ],
#)

# ------------------------------------------------------------
# Graph 5: Clients mit Frequenzen + Total
# ------------------------------------------------------------
graph_xiq_clients_combined = graphs.Graph(
    name="xiq_clients_combined",
    title=metrics.Title("XIQ: Clients (total and by frequency)"),
    minimal_range=graphs.MinimalRange(0, 10),
    compound_lines=[
        "xiq_clients_24",
        "xiq_clients_5",
        "xiq_clients_6",
    ],
    simple_lines=["xiq_clients_total"],
)

# ------------------------------------------------------------
# Graph 6: API Remaining
# ------------------------------------------------------------
graph_xiq_api_remaining = graphs.Graph(
    name="xiq_api_remaining",
    title=metrics.Title("XIQ: API Calls Remaining"),
    minimal_range=graphs.MinimalRange(0, 1000),
    simple_lines=["xiq_api_remaining"],
)

Danke @andreas-doehler und @alex23

Wichtige Erkenntnisse:

1. Perfometer-Namen sind FLEXIBEL

Aus dem Code:

python

for perfometer in perfometers_from_api.values():
    if _perfometer_matches(perfometer, translated_metrics):
        return _get_renderer(perfometer, translated_metrics)

Das bedeutet: Der Perfometer-Name muss NICHT exakt dem Check-Namen entsprechen! CMK sucht automatisch nach einem passenden Perfometer basierend auf den verfügbaren Metriken.

2. Mehrere Perfometer möglich

Ihr könnt mehrere Perfometer definieren:

  • perfometer_xiq_summary (wird automatisch ausgewählt wenn alle Metriken verfügbar sind)
  • perfometer_xiq_aps_total (nur für AP-Metrik)
  • perfometer_xiq_clients_total (nur für Client-Metriken)

CMK wählt automatisch den ersten passenden aus.

3. Metric-Namen-Matching

Der Code prüft:

python

for metric_name in metric_names_or_scalars.metric_names:
    if metric_name not in translated_metrics:
        return False

Alle Metriken im Perfometer müssen vorhanden sein, sonst wird er übersprungen.

4. Segment-Reihenfolge

Die Reihenfolge der Segmente bestimmt die visuelle Darstellung (von unten nach oben bei gestackten Perfometern)

4 Likes