Advice for Creating SNMP Based Discovery and Check with Multiple Metrics for Broadworks

After a lot of trial and error among several releases of Broadworks, I found inconsistencies with getting responses via SNMP across various servers (likely application rules, acls, firewalls). Instead I went with a perl based script (due to lesser added dependencies) to poll via localhost and write output for use by the Check_MK agent.

Monitored host local path /lib/check_mk_agent/plugins/broadworks.pl
CheckMK host for future autodeployment $OMD_ROOT/local/share/check_mk/agents/plugins/broadworks.pl

#!/usr/bin/perl

use strict;
use warnings;
use Net::SNMP;
use JSON;

my %oid_map = (
    "AS" => {
        "UserOrigAttempt"           => ".1.3.6.1.4.1.6431.1.2.7.1.4.0",
        "UserTermAttempt"           => ".1.3.6.1.4.1.6431.1.2.7.1.5.0",
        "UserTermAnswered"          => ".1.3.6.1.4.1.6431.1.2.7.1.6.0",
        "NetOrigAttempt"            => ".1.3.6.1.4.1.6431.1.2.7.1.1.0",
        "NetTermAttempt"            => ".1.3.6.1.4.1.6431.1.2.7.1.2.0",
        "NetTermAnswered"           => ".1.3.6.1.4.1.6431.1.2.7.1.3.0",
        "Calls"                     => ".1.3.6.1.4.1.6431.1.2.7.1.10.0",
        "QueryRequests"             => ".1.3.6.1.4.1.6431.1.6.8.1.3.0",
        "UpdateRequests"            => ".1.3.6.1.4.1.6431.1.6.8.1.1.0",
        "RegisterIn"                => ".1.3.6.1.4.1.6431.1.2.9.1.12.0",
        "RegisterResponseOuts200"   => ".1.3.6.1.4.1.6431.1.2.9.1.26.1.3.200",
        "RegisterResponseOuts401"   => ".1.3.6.1.4.1.6431.1.2.9.1.26.1.3.401",
        "RegisterResponseOuts403"   => ".1.3.6.1.4.1.6431.1.2.9.1.26.1.3.403",
        "RegisterResponseOuts404"   => ".1.3.6.1.4.1.6431.1.2.9.1.26.1.3.404",
        "MinSetupSignalDelay"       => ".1.3.6.1.4.1.6431.1.2.9.1.45.0",
        "MaxSetupSignalDelay"       => ".1.3.6.1.4.1.6431.1.2.9.1.46.0",
        "MinAnswerSignalDelay"      => ".1.3.6.1.4.1.6431.1.2.9.1.49.0",
        "MaxAnswerSignalDelay"      => ".1.3.6.1.4.1.6431.1.2.9.1.50.0",
        "SetupSignalDelay"          => ".1.3.6.1.4.1.6431.1.2.9.1.44.0",
        "AnswerSignalDelay"         => ".1.3.6.1.4.1.6431.1.2.9.1.47.0",
        "NumMigratedUsers"          => ".1.3.6.1.4.1.6431.1.2.18.1.1.0",
        "MeetMeInUse"               => ".1.3.6.1.4.1.6431.1.2.11.89.3.0",
        "MeetMeFailureLicense"      => ".1.3.6.1.4.1.6431.1.2.11.89.6.0",
        "NumActiveConferences"      => ".1.3.6.1.4.1.6431.1.2.11.89.1.0",
        "MeetMeFailureMSBusy"       => ".1.3.6.1.4.1.6431.1.2.11.89.8.0",
        "AuthChallenges"            => ".1.3.6.1.4.1.6431.1.2.11.3.1.0",
        "ValidResponses"            => ".1.3.6.1.4.1.6431.1.2.11.3.2.0",
    },
    "MS" => {
        "IvrSessions"           => ".1.3.6.1.4.1.6431.1.3.1.4.16.0",
        "PortsInUse"            => ".1.3.6.1.4.1.6431.1.3.1.5.0",
        "MaxPorts"              => ".1.3.6.1.4.1.6431.1.3.4.4.0",
        "NumLicensedPorts"      => ".1.3.6.1.4.1.6431.1.3.4.5.0",
        "NoPortError"           => ".1.3.6.1.4.1.6431.1.3.1.6.0",
        "G729Ports"             => ".1.3.6.1.4.1.6431.1.3.1.10.0",
        "G722Ports"             => ".1.3.6.1.4.1.6431.1.3.1.12.0",
        "MP3EncoderPorts"       => ".1.3.6.1.4.1.6431.1.3.1.13.0",
        "MP3DecoderPorts"       => ".1.3.6.1.4.1.6431.1.3.1.14.0",
        "RTPSessionCount"       => ".1.3.6.1.4.1.6431.1.3.2.1.0",
        "RTPPacketsExpected"    => ".1.3.6.1.4.1.6431.1.3.2.2.2.0",
        "RTPPacketsReceived"    => ".1.3.6.1.4.1.6431.1.3.2.2.3.0",
        "RTPPacketsSent"        => ".1.3.6.1.4.1.6431.1.3.2.3.4.0",
        "PrimaryEmailSent"      => ".1.3.6.1.4.1.6431.1.3.3.1.1.0",
        "FilesDownloaded"       => ".1.3.6.1.4.1.6431.1.3.5.1.0",
        "FilesRetreivedCache"   => ".1.3.6.1.4.1.6431.1.3.5.3.0",
        "ConfChansInUse"        => ".1.3.6.1.4.1.6431.1.3.14.3.1.0",
    },
    "NS" => {
        "StatsInviteIns.0"              => ".1.3.6.1.4.1.6431.1.5.3.1.1.0",
        "StatsInviteResponseOuts.302"   => ".1.3.6.1.4.1.6431.1.5.3.1.3.1.3.302",
        "StatsInviteResponseOuts.404"   => ".1.3.6.1.4.1.6431.1.5.3.1.3.1.3.404",
        "StatsInviteResponseOuts.406"   => ".1.3.6.1.4.1.6431.1.5.3.1.3.1.3.406",
        "StatsInviteResponseOuts.484"   => ".1.3.6.1.4.1.6431.1.5.3.1.3.1.3.484",
        "StatsInviteResponseOuts.500"   => ".1.3.6.1.4.1.6431.1.5.3.1.3.1.3.500",
        "StatsRegisterIns.0"            => ".1.3.6.1.4.1.6431.1.5.3.1.5.0",
        "StatsUdpIns.0"                 => ".1.3.6.1.4.1.6431.1.5.3.1.22.0",
        "StatsUdpOuts.0"                => ".1.3.6.1.4.1.6431.1.5.3.1.23.0",
        "StatsTcpIns.0"                 => ".1.3.6.1.4.1.6431.1.5.3.1.19.0",
        "StatsTcpOuts.0"                => ".1.3.6.1.4.1.6431.1.5.3.1.20.0",
        "CallsPerSecond.0"              => ".1.3.6.1.4.1.6431.1.5.2.6.0",
        "UserLocationRequests.0"        => ".1.3.6.1.4.1.6431.1.19.1.1.0",
        "UserLocationRequestSuccess.0"  => ".1.3.6.1.4.1.6431.1.19.1.2.0",
        "UserLocationRequestUnknownUser.0" => ".1.3.6.1.4.1.6431.1.19.1.3.0",
    },
);

