Hi, I want to share my working check_MK v2.0 plugin to discover and check Mikrotik QueueTree Queues via SNMP.
It creates one Service for every Queue in the Queue Tree and shows
- Bits per second
- Packets per second
- Dropped Packets per second
Via a service monitoring rule “Mikrotik QueueTree Parameters” the warn- and critical-Limits for packet drops can be adjusted.
I hope that helps anyone - have fun,
Bernhard
The check-plugin comes to folder local/lib/check_mk/base/plugins/agent_based/
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2022 Bernhard Voit - License: GNU General Public License v2
# check-plugin for mikrotik_queuetree
# OIDs overview
# .1.3.6.1.4.1.14988.1.1.2 mtxrQueues
# .1.3.6.1.4.1.14988.1.1.2.1 mtxrQueueSimpleTable
# .1.3.6.1.4.1.14988.1.1.2.1 mtxrQueueTreeTable
# .1.3.6.1.4.1.14988.1.1.2.2.1 mtxrQueueTreeEntry
# .1.3.6.1.4.1.14988.1.1.2.2.1.1 mtxrQueueTreeIndex
# .1.3.6.1.4.1.14988.1.1.2.2.1.2 mtxrQueueTreeName (used here)
# .1.3.6.1.4.1.14988.1.1.2.2.1.3 mtxrQueueTreeFlow
# .1.3.6.1.4.1.14988.1.1.2.2.1.4 mtxrQueueTreeParentIndex
# .1.3.6.1.4.1.14988.1.1.2.2.1.5 mtxrQueueTreeBytes (used here)
# .1.3.6.1.4.1.14988.1.1.2.2.1.6 mtxrQueueTreePackets (used here)
# .1.3.6.1.4.1.14988.1.1.2.2.1.7 mtxrQueueTreeHCBytes
# .1.3.6.1.4.1.14988.1.1.2.2.1.8 mtxrQueueTreePCQQueues
# .1.3.6.1.4.1.14988.1.1.2.2.1.9 mtxrQueueTreeDropped (used here)
# Example:
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777216 Total upstream
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777218 up_Citrix
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777219 up_default
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777220 up_Teams_Audio
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777221 Teams_Video
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777222 Teams_TRAP
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777223 Total downstream
# .1.3.6.1.4.1.14988.1.1.2.2.1.2.16777225 down_default
#
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777216 4151882005
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777218 241862080
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777219 3862058184
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777220 34687687
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777221 12577891
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777222 696163
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777223 917641369
# .1.3.6.1.4.1.14988.1.1.2.2.1.5.16777225 917641369
#
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777216 7061846
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777218 3098779
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777219 3643690
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777220 184218
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777221 129855
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777222 5304
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777223 3325213
# .1.3.6.1.4.1.14988.1.1.2.2.1.6.16777225 3325213
#
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777216 0
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777218 0
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777219 3087
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777220 0
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777221 0
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777222 0
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777223 0
# .1.3.6.1.4.1.14988.1.1.2.2.1.9.16777225 0
from .agent_based_api.v1 import *
from .agent_based_api.v1.render import bytes as render_bytes
from .agent_based_api.v1.type_defs import CheckResult, DiscoveryResult
from time import time
from cmk.base.plugins.agent_based.agent_based_api.v1 import (
get_rate,
get_value_store,
)
import pprint
def discover_mikrotik_queuetree(section):
# pprint.pprint(section)
for id, QueueTreeName, QueueTreeBytes, QueueTreePackets, QueueTreeDropped in section:
yield Service(item=QueueTreeName)
# def check_mikrotik_queuetree(item, section) -> CheckResult:
# def check_mikrotik_queuetree(item, section):
def check_mikrotik_queuetree(item, params, section):
for id, QueueTreeName, QueueTreeBytes, QueueTreePackets, QueueTreeDropped in section:
if QueueTreeName == item:
QueueTreeBits = int(QueueTreeBytes)*8 # convert string to int (and Bytes to Bits)
QueueTreePackets = int(QueueTreePackets) # convert string to int
QueueTreeDropped = int(QueueTreeDropped) # convert string to int
# print(item, ": ", QueueTreeBytes, "Bytes, ", QueueTreePackets, "Packets, ", QueueTreeDropped, "Drops")
# pprint.pprint(params)
now_time = time()
value_store = get_value_store()
rate_Bits = get_rate(value_store, f'QueueTreeBits', now_time, QueueTreeBits, raise_overflow=True)
rate_Packets = get_rate(value_store, f'QueueTreePackets', now_time, QueueTreePackets, raise_overflow=True)
rate_Drops = get_rate(value_store, f'QueueTreeDropped', now_time, QueueTreeDropped, raise_overflow=True)
warn_level = params["warn_level"]
crit_level = params["crit_level"]
# print(item, ": ", rate_Bits, "Bits/s, ", rate_Packets, "Packets/s, ", rate_Drops, "Drops/s")
yield Metric(
"queue_bps",
rate_Bits,
boundaries=(0, None))
yield Metric(
"queue_pkts",
rate_Packets,
boundaries=(0, None))
yield Metric(
"queue_drops",
rate_Drops,
levels=(warn_level, crit_level),
boundaries=(0, None))
if rate_Drops >= crit_level:
queue_state = State.CRIT
elif rate_Drops >= warn_level:
queue_state = State.WARN
else:
queue_state = State.OK
yield Result(state = queue_state, notice = f"{rate_Drops} dropped Packets per second (average last minute)")
return
register.snmp_section(
name = "mikrotik_queuetree",
detect = matches(".1.3.6.1.2.1.1.1.0","RouterOS RB4011iGS\+"),
fetch = SNMPTree(
base = '.1.3.6.1.4.1.14988.1.1.2.2.1', # mtxrQueueTreeEntry
oids = [
OIDEnd(),
'2', # mtxrQueueTreeName
'5', # mtxrQueueTreeBytes
'6', # mtxrQueueTreePackets
'9', # mtxrQueueTreeDropped
],
),
)
register.check_plugin(
name="mikrotik_queuetree",
service_name="Queue %s",
discovery_function=discover_mikrotik_queuetree,
check_function=check_mikrotik_queuetree,
check_default_parameters={"warn_level": 0.01, 'crit_level': 0.01},
check_ruleset_name="mikrotik_queuetree",
)
The metric-definition comes to folder local/share/check_mk/web/plugins/metrics
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from cmk.gui.i18n import _
from cmk.gui.plugins.metrics import metric_info
#.
# .--Metrics-------------------------------------------------------------.
# | __ __ _ _ |
# | | \/ | ___| |_ _ __(_) ___ ___ |
# | | |\/| |/ _ \ __| '__| |/ __/ __| |
# | | | | | __/ |_| | | | (__\__ \ |
# | |_| |_|\___|\__|_| |_|\___|___/ |
# | |
# +----------------------------------------------------------------------+
# | Definitions of metrics |
# '----------------------------------------------------------------------'
metric_info["queue_bps"] = {
"title": _("Queue bandwidth"),
"unit": "bits/s",
"color": "#00e060",
}
metric_info["queue_pkts"] = {
"title": _("Queue Packets"),
"unit": "1/s",
"color": "#00e060",
}
metric_info["queue_drops"] = {
"title": _("Queue Drops"),
"unit": "1/s",
"color": "#ff0080",
}
and the parameter-rule comes to local/share/check_mk/web/plugins/wato
:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2022 Bernhard Voit - License: GNU General Public License v2
# check_parameter definition for the mikrotik_queuetree
from cmk.gui.i18n import _
from cmk.gui.valuespec import (
Dictionary,
Float,
TextAscii,
)
from cmk.gui.plugins.wato import (
CheckParameterRulespecWithItem,
rulespec_registry,
RulespecGroupCheckParametersNetworking,
)
def _item_valuespec_mikrotik_queuetree():
return TextAscii(title=_("Queue Name"))
def _parameter_valuespec_mikrotik_queuetree():
return Dictionary(
elements=[
("warn_level", Float(title=_("Warning above Drops per second"))),
("crit_level", Float(title=_("Critical above Drops per second"))),
],
)
rulespec_registry.register(
CheckParameterRulespecWithItem(
check_group_name="mikrotik_queuetree",
group=RulespecGroupCheckParametersNetworking,
match_type="dict",
item_spec=_item_valuespec_mikrotik_queuetree,
parameter_valuespec=_parameter_valuespec_mikrotik_queuetree,
title=lambda: _("Mikrotik QueueTree Parameters"),
))