open-telemetry / open-telemetry/opentelemetry-python-contrib

Potential Conflict between ThreadingInstrumentor and Gevent Workers in Flask/Gunicorn Setup

Open
#3,694 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
1.1k
Forks
1.1k
Avg merge
4d 15h
Merged PRs (30d)
16

Description

Describe your environment

OS: Ubuntu, centos(e.g, Ubuntu)
Python version: (e.g., Python 3.10)
Package version: (e.g., 0.46.0)
OpenTelemetry Instrumentation: opentelemetry-instrumentation-threading
WSGI Server: Gunicorn (with gevent worker class)
Application: Flask

What happened?

Enabling ThreadingInstrumentor appears to conflict with gevent workers when running a Flask app under Gunicorn.
Code Snippet (manager_test.py)

import logging
import sys
import threading
from flask import Flask
from opentelemetry.instrumentation.threading import ThreadingInstrumentor

ThreadingInstrumentor().instrument()  # Enables instrumentation

app = Flask(__name__)
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(process)d %(thread)d %(name)s %(filename)s:%(lineno)d:%(funcName)s - %(message)s',
    stream=sys.stdout
)

def test_timer(pos):
    logging.info("-------->>>> Timer task executed, pos=%s", pos)
    # Periodically reschedule itself
    threading.Timer(1, test_timer, [pos]).start()

# Start initial timer
threading.Timer(1, test_timer, [pos]).start()

@app.route('/vi/health', methods=['POST', 'GET'])
def healthcheck():
    return 'ok'

if __name__ == '__main__':
    app.run('0.0.0.0', 8080)

Gunicorn Configuration (manager.conf.py)

daemon = False
chdir = '/opt/app/'
bind = '0.0.0.0:8080'
reuse_port = True
proc_name = 'mms_manager'
workers = 1
worker_class = 'gevent'  # Problem occurs with this
timeout = 60
graceful_timeout = 300
Steps to Reproduce

Run app with:
gunicorn -c manager.conf.py manager_test:app

Expected Result

The test_timer() function should still execute periodically when using worker_class = 'gevent'.

Actual Result

The scheduled test_timer() function ​never executes​ when using worker_class = 'gevent'.

Additional context

Switching to worker_class = 'gthread' resolves the issue immediately:

  • Timer tasks execute as expected
  • All other functionality remains unchanged
Would you like to implement a fix?

None

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 manager_test.py and manager.conf.py, then reproduce with gunicorn -c manager.conf.py manager_test:app using the gevent worker class. Compare the behavior with gthread and inspect how ThreadingInstrumentor interacts with the scheduled threading.Timer. Done means test_timer() executes periodically under gevent without changing the existing Flask endpoint behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
flask, python
Domain
backend, observability
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.