Skip to content

docs: enhance troubleshooting for Gunicorn/Uvicorn worker spans#2555

Open
adionit7 wants to merge 3 commits intoSigNoz:mainfrom
adionit7:docs/python-gunicorn-worker-troubleshooting
Open

docs: enhance troubleshooting for Gunicorn/Uvicorn worker spans#2555
adionit7 wants to merge 3 commits intoSigNoz:mainfrom
adionit7:docs/python-gunicorn-worker-troubleshooting

Conversation

@adionit7
Copy link

Pull Request


📄 Summary

Why does this change exist?
What problem does it solve, and why is this the right approach?

Users deploying FastAPI/Python apps with Gunicorn or Uvicorn multiple workers often experience missing spans in SigNoz. The existing troubleshooting section mentions this briefly but doesn't explain the root cause or provide a concrete solution.

This PR enhances the troubleshooting section with:

  • Clear explanation of why spans drop (forking issue with OpenTelemetry SDK)
  • Complete gunicorn_config.py example with post_fork hook
  • Link to the FastAPI production example for a full working reference
  • Link to official OpenTelemetry multiprocessing docs

This helps users understand the problem and implement the fix themselves, reducing support load.


✅ Change Type

Select all that apply

  • ✨ Feature
  • 🐛 Bug fix
  • ♻️ Refactor
  • 🛠️ Infra / Tooling
  • 🧪 Test-only
  • 📚 Documentation

🐛 Bug Context

Required if this PR fixes a bug

N/A - Documentation enhancement.


🧪 Testing Strategy

How was this change validated?

  • Tests added/updated: N/A (documentation)
  • Manual verification:
    • Verified markdown syntax
    • Checked code example syntax
    • Confirmed links are valid
    • Reviewed content for accuracy
  • Edge cases covered: N/A

⚠️ Risk & Impact Assessment

What could break? How do we recover?

  • Blast radius: None - documentation only
  • Potential regressions: None
  • Rollback plan: Simple revert if needed

📝 Changelog

Fill only if this affects users, APIs, UI, or documented behavior
Use N/A for internal or non-user-facing changes

Field Value
Deployment Type OSS
Change Type Maintenance
Description Enhanced troubleshooting section for Gunicorn/Uvicorn worker span issues with code example and links

📋 Checklist

  • Tests added or explicitly not required (documentation)
  • Manually tested (verified formatting and links)
  • Breaking changes documented (N/A)
  • Backward compatibility considered (N/A)

👀 Notes for Reviewers

This addresses the issue mentioned in the tweet thread where users struggle with Gunicorn workers dropping spans. The existing troubleshooting section was too brief - this adds the detailed explanation and working code example that users need.

The gunicorn_config.py example matches the pattern used in the FastAPI production example we added to the examples repo, ensuring consistency across documentation.


@vercel
Copy link

vercel bot commented Jan 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
signoz-web Ready Ready Preview, Comment Jan 20, 2026 8:44am

Request Review

- Add detailed explanation of forking issue with multi-worker servers
- Include gunicorn_config.py example with post_fork hook
- Link to FastAPI production example for complete reference
- Add link to OpenTelemetry multiprocessing docs
Copy link
Collaborator

@shubham-signoz shubham-signoz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, thanks for taking the time to improve the docs here!

A couple of things though - the post_fork example won't quite work as written. opentelemetry-bootstrap -a install is actually a package installer so calling it at runtime on every worker fork isn't what we want or the right way to do it. (With 4 workers you'd have 4 pip install attempts on startup, and more each time workers recycle. In most production setups this just fails (read-only containers, no network, slim images without pip). And even if it ran, it's not a reliable fix since it might work for some setups but not others - the packages are already there, it's the SDK state (TracerProvider, exporters, processors) that didn't survive the fork).

The correct approach is reinitialising the TracerProvider/MeterProvider in each worker.We do already cover this in the #running-with-gunicorn-or-uwsgi section with links to the official post_fork examples.

That said - I'm curious what prompted this. Was something confusing about the existing pre-fork/post-fork explanation? Would love to hear what tripped you up so we can fix it in the right place.

Removes the opentelemetry-bootstrap --action=install example which
is incorrect for post_fork (it's a package installer, not runtime
initialization). Instead points to the existing #running-with-gunicorn
section and official OTel Python post_fork examples.
@adionit7
Copy link
Author

adionit7 commented Jan 20, 2026

shubham-signoz

Thanks for the catch, Shubham! You are right.. running opentelemetry-bootstrap at runtime is an anti-pattern for production.

What tripped me up: I was specifically looking for a 'Troubleshooting' section for missing spans and completely missed the #running-with-gunicorn link further down. Since the auto-instrumentation docs imply it 'just works', I didn't initially think to look for manual post_fork hooks.

Updates pushed:

  • Removed the runtime bootstrap snippet.
  • Added a clear pointer/admonition to the existing #running-with-gunicorn section so others find it faster.

(Note: I also updated my PR in the examples repo to reflect the correct post_fork approach).

Ready for re-review!

@shubham-signoz
Copy link
Collaborator

shubham-signoz commented Jan 20, 2026

shubham-signoz

Thanks for the catch, Shubham! You are right.. running opentelemetry-bootstrap at runtime is an anti-pattern for production.

What tripped me up: I was specifically looking for a 'Troubleshooting' section for missing spans and completely missed the #running-with-gunicorn link further down. Since the auto-instrumentation docs imply it 'just works', I didn't initially think to look for manual post_fork hooks.

Updates pushed:

  • Removed the runtime bootstrap snippet.
  • Added a clear pointer/admonition to the existing #running-with-gunicorn section so others find it faster.

(Note: I also updated my PR in the examples repo to reflect the correct post_fork approach).

Ready for re-review!

@adionit7 I think the existing troubleshooting already has a reference for the gunicorn preload. I don't think we need any more additional information except on this line. Do you think maybe we need to make this line more explicit about the issue?

- **Gunicorn with `--preload`** or **uWSGI** need extra config. See [Running with Gunicorn or uWSGI](#running-with-gunicorn-or-uwsgi).

@adionit7
Copy link
Author

adionit7 commented Jan 20, 2026

@shubham-signoz That makes total sense! I agree.. keeping it concise is better.

The current line (need extra config) is a bit passive, which is why I scrolled past it. I'll update it to explicitly mention 'missing spans' and 'forking issues'. That way, anyone debugging dropped traces will immediately know this is the relevant section.

Updating the PR now to just modify this line.

Removed verbose troubleshooting section. Instead, explicitly mention
'missing spans' and 'forking issues' in the existing Gunicorn/uWSGI
section so users searching for these terms find the fix immediately.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants