Merge "[fix] Openstack Exporter - Handle Duplicate Values"

This commit is contained in:
Zuul 2020-04-13 23:52:23 +00:00 committed by Gerrit Code Review
commit da352c0880
9 changed files with 110 additions and 93 deletions

View File

@ -14,7 +14,6 @@
import re import re
class OSBase(object): class OSBase(object):
FAIL = 0 FAIL = 0
OK = 1 OK = 1

View File

@ -12,17 +12,15 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import logging
from urllib.parse import urlparse
from prometheus_client import CollectorRegistry, generate_latest, Gauge
from base import OSBase from base import OSBase
from urllib.parse import urlparse
from prometheus_client import CollectorRegistry, generate_latest, Gauge
import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s")
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class CheckOSApi(OSBase): class CheckOSApi(OSBase):
"""Class to check the status of OpenStack API services.""" """Class to check the status of OpenStack API services."""

View File

@ -12,14 +12,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from base import OSBase
from collections import Counter
from collections import defaultdict
from prometheus_client import CollectorRegistry, generate_latest, Gauge
import logging import logging
logging.basicConfig( from collections import Counter, defaultdict
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s") from prometheus_client import CollectorRegistry, generate_latest, Gauge
from base import OSBase
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -33,7 +32,7 @@ class CinderServiceStats(OSBase):
aggregated_workers = defaultdict(Counter) aggregated_workers = defaultdict(Counter)
stats = self.osclient.get_workers('cinder') stats = self.osclient.get_workers('cinderv3')
for worker in stats: for worker in stats:
service = worker['service'] service = worker['service']
state = worker['state'] state = worker['state']

View File

@ -12,13 +12,12 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from base import OSBase import logging
from prometheus_client import CollectorRegistry, generate_latest, Gauge from prometheus_client import CollectorRegistry, generate_latest, Gauge
import logging
logging.basicConfig( from base import OSBase
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s")
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -59,7 +58,7 @@ class HypervisorStats(OSBase):
'metrics': {'free_vcpus': 0}, 'metrics': {'free_vcpus': 0},
} }
nova_aggregates[agg['name']]['metrics'].update( nova_aggregates[agg['name']]['metrics'].update(
{v: 0 for v in list(self.VALUE_MAP.values())} {v: 0 for v in list(self.VALUE_MAP.values())}
) )
r = self.osclient.get('nova', 'os-hypervisors/detail') r = self.osclient.get('nova', 'os-hypervisors/detail')
@ -137,15 +136,28 @@ class HypervisorStats(OSBase):
labels = ['region', 'host', 'aggregate', 'aggregate_id'] labels = ['region', 'host', 'aggregate', 'aggregate_id']
hypervisor_stats_cache = self.get_cache_data() hypervisor_stats_cache = self.get_cache_data()
for hypervisor_stat in hypervisor_stats_cache: for hypervisor_stat in hypervisor_stats_cache:
stat_gauge = Gauge( try:
self.gauge_name_sanitize( stat_gauge = Gauge(
hypervisor_stat['stat_name']), self.gauge_name_sanitize(
'Openstack Hypervisor statistic', hypervisor_stat['stat_name']),
labels, 'Openstack Hypervisor statistic',
registry=registry) labels,
label_values = [self.osclient.region, registry=registry)
hypervisor_stat.get('host', ''), label_values = [self.osclient.region,
hypervisor_stat.get('aggregate', ''), hypervisor_stat.get('host', ''),
hypervisor_stat.get('aggregate_id', '')] hypervisor_stat.get('aggregate', ''),
stat_gauge.labels(*label_values).set(hypervisor_stat['stat_value']) hypervisor_stat.get('aggregate_id', '')]
stat_gauge.labels(*label_values).set(hypervisor_stat['stat_value'])
except ValueError:
if 'host' in hypervisor_stat:
location = hypervisor_stat['host']
elif 'aggregate' in hypervisor_stat:
location = hypervisor_stat['aggregate']
else:
location = 'N/A'
logger.debug('Unchanged value for stat {} already present in '
'hypervisor registry for host {}; ignoring.'
.format(hypervisor_stat['stat_name'], location))
return generate_latest(registry) return generate_latest(registry)

View File

@ -17,10 +17,10 @@ import argparse
import yaml import yaml
import os import os
import urllib.parse import urllib.parse
import logging
from http.server import BaseHTTPRequestHandler from http.server import BaseHTTPRequestHandler, HTTPServer
from http.server import HTTPServer
from socketserver import ForkingMixIn from socketserver import ForkingMixIn
from prometheus_client import CONTENT_TYPE_LATEST from prometheus_client import CONTENT_TYPE_LATEST
from osclient import OSClient from osclient import OSClient
@ -31,10 +31,10 @@ from nova_services import NovaServiceStats
from cinder_services import CinderServiceStats from cinder_services import CinderServiceStats
from hypervisor_stats import HypervisorStats from hypervisor_stats import HypervisorStats
import logging
logging.basicConfig( logging.basicConfig(
level=logging.DEBUG, level=logging.INFO,
format="%(asctime)s:%(levelname)s:%(message)s") format="%(asctime)s:%(levelname)s: %(message)s")
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
collectors = [] collectors = []
@ -57,10 +57,15 @@ class OpenstackExporterHandler(BaseHTTPRequestHandler):
stats = collector.get_stats() stats = collector.get_stats()
if stats is not None: if stats is not None:
output = output + stats output = output + stats
except BaseException: except BaseException as inst:
logger.warning( logger.warning(
"Could not get stats for collector {}".format( 'Could not get stats for collector {}.'
collector.get_cache_key())) '"{}" Exception "{}" occured.'
.format(
collector.get_cache_key(),
type(inst),
inst
))
self.send_response(200) self.send_response(200)
self.send_header('Content-Type', CONTENT_TYPE_LATEST) self.send_header('Content-Type', CONTENT_TYPE_LATEST)
self.end_headers() self.end_headers()