sub broadworksType {
    my ($ip, $comm, $port) = @_;
    my ($session, $error) = Net::SNMP->session(
        -hostname  => $ip,
        -community => $comm,
        -port      => $port,
    );

    if (!$session) {
        print("Error: $error");
        exit(1);
    }

    my $result = $session->get_request(-varbindlist => [".1.3.6.1.4.1.6431.1.1.2.1.1.0"]);

    if (!$result) {
        print("Error: " . $session->error());
        $session->close();
        exit(1);
    }

    my $value = $result->{".1.3.6.1.4.1.6431.1.1.2.1.1.0"};

    if ($value eq "Application Server") {
        return 'AS';
    } elsif ($value eq "Media Server") {
        return "MS";
    } elsif ($value eq "Network Server") {
        return "NS";
    } else {
        return "UNKNOWN";
    }
}

my ($ip, $comm, $port);

if (@ARGV == 3) {
    ($ip, $port, $comm) = @ARGV;
    #print("Parameters passed for check IP: $ip, Port: $port, Community: $comm.\n");
} else {
    $ip = "127.0.0.1";
    $port = 8001;
    $comm = "public";
    #print("Default parameters used for check IP: $ip, Port: $port, Community: $comm.\n");
}

my $broadworks_type = broadworksType($ip, $comm, $port);

