From 1d784294e0078b2a572e058b521abac407054cb6 Mon Sep 17 00:00:00 2001 From: Eoghan Glynn Date: Tue, 14 Jan 2014 18:03:42 +0000 Subject: [PATCH] Add new rate-based disk and network pipelines Addresses: BP rates-derived-from-cumulative Add new pipeline config to derive rate-based gauge meters from the current set of cumulative disk and network meters gathered by the compute agent. The latter form of meter is not suitable for alarming against a static threshold, whereas rate-based meters would allow for example autoscaling actions to be driven off the observed per-second rates of I/O. Change-Id: I5764797d4eebb129b66a1524d47c38282c6ef095 --- ceilometer/tests/test_pipeline.py | 125 ++++++++++++++++++++---------- doc/source/measurements.rst | 48 +++++++----- etc/ceilometer/pipeline.yaml | 44 +++++++++++ 3 files changed, 157 insertions(+), 60 deletions(-) diff --git a/ceilometer/tests/test_pipeline.py b/ceilometer/tests/test_pipeline.py index 6e1f13c5a..8981e8adb 100644 --- a/ceilometer/tests/test_pipeline.py +++ b/ceilometer/tests/test_pipeline.py @@ -18,6 +18,7 @@ # under the License. import datetime +import yaml from stevedore import extension @@ -1068,6 +1069,48 @@ class TestPipeline(test.BaseTestCase): self.assertEqual(len(pipeline_manager.pipelines[0].resources), 0) + def _do_test_rate_of_change_mapping(self, pipe, meters, units): + now = timeutils.utcnow() + base = 1000 + offset = 7 + rate = 42 + later = now + datetime.timedelta(minutes=offset) + counters = [] + for v, ts in [(base, now.isoformat()), + (base + (offset * 60 * rate), later.isoformat())]: + for n, u, r in [(meters[0], units[0], 'resource1'), + (meters[1], units[1], 'resource2')]: + s = sample.Sample( + name=n, + type=sample.TYPE_CUMULATIVE, + volume=v, + unit=u, + user_id='test_user', + project_id='test_proj', + resource_id=r, + timestamp=ts, + resource_metadata={}, + ) + counters.append(s) + + pipe.publish_samples(None, counters) + publisher = pipe.publishers[0] + self.assertEqual(len(publisher.samples), 2) + pipe.flush(None) + self.assertEqual(len(publisher.samples), 2) + bps = publisher.samples[0] + self.assertEqual(getattr(bps, 'name'), '%s.rate' % meters[0]) + self.assertEqual(getattr(bps, 'resource_id'), 'resource1') + self.assertEqual(getattr(bps, 'unit'), '%s/s' % units[0]) + self.assertEqual(getattr(bps, 'type'), sample.TYPE_GAUGE) + self.assertEqual(getattr(bps, 'volume'), rate) + rps = publisher.samples[1] + self.assertEqual(getattr(rps, 'name'), '%s.rate' % meters[1]) + self.assertEqual(getattr(rps, 'resource_id'), 'resource2') + self.assertEqual(getattr(rps, 'unit'), '%s/s' % units[1]) + self.assertEqual(getattr(rps, 'type'), sample.TYPE_GAUGE) + self.assertEqual(getattr(rps, 'volume'), rate) + def test_rate_of_change_mapping(self): map_from = {'name': 'disk\\.(read|write)\\.(bytes|requests)', 'unit': '(B|request)'} @@ -1089,47 +1132,49 @@ class TestPipeline(test.BaseTestCase): ] self.pipeline_cfg[0]['counters'] = ['disk.read.bytes', 'disk.write.requests'] - now = timeutils.utcnow() - base = 1000 - offset = 7 - rate = 42 - later = now + datetime.timedelta(minutes=offset) - counters = [] - for v, ts in [(base, now.isoformat()), - (base + (offset * 60 * rate), later.isoformat())]: - for n, u, r in [('disk.read.bytes', 'B', 'resource1'), - ('disk.write.requests', 'request', 'resource2')]: - s = sample.Sample( - name=n, - type=sample.TYPE_CUMULATIVE, - volume=v, - unit=u, - user_id='test_user', - project_id='test_proj', - resource_id=r, - timestamp=ts, - resource_metadata={}, - ) - counters.append(s) - pipeline_manager = pipeline.PipelineManager(self.pipeline_cfg, self.transformer_manager) pipe = pipeline_manager.pipelines[0] + meters = ('disk.read.bytes', 'disk.write.requests') + units = ('B', 'request') + self._do_test_rate_of_change_mapping(pipe, meters, units) - pipe.publish_samples(None, counters) - publisher = pipeline_manager.pipelines[0].publishers[0] - self.assertEqual(len(publisher.samples), 2) - pipe.flush(None) - self.assertEqual(len(publisher.samples), 2) - bps = publisher.samples[0] - self.assertEqual(getattr(bps, 'name'), 'disk.read.bytes.rate') - self.assertEqual(getattr(bps, 'resource_id'), 'resource1') - self.assertEqual(getattr(bps, 'unit'), 'B/s') - self.assertEqual(getattr(bps, 'type'), sample.TYPE_GAUGE) - self.assertEqual(getattr(bps, 'volume'), rate) - rps = publisher.samples[1] - self.assertEqual(getattr(rps, 'name'), 'disk.write.requests.rate') - self.assertEqual(getattr(rps, 'resource_id'), 'resource2') - self.assertEqual(getattr(rps, 'unit'), 'request/s') - self.assertEqual(getattr(rps, 'type'), sample.TYPE_GAUGE) - self.assertEqual(getattr(rps, 'volume'), rate) + def _do_test_rate_of_change_in_boilerplate_pipeline_cfg(self, index, + meters, units): + with open('etc/ceilometer/pipeline.yaml') as fap: + data = fap.read() + pipeline_cfg = yaml.safe_load(data) + for p in pipeline_cfg: + p['publishers'] = ['test://'] + pipeline_manager = pipeline.PipelineManager(pipeline_cfg, + self.transformer_manager) + pipe = pipeline_manager.pipelines[index] + self._do_test_rate_of_change_mapping(pipe, meters, units) + + def test_rate_of_change_boilerplate_disk_read_cfg(self): + meters = ('disk.read.bytes', 'disk.read.requests') + units = ('B', 'request') + self._do_test_rate_of_change_in_boilerplate_pipeline_cfg(2, + meters, + units) + + def test_rate_of_change_boilerplate_disk_write_cfg(self): + meters = ('disk.write.bytes', 'disk.write.requests') + units = ('B', 'request') + self._do_test_rate_of_change_in_boilerplate_pipeline_cfg(2, + meters, + units) + + def test_rate_of_change_boilerplate_network_incoming_cfg(self): + meters = ('network.incoming.bytes', 'network.incoming.packets') + units = ('B', 'packet') + self._do_test_rate_of_change_in_boilerplate_pipeline_cfg(3, + meters, + units) + + def test_rate_of_change_boilerplate_network_outgoing_cfg(self): + meters = ('network.outgoing.bytes', 'network.outgoing.packets') + units = ('B', 'packet') + self._do_test_rate_of_change_in_boilerplate_pipeline_cfg(3, + meters, + units) diff --git a/doc/source/measurements.rst b/doc/source/measurements.rst index 467f58474..1b0b788a2 100644 --- a/doc/source/measurements.rst +++ b/doc/source/measurements.rst @@ -65,26 +65,34 @@ Compute (Nova) All meters are related to the guest machine, not the host. -======================== ========== ======== ======== ============ ======================================================= -Name Type Unit Resource Origin Note -======================== ========== ======== ======== ============ ======================================================= -instance Gauge instance inst ID both Duration of instance -instance: Gauge instance inst ID both Duration of instance (openstack types) -memory Gauge MB inst ID notification Volume of RAM in MB -cpu Cumulative ns inst ID pollster CPU time used -cpu_util Gauge % inst ID pollster Average CPU utilisation -vcpus Gauge vcpu inst ID notification Number of VCPUs -disk.read.requests Cumulative request inst ID pollster Number of read requests -disk.write.requests Cumulative request inst ID pollster Number of write requests -disk.read.bytes Cumulative B inst ID pollster Volume of read in B -disk.write.bytes Cumulative B inst ID pollster Volume of write in B -disk.root.size Gauge GB inst ID notification Size of root disk in GB -disk.ephemeral.size Gauge GB inst ID notification Size of ephemeral disk in GB -network.incoming.bytes Cumulative B iface ID pollster number of incoming bytes on the network for a VM interface -network.outgoing.bytes Cumulative B iface ID pollster number of outgoing bytes on the network for a VM interface -network.incoming.packets Cumulative packet iface ID pollster number of incoming packets for a VM interface -network.outgoing.packets Cumulative packet iface ID pollster number of outgoing packets for a VM interface -======================== ========== ======== ======== ============ ======================================================= +============================= ========== ======== ======== ============ ================================================================== +Name Type Unit Resource Origin Note +============================= ========== ======== ======== ============ ================================================================== +instance Gauge instance inst ID both Duration of instance +instance: Gauge instance inst ID both Duration of instance (openstack types) +memory Gauge MB inst ID notification Volume of RAM in MB +cpu Cumulative ns inst ID pollster CPU time used +cpu_util Gauge % inst ID pollster Average CPU utilisation +vcpus Gauge vcpu inst ID notification Number of VCPUs +disk.read.requests Cumulative request inst ID pollster Number of read requests +disk.read.requests.rate Gauge request/s inst ID pollster Average rate of read requests per second +disk.write.requests Cumulative request inst ID pollster Number of write requests +disk.write.requests.rate Cumulative request/s inst ID pollster Average rate of write requests per second +disk.read.bytes Cumulative B inst ID pollster Volume of reads in B +disk.read.bytes.rate Cumulative B/s inst ID pollster Average rate of reads in B per second +disk.write.bytes Cumulative B inst ID pollster Volume of writes in B +disk.write.bytes.rate Cumulative B/s inst ID pollster Average volume of writes in B per second +disk.root.size Gauge GB inst ID notification Size of root disk in GB +disk.ephemeral.size Gauge GB inst ID notification Size of ephemeral disk in GB +network.incoming.bytes Cumulative B iface ID pollster Number of incoming bytes on a VM network interface +network.incoming.bytes.rate Gauge B/s iface ID pollster Average rate per sec of incoming bytes on a VM network interface +network.outgoing.bytes Cumulative B iface ID pollster Number of outgoing bytes on a VM network interface +network.outgoing.bytes.rate Gauge B/s iface ID pollster Average rate per sec of outgoing bytes on a VM network interface +network.incoming.packets Cumulative packet iface ID pollster Number of incoming packets on a VM network interface +network.incoming.packets.rate Gauge packet/s iface ID pollster Average rate per sec of incoming packets on a VM network interface +network.outgoing.packets Cumulative packet iface ID pollster Number of outgoing packets on a VM network interface +network.outgoing.packets.rate Gauge packet/s iface ID pollster Average rate per sec of outgoing packets on a VM network interface +============================= ========== ======== ======== ============ ================================================================== At present, most of the Nova meters will only work with libvirt front-end hypervisors while test coverage was mostly done based on KVM. Contributors diff --git a/etc/ceilometer/pipeline.yaml b/etc/ceilometer/pipeline.yaml index 5c20c1ca6..b34f5ab52 100644 --- a/etc/ceilometer/pipeline.yaml +++ b/etc/ceilometer/pipeline.yaml @@ -23,3 +23,47 @@ scale: "100.0 / (10**9 * (resource_metadata.cpu_number or 1))" publishers: - rpc:// +- + name: disk_pipeline + interval: 600 + meters: + - "disk.read.bytes" + - "disk.read.requests" + - "disk.write.bytes" + - "disk.write.requests" + transformers: + - name: "rate_of_change" + parameters: + source: + map_from: + name: "disk\\.(read|write)\\.(bytes|requests)" + unit: "(B|request)" + target: + map_to: + name: "disk.\\1.\\2.rate" + unit: "\\1/s" + type: "gauge" + publishers: + - rpc:// +- + name: network_pipeline + interval: 600 + meters: + - "network.incoming.bytes" + - "network.incoming.packets" + - "network.outgoing.bytes" + - "network.outgoing.packets" + transformers: + - name: "rate_of_change" + parameters: + source: + map_from: + name: "network\\.(incoming|outgoing)\\.(bytes|packets)" + unit: "(B|packet)" + target: + map_to: + name: "network.\\1.\\2.rate" + unit: "\\1/s" + type: "gauge" + publishers: + - rpc://