From 063af43744bb0c29ce866bba6d3c40e3508a201f Mon Sep 17 00:00:00 2001 From: Richard Devers Date: Fri, 27 Jul 2018 08:03:44 -0400 Subject: [PATCH] Add option to file publisher to write json Change-Id: I21f6f8fca8de1d6b8784e140382d1a1a99398279 Closes-Bug: #1783985 --- ceilometer/publisher/file.py | 22 ++++++++++---- ceilometer/tests/unit/publisher/test_file.py | 30 +++++++++++++++++++ doc/source/admin/telemetry-data-pipelines.rst | 4 +++ ...ut-to-file-publisher-786380cb7e21b56b.yaml | 5 ++++ 4 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 releasenotes/notes/add-json-output-to-file-publisher-786380cb7e21b56b.yaml diff --git a/ceilometer/publisher/file.py b/ceilometer/publisher/file.py index 3fb0f72eb9..43af7e8554 100644 --- a/ceilometer/publisher/file.py +++ b/ceilometer/publisher/file.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import json import logging import logging.handlers @@ -41,12 +42,13 @@ class FilePublisher(publisher.ConfigPublisherBase): meters: - "*" publishers: - - file:///var/test?max_bytes=10000000&backup_count=5 + - file:///var/test?max_bytes=10000000&backup_count=5&json File path is required for this publisher to work properly. If max_bytes or backup_count is missing, FileHandler will be used to save the metering data. If max_bytes and backup_count are present, RotatingFileHandler will - be used to save the metering data. + be used to save the metering data. The json argument is used to explicitely + ask ceilometer to write json into the file. """ def __init__(self, conf, parsed_url): @@ -61,9 +63,13 @@ class FilePublisher(publisher.ConfigPublisherBase): rfh = None max_bytes = 0 backup_count = 0 + self.output_json = None # Handling other configuration options in the query string if parsed_url.query: - params = urlparse.parse_qs(parsed_url.query) + params = urlparse.parse_qs(parsed_url.query, + keep_blank_values=True) + if "json" in params: + self.output_json = True if params.get('max_bytes') and params.get('backup_count'): try: max_bytes = int(params.get('max_bytes')[0]) @@ -90,7 +96,10 @@ class FilePublisher(publisher.ConfigPublisherBase): """ if self.publisher_logger: for sample in samples: - self.publisher_logger.info(sample.as_dict()) + if self.output_json: + self.publisher_logger.info(json.dumps(sample.as_dict())) + else: + self.publisher_logger.info(sample.as_dict()) def publish_events(self, events): """Send an event message for publishing @@ -99,4 +108,7 @@ class FilePublisher(publisher.ConfigPublisherBase): """ if self.publisher_logger: for event in events: - self.publisher_logger.info(event.as_dict()) + if self.output_json: + self.publisher_logger.info(json.dumps(event.as_dict())) + else: + self.publisher_logger.info(event.as_dict()) diff --git a/ceilometer/tests/unit/publisher/test_file.py b/ceilometer/tests/unit/publisher/test_file.py index 433b1414ce..1f45ce2850 100644 --- a/ceilometer/tests/unit/publisher/test_file.py +++ b/ceilometer/tests/unit/publisher/test_file.py @@ -16,6 +16,7 @@ """ import datetime +import json import logging.handlers import os import tempfile @@ -120,3 +121,32 @@ class TestFilePublisher(base.BaseTestCase): publisher.publish_samples(self.test_data) self.assertIsNone(publisher.publisher_logger) + + def test_file_publisher_json(self): + tempdir = tempfile.mkdtemp() + name = '%s/log_file_json' % tempdir + parsed_url = netutils.urlsplit('file://%s?json' % name) + + publisher = file.FilePublisher(self.CONF, parsed_url) + publisher.publish_samples(self.test_data) + + handler = publisher.publisher_logger.handlers[0] + self.assertIsInstance(handler, + logging.handlers.RotatingFileHandler) + self.assertEqual([0, name, 0], [handler.maxBytes, + handler.baseFilename, + handler.backupCount]) + self.assertTrue(os.path.exists(name)) + with open(name, 'r') as f: + content = f.readlines() + + self.assertEqual(len(self.test_data), len(content)) + for index, line in enumerate(content): + try: + json_data = json.loads(line) + except ValueError: + self.fail("File written is not valid json") + self.assertEqual(self.test_data[index].id, + json_data['id']) + self.assertEqual(self.test_data[index].timestamp, + json_data['timestamp']) diff --git a/doc/source/admin/telemetry-data-pipelines.rst b/doc/source/admin/telemetry-data-pipelines.rst index d3c6bb5600..30366d0489 100644 --- a/doc/source/admin/telemetry-data-pipelines.rst +++ b/doc/source/admin/telemetry-data-pipelines.rst @@ -247,6 +247,10 @@ The following options are available for the ``file`` publisher: the newest data is always the one that is specified without any extensions. +``json`` + If this option is present, will force ceilometer to write json format + into the file. + http ```` diff --git a/releasenotes/notes/add-json-output-to-file-publisher-786380cb7e21b56b.yaml b/releasenotes/notes/add-json-output-to-file-publisher-786380cb7e21b56b.yaml new file mode 100644 index 0000000000..e30aca1e8b --- /dev/null +++ b/releasenotes/notes/add-json-output-to-file-publisher-786380cb7e21b56b.yaml @@ -0,0 +1,5 @@ +--- +features: + - > + Add new json output option for the existing file publisher. +