Move timestamp registry to a sharable 'header' module

The timestamp registry is going to be used by other parsers
in the future. Thus it seems reasonable to move if from ipmi
to something sharable.

Conceptually, `timestamp_registry` operates on Oslo message
header - perhaps we can have a dedicated parser module for
such common things - 'header'.

Change-Id: I2ba2f0ae28f09dbccd818c82005d47c7a515dfd4
This commit is contained in:
Ilya Etingof 2019-09-05 16:32:05 +02:00
parent 5398f864f1
commit 46e50fb56f
6 changed files with 95 additions and 26 deletions

View File

@ -14,6 +14,7 @@ import logging
import os import os
from ironic_prometheus_exporter.parsers import ipmi from ironic_prometheus_exporter.parsers import ipmi
from ironic_prometheus_exporter.parsers import header
from oslo_config import cfg from oslo_config import cfg
from oslo_messaging.notify import notifier from oslo_messaging.notify import notifier
from prometheus_client import write_to_textfile, CollectorRegistry from prometheus_client import write_to_textfile, CollectorRegistry
@ -45,7 +46,7 @@ class PrometheusFileDriver(notifier.Driver):
if message['event_type'] == 'hardware.ipmi.metrics': if message['event_type'] == 'hardware.ipmi.metrics':
registry = CollectorRegistry() registry = CollectorRegistry()
node_message = message['payload'] node_message = message['payload']
ipmi.timestamp_registry(node_message, registry) header.timestamp_registry(node_message, registry)
ipmi.category_registry(node_message, registry) ipmi.category_registry(node_message, registry)
nodeFile = os.path.join(self.location, nodeFile = os.path.join(self.location,
node_message['node_name']) node_message['node_name'])

View File

@ -0,0 +1,28 @@
# 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.
from datetime import datetime
from prometheus_client import Gauge
def timestamp_registry(node_information, ipmi_metric_registry):
metric = 'baremetal_last_payload_timestamp_seconds'
labels = {'node_name': node_information['node_name'],
'node_uuid': node_information['node_uuid'],
'instance_uuid': node_information['instance_uuid']}
dt_1970 = datetime(1970, 1, 1, 0, 0, 0)
dt_timestamp = datetime.strptime(node_information['timestamp'],
'%Y-%m-%dT%H:%M:%S.%f')
value = int((dt_timestamp - dt_1970).total_seconds())
g = Gauge(metric, 'Timestamp of the last received payload',
labelnames=labels.keys(), registry=ipmi_metric_registry)
g.labels(**labels).set(value)

View File

@ -15,7 +15,6 @@ import logging
import pkg_resources import pkg_resources
import re import re
from datetime import datetime
from prometheus_client import Gauge from prometheus_client import Gauge
# NOTE (iurygregory): most of the sensor readings come in the ipmi format # NOTE (iurygregory): most of the sensor readings come in the ipmi format
@ -243,19 +242,5 @@ def category_registry(node_message, ipmi_metric_registry):
available_metrics) available_metrics)
def timestamp_registry(node_information, ipmi_metric_registry):
metric = 'baremetal_last_payload_timestamp_seconds'
labels = {'node_name': node_information['node_name'],
'node_uuid': node_information['node_uuid'],
'instance_uuid': node_information['instance_uuid']}
dt_1970 = datetime(1970, 1, 1, 0, 0, 0)
dt_timestamp = datetime.strptime(node_information['timestamp'],
'%Y-%m-%dT%H:%M:%S.%f')
value = int((dt_timestamp - dt_1970).total_seconds())
g = Gauge(metric, get_metric_description(metric),
labelnames=list(labels), registry=ipmi_metric_registry)
g.labels(**labels).set(value)
def get_metric_description(metric_name): def get_metric_description(metric_name):
return IPMI_METRICS_DESCRIPTION.get(metric_name, '') return IPMI_METRICS_DESCRIPTION.get(metric_name, '')

View File

@ -0,0 +1,17 @@
{
"priority": "INFO",
"event_type": "hardware.redfish.metrics",
"timestamp": "2019-03-29 20:12:26.885347",
"publisher_id": "None.localhost.localdomain",
"payload": {
"instance_uuid": "ac2aa2fd-6e1a-41c8-a114-2084c8705228",
"node_uuid": "ac2aa2fd-6e1a-41c8-a114-2084c8705228",
"event_type": "hardware.redfish.metrics.update",
"timestamp": "2019-03-29T20:12:22.989020",
"node_name": "knilab-master-u9",
"message_id": "85d6b2c8-fe57-432d-868a-330e0e28cf34",
"payload": {
}
},
"message_id": "2c0da1e8-1958-484f-9bdd-9117d717f7fa"
}

View File

@ -0,0 +1,48 @@
# 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.
import json
import os
import unittest
import ironic_prometheus_exporter
from ironic_prometheus_exporter.parsers import header
from prometheus_client import CollectorRegistry
sample_file = os.path.join(
os.path.dirname(ironic_prometheus_exporter.__file__),
'tests', 'json_samples', 'notification-header.json')
DATA = json.load(open(sample_file))
class TestPayloadsParser(unittest.TestCase):
def setUp(self):
self.node_message = DATA['payload']
self.node_name = DATA['payload']['node_name']
self.node_uuid = DATA['payload']['node_uuid']
self.instance_uuid = DATA['payload']['instance_uuid']
self.timestamp = DATA['payload']['timestamp']
self.payload = DATA['payload']['payload']
self.metric_registry = CollectorRegistry()
def test_timestamp_metric(self):
header.timestamp_registry(self.node_message, self.metric_registry)
self.assertEqual(1553890342.0, self.metric_registry.get_sample_value(
'baremetal_last_payload_timestamp_seconds',
{'node_name': self.node_name,
'node_uuid': self.node_uuid,
'instance_uuid': self.instance_uuid}
))

View File

@ -559,16 +559,6 @@ class TestPayloadsParser(unittest.TestCase):
'entity_id': '7.1 (System Board)', 'entity_id': '7.1 (System Board)',
'status': 'ok'})) 'status': 'ok'}))
def test_timestamp_metric(self):
ipmi.timestamp_registry(self.node_message, self.metric_registry)
self.assertEqual(1553890342.0, self.metric_registry.get_sample_value(
'baremetal_last_payload_timestamp_seconds',
{'node_name': self.node_name,
'node_uuid': self.node_uuid,
'instance_uuid': self.instance_uuid}
))
def test_voltage_manager(self): def test_voltage_manager(self):
voltage_category_info = ipmi.CATEGORY_PARAMS['voltage'].copy() voltage_category_info = ipmi.CATEGORY_PARAMS['voltage'].copy()
voltage_category_info['data'] = \ voltage_category_info['data'] = \