Move SampleContainer to collectd_ceilometer/common
SampleContainer was duplicated in ceilometer/ and gnocchi/ - Moved SampleContainer to collectd_ceilometer/common - Added unit tests for SampleContainer Change-Id: Id394c6b489d69840ff5de1eb07f1a4b357d3bb22
This commit is contained in:
parent
e2ce9e8ffd
commit
a3effa6023
@ -16,12 +16,11 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from collectd_ceilometer.ceilometer import sender as ceilometer_sender
|
from collectd_ceilometer.ceilometer import sender as ceilometer_sender
|
||||||
from collections import defaultdict
|
from collectd_ceilometer.common.meters.storage import SampleContainer
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import six
|
import six
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
@ -46,43 +45,6 @@ class Sample(namedtuple('Sample', ['value', 'timestamp', 'meta',
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SampleContainer(object):
|
|
||||||
"""Sample storage"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._lock = threading.Lock()
|
|
||||||
self._data = defaultdict(list)
|
|
||||||
|
|
||||||
def add(self, key, samples, limit):
|
|
||||||
"""Store list of samples under the key
|
|
||||||
|
|
||||||
Store the list of samples under the given key. If numer of stored
|
|
||||||
samples is greater than the given limit, all the samples are returned
|
|
||||||
and the stored samples are dropped. Otherwise None is returned.
|
|
||||||
|
|
||||||
@param key key of the samples
|
|
||||||
@param samples list of samples
|
|
||||||
@param limit sample list limit
|
|
||||||
"""
|
|
||||||
with self._lock:
|
|
||||||
current = self._data[key]
|
|
||||||
current += samples
|
|
||||||
if len(current) >= limit:
|
|
||||||
self._data[key] = []
|
|
||||||
return current
|
|
||||||
return None
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
"""Reset stored samples
|
|
||||||
|
|
||||||
Returns all samples and removes them from the container.
|
|
||||||
"""
|
|
||||||
with self._lock:
|
|
||||||
retval = self._data
|
|
||||||
self._data = defaultdict(list)
|
|
||||||
return retval
|
|
||||||
|
|
||||||
|
|
||||||
class Writer(object):
|
class Writer(object):
|
||||||
"""Data collector"""
|
"""Data collector"""
|
||||||
|
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
import six
|
import six
|
||||||
|
import threading
|
||||||
|
|
||||||
from collectd_ceilometer.common.meters.base import Meter
|
from collectd_ceilometer.common.meters.base import Meter
|
||||||
from collectd_ceilometer.common.meters.libvirt import LibvirtMeter
|
from collectd_ceilometer.common.meters.libvirt import LibvirtMeter
|
||||||
@ -41,3 +43,40 @@ class MeterStorage(object):
|
|||||||
"""Get meter for the collectd plugin"""
|
"""Get meter for the collectd plugin"""
|
||||||
# return specialized meter class for collectd plugin or default Meter
|
# return specialized meter class for collectd plugin or default Meter
|
||||||
return self._meters.get(plugin, self._default)
|
return self._meters.get(plugin, self._default)
|
||||||
|
|
||||||
|
|
||||||
|
class SampleContainer(object):
|
||||||
|
"""Temporary storage for collectd samples"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._lock = threading.Lock()
|
||||||
|
self._data = defaultdict(list)
|
||||||
|
|
||||||
|
def add(self, key, samples, limit):
|
||||||
|
"""Store list of samples under the key
|
||||||
|
|
||||||
|
Store the list of samples under the given key. If the number of stored
|
||||||
|
samples is greater than the given limit, all the samples are returned
|
||||||
|
and the stored samples are dropped. Otherwise None is returned.
|
||||||
|
|
||||||
|
@param key key of the samples
|
||||||
|
@param samples list of samples
|
||||||
|
@param limit sample list limit
|
||||||
|
"""
|
||||||
|
with self._lock:
|
||||||
|
current = self._data[key]
|
||||||
|
current += samples
|
||||||
|
if len(current) >= limit:
|
||||||
|
self._data[key] = []
|
||||||
|
return current
|
||||||
|
return None
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Reset stored samples
|
||||||
|
|
||||||
|
Returns all samples and removes them from the container.
|
||||||
|
"""
|
||||||
|
with self._lock:
|
||||||
|
retval = self._data
|
||||||
|
self._data = defaultdict(list)
|
||||||
|
return retval
|
||||||
|
@ -15,14 +15,13 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from collectd_ceilometer.common.meters.storage import SampleContainer
|
||||||
from collectd_ceilometer.gnocchi import sender as gnocchi_sender
|
from collectd_ceilometer.gnocchi import sender as gnocchi_sender
|
||||||
from collections import defaultdict
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import six
|
import six
|
||||||
import threading
|
|
||||||
|
|
||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -39,43 +38,6 @@ class Sample(namedtuple('Sample', ['value', 'timestamp', 'meta',
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SampleContainer(object):
|
|
||||||
"""Sample storage"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._lock = threading.Lock()
|
|
||||||
self._data = defaultdict(list)
|
|
||||||
|
|
||||||
def add(self, key, samples, limit):
|
|
||||||
"""Store list of samples under the key
|
|
||||||
|
|
||||||
Store the list of samples under the given key. If numer of stored
|
|
||||||
samples is greater than the given limit, all the samples are returned
|
|
||||||
and the stored samples are dropped. Otherwise None is returned.
|
|
||||||
|
|
||||||
@param key key of the samples
|
|
||||||
@param samples list of samples
|
|
||||||
@param limit sample list limit
|
|
||||||
"""
|
|
||||||
with self._lock:
|
|
||||||
current = self._data[key]
|
|
||||||
current += samples
|
|
||||||
if len(current) >= limit:
|
|
||||||
self._data[key] = []
|
|
||||||
return current
|
|
||||||
return None
|
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
"""Reset stored samples
|
|
||||||
|
|
||||||
Returns all samples and removes them from the container.
|
|
||||||
"""
|
|
||||||
with self._lock:
|
|
||||||
retval = self._data
|
|
||||||
self._data = defaultdict(list)
|
|
||||||
return retval
|
|
||||||
|
|
||||||
|
|
||||||
class Writer(object):
|
class Writer(object):
|
||||||
"""Data collector"""
|
"""Data collector"""
|
||||||
|
|
||||||
|
91
collectd_ceilometer/tests/common/test_sample_container.py
Normal file
91
collectd_ceilometer/tests/common/test_sample_container.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright 2010-2011 OpenStack Foundation
|
||||||
|
# Copyright (c) 2015 Intel Corporation.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
"""Plugin tests"""
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from collectd_ceilometer.common.meters.storage import SampleContainer
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
|
|
||||||
|
class TestSampleContainer(unittest.TestCase):
|
||||||
|
"""Test the common.meters.storage.SampleContainer class"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestSampleContainer, self).setUp()
|
||||||
|
self.container = SampleContainer()
|
||||||
|
|
||||||
|
def test_sample_container_init(self):
|
||||||
|
"""Test creating the SampleContainer
|
||||||
|
|
||||||
|
Set-up: create a container
|
||||||
|
Test: Container is empty
|
||||||
|
Expected behaviour: container is an empty dict of lists
|
||||||
|
"""
|
||||||
|
self.assertEqual({}, self.container._data)
|
||||||
|
|
||||||
|
def test_sample_container_add(self):
|
||||||
|
"""Test adding an element to SampleContainer
|
||||||
|
|
||||||
|
Set-up: create empty SampleContainer
|
||||||
|
Test: add an element to the SampleContainer
|
||||||
|
Expected behaviour: _data contains the added elements
|
||||||
|
"""
|
||||||
|
retval = self.container.add("key1", ["value1"], 5)
|
||||||
|
|
||||||
|
self.assertEqual(retval, None)
|
||||||
|
self.assertEqual(["value1", ], self.container._data["key1"])
|
||||||
|
|
||||||
|
def test_sample_container_add_exceeds_limit(self):
|
||||||
|
"""Test adding an element to the Container so len > limit.
|
||||||
|
|
||||||
|
Set-up: len(SampleContainer._data ) < limit;
|
||||||
|
Test: Add items to the container so len() > limit
|
||||||
|
Expected behaviour: SampleContainer._data[key] is empty and add()
|
||||||
|
returns a list of samples of length limit
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.container._data, defaultdict(list))
|
||||||
|
|
||||||
|
retval = self.container.add("key1", ["1", "2", "3", ], 2)
|
||||||
|
|
||||||
|
self.assertEqual(retval, ["1", "2", "3", ])
|
||||||
|
self.assertEqual([], self.container._data["key1"])
|
||||||
|
|
||||||
|
def test_sample_container_reset(self):
|
||||||
|
"""Test resetting the contents of a meter entry in SampleContainer
|
||||||
|
|
||||||
|
Set-up: add some entries to the container (two meters)
|
||||||
|
action: call container.reset
|
||||||
|
Expected behaviour: the container will be equivalent to a default dict
|
||||||
|
and reset returns the stored data
|
||||||
|
"""
|
||||||
|
expected = {"key1": ["one", "two", "three", ],
|
||||||
|
"key2": ["1", "2", "3", ]}
|
||||||
|
|
||||||
|
self.container.add("key1", expected["key1"], 42)
|
||||||
|
self.container.add("key2", expected["key2"], 42)
|
||||||
|
|
||||||
|
self.assertEqual(expected, self.container._data)
|
||||||
|
|
||||||
|
retval = self.container.reset()
|
||||||
|
|
||||||
|
self.assertEqual(expected, retval)
|
||||||
|
self.assertEqual({}, self.container._data)
|
Loading…
Reference in New Issue
Block a user