class TestHekaClient(object): logger = 'tests' timer_name = 'test' def setUp(self): self.mock_stream = DebugCaptureStream() class NoEncoder(object): def __init__(self, hmc): pass def encode(self, msg): return msg self.client = HekaClient(self.mock_stream, self.logger, encoder=NoEncoder) # overwrite the class-wide threadlocal w/ an instance one # so values won't persist btn tests self.timer_ob = self.client.timer(self.timer_name) self.timer_ob.__dict__['_local'] = threading.local() def tearDown(self): del self.timer_ob.__dict__['_local'] del self.mock_stream def _extract_full_msg(self): msg = self.mock_stream.msgs.pop() return msg def compute_timestamp(self): """ These should be nanoseconds """ return int(time.time() * 1000000000) @raises(ValueError) def test_heka_flatten_nulls(self): """ None values in the fields dictionary should throw an error """ payload = 'this is a test' self.client.heka('some_msg_type', payload=payload, fields={'foo': None}) def test_heka_bare(self): payload = 'this is a test' before = self.compute_timestamp() msgtype = 'testtype' self.client.heka(msgtype, payload=payload) after = self.compute_timestamp() full_msg = self._extract_full_msg() # check the payload eq_(full_msg.payload, payload) # check the various default values ok_(before < full_msg.timestamp < after) eq_(full_msg.type, msgtype) eq_(full_msg.severity, self.client.severity) eq_(full_msg.logger, self.logger) eq_(full_msg.pid, os.getpid()) eq_(full_msg.hostname, socket.gethostname()) eq_(full_msg.env_version, self.client.env_version) def test_heka_full(self): heka_args = dict(payload='this is another test', logger='alternate', severity=2, fields={'foo': 'bar', 'boo': 'far'}) msgtype = 'bawlp' self.client.heka(msgtype, **heka_args) actual_msg = self._extract_full_msg() heka_args.update({'type': msgtype, 'env_version': self.client.env_version, 'heka_pid': os.getpid(), 'heka_hostname': socket.gethostname(), 'timestamp': actual_msg.timestamp}) # Everything but the UUID should be identical expected_msg = dict_to_msg(heka_args) pbencoder = ProtobufEncoder() h, actual_msg = decode_message(pbencoder.encode(actual_msg)) h, expected_msg = decode_message(pbencoder.encode(expected_msg)) expected_msg.uuid = '' actual_msg.uuid = '' eq_(actual_msg, expected_msg) def test_heka_timestamp(self): payload = 'this is a timestamp test' timestamp = time.time() msgtype = 'testtype' self.client.heka(msgtype, payload=payload, timestamp=timestamp) full_msg = self._extract_full_msg() eq_(full_msg.timestamp, timestamp * 1000000000) timestamp = datetime.datetime.now() self.client.heka(msgtype, payload=payload, timestamp=timestamp) full_msg = self._extract_full_msg() eq_(full_msg.timestamp, time.mktime(timestamp.timetuple()) * 1000000000) def test_oldstyle(self): payload = 'debug message' self.client.debug(payload) full_msg = self._extract_full_msg() eq_(full_msg.payload, payload) eq_(full_msg.severity, SEVERITY.DEBUG) def test_oldstyle_args(self): payload = '1, 2: %s\n3, 4: %s' args = ('buckle my shoe', 'shut the door') self.client.warn(payload, *args) full_msg = self._extract_full_msg() eq_(full_msg.payload, payload % args) def test_oldstyle_mapping_arg(self): payload = '1, 2: %(onetwo)s\n3, 4: %(threefour)s' args = {'onetwo': 'buckle my shoe', 'threefour': 'shut the door'} self.client.warn(payload, args) full_msg = self._extract_full_msg() eq_(full_msg.payload, payload % args) def test_oldstyle_exc_info(self): payload = 'traceback ahead -->' try: a = b # NOQA except NameError: self.client.error(payload, exc_info=True) full_msg = self._extract_full_msg() ok_(full_msg.payload.startswith(payload)) ok_("NameError: global name 'b' is not defined" in full_msg.payload) ok_('test_client.py' in full_msg.payload) def test_oldstyle_exc_info_auto(self): payload = 'traceback ahead -->' try: a = b # NOQA except NameError: self.client.exception(payload) full_msg = self._extract_full_msg() ok_(full_msg.payload.startswith(payload)) ok_("NameError: global name 'b' is not defined" in full_msg.payload) ok_('test_client.py' in full_msg.payload) def test_oldstyle_exc_info_passed(self): def name_error(): try: a = b # NOQA except NameError: return sys.exc_info() ei = name_error() payload = 'traceback ahead -->' self.client.critical(payload, exc_info=ei) full_msg = self._extract_full_msg() ok_(full_msg.payload.startswith(payload)) ok_("NameError: global name 'b' is not defined" in full_msg.payload) ok_('test_client.py' in full_msg.payload) def test_timer_contextmanager(self): name = self.timer_name with self.client.timer(name) as timer: time.sleep(0.01) ok_(timer.result >= 10) full_msg = self._extract_full_msg() eq_(full_msg.payload, str(timer.result)) eq_(full_msg.type, 'timer') eq_(first_value(full_msg, 'name'), name) eq_(first_value(full_msg, 'rate'), 1) def test_timer_decorator(self): @self.client.timer(self.timer_name) def timed(): time.sleep(0.01) ok_(not len(self.mock_stream.msgs)) timed() full_msg = self._extract_full_msg() ok_(int(full_msg.payload) >= 10) eq_(full_msg.type, 'timer') eq_(first_value(full_msg, 'name'), self.timer_name) eq_(first_value(full_msg, 'rate'), 1) eq_(first_value(full_msg, 'rate'), 1) def test_timer_with_rate(self): name = self.timer_name @self.client.timer(name, rate=0.01) def timed(): time.sleep(0.001) # leverage chance by using a large sample # instead of just 10 samples for i in range(1000): timed() # this is a weak test, but not quite sure how else to # test explicitly random behaviour ok_(len(self.mock_stream.msgs) < 200) def test_incr(self): name = 'incr' self.client.incr(name) full_msg = self._extract_full_msg() eq_(full_msg.type, 'counter') eq_(full_msg.logger, self.logger) eq_(first_value(full_msg, 'name'), name) # You have to have a rate set here eq_(first_value(full_msg, 'rate'), 1) eq_(full_msg.payload, '1') self.client.incr(name, 10) full_msg = self._extract_full_msg() eq_(full_msg.payload, '10')
class TestHekaClient(object): logger = 'tests' timer_name = 'test' def setUp(self): self.mock_sender = Mock() self.client = HekaClient(self.mock_sender, self.logger) # overwrite the class-wide threadlocal w/ an instance one # so values won't persist btn tests self.timer_ob = self.client.timer(self.timer_name) self.timer_ob.__dict__['_local'] = threading.local() def tearDown(self): del self.timer_ob.__dict__['_local'] del self.mock_sender def _extract_full_msg(self): msg = self.mock_sender.send_message.call_args[0][0] return msg def compute_timestamp(self): return int(time.time() * 1000000) @raises(ValueError) def test_heka_flatten_nulls(self): """ None values in the fields dictionary should throw an error """ payload = 'this is a test' self.client.heka('some_msg_type', payload=payload, fields={'foo': None}) def test_heka_bare(self): payload = 'this is a test' before = self.compute_timestamp() msgtype = 'testtype' self.client.heka(msgtype, payload=payload) after = self.compute_timestamp() full_msg = self._extract_full_msg() # check the payload eq_(full_msg.payload, payload) # check the various default values ok_(before < full_msg.timestamp < after) eq_(full_msg.type, msgtype) eq_(full_msg.severity, self.client.severity) eq_(full_msg.logger, self.logger) eq_(full_msg.pid, os.getpid()) eq_(full_msg.hostname, socket.gethostname()) eq_(full_msg.env_version, self.client.env_version) def test_heka_full(self): heka_args = dict(payload='this is another test', logger='alternate', severity=2, fields={ 'foo': 'bar', 'boo': 'far' }) msgtype = 'bawlp' self.client.heka(msgtype, **heka_args) actual_msg = self._extract_full_msg() heka_args.update({ 'type': msgtype, 'env_version': self.client.env_version, 'heka_pid': os.getpid(), 'heka_hostname': socket.gethostname(), 'timestamp': actual_msg.timestamp }) # Everything but the UUID should be identical expected_msg = dict_to_msg(heka_args) actual_dict = json.loads(JSONMessageEncoder().encode(actual_msg)) expected_dict = json.loads(JSONMessageEncoder().encode(expected_msg)) del expected_dict['uuid'] del actual_dict['uuid'] eq_(actual_dict, expected_dict) def test_oldstyle(self): payload = 'debug message' self.client.debug(payload) full_msg = self._extract_full_msg() eq_(full_msg.payload, payload) eq_(full_msg.severity, SEVERITY.DEBUG) def test_oldstyle_args(self): payload = '1, 2: %s\n3, 4: %s' args = ('buckle my shoe', 'shut the door') self.client.warn(payload, *args) full_msg = self._extract_full_msg() eq_(full_msg.payload, payload % args) def test_oldstyle_mapping_arg(self): payload = '1, 2: %(onetwo)s\n3, 4: %(threefour)s' args = {'onetwo': 'buckle my shoe', 'threefour': 'shut the door'} self.client.warn(payload, args) full_msg = self._extract_full_msg() eq_(full_msg.payload, payload % args) def test_oldstyle_exc_info(self): payload = 'traceback ahead -->' try: a = b # NOQA except NameError: self.client.error(payload, exc_info=True) full_msg = self._extract_full_msg() ok_(full_msg.payload.startswith(payload)) ok_("NameError: global name 'b' is not defined" in full_msg.payload) ok_('test_client.py' in full_msg.payload) def test_oldstyle_exc_info_auto(self): payload = 'traceback ahead -->' try: a = b # NOQA except NameError: self.client.exception(payload) full_msg = self._extract_full_msg() ok_(full_msg.payload.startswith(payload)) ok_("NameError: global name 'b' is not defined" in full_msg.payload) ok_('test_client.py' in full_msg.payload) def test_oldstyle_exc_info_passed(self): def name_error(): try: a = b # NOQA except NameError: return sys.exc_info() ei = name_error() payload = 'traceback ahead -->' self.client.critical(payload, exc_info=ei) full_msg = self._extract_full_msg() ok_(full_msg.payload.startswith(payload)) ok_("NameError: global name 'b' is not defined" in full_msg.payload) ok_('test_client.py' in full_msg.payload) def test_timer_contextmanager(self): name = self.timer_name with self.client.timer(name) as timer: time.sleep(0.01) ok_(timer.result >= 10) full_msg = self._extract_full_msg() eq_(full_msg.payload, str(timer.result)) eq_(full_msg.type, 'timer') eq_(first_value(full_msg, 'name'), name) eq_(first_value(full_msg, 'rate'), 1) def test_timer_decorator(self): @self.client.timer(self.timer_name) def timed(): time.sleep(0.01) ok_(not self.mock_sender.send_message.called) timed() full_msg = self._extract_full_msg() ok_(int(full_msg.payload) >= 10) eq_(full_msg.type, 'timer') eq_(first_value(full_msg, 'name'), self.timer_name) eq_(first_value(full_msg, 'rate'), 1) eq_(first_value(full_msg, 'rate'), 1) def test_timer_with_rate(self): name = self.timer_name @self.client.timer(name, rate=0.01) def timed(): time.sleep(0.001) # leverage chance by using a large sample # instead of just 10 samples for i in range(1000): timed() # this is a weak test, but not quite sure how else to # test explicitly random behaviour ok_(self.mock_sender.send_message.call_count < 100) def test_incr(self): name = 'incr' self.client.incr(name) full_msg = self._extract_full_msg() eq_(full_msg.type, 'counter') eq_(full_msg.logger, self.logger) eq_(first_value(full_msg, 'name'), name) # You have to have a rate set here eq_(first_value(full_msg, 'rate'), 1) eq_(full_msg.payload, '1') self.client.incr(name, 10) full_msg = self._extract_full_msg() eq_(full_msg.payload, '10')
class TestHekaClientFilters(object): logger = 'tests' timer_name = 'test' def setUp(self): self.stream = DebugCaptureStream() self.client = HekaClient(self.stream, self.logger) def tearDown(self): del self.stream del self.client def test_severity_max(self): from heka.filters import severity_max_provider self.client.filters = [severity_max_provider(severity=SEVERITY.ERROR)] payload = 'foo' self.client.debug(payload) self.client.info(payload) self.client.warn(payload) self.client.error(payload) self.client.exception(payload) self.client.critical(payload) # only half of the messages should have gone out eq_(len(self.stream.msgs), 3) # make sure it's the right half for json_msg in self.stream.msgs: msg = self._extract_msg(json_msg) ok_(msg.severity <= SEVERITY.ERROR) def test_type_blacklist(self): from heka.filters import type_blacklist_provider type_blacklist = type_blacklist_provider(types=set(['foo'])) self.client.filters = [type_blacklist] choices = ['foo', 'bar'] notfoos = 0 for i in range(10): choice = random.choice(choices) if choice != 'foo': notfoos += 1 self.client.heka(choice, payload='msg') eq_(len(self.stream.msgs), notfoos) def test_type_whitelist(self): from heka.filters import type_whitelist_provider type_whitelist = type_whitelist_provider(types=set(['foo'])) self.client.filters = [type_whitelist] choices = ['foo', 'bar'] foos = 0 for i in range(10): choice = random.choice(choices) if choice == 'foo': foos += 1 self.client.heka(choice, payload='msg') eq_(len(self.stream.msgs), foos) def test_type_severity_max(self): from heka.filters import type_severity_max_provider config = {'types': {'foo': {'severity': 3}, 'bar': {'severity': 5}, }, } type_severity_max = type_severity_max_provider(**config) self.client.filters = [type_severity_max] for msgtype in ['foo', 'bar']: for sev in range(8): self.client.heka(msgtype, severity=sev, payload='msg') eq_(len(self.stream.msgs), 10) msgs = [self._extract_msg(msg) for msg in self.stream.msgs] foos = [msg for msg in msgs if msg.type == 'foo'] eq_(len(foos), 4) bars = [msg for msg in msgs if msg.type == 'bar'] eq_(len(bars), 6) def _extract_msg(self, bytes): h, m = decode_message(bytes) return m