Add Monasca-statsd metric generation
Statsd integration is disabled by default. Add a simple local daemon for testing/devstack use. Change-Id: I990472fa059afde37f7e4a1284360c17162aab49
This commit is contained in:
parent
3941bb2088
commit
2f061879cd
|
@ -28,9 +28,10 @@ import dns.opcode
|
|||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from designate.mdns import base
|
||||
from designate.i18n import _LI
|
||||
from designate.i18n import _LW
|
||||
from designate.mdns import base
|
||||
from designate.metrics import metrics
|
||||
|
||||
dns_query = eventlet.import_patched('dns.query')
|
||||
|
||||
|
@ -42,6 +43,7 @@ class NotifyEndpoint(base.BaseEndpoint):
|
|||
RPC_API_VERSION = '2.0'
|
||||
RPC_API_NAMESPACE = 'notify'
|
||||
|
||||
@metrics.timed('mdns.notify_zone_changed')
|
||||
def notify_zone_changed(self, context, zone, host, port, timeout,
|
||||
retry_interval, max_retries, delay):
|
||||
"""
|
||||
|
|
|
@ -20,6 +20,7 @@ from oslo_log import log as logging
|
|||
from designate import dnsutils
|
||||
from designate import exceptions
|
||||
from designate.mdns import base
|
||||
from designate.metrics import metrics
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
@ -29,6 +30,7 @@ class XFRMixin(object):
|
|||
"""
|
||||
Utility mixin that holds common methods for XFR functionality.
|
||||
"""
|
||||
@metrics.timed('mdns.xfr.zone_sync')
|
||||
def zone_sync(self, context, zone, servers=None):
|
||||
servers = servers or zone.masters
|
||||
servers = servers.to_list()
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
# Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Monasca-Statsd based metrics
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Based on metrics-and-stats blueprint
|
||||
|
||||
Usage examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from designate.metrics import metrics
|
||||
|
||||
@metrics.timed('dot.separated.name')
|
||||
def your_function():
|
||||
pass
|
||||
|
||||
with metrics.time('dot.separated.name'):
|
||||
pass
|
||||
|
||||
# Increment and decrement a counter.
|
||||
metrics.counter(name='foo.bar').increment()
|
||||
metrics.counter(name='foo.bar') -= 10
|
||||
|
||||
"""
|
||||
|
||||
import monascastatsd
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from designate.i18n import _LI
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CFG_GROUP = 'monasca:statsd'
|
||||
cfg.CONF.register_group(cfg.OptGroup(
|
||||
name=CFG_GROUP, title="Configuration for Monasca Statsd"
|
||||
))
|
||||
|
||||
cfg.CONF.register_opts([
|
||||
cfg.BoolOpt('enabled', default=False, help='enable'),
|
||||
cfg.IntOpt('port', default=8125, help='UDP port'),
|
||||
cfg.StrOpt('hostname', default='127.0.0.1', help='hostname')
|
||||
], group=CFG_GROUP)
|
||||
|
||||
|
||||
# Global metrics client to be imported by other modules
|
||||
metrics = None
|
||||
|
||||
|
||||
class Metrics(object):
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize Monasca-Statsd client with its default configuration.
|
||||
Do not start sending metrics yet.
|
||||
"""
|
||||
self._client = monascastatsd.Client(dimensions={
|
||||
'service_name': 'dns'
|
||||
})
|
||||
# cfg.CONF is not available at this time
|
||||
# Buffer all metrics until init() is called
|
||||
# https://bugs.launchpad.net/monasca/+bug/1616060
|
||||
self._client.connection.open_buffer()
|
||||
self._client.connection.max_buffer_size = 50000
|
||||
|
||||
def init(self):
|
||||
"""Setup client connection or disable metrics based on configuration.
|
||||
This is called once the cfg.CONF is ready.
|
||||
"""
|
||||
conf = cfg.CONF[CFG_GROUP]
|
||||
if conf.enabled:
|
||||
LOG.info(_LI("Statsd reports to %(host)s %(port)d") % {
|
||||
'host': conf.hostname,
|
||||
'port': conf.port
|
||||
})
|
||||
self._client.connection._flush_buffer()
|
||||
self._client.connection.close_buffer()
|
||||
self._client.connection.connect(conf.hostname, conf.port)
|
||||
else:
|
||||
LOG.info(_LI("Statsd disabled"))
|
||||
# The client cannot be disabled: mock out report()
|
||||
self._client.connection.report = lambda *a, **kw: None
|
||||
# There's no clean way to drain the outgoing buffer
|
||||
|
||||
def counter(self, *a, **kw):
|
||||
return self._client.get_counter(*a, **kw)
|
||||
|
||||
def gauge(self, *a, **kw):
|
||||
return self._client.get_gauge(*a, **kw)
|
||||
|
||||
@property
|
||||
def timed(self):
|
||||
return self._client.get_timer().timed
|
||||
|
||||
def timer(self):
|
||||
return self._client.get_timer()
|
||||
|
||||
|
||||
metrics = Metrics()
|
|
@ -35,6 +35,7 @@ from designate.i18n import _
|
|||
from designate.i18n import _LE
|
||||
from designate.i18n import _LI
|
||||
from designate.i18n import _LW
|
||||
from designate.metrics import metrics
|
||||
from designate import policy
|
||||
from designate import rpc
|
||||
from designate import service_status
|
||||
|
@ -74,6 +75,7 @@ class Service(service.Service):
|
|||
self._service_config = CONF['service:%s' % self.service_name]
|
||||
|
||||
policy.init()
|
||||
metrics.init()
|
||||
|
||||
# NOTE(kiall): All services need RPC initialized, as this is used
|
||||
# for clients AND servers. Hence, this is common to
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#!/usr/bin/env python
|
||||
# Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
A simple mock UDP server to receive monasca-statsd traffic
|
||||
Log to stdout or to a file.
|
||||
"""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from time import gmtime
|
||||
from time import strftime
|
||||
import SocketServer
|
||||
|
||||
|
||||
def parse_args():
|
||||
ap = ArgumentParser()
|
||||
ap.add_argument('--addr', default='127.0.0.1',
|
||||
help='Listen IP addr (default: 127.0.0.1)')
|
||||
ap.add_argument('--port', default=8125, type=int,
|
||||
help='UDP port (default: 8125)')
|
||||
ap.add_argument('--output-fname', default=None,
|
||||
help='Output file (default: stdout)')
|
||||
return ap.parse_args()
|
||||
|
||||
|
||||
class StatsdMessageHandler(SocketServer.BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
data = self.request[0].strip()
|
||||
tstamp = strftime("%Y-%m-%dT%H:%M:%S", gmtime())
|
||||
if self._output_fd:
|
||||
self._output_fd.write("%s %s\n" % (tstamp, data))
|
||||
else:
|
||||
print("%s %s" % (tstamp, data))
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
fd = open(args.output_fname, 'a') if args.output_fname else None
|
||||
StatsdMessageHandler._output_fd = fd
|
||||
server = SocketServer.UDPServer(
|
||||
(args.addr, args.port),
|
||||
StatsdMessageHandler,
|
||||
)
|
||||
server.serve_forever()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -77,7 +77,7 @@ Designate in general
|
|||
service_status
|
||||
notifications
|
||||
support-matrix
|
||||
|
||||
metrics
|
||||
|
||||
Developer Documentation
|
||||
=======================
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
.. _metrics:
|
||||
|
||||
****
|
||||
metrics
|
||||
****
|
||||
|
||||
metrics Base
|
||||
=========
|
||||
.. automodule:: designate.metrics
|
||||
:members:
|
||||
:special-members:
|
||||
:private-members:
|
||||
:undoc-members:
|
||||
:show-inheritance:
|
||||
|
|
@ -568,3 +568,14 @@ debug = False
|
|||
# name = '%s.%s' % (func.__module__, func.__name__)
|
||||
|
||||
# [hook_point:designate.api.v2.controllers.zones.get_one]
|
||||
|
||||
##################
|
||||
## Monasca Statsd
|
||||
##################
|
||||
[monasca:statsd]
|
||||
# Disabled by default
|
||||
# enabled = False
|
||||
# Statsd server hostname
|
||||
# hostname = 127.0.0.1
|
||||
# Statsd server UDP port
|
||||
# port = 8125
|
||||
|
|
|
@ -48,3 +48,4 @@ python-memcached>=1.56 # PSF
|
|||
tooz>=1.28.0 # Apache-2.0
|
||||
debtcollector>=1.2.0 # Apache-2.0
|
||||
os-win>=0.2.3 # Apache-2.0
|
||||
monasca-statsd>=1.1.0 # Apache-2.0
|
||||
|
|
Loading…
Reference in New Issue