if ($broadworks_type eq "UNKNOWN") {
    exit(0);  # Exit with code 0 when broadworksType is UNKNOWN
}

#print("Broadworks Type: $broadworks_type\n");

my %result_in;

foreach my $item (keys %{$oid_map{$broadworks_type}}) {
    my $oid = $oid_map{$broadworks_type}{$item};
    my ($session, $error) = Net::SNMP->session(
        -hostname  => $ip,
        -community => $comm,
        -port      => $port,
    );

    if (!$session) {
        print("Error: $error\n");
        exit(1);
    }

    my $result = $session->get_request(-varbindlist => [$oid]);

    if (!$result) {
        print("Error: " . $session->error() . "\n");
        $session->close();
        exit(1);
    }
    $result_in{$item} = $result->{$oid};
    $session->close();
}

my $result_json = encode_json(\%result_in);
my $broadworks_type_lc = lc $broadworks_type;

print("<<<broadworks_$broadworks_type_lc:sep(0)>>>\n");
print("$result_json\n");
print("<<<>>>\n");

I have 2 working “AS” type hosts and am working through tweaking the graphing metrics for those.
CheckMK host path $OMD_ROOT/local/share/check_mk/web/plugins/metrics/broadworks_metric.py

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

from cmk.gui.i18n import _l
from cmk.gui.plugins.metrics.utils import graph_info, metric_info

### Broadworks AS Example Feed ###
"""
<<<broadworks_as:sep(0)>>>
{"MaxSetupSignalDelay":363,"ValidResponses":26787,"Calls":0,"MeetMeInUse":0,"RegisterResponseOuts404":4703,"AuthChallenges":26961,"NetOrigAttempt":67,"RegisterResponseOuts401":4353,"NumMigratedUsers":0,"UserTermAnswered":50,"AnswerSignalDelay":3,"MeetMeFailureMSBusy":0,"UserTermAttempt":107,"UserTerminationsAnswered":50,"MeetMeFailureLicense":0,"SetupSignalDelay":63,"MinSetupSignalDelay":8,"RegisterResponseOuts200":10094,"RegisterIn":19150,"QueryRequests":13744936,"UserOrigAttempt":8,"MinAnswerSignalDelay":1,"MaxAnswerSignalDelay":13,"UpdateRequests":45,"RegisterResponseOuts403":0,"NumActiveConferences":0,"NetTermAttempt":8,"NetTermAnswered":5}
<<<>>>
"""


# .
#   .--Metrics-------------------------------------------------------------.
#   |                   __  __      _        _                             |
#   |                  |  \/  | ___| |_ _ __(_) ___ ___                    |
#   |                  | |\/| |/ _ \ __| '__| |/ __/ __|                   |
#   |                  | |  | |  __/ |_| |  | | (__\__ \                   |
#   |                  |_|  |_|\___|\__|_|  |_|\___|___/                   |
#   |                                                                      |
#   +----------------------------------------------------------------------+
#   |  Definitions of metrics                                              |
#   '----------------------------------------------------------------------'

# Title are always lower case - except the first character!
# Colors: See indexed_color() in cmk/gui/plugins/metrics/utils.py

metric_info["Calls"] = {
    "title": _l("BW AS Calls in Progress"),
    "unit": "count",
    "color": "11/a",
}

metric_info["NumMigratedUsers"] = {
    "title": _l("# of Migrated Users"),
    "unit": "count",
    "color": "11/a",
}

# .
#   .--Graphs--------------------------------------------------------------.
#   |                    ____                 _                            |
#   |                   / ___|_ __ __ _ _ __ | |__  ___                    |
#   |                  | |  _| '__/ _` | '_ \| '_ \/ __|                   |
#   |                  | |_| | | | (_| | |_) | | | \__ \                   |
#   |                   \____|_|  \__,_| .__/|_| |_|___/                   |
#   |                                  |_|                                 |
#   +----------------------------------------------------------------------+
#   |  Definitions of time series graphs                                   |
#   '----------------------------------------------------------------------'

