open-telemetry / open-telemetry/opentelemetry-python
Is it possible to use opentelemetry as downstream of an old system using zipkin?
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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