def test_run_hooks_and_send_presend_hook(self): ''' ensure send works when presend hook is defined ''' def _presend_hook(fields): fields["thing i want"] = "put it there" del fields["thing i don't want"] m_presend_hook = Mock() m_presend_hook.side_effect = _presend_hook _beeline = beeline.Beeline(presend_hook=m_presend_hook) _beeline.tracer_impl = Mock() ev = Mock() ev.fields.return_value = { "thing i don't want": "get it out of here", "happy data": "so happy", } _beeline._run_hooks_and_send(ev) ev.send_presampled.assert_not_called() ev.send.assert_called_once_with() self.assertDictEqual( ev.fields(), { "thing i want": "put it there", "happy data": "so happy", }, )
def test_generator_wrapper(self): ''' ensure that the trace wrapper decorates a generator function and starts a trace also ensure that child traces get the parent trace correctly set ''' _beeline = beeline.Beeline() with patch('beeline.get_beeline') as m_gbl: m_gbl.return_value = _beeline _beeline.tracer_impl._run_hooks_and_send = Mock() @beeline.traced(name="return_integer_n") def return_integer(n): return n @beeline.traced(name="output_integers_to") def output_integers_to(n): for i in range(n): yield return_integer(i) # should accept the function's arguments normally and yield the items from the # generator self.assertEqual(list(output_integers_to(3)), [0, 1, 2]) self.assertTrue(_beeline.tracer_impl._run_hooks_and_send.called) spans = [x[0][0] for x in _beeline.tracer_impl._run_hooks_and_send.call_args_list] # check the child spans now parent_span = spans[-1] child_spans = spans[:-1] for child_span in child_spans: self.assertEqual(child_span.parent_id, parent_span.id)
def test_run_hooks_and_send_sampler(self): ''' ensure send works with a sampler hook defined ''' def _sampler_drop_all(fields): return False, 0 m_sampler_hook = Mock() m_sampler_hook.side_effect = _sampler_drop_all _beeline = beeline.Beeline(sampler_hook=m_sampler_hook) _beeline.tracer_impl = Mock() ev = Mock() _beeline._run_hooks_and_send(ev) m_sampler_hook.assert_called_once_with(ev.fields()) ev.send_presampled.assert_not_called() ev.send.assert_not_called() def _sampler_drop_none(fields): return True, 100 ev = Mock() m_sampler_hook.reset_mock() m_sampler_hook.side_effect = _sampler_drop_none _beeline._run_hooks_and_send(ev) m_sampler_hook.assert_called_once_with(ev.fields()) self.assertEqual(ev.sample_rate, 100) ev.send_presampled.assert_called_once_with() ev.send.assert_not_called()
def test_synchronous_tracer_should_be_used_by_default(self): """Verify that the SynchronousTracer implementation is chosen when a Beeline object is initialised outside of an asyncio loop. """ _beeline = beeline.Beeline() self.assertIsInstance(_beeline.tracer_impl, beeline.trace.SynchronousTracer)
def test_send_no_events(self): ''' ensure nothing crashes when we try to send with no events in the stack ''' _beeline = beeline.Beeline() _beeline.tracer_impl = Mock() _beeline.tracer_impl.get_active_span.return_value = None _beeline.send_event() _beeline.tracer_impl.get_active_span.assert_called_once_with()
async def async_setup(self): self.finished_spans = [] def add_span(span): self.finished_spans.append(span_data(span)) self.beeline = beeline.Beeline() self.tracer = self.beeline.tracer_impl self.tracer._run_hooks_and_send = add_span
async def test_asyncio_tracer_should_be_used_in_async_code(self): """Verify that the AsyncioTracer implementation is chosen when a Beeline object is initialised while running inside an asyncio loop. """ _beeline = beeline.Beeline() self.assertIsInstance(_beeline.tracer_impl, beeline.aiotrace.AsyncioTracer)
def test_send_event(self): ''' test correct behavior for send_event ''' _beeline = beeline.Beeline() _beeline.tracer_impl = Mock() m_span = Mock() _beeline.tracer_impl.get_active_span.return_value = m_span _beeline.send_event() _beeline.tracer_impl.get_active_span.assert_called_once_with() _beeline.tracer_impl.finish_trace.assert_called_once_with(m_span)
def test_run_hooks_and_send_no_hooks(self): ''' ensure send works when no hooks defined ''' ev = Mock() _beeline = beeline.Beeline() _beeline.tracer_impl = Mock() _beeline._run_hooks_and_send(ev) # no hooks, not a traced event - call send ev.send.assert_called_once_with() ev.send_presampled.assert_not_called()
def test_trace_wrapper(self): ''' ensure that the trace wrapper decorates a function and starts a trace ''' _beeline = beeline.Beeline() with patch('beeline.get_beeline') as m_gbl: m_gbl.return_value = _beeline _beeline.tracer_impl._run_hooks_and_send = Mock() @beeline.traced(name="my_sum") def my_sum(a, b): return a + b # this should accept the function's arguments normally and return the function's value # if there is one self.assertEqual(my_sum(1, 2), 3) # check that an event was sent, from which we can infer that the function was wrapped self.assertTrue(_beeline.tracer_impl._run_hooks_and_send.called)
def test_request_fn_injects_correct_context(self): ''' confirm that the injected trace context references the child span wrapping the request call ''' from beeline.patch.requests import request # pylint: disable=bad-option-value,import-outside-toplevel _beeline = beeline.Beeline(transmission_impl=Mock()) # prevent spans from being sent/closed so we can get at the span generated by the request patch _beeline.tracer_impl.finish_span = Mock() with patch('beeline.get_beeline') as m_bl: m_bl.return_value = _beeline with _beeline.tracer("parent", trace_id="abc"): parent_span = _beeline.tracer_impl.get_active_span() # this is the class instance (Session object) that is passed to our request function by wrapt m_session = Mock() m_session.headers = {} # this is our request call that's being wrapped m_request = Mock() m_request.return_value = Mock(headers={ 'content-type': 'application/json', 'content-length': 23 }, status_code=500) args = ['get'] kwargs = {'url': 'http://example.com'} ret = request(m_request, m_session, args, kwargs) m_request.assert_called_once_with(*args, **kwargs) self.assertEqual(ret, m_request.return_value) self.assertEqual(len(_beeline.tracer_impl._trace.stack), 2) child_span = _beeline.tracer_impl.get_active_span() # we should have two distinct spans in this trace self.assertNotEqual(child_span.id, parent_span.id) self.assertEqual(child_span.parent_id, parent_span.id) trace_context = m_session.headers['X-Honeycomb-Trace'] trace_id, parent_id, _ = beeline.trace.unmarshal_trace_context( trace_context) # confirm the trace context parent is the child span, not the parent span self.assertEqual(child_span.trace_id, trace_id) self.assertEqual(child_span.id, parent_id) # should be the same trace self.assertEqual(parent_span.trace_id, trace_id)
def test_treaded_trace(self): _beeline = beeline.Beeline() with patch('beeline.get_beeline') as m_gbl: m_gbl.return_value = _beeline _beeline.tracer_impl._run_hooks_and_send = Mock() _beeline.tracer_impl.start_trace(trace_id="asdf") self.assertEqual(_beeline.tracer_impl._state.trace_id, "asdf") def thread_func(): # confirm no trace state in new thread self.assertFalse( hasattr(_beeline.tracer_impl._state, 'trace_id')) t = threading.Thread(target=thread_func) t.start() t.join() @beeline.traced_thread def traced_thread_func(): self.assertEqual(_beeline.tracer_impl._state.trace_id, "asdf") with _beeline.tracer(name="foo") as span: self.assertEqual(span.trace_id, "asdf") self.assertEqual(span.parent_id, _beeline.tracer_impl._state.stack[0].id) t = threading.Thread(target=traced_thread_func) t.start() t.join() # test use of beeline client @_beeline.traced_thread def traced_thread_func_2(): self.assertEqual(_beeline.tracer_impl._state.trace_id, "asdf") with _beeline.tracer(name="foo2") as span: self.assertEqual(span.trace_id, "asdf") self.assertEqual(span.parent_id, _beeline.tracer_impl._state.stack[0].id) t = threading.Thread(target=traced_thread_func_2) t.start() t.join()
def test_send_all(self): ''' ensure events are flushed, and that the root span is handled with finish_trace ''' s1, s2, s3 = Mock(), Mock(), Mock() s1.is_root.return_value = False s2.is_root.return_value = False s3.is_root.return_value = True _beeline = beeline.Beeline() _beeline.tracer_impl = Mock() _beeline.tracer_impl.get_active_span.side_effect = [s1, s2, s3, None] _beeline.send_all() _beeline.tracer_impl.finish_span.assert_has_calls([ call(s1), call(s2), ]) _beeline.tracer_impl.finish_trace.assert_called_once_with(s3)
def test_treaded_trace(self): _beeline = beeline.Beeline() with patch('beeline.get_beeline') as m_gbl: m_gbl.return_value = _beeline _beeline.tracer_impl._run_hooks_and_send = Mock() _beeline.tracer_impl.start_trace(trace_id="asdf") self.assertEqual(_beeline.tracer_impl._trace.id, "asdf") def thread_func(): # confirm no trace state in new thread self.assertIsNone(_beeline.tracer_impl._trace) self.raising_run_in_thread(target=thread_func) @beeline.traced_thread def traced_thread_func(): self.assertEqual(_beeline.tracer_impl._trace.id, "asdf") with _beeline.tracer(name="foo") as span: self.assertEqual(span.trace_id, "asdf") self.assertEqual(span.parent_id, _beeline.tracer_impl._trace.stack[0].id) self.raising_run_in_thread(target=traced_thread_func) # test use of beeline client @_beeline.traced_thread def traced_thread_func_2(): self.assertEqual(_beeline.tracer_impl._trace.id, "asdf") with _beeline.tracer(name="foo2") as span: self.assertEqual(span.trace_id, "asdf") self.assertEqual(span.parent_id, _beeline.tracer_impl._trace.stack[0].id) self.raising_run_in_thread(target=traced_thread_func_2)
def test_finish_span_none(self): ''' ensure finish_span does not crash if an empty span is passed to it ''' _beeline = beeline.Beeline() # should not crash _beeline.tracer_impl.finish_span(None)