View File

@ -12,14 +12,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from base import OSBase
from collections import Counter
from collections import defaultdict
from prometheus_client import CollectorRegistry, generate_latest, Gauge
import logging import logging
logging.basicConfig( from collections import Counter, defaultdict
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s") from prometheus_client import CollectorRegistry, generate_latest, Gauge
from base import OSBase
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -67,18 +66,25 @@ class NeutronAgentStats(OSBase):
labels = ['region', 'host', 'service', 'state'] labels = ['region', 'host', 'service', 'state']
neutron_agent_stats_cache = self.get_cache_data() neutron_agent_stats_cache = self.get_cache_data()
for neutron_agent_stat in neutron_agent_stats_cache: for neutron_agent_stat in neutron_agent_stats_cache:
stat_gauge = Gauge( try:
self.gauge_name_sanitize( stat_gauge = Gauge(
neutron_agent_stat['stat_name']), self.gauge_name_sanitize(
'Openstack Neutron agent statistic', neutron_agent_stat['stat_name']),
labels, 'Openstack Neutron agent statistic',
registry=registry) labels,
label_values = [self.osclient.region, registry=registry)
neutron_agent_stat.get('host', ''), label_values = [self.osclient.region,
neutron_agent_stat.get('service', ''), neutron_agent_stat.get('host', ''),
neutron_agent_stat.get('state', '')] neutron_agent_stat.get('service', ''),
stat_gauge.labels( neutron_agent_stat.get('state', '')]
* stat_gauge.labels(
label_values).set( *
neutron_agent_stat['stat_value']) label_values).set(
neutron_agent_stat['stat_value'])
except ValueError:
logger.debug('Unchanged value for stat {} already present in '
'neutron agent registry for host {}; ignoring.'
.format(neutron_agent_stat['stat_name'],
neutron_agent_stat['host']))
return generate_latest(registry) return generate_latest(registry)

View File

@ -12,16 +12,14 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from base import OSBase
from collections import Counter
from collections import defaultdict
from prometheus_client import CollectorRegistry, generate_latest, Gauge
import logging import logging
logging.basicConfig( from collections import Counter, defaultdict
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s")
logger = logging.getLogger(__name__)
from prometheus_client import CollectorRegistry, generate_latest, Gauge
from base import OSBase
logger = logging.getLogger(__name__)
class NovaServiceStats(OSBase): class NovaServiceStats(OSBase):
""" Class to report the statistics on Nova services. """ Class to report the statistics on Nova services.
@ -68,15 +66,22 @@ class NovaServiceStats(OSBase):
labels = ['region', 'host', 'service', 'state'] labels = ['region', 'host', 'service', 'state']
services_stats_cache = self.get_cache_data() services_stats_cache = self.get_cache_data()
for services_stat in services_stats_cache: for services_stat in services_stats_cache:
stat_gauge = Gauge( try:
self.gauge_name_sanitize( stat_gauge = Gauge(
services_stat['stat_name']), self.gauge_name_sanitize(
'Openstack Nova Service statistic', services_stat['stat_name']),
labels, 'Openstack Nova Service statistic',
registry=registry) labels,
label_values = [self.osclient.region, registry=registry)
services_stat.get('host', ''), label_values = [self.osclient.region,
services_stat.get('service', ''), services_stat.get('host', ''),
services_stat.get('state', '')] services_stat.get('service', ''),
stat_gauge.labels(*label_values).set(services_stat['stat_value']) services_stat.get('state', '')]
stat_gauge.labels(*label_values).set(services_stat['stat_value'])
except ValueError:
logger.debug('Unchanged value for stat {} already present in '
'nova services registry for host {}; ignoring.'
.format(services_stat['stat_name'],
services_stat['host']))
return generate_latest(registry) return generate_latest(registry)

View File

@ -14,14 +14,12 @@
from threading import Thread from threading import Thread
from threading import Lock from threading import Lock
from prometheus_client import CollectorRegistry, generate_latest, Gauge
from time import sleep, time from time import sleep, time
import logging import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s")
logger = logging.getLogger(__name__)
from prometheus_client import CollectorRegistry, generate_latest, Gauge
logger = logging.getLogger(__name__)
class ThreadSafeDict(dict): class ThreadSafeDict(dict):
def __init__(self, * p_arg, ** n_arg): def __init__(self, * p_arg, ** n_arg):
@ -35,7 +33,6 @@ class ThreadSafeDict(dict):
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
self._lock.release() self._lock.release()
class OSCache(Thread): class OSCache(Thread):
def __init__(self, refresh_interval, region): def __init__(self, refresh_interval, region):

View File

@ -18,16 +18,12 @@ import dateutil.tz
import requests import requests
import simplejson as json import simplejson as json
import logging import logging
logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s:%(levelname)s:%(message)s")
logger = logging.getLogger(__name__)
logger = logging.getLogger(__name__)
class KeystoneException(Exception): class KeystoneException(Exception):
pass pass
class OSClient(object): class OSClient(object):
""" Base class for querying the OpenStack API endpoints. """ Base class for querying the OpenStack API endpoints.