diff --git a/ceilometer/dispatcher/http.py b/ceilometer/dispatcher/http.py index b69c473d..87b00a63 100644 --- a/ceilometer/dispatcher/http.py +++ b/ceilometer/dispatcher/http.py @@ -91,28 +91,43 @@ class HttpDispatcher(dispatcher.MeterDispatcherBase, 'counter_volume': meter['counter_volume']}) try: # Every meter should be posted to the target + meter_json = json.dumps(meter) + LOG.trace('Meter Message: %s', meter_json) res = requests.post(self.target, - data=json.dumps(meter), + data=meter_json, headers=self.headers, timeout=self.timeout) - LOG.debug('Message posting finished with status code ' + LOG.debug('Meter message posting finished with status code ' '%d.', res.status_code) - except Exception as err: - LOG.exception(_LE('Failed to record metering data: %s.'), err) + res.raise_for_status() + except requests.exceptions.HTTPError: + LOG.exception(_LE('Status Code: %{code}s. Failed to' + 'dispatch meter: %{meter}s'), + {'code': res.status_code, 'meter': meter}) def record_events(self, events): + if self.event_target == '': + # if the event target was not set, do not do anything + LOG.error(_LE('Dispatcher event target was not set, no event will ' + 'be posted. Set event_target in the ceilometer.conf ' + 'file.')) + return + if not isinstance(events, list): events = [events] for event in events: - res = None try: - res = requests.post(self.event_target, data=event, + event_json = json.dumps(event) + LOG.trace('Event Message: %s', event_json) + res = requests.post(self.event_target, + data=event_json, headers=self.headers, timeout=self.timeout) + LOG.debug('Event Message posting finished with status code ' + '%d.', res.status_code) res.raise_for_status() - except Exception: - error_code = res.status_code if res else 'unknown' + except requests.exceptions.HTTPError: LOG.exception(_LE('Status Code: %{code}s. Failed to' 'dispatch event: %{event}s'), - {'code': error_code, 'event': event}) + {'code': res.status_code, 'event': event}) diff --git a/ceilometer/tests/unit/dispatcher/test_http.py b/ceilometer/tests/unit/dispatcher/test_http.py index 9c7f352d..aed0e84f 100644 --- a/ceilometer/tests/unit/dispatcher/test_http.py +++ b/ceilometer/tests/unit/dispatcher/test_http.py @@ -27,6 +27,7 @@ from ceilometer.publisher import utils class TestDispatcherHttp(base.BaseTestCase): + """Test sending meters with the http dispatcher""" def setUp(self): super(TestDispatcherHttp, self).setUp() @@ -72,50 +73,61 @@ class TestDispatcherHttp(base.BaseTestCase): class TestEventDispatcherHttp(base.BaseTestCase): - + """Test sending events with the http dispatcher""" def setUp(self): super(TestEventDispatcherHttp, self).setUp() self.CONF = self.useFixture(fixture_config.Config()).conf + # repr(uuid.uuid4()) is used in test event creation to avoid an + # exception being thrown when the uuid is serialized to JSON + event = event_models.Event(repr(uuid.uuid4()), 'test', + datetime.datetime(2012, 7, 2, 13, 53, 40), + [], {}) + event = utils.message_from_event(event, + self.CONF.publisher.telemetry_secret) + self.event = event + def test_http_dispatcher(self): self.CONF.dispatcher_http.event_target = 'fake' dispatcher = http.HttpDispatcher(self.CONF) - event = event_models.Event(uuid.uuid4(), 'test', - datetime.datetime(2012, 7, 2, 13, 53, 40), - [], {}) - event = utils.message_from_event(event, - self.CONF.publisher.telemetry_secret) - with mock.patch.object(requests, 'post') as post: - dispatcher.record_events(event) + dispatcher.record_events(self.event) self.assertEqual(1, post.call_count) - def test_http_dispatcher_bad(self): + def test_http_dispatcher_bad_server(self): + self.CONF.dispatcher_http.event_target = 'fake' + dispatcher = http.HttpDispatcher(self.CONF) + + with mock.patch.object(requests, 'post') as post: + response = requests.Response() + response.status_code = 500 + post.return_value = response + with mock.patch('ceilometer.dispatcher.http.LOG', + mock.MagicMock()) as LOG: + dispatcher.record_events(self.event) + self.assertTrue(LOG.exception.called) + + def test_http_dispatcher_with_no_target(self): self.CONF.dispatcher_http.event_target = '' dispatcher = http.HttpDispatcher(self.CONF) - event = event_models.Event(uuid.uuid4(), 'test', - datetime.datetime(2012, 7, 2, 13, 53, 40), - [], {}) - event = utils.message_from_event(event, - self.CONF.publisher.telemetry_secret) - with mock.patch('ceilometer.dispatcher.http.LOG', - mock.MagicMock()) as LOG: - dispatcher.record_events(event) - self.assertTrue(LOG.exception.called) + # The target should be None + self.assertEqual('', dispatcher.event_target) + + with mock.patch.object(requests, 'post') as post: + dispatcher.record_events(self.event) + + # Since the target is not set, no http post should occur, thus the + # call_count should be zero. + self.assertEqual(0, post.call_count) def test_http_dispatcher_share_target(self): self.CONF.dispatcher_http.target = 'fake' dispatcher = http.HttpDispatcher(self.CONF) - event = event_models.Event(uuid.uuid4(), 'test', - datetime.datetime(2012, 7, 2, 13, 53, 40), - [], {}) - event = utils.message_from_event(event, - self.CONF.publisher.telemetry_secret) with mock.patch.object(requests, 'post') as post: - dispatcher.record_events(event) + dispatcher.record_events(self.event) self.assertEqual('fake', post.call_args[0][0])