diff --git a/ceilometer/profiler/__init__.py b/ceilometer/profiler/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ceilometer/profiler/notifications.py b/ceilometer/profiler/notifications.py new file mode 100644 index 0000000000..f1735b72ea --- /dev/null +++ b/ceilometer/profiler/notifications.py @@ -0,0 +1,56 @@ +# Copyright 2014: Mirantis Inc. +# 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. + +import oslo.messaging + +from ceilometer import plugin +from ceilometer import sample + + +class ProfilerNotifications(plugin.NotificationBase): + + event_types = ["profiler.*"] + + def get_targets(self, conf): + """Return a sequence of oslo.messaging.Target defining the exchange and + topics to be connected for this plugin. + + :param conf: Configuration. + """ + targets = [] + exchanges = [ + conf.nova_control_exchange, + conf.cinder_control_exchange, + conf.glance_control_exchange, + conf.neutron_control_exchange, + conf.heat_control_exchange + ] + + for exchange in exchanges: + targets.extend(oslo.messaging.Target(topic=topic, + exchange=exchange) + for topic in conf.notification_topics) + return targets + + def process_notification(self, message): + yield sample.Sample.from_notification( + name=message["payload"]["name"], + type=sample.TYPE_GAUGE, + volume=1, + unit="trace", + user_id=message["payload"].get("user_id"), + project_id=message["payload"].get("project_id"), + resource_id="profiler-%s" % message["payload"]["base_id"], + message=message) diff --git a/ceilometer/tests/profiler/__init__.py b/ceilometer/tests/profiler/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/ceilometer/tests/profiler/test_notifications.py b/ceilometer/tests/profiler/test_notifications.py new file mode 100644 index 0000000000..943f71b199 --- /dev/null +++ b/ceilometer/tests/profiler/test_notifications.py @@ -0,0 +1,61 @@ +# Copyright 2014: Mirantis Inc. +# 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 ceilometer.openstack.common import test +from ceilometer.profiler import notifications +from ceilometer import sample + + +NOTIFICATION = { + "event_type": "profiler.compute", + "message_id": "dae6f69c-00e0-41c0-b371-41ec3b7f4451", + "publisher_id": "some_host", + + "payload": { + "user_id": "1e3ce043029547f1a61c1996d1a531a2", + "project_id": "663ce04332954555a61c1996d1a53143", + "base_id": "2e3ce043029547f1a61c1996d1a531a2", + "trace_id": "3e3ce043029547f1a61c1996d1a531a2", + "parent_id": "4e3ce043029547f1a61c1996d1a531a2", + "name": "some_name", + "info": { + "foo": "bar" + } + }, + "priority": "INFO", + "timestamp": "2012-05-08 20:23:48.028195" +} + + +class ProfilerNotificationsTestCase(test.BaseTestCase): + + def test_process_notification(self): + prof = notifications.ProfilerNotifications(None) + info = prof.process_notification(NOTIFICATION).next() + + self.assertEqual(NOTIFICATION["payload"]["name"], info.name) + self.assertEqual(sample.TYPE_GAUGE, info.type) + self.assertEqual("trace", info.unit) + self.assertEqual(NOTIFICATION["payload"]["user_id"], info.user_id) + self.assertEqual(NOTIFICATION["payload"]["project_id"], + info.project_id) + self.assertEqual("profiler-%s" % NOTIFICATION["payload"]["base_id"], + info.resource_id) + self.assertEqual(1, info.volume) + self.assertEqual(NOTIFICATION["timestamp"], info.timestamp) + self.assertEqual(NOTIFICATION["payload"]["info"], + info.resource_metadata["info"]) + self.assertEqual(NOTIFICATION["publisher_id"], + info.resource_metadata["host"]) diff --git a/doc/source/measurements.rst b/doc/source/measurements.rst index 9f6a0421f6..30ea3cd0cb 100644 --- a/doc/source/measurements.rst +++ b/doc/source/measurements.rst @@ -337,3 +337,17 @@ refer to :ref:`installing_manually` for details. For example, this could be used to distinguish external and internal users. You'd have to implement a custom Swift middleware that sets a proper header and just add it to metadata_headers. + + +OSprofiler data +=============== + +All messages with event type "profiler.*" will be collected as profiling data. +Using notification plugin profiler/notifications.py. + +.. note:: + + Be sparing with heavy usage of OSprofiler, especially in case of complex + operations like booting and deleting instance that may create over 100kb of + sample data per each request. + diff --git a/setup.cfg b/setup.cfg index 2043c98b5e..1df6cd9b3c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -65,6 +65,7 @@ ceilometer.notification = http.request = ceilometer.middleware:HTTPRequest http.response = ceilometer.middleware:HTTPResponse stack_crud = ceilometer.orchestration.notifications:StackCRUD + profiler = ceilometer.profiler.notifications:ProfilerNotifications ceilometer.discover = local_instances = ceilometer.compute.discovery:InstanceDiscovery