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.
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)

View File

@ -65,9 +65,9 @@ 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:<type> Gauge instance inst ID both Duration of instance <type> (openstack types)
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
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.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.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 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
======================== ========== ======== ======== ============ =======================================================
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

View File

@ -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://