Requests freeze when combining both threading and requests integrations with StrackdriverExporter(SyncTransport)
Requests freeze when combining both threading and requests integrations with StrackdriverExporter(SyncTransport)
Describe your environment.
Here are the relevant versions of Python packages:
python==3.7.3
flask==1.0.2
opencensus==0.6.0
opencensus-context==0.1.1
opencensus-ext-flask==0.3.1
opencensus-ext-requests==0.1.2
opencensus-ext-stackdriver==0.4.0
opencensus-ext-threading==0.1.2
I'm seeing this in a Flask app that's set up with the following:
OPENCENSUS = {
'TRACE': {
'SAMPLER':
'opencensus.trace.samplers.AlwaysOnSampler()',
'EXPORTER':
"""opencensus.ext.stackdriver.trace_exporter.StackdriverExporter(
transport=opencensus.common.transports.sync.SyncTransport
)"""
}
}
import opencensus.ext.flask.flask_middleware as opencensus_flask
import opencensus.trace.config_integration
opencensus_flask.FlaskMiddleware(app)
opencensus.trace.config_integration.trace_integrations(['threading', 'requests'])
Steps to reproduce.
Let me know if you need me to code up a minimum working example, but:
- Set up integrations for
threading&requestsas shown above. - Set up a
StackdriverExporterwithSyncTransportas shown above. - In your Flask endpoint code, make any HTTP call to another server using the
requestspackage, e.g.requests.get(url). The bug can be reproduced whether you make this call from within another ThreadPoolExecutor or not.
What is the expected behavior?
- My flask app forwards the Trace-Context header to the service being called.
- My flask app records its own spans around calling that service.
- After the HTTP call finishes, execution continues nominally.
What is the actual behavior?
- My flask app forwards the Trace-Context header to the service being called. (good)
- The service being called receives these headers and responds to the request. (good)
-
My flask app hangs before
requests.getreturns.
Presumably something seems to be going wrong when the SyncTransport is exporting my flask app's spans from the requests integration.
Additional context.
I can reproduce this only with the combination of threading, requests and SyncTransport. If I remove either integration, it works fine. If I switch to AsyncTransport, it works fine.
I have not tried using a different exporter than StackdriverExporter.
This is pretty low priority for me since in production I'll always use AsyncTransport. But it definitely threw me for a loop while first playing with OpenCensus, since I had chosen to use SyncTransport for a quicker feedback cycle.
I've noticed the same problem when combining threading with the gRPC integration: the gRPC server hangs.
@c24t @songy23 would you recommend SyncTransport or we should always use AsyncTransport for StackdriverExporter?
SyncTransport will slow your app significantly - IMO the only good option is the AsyncTransport, for any exporter. There is one exception to this: an app that can only run one thread (e.g Cloud Function). The issue I have with combining threading and gRPC integration happen with both transports anyways: maybe I should open a new issue for this.
I second @ocervell, AsyncTransport should definitely be the default, with SyncTransport provided as option for special use cases like Cloud Functions