Downloads: 30

Reviews: 0

  • DNS Masq-1597667047637.png
    DNS Masq-1597667047637.png

On Dashboard:

  • Internal dnsmasq stats (evictions, hits, auth, insections and misses queries)
  • Upstream queries
  • Upstream errors

Requirement: python-dnspython

grafana->graphite->collectd

Collector Configuration Details

LoadPlugin python
<Plugin python>
    ModulePath "/opt/collectd/python"

    Import "dns_masq"
    <Module dns_masq>
#       Verbose true
        Interval 60
        Address "<dnsmasq_address>"
        Timeout 1
    </Module>
</Plugin>

/opt/collectd/python/dns_masq.py

import collectd

import dns.resolver

class dns_masq(object):
    def __init__(self):
        self.plugin_name = 'dns_masq'
        self.verbose_logging = False
        self.address = '127.0.0.1'
        self.timeout = 0.5

    def log_verbose(self, msg):
        if not self.verbose_logging:
            return
        collectd.info('%s plugin [verbose]: %s' % (self.plugin_name, msg))

    def store(self, key, val):
        val = collectd.Values(type='gauge', plugin=self.plugin_name, type_instance=key, values=[val])
        val.dispatch()
        self.log_verbose('Sending value: %s:%s' % (key, val))

    def read(self):
        # init
        self.resolver = dns.resolver.Resolver(configure=False)
        self.resolver.lifetime = self.timeout
        self.resolver.nameservers = [self.address]
        #dig +short chaos txt *.bind. @address
        for name_metric in ['insertions','evictions','misses','hits','auth']:
            answer = self.resolver.query('%s.bind' % name_metric, 'TXT', 'CHAOS')
            self.store(name_metric, str(answer.rrset[0])[1:-1])
        #dig +short chaos txt servers.bind. @address
        answer = self.resolver.query('servers.bind', 'TXT', 'CHAOS')
        for uplink in str(answer.rrset[0]).split('"'):
            raw = uplink.split(" ")
            if isinstance(raw, list) and len(raw) == 3:
                name = raw[0].replace('.','_')
                queries = raw[1]
                errors = raw[2]
                self.store('upstream_%s_queries' % name, queries)
                self.store('upstream_%s_errors' % name, errors)

    def configure_callback(self, conf):
        for node in conf.children:
            vals = [str(v) for v in node.values]
            if node.key == 'Verbose':
                self.verbose_logging = (vals[0].lower() == 'true')
            elif node.key == 'Interval':
                self.interval = float(vals[0])
            elif node.key == 'Address':
                self.address = str(vals[0])
            elif node.key == 'Timeout':
                self.timeout = float(vals[0])
            else:
                raise ValueError('%s plugin: Unknown config key: %s' % (self.plugin_name, node.key))
        collectd.register_read(self.read, self.interval)
        self.log_verbose('configured with interval=%s' % self.interval)


app_dns_masq = dns_masq()
collectd.register_config(app_dns_masq.configure_callback)