Add notifier plugin based on Ceilometer

This drivers sends notifications using notifer API from oslo.messaging

These notifications has speical topic "profiler", and they are collected
by this Ceilometer notification pluging:

https://review.openstack.org/#/c/100239/

Change-Id: I305fc7a13d3c052ffd22073d77ae4f12fae348ca
This commit is contained in:
Boris Pavlovic 2014-07-03 15:18:13 +04:00
parent 090e577244
commit 25eeb78cfe
6 changed files with 103 additions and 2 deletions

@ -0,0 +1,20 @@
# Copyright 2011 OpenStack Foundation.
# All Rights Reserved.
#
# 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.
from osprofiler import _utils as utils
utils.import_modules_from_package("osprofiler._notifiers")

@ -18,11 +18,26 @@ from osprofiler import _utils as utils
class Notifier(object): class Notifier(object):
def notify(self, info): def notify(self, info, context=None):
"""This method will be called on each notifier.notify() call. """This method will be called on each notifier.notify() call.
To add new drivers you should, create new subclass of this class and To add new drivers you should, create new subclass of this class and
implement notify method. implement notify method.
:param info: Contains information about trace element.
In payload dict there are always 3 ids:
"base_id" - uuid that is common for all notifications
related to one trace. Used to simplify
retrieving of all trace elements from
Ceilometer.
"parent_id" - uuid of parent element in trace
"trace_id" - uuid of current element in trace
With parent_id and trace_id it's quite simple to build
tree of trace elements, which simplify analyze of trace.
:param context: request context that is mostly used to specify
current active user and tenant.
""" """
@staticmethod @staticmethod

@ -12,3 +12,45 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from osprofiler._notifiers import base
class Messaging(base.Notifier):
def __init__(self, messaging, context, transport, project, service, host):
"""Init Messaging notify driver.
"""
super(Messaging, self).__init__()
self.messaging = messaging
self.context = context
self.project = project
self.service = service
self.notifier = messaging.Notifier(
transport, publisher_id=host, driver="messaging", topic="profiler")
def notify(self, info, context=None):
"""Send notifications to Ceilometer via oslo.messaging notifier API.
:param info: Contains information about trace element.
In payload dict there are always 3 ids:
"base_id" - uuid that is common for all notifications
related to one trace. Used to simplify
retrieving of all trace elements from
Ceilometer.
"parent_id" - uuid of parent element in trace
"trace_id" - uuid of current element in trace
With parent_id and trace_id it's quite simple to build
tree of trace elements, which simplify analyze of trace.
:param context: request context that is mostly used to specify
current active user and tenant.
"""
info["project"] = self.project
info["service"] = self.service
self.notifier.info(context or self.context,
"profiler.%s" % self.service, info)

@ -17,6 +17,8 @@ import base64
import hashlib import hashlib
import hmac import hmac
import json import json
import os
import six import six
@ -110,3 +112,19 @@ def itersubclasses(cls, _seen=None):
yield sub yield sub
for sub in itersubclasses(sub, _seen): for sub in itersubclasses(sub, _seen):
yield sub yield sub
def import_modules_from_package(package):
"""Import modules from package and append into sys.modules
:param: package - Full package name. For example: rally.deploy.engines
"""
path = [os.path.dirname(__file__), '..'] + package.split('.')
path = os.path.join(*path)
for root, dirs, files in os.walk(path):
for filename in files:
if filename.startswith('__') or not filename.endswith('.py'):
continue
new_package = ".".join(root.split(os.sep)).split("....")[1]
module_name = '%s.%s' % (new_package, filename[:-3])
__import__(module_name)

@ -16,7 +16,7 @@
from osprofiler._notifiers import base from osprofiler._notifiers import base
def _noop_notifier(info): def _noop_notifier(info, context=None):
"""Do nothing on notify().""" """Do nothing on notify()."""
pass pass

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import mock
from osprofiler._notifiers import base from osprofiler._notifiers import base
from tests import test from tests import test
@ -46,3 +48,7 @@ class NotifierBaseTestCase(test.TestCase):
def test_notify(self): def test_notify(self):
base.Notifier().notify("") base.Notifier().notify("")
def test_plugins_are_imported(self):
base.Notifier.factory("Messaging", mock.MagicMock(), "context",
"transport", "project", "service", "host")