Skip to content

Instantly share code, notes, and snippets.

@labeneator
Created September 18, 2018 08:11
Show Gist options
  • Save labeneator/046c05b1ae8a63eadc48f7060f366966 to your computer and use it in GitHub Desktop.
Save labeneator/046c05b1ae8a63eadc48f7060f366966 to your computer and use it in GitHub Desktop.
Simple Cron invoked job to send metrics from airmax devices to Carbon-cache (Graphite).
* * * * * root /usr/local/bin/send_metrics.sh
# Create a virtual env with the following packages
# This will be sourced by your runner script. (source ~/path/to/my/venv/snmp/bin/activate)
backports-abc==0.5
backports.shutil-get-terminal-size==1.0.0
bleach==2.1.4
click==6.7
configparser==3.5.0
decorator==4.3.0
easysnmp==0.2.5
entrypoints==0.2.3
enum34==1.1.6
functools32==3.2.3.post2
futures==3.2.0
html5lib==1.0.1
ipaddress==1.0.22
ipykernel==4.8.2
ipython==5.8.0
ipython-genutils==0.2.0
Jinja2==2.10
jsonschema==2.6.0
jupyter-client==5.2.3
jupyter-core==4.4.0
MarkupSafe==1.0
mistune==0.8.3
nbconvert==5.3.1
nbformat==4.4.0
notebook==5.6.0
pandocfilters==1.4.2
pathlib2==2.3.2
pexpect==4.6.0
pickleshare==0.7.4
prometheus-client==0.3.1
prompt-toolkit==1.0.15
ptyprocess==0.6.0
Pygments==2.2.0
python-dateutil==2.7.3
pyzmq==17.1.2
scandir==1.9.0
Send2Trash==1.5.0
simplegeneric==0.8.1
singledispatch==3.4.0.3
six==1.11.0
terminado==0.8.1
testpath==0.3.1
tornado==5.1
traitlets==4.3.2
wcwidth==0.1.7
webencodings==0.5.1
#!/bin/bash
source ~/path/to/my/venv/snmp/bin/activate
/usr/local/bin/ubnt_snmp.py --snmp-community public --carbon-host metrics.xyz.co.ke --snmp-host 172.16.0.1
/usr/local/bin/ubnt_snmp.py --snmp-community public --carbon-host metrics.xyz.co.ke --snmp-host 172.16.0.2
#!/usr/bin/env python
import click
import time
import socket
from contextlib import closing
from easysnmp import Session
from collections import defaultdict
# Dict of OIDs and functions to transmute their values
INTERFACE_DICT = dict(
ifInUcastPkts=dict(oid=".1.3.6.1.2.1.2.2.1.11", fn=int),
ifInOctets=dict(oid=".1.3.6.1.2.1.2.2.1.10", fn=int),
ifAdminStatus=dict(oid=".1.3.6.1.2.1.2.2.1.7", fn=int),
ifDescr= dict(oid=".1.3.6.1.2.1.2.2.1.2", fn=lambda x: x),
ifInNUcastPkts= dict(oid=".1.3.6.1.2.1.2.2.1.12", fn=int),
ifInDiscards=dict(oid=".1.3.6.1.2.1.2.2.1.13", fn=int),
ifInErrors=dict(oid=".1.3.6.1.2.1.2.2.1.14", fn=int),
ifOutOctets=dict(oid=".1.3.6.1.2.1.2.2.1.16", fn=int),
ifOutUcastPkts=dict(oid=".1.3.6.1.2.1.2.2.1.17", fn=int),
ifOutNUcastPkts=dict(oid=".1.3.6.1.2.1.2.2.1.18", fn=int),
ifOutDiscards=dict(oid=".1.3.6.1.2.1.2.2.1.19", fn=int),
ifOutErrors=dict(oid=".1.3.6.1.2.1.2.2.1.20", fn=int),
ifOutQLen=dict(oid=".1.3.6.1.2.1.2.2.1.21" , fn=int))
# Change your name space below to fit your carbon/graphite one.
def mk_metric_prefix(session):
return "<my_name_space>.ubiquiti.airmax." + ".".join([session.get('sysLocation.0').value, session.get('sysName.0').value])
def mk_time(session):
return int(session.get('sysUpTimeInstance').value)
# Convert the interfaces tree into a dict
def mk_interfaces_metrics(session):
interfaces = defaultdict(dict)
for key, op_dict in INTERFACE_DICT.items():
for idx, entry in enumerate(session.walk(op_dict['oid'])): interfaces[idx][key] = op_dict['fn'](entry.value)
return interfaces
# Walk the device and generate a dict of metrics
def snmp_walk(snmp_version, snmp_host, snmp_community):
session = Session(hostname=snmp_host, community=snmp_community, version=snmp_version)
metrics_dict = {}
metrics_dict['metric_prefix'] = mk_metric_prefix(session)
metrics_dict['uptime'] = mk_time(session)
metrics_dict['interface_metrics'] = mk_interfaces_metrics(session)
return metrics_dict
def send_metric(sock, timestamp, metric_prefix, metric):
msg = "%s %s %s\n" % (metric_prefix, metric, timestamp)
print("Sending: %s" % msg)
sock.sendall(msg)
def send_metrics(carbon_host, carbon_port, metrics):
timestamp = int(time.time())
with closing(socket.socket()) as sock:
sock.connect((carbon_host, carbon_port))
metric_prefix = metrics.get('metric_prefix')
send_metric(sock, timestamp, metric_prefix+".uptime", metrics.get('uptime'))
interface_metrics = metrics.get('interface_metrics')
for interface_metric in interface_metrics.values():
interface_name = interface_metric.pop('ifDescr')
for metric_name, metric_value in interface_metric.items():
metric_name = "%s.%s.%s" % (metric_prefix, interface_name, metric_name)
send_metric(sock, timestamp, metric_name, metric_value)
@click.command()
@click.option('--snmp-version', default=1, help='SNMP Version.')
@click.option('--snmp-host', required=True, help='The host to walk')
@click.option('--snmp-community', default='public', help='SNMP Community')
@click.option('--carbon-host', default="localhost", help='The carbon host')
@click.option('--carbon-port', default=2003, type=int, help='The carbon port')
def main(snmp_version, snmp_host, snmp_community, carbon_host, carbon_port):
"""Simple program that SNMP walks an AIRMAX device and sends metrics to Carbon"""
click.echo('SNMP walking %s' % snmp_host)
metrics = snmp_walk(snmp_version, snmp_host, snmp_community)
send_metrics(carbon_host, carbon_port, metrics)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment