open-telemetry / open-telemetry/opentelemetry-python

Is it possible to use opentelemetry as downstream of an old system using zipkin?

Open
#4,387 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

question
Dominant language
Python
Stars
2.6k
Forks
1k
Avg merge
4d 15h
Merged PRs (30d)
19

Description

I would like to use the custom traceId received from the upstream system as the request context in my current Flask project, and pass this traceId forward in the same header.

It’s possible to instrument OpenTelemetry and log the traceId in my Flask project, but it seems difficult to analyze incoming requests and extract the traceId from the headers set by the upstream server.

I haven’t found any documentation regarding parsing the traceId from headers in upstream systems and applying it to the current request context. I’m unsure if OpenTelemetry supports such operations.

GPT provided some insights, suggesting that I might be able to perform the related operations in app.before_request and app.after_request. The example code is as follows, but I am still unable to apply the traceId from the upstream system to the current Flask project.

Here is the code which will always crash when trying to start a new span using given trace id:

def register_link_tracing(app):
    trace.set_tracer_provider(TracerProvider())
    FlaskInstrumentor().instrument_app(app)
    LoggingInstrumentor().instrument(set_logging_format=True, logging_format=app.config.get('OTEL_PYTHON_LOG_FORMAT'))

    IGNORING_URL = {'/health'}

    @app.before_request
    def before_request():
        try:
            if request.path not in IGNORING_URL:
                g.start_datetime = int(time.time() * 1000)
                trace_id = request.environ.get('X_B3_TRACEID')
                parent_span_id = request.environ.get('X_B3_SPANID')
                int_trace_id = int(trace_id, 16)
                int_parent_span_id = int(parent_span_id, 16)
                # request.headers.get('HTTP_X_B3_PARENTSPANID')
                if trace_id:
                    span_context = SpanContext(
                        trace_id=int_trace_id,
                        span_id=int_parent_span_id,
                        is_remote=True,
                        trace_flags=TraceFlags.SAMPLED
                    )
                    tracer=trace.get_tracer(__name__)
                    span =tracer.start_span(name='upstream_call', context=span_context)
                    trace.set_span_in_context(span)
                current_app.logger.info(f"{request.method} {request.base_url} requesting...")
        except Exception as e:
            current_app.logger.error(f'error! {e},traceback:{traceback.format_exc()}')

    @app.after_request
    def after_request(response):
        try:
            if request.path not in IGNORING_URL:
                start_time = g.get('start_datetime')
                end_time = int(time.time() * 1000)
                time_spend = end_time - start_time
                status = response.json.get('status', '')
                message = response.json.get('message', '')
                current_app.logger.info(f"{request.method} {request.base_url} code:{response.status_code} status:{status} message:{message} time_spend:{time_spend}ms")
        except Exception as e:
            current_app.logger.error(f'error! {e},traceback:{traceback.format_exc()}')
        return response

I think I might need to implement a custom provider to replace the default TracerProvider.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the FlaskInstrumentor setup and the app.before_request and app.after_request entry points shown in the issue. Read the SpanContext, context propagation, and TracerProvider APIs to determine how incoming headers should be handled. Done means identifying a supported approach or documenting the missing capability and its required behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
flask, python
Domain
backend, observability
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.