graph_info["bw_as_answer_delay"] = {
    "title": _l("BW AS Answer Delay"),
    "metrics": [
        ("AnswerSignalDelay", "area", _l("Signal Delay")),
        ("MinAnswerSignalDelay", "line", _l("Minimum Answer Signal Delay")),
        ("MaxAnswerSignalDelay", "line", _l("Max Answer Signal Delay Since Reset")),
    ],
}

graph_info["bw_as_auth_challenges"] = {
    "title": _l("BW AS Auth Challenges"),
    "metrics": [
        ("AuthChallenges,60,*", "line", _l("Auth Challenges per Minute")),
        ("ValidResponses,60,*", "area", _l("Valid Responses per Minute")),
    ],
    "scalars": [
        ("ValidResponses,AuthChallenges,/", "%", _l("Percentage")),
    ],
}

graph_info["bw_as_collaborate"] = {
    "title": _l("BW AS Collaborate"),
    "metrics": [
        ("NumActAudioPorts", "line", _l("Active Audio Ports")),
        ("NumActVideoPorts", "line", _l("Active Video Ports")),
        ("NumNoRsrcJoinFail", "line", _l("No Resource Failures")),
    ],
}

graph_info["bw_as_meet_me"] = {
    "title": _l("BW AS Meet Me"),
    "metrics": [
        ("MeetMeFailureLicense", "line", _l("Meet Me Failure - License")),
        ("MeetMeFailureMSBusy", "line", _l("Meet Me Failure - MS Busy")),
        ("MeetMeInUse", "area", _l("Meet Me In Use")),
    ],
}

graph_info["bw_as_network_attempts"] = {
    "title": _l("BW AS Network Attempts"),
    "metrics": [
        ("NetOrigAttempt,60,*", "area", _l("Net Origination Attempts per minute")),
        ("NetTermAttempt,60,*", "stack", _l("Net Termination Attempts per minute")),
        ("NetTermAnswered,60,*", "line", _l("Net Termination Answered per minute")),
        ("NetOrigAttempt,NetTermAttempt,+,60,*", "line", _l("Total Calls per minute")),
    ],
}

graph_info["bw_as_requests"] = {
    "title": _l("BW AS Requests"),
    "metrics": [
        ("QueryRequests,60,*", "line", _l("Query Requests")),
        ("UpdateRequests,60,*", "area", _l("Update Requests")),
    ],
}

graph_info["bw_as_setup_delay"] = {
    "title": _l("BW AS Setup Delay"),
    "metrics": [
        ("SetupSignalDelay", "area", _l("Current Setup Signal Delay")),
        ("MaxSetupSignalDelay", "line", _l("Maximum Setup Signal Delay Since Reset")),
        ("MinSetupSignalDelay", "line", _l("Minimum Setup Signal Delay")),
    ],
}

graph_info["bw_as_sip_registers"] = {
    "title": _l("BW AS SIP Registers"),
    "metrics": [
        ("RegisterIn", "line", _l("Registers In")),
        ("RegisterResponseOuts200", "area", _l("200 Responses Out")),
        ("RegisterResponseOuts401", "stack", _l("401 Responses Out")),
        ("RegisterResponseOuts403", "stack", _l("403 Responses Out")),
        ("RegisterResponseOuts404", "stack", _l("404 Responses Out")),
    ],
}

graph_info["bw_as_user_attempts"] = {
    "title": _l("BW AS User Attempts"),
    "metrics": [
        ("UserOrigAttempt,60,*", "area", _l("User Origination Attempts per minute")),
        ("UserTermAttempt,60,*", "stack", _l("User Termination Attempts per minute")),
        ("UserTermAnswered,60,*", "line", _l("User Termination Answered per minute")),
        ("UserOrigAttempt,UserTermAttempt,+,60,*", "line", _l("Total Calls per minute")),
    ],
}

Struggling with mimicking some cacti graphs at the moment and digging through existing settings to piece it together since documentation shows ‘coming soon’. I will post another question specific to graphing though to keep on topic.

With this as a base though I will also try to work on building this as an official package to put out there for community use.

As always, if you have any advice or feedback, it’s always welcome. I’ve learned a lot just seeing how other stuff works and from pointers provided in these forums.

Sincerely,
Scotsie