def test_common_tags_are_applied_to_new_spans(self):
        common_tags = {"a": "common_tag", "another": "common_tag"}
        tracer = HaystackTracer("any_service",
                                NoopRecorder(),
                                common_tags=common_tags)

        span = tracer.start_span("any_operation")

        self.assertDictEqual(common_tags, span.tags)
    def test_common_tags_are_overridden_if_span_specifies_the_same(self):
        common_tags = {"a": "common_tag", "another": "common_tag"}
        tracer = HaystackTracer("any_service",
                                NoopRecorder(),
                                common_tags=common_tags)

        span_tags = {"another": "span_tag"}
        span = tracer.start_span("any_operation", tags=span_tags)

        expected_tags = {**common_tags, **span_tags}
        self.assertDictEqual(expected_tags, span.tags)
    def test_non_shared_spans_are_created_by_default(self):
        tracer = HaystackTracer("any_service", NoopRecorder())
        trace_id = "123"
        span_id = "1234"
        parent_id = "12345"
        upstream_ctx = SpanContext(trace_id=trace_id,
                                   span_id=span_id,
                                   parent_id=parent_id)

        span = tracer.start_span("any_operation", child_of=upstream_ctx)

        self.assertEqual(span.context.trace_id, trace_id)
        self.assertNotEqual(span.context.span_id, span_id)
        self.assertEqual(span.context.parent_id, span_id)
예제 #4
0
def setup_tracer():
    global recorder
    recorder = LoggerRecorder()

    # instantiate a haystack tracer for this service and set a common tag which applies to all traces
    tracer = HaystackTracer("Service-A",
                            recorder,
                            common_tags={"app.version": "1234"})

    # now set the global tracer, so we can reference it with opentracing.tracer anywhere in our app
    opentracing.set_global_tracer(tracer)
예제 #5
0
def act_as_remote_service(headers):
    # remote service would have it"s own tracer
    with HaystackTracer("Service-B", recorder) as tracer:
        # simulate network transfer delay
        time.sleep(.25)

        # now as-if this was executing on the remote service, extract the parent span ctx from headers
        upstream_span_ctx = tracer.extract(opentracing.Format.HTTP_HEADERS, headers)
        with tracer.start_active_span("controller_method", child_of=upstream_span_ctx) as parent_scope:
            parent_scope.span.set_tag(tags.SPAN_KIND, "server")
            # simulate downstream service doing some work before replying
            time.sleep(1)
    def test_haystack_agent(self):
        span_name = "agent-test-span"
        service_name = "agent-test"

        opentracing.tracer = HaystackTracer(
            service_name, HaystackAgentRecorder("sandbox_haystack_agent_1"))
        thread = threading.Thread(target=send_a_span, args=(span_name, ))

        thread.start()
        retrieved_spans = get_spans()

        client_span = retrieved_spans["client"]
        server_span = retrieved_spans["server"]

        self.assertEqual(f"{span_name}-client", client_span.operationName)
        self.assertEqual(span_name, server_span.operationName)

        self.assertEqual(service_name, server_span.serviceName)
        self.assertEqual(service_name, client_span.serviceName)

        self.assertEqual(client_span.parentSpanId, server_span.spanId)
        self.assertEqual(client_span.traceId, server_span.traceId)
    def test_http_collector(self):
        span_name = "http-test-span"
        service_name = "http-test"

        opentracing.tracer = HaystackTracer(
            service_name,
            AsyncHttpRecorder(
                collector_url="http://sandbox_haystack_collector_1:8080/span"))
        thread = threading.Thread(target=send_a_span, args=(span_name, ))

        thread.start()
        retrieved_spans = get_spans()

        client_span = retrieved_spans["client"]
        server_span = retrieved_spans["server"]

        self.assertEqual(f"{span_name}-client", client_span.operationName)
        self.assertEqual(span_name, server_span.operationName)

        self.assertEqual(service_name, server_span.serviceName)
        self.assertEqual(service_name, client_span.serviceName)

        self.assertEqual(client_span.parentSpanId, server_span.spanId)
        self.assertEqual(client_span.traceId, server_span.traceId)
예제 #8
0
consideration. For Example, in AWS, due to the way AWS lambda freezes execution 
context, it's not reliable to send requests via the AsyncHttpRecorder. If the 
function is not time-sensitive in reply or is async, SyncHttpRecorder is a good 
fit as shown below. If the function cannot afford to dispatch the span 
in-process, then it is recommended to either setup a haystack agent in the 
network and utilize HaystackAgentRecorder or offload the span record dispatching
via Queue -> Worker model. In AWS this could mean implementing a SQSRecorder 
which puts the finished span onto a SQS queue. The queue could then notify a 
lambda implementing SyncHttpRecorder to dispatch the records. 
"""

recorder = SyncHttpRecorder(os.env["COLLECTOR_URL"])

# suppose it is desired to tag all traces with the application version
common_tags = {"svc_ver": os["APP_VERSION"]}
tracer = HaystackTracer("example-service", recorder, common_tags=common_tags)
opentracing.set_global_tracer(tracer)


def invoke_downstream(headers):
    return "done"


def process_downstream_response(response):
    return "done"


def handler(event, context):

    # extract the span context from headers if this is a downstream service
    parent_ctx = opentracing.tracer.extract(opentracing.Format.HTTP_HEADERS,