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
This commit is contained in:
Eoghan Glynn 2014-01-14 18:03:42 +00:00
parent 943fafb929
commit 1d784294e0
3 changed files with 157 additions and 60 deletions

View File

@ -18,6 +18,7 @@
# under the License. # under the License.
import datetime import datetime
import yaml
from stevedore import extension from stevedore import extension
@ -1068,6 +1069,48 @@ class TestPipeline(test.BaseTestCase):
self.assertEqual(len(pipeline_manager.pipelines[0].resources), self.assertEqual(len(pipeline_manager.pipelines[0].resources),
0) 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): def test_rate_of_change_mapping(self):
map_from = {'name': 'disk\\.(read|write)\\.(bytes|requests)', map_from = {'name': 'disk\\.(read|write)\\.(bytes|requests)',
'unit': '(B|request)'} 'unit': '(B|request)'}
@ -1089,47 +1132,49 @@ class TestPipeline(test.BaseTestCase):
] ]
self.pipeline_cfg[0]['counters'] = ['disk.read.bytes', self.pipeline_cfg[0]['counters'] = ['disk.read.bytes',
'disk.write.requests'] '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, pipeline_manager = pipeline.PipelineManager(self.pipeline_cfg,
self.transformer_manager) self.transformer_manager)
pipe = pipeline_manager.pipelines[0] 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) def _do_test_rate_of_change_in_boilerplate_pipeline_cfg(self, index,
publisher = pipeline_manager.pipelines[0].publishers[0] meters, units):
self.assertEqual(len(publisher.samples), 2) with open('etc/ceilometer/pipeline.yaml') as fap:
pipe.flush(None) data = fap.read()
self.assertEqual(len(publisher.samples), 2) pipeline_cfg = yaml.safe_load(data)
bps = publisher.samples[0] for p in pipeline_cfg:
self.assertEqual(getattr(bps, 'name'), 'disk.read.bytes.rate') p['publishers'] = ['test://']
self.assertEqual(getattr(bps, 'resource_id'), 'resource1') pipeline_manager = pipeline.PipelineManager(pipeline_cfg,
self.assertEqual(getattr(bps, 'unit'), 'B/s') self.transformer_manager)
self.assertEqual(getattr(bps, 'type'), sample.TYPE_GAUGE) pipe = pipeline_manager.pipelines[index]
self.assertEqual(getattr(bps, 'volume'), rate) self._do_test_rate_of_change_mapping(pipe, meters, units)
rps = publisher.samples[1]
self.assertEqual(getattr(rps, 'name'), 'disk.write.requests.rate') def test_rate_of_change_boilerplate_disk_read_cfg(self):
self.assertEqual(getattr(rps, 'resource_id'), 'resource2') meters = ('disk.read.bytes', 'disk.read.requests')
self.assertEqual(getattr(rps, 'unit'), 'request/s') units = ('B', 'request')
self.assertEqual(getattr(rps, 'type'), sample.TYPE_GAUGE) self._do_test_rate_of_change_in_boilerplate_pipeline_cfg(2,
self.assertEqual(getattr(rps, 'volume'), rate) 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)

View File

@ -65,9 +65,9 @@ Compute (Nova)
All meters are related to the guest machine, not the host. All meters are related to the guest machine, not the host.
======================== ========== ======== ======== ============ ======================================================= ============================= ========== ======== ======== ============ ==================================================================
Name Type Unit Resource Origin Note Name Type Unit Resource Origin Note
======================== ========== ======== ======== ============ ======================================================= ============================= ========== ======== ======== ============ ==================================================================
instance Gauge instance inst ID both Duration of instance instance Gauge instance inst ID both Duration of instance
instance:<type> Gauge instance inst ID both Duration of instance <type> (openstack types) instance:<type> Gauge instance inst ID both Duration of instance <type> (openstack types)
memory Gauge MB inst ID notification Volume of RAM in MB memory Gauge MB inst ID notification Volume of RAM in MB
@ -75,16 +75,24 @@ cpu Cumulative ns inst ID pollster CPU time
cpu_util Gauge % inst ID pollster Average CPU utilisation cpu_util Gauge % inst ID pollster Average CPU utilisation
vcpus Gauge vcpu inst ID notification Number of VCPUs vcpus Gauge vcpu inst ID notification Number of VCPUs
disk.read.requests Cumulative request inst ID pollster Number of read requests 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 Cumulative request inst ID pollster Number of write requests
disk.read.bytes Cumulative B inst ID pollster Volume of read in B disk.write.requests.rate Cumulative request/s inst ID pollster Average rate of write requests per second
disk.write.bytes Cumulative B inst ID pollster Volume of write in B 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.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 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.incoming.bytes Cumulative B iface ID pollster Number of incoming bytes on a VM network interface
network.outgoing.bytes Cumulative B iface ID pollster number of outgoing bytes on the network for a VM interface network.incoming.bytes.rate Gauge B/s iface ID pollster Average rate per sec of incoming bytes on a VM network interface
network.incoming.packets Cumulative packet iface ID pollster number of incoming packets for a VM interface network.outgoing.bytes Cumulative B iface ID pollster Number of outgoing bytes on a VM network interface
network.outgoing.packets Cumulative packet iface ID pollster number of outgoing packets for a VM 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 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 hypervisors while test coverage was mostly done based on KVM. Contributors

View File

@ -23,3 +23,47 @@
scale: "100.0 / (10**9 * (resource_metadata.cpu_number or 1))" scale: "100.0 / (10**9 * (resource_metadata.cpu_number or 1))"
publishers: publishers:
- rpc:// - 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://