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:
parent
943fafb929
commit
1d784294e0
@ -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)
|
||||||
|
@ -65,26 +65,34 @@ 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
|
||||||
cpu Cumulative ns inst ID pollster CPU time used
|
cpu Cumulative ns inst ID pollster CPU time used
|
||||||
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.write.requests Cumulative request inst ID pollster Number of write requests
|
disk.read.requests.rate Gauge request/s inst ID pollster Average rate of read requests per second
|
||||||
disk.read.bytes Cumulative B inst ID pollster Volume of read in B
|
disk.write.requests Cumulative request inst ID pollster Number of write requests
|
||||||
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.root.size Gauge GB inst ID notification Size of root disk in GB
|
disk.read.bytes Cumulative B inst ID pollster Volume of reads in B
|
||||||
disk.ephemeral.size Gauge GB inst ID notification Size of ephemeral disk in GB
|
disk.read.bytes.rate Cumulative B/s inst ID pollster Average rate of reads in B per second
|
||||||
network.incoming.bytes Cumulative B iface ID pollster number of incoming bytes on the network for a VM interface
|
disk.write.bytes Cumulative B inst ID pollster Volume of writes in B
|
||||||
network.outgoing.bytes Cumulative B iface ID pollster number of outgoing bytes on the network for a VM interface
|
disk.write.bytes.rate Cumulative B/s inst ID pollster Average volume of writes in B per second
|
||||||
network.incoming.packets Cumulative packet iface ID pollster number of incoming packets for a VM interface
|
disk.root.size Gauge GB inst ID notification Size of root disk in GB
|
||||||
network.outgoing.packets Cumulative packet iface ID pollster number of outgoing packets for a VM interface
|
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
|
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
|
||||||
|
@ -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://
|
||||||
|
Loading…
Reference in New Issue
Block a user