Flask Integration
Instrument Flask applications with one pip install. WSGI request tracing, SQLAlchemy query capture, Celery task monitoring, and Redis cache spans — zero configuration.
How It Works
Install the pip Package
Run pip install tigerops or add tigerops to requirements.txt. The package includes the opentelemetry-instrumentation-flask SDK, SQLAlchemy instrumentation, Celery task hooks, and OTLP exporters preconfigured for TigerOps endpoints.
Initialize Before app.run()
Call TigerOps.init_app(app) after creating your Flask application instance. For application factory patterns, call TigerOps.init_app(app) inside the factory function after all extensions are registered. Works with Flask-SQLAlchemy and Flask-Migrate.
Set Environment Variables
Set TIGEROPS_API_KEY, TIGEROPS_SERVICE_NAME, and TIGEROPS_ENVIRONMENT in your environment or .env file. Flask's config system is supported: app.config["TIGEROPS_API_KEY"] = os.environ["TIGEROPS_API_KEY"]. python-dotenv is compatible.
Traces, SQL & Celery Tasks Flow
Within seconds TigerOps receives Flask request spans with route rules and view function names, SQLAlchemy query spans with normalized SQL and row counts, Celery task execution spans, and Redis or Memcached cache operation traces.
What You Get Out of the Box
WSGI Request Tracing
Every Flask HTTP request creates a root span with URL rule, view function name, HTTP method, status code, and response time. Before-request and after-request hook execution times are captured as child spans. Works with Gunicorn and uWSGI.
SQLAlchemy Query Spans
All SQLAlchemy Core and ORM queries are instrumented. Each span includes normalized SQL text, database URL (sanitized), execution time, and row count. N+1 query patterns are detected and flagged in the TigerOps dashboard.
Celery Task Visibility
Celery task publish and worker execution create linked spans with trace context propagated through the broker. Task name, queue, retry count, execution time, and exception tracebacks are captured. Queue depth is reported as a metric.
Flask-RESTful & Flask-RESTX
Resource class method execution is auto-instrumented. Request parser validation time, marshalling duration, and namespace routing are captured as child spans. API versioning and blueprint prefixes appear in span route attributes.
Redis & Cache Instrumentation
Flask-Caching and direct redis-py operations are traced as child spans with command name, key pattern, and execution time. Cache hit/miss ratios are emitted as metrics. Redis pipeline batches appear as a single grouped span.
Error Tracking & Exception Spans
Unhandled exceptions in Flask views are captured with full Python traceback, request context (URL, method, user agent), and any active span attributes. HTTP 4xx and 5xx responses are tagged with error=true for quick filtering.
Install & Initialize
One pip install and one init_app call. Full Flask observability.
# Install the TigerOps Flask package
pip install tigerops
# Set environment variables
export TIGEROPS_API_KEY="your-api-key"
export TIGEROPS_SERVICE_NAME="my-flask-app"
export TIGEROPS_ENVIRONMENT="production"
# app.py — application factory pattern
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from tigerops.contrib.flask import TigerOps
db = SQLAlchemy()
tigerops = TigerOps()
def create_app(config_name="production"):
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"]
app.config["TIGEROPS_API_KEY"] = os.environ["TIGEROPS_API_KEY"]
app.config["TIGEROPS_SERVICE_NAME"] = "my-flask-app"
app.config["TIGEROPS_TRACE_CELERY"] = True
app.config["TIGEROPS_TRACE_CACHE"] = True
app.config["TIGEROPS_SLOW_QUERY_MS"] = 100
db.init_app(app)
tigerops.init_app(app) # <-- add after all extensions
from .api import api_bp
app.register_blueprint(api_bp, url_prefix="/api/v1")
return app
# Custom span in a view
from tigerops import span
@api_bp.route("/orders/<order_id>", methods=["GET"])
def get_order(order_id):
with span("order.fetch") as s:
s.set_attribute("order.id", order_id)
order = Order.query.get_or_404(order_id)
with span("order.enrich") as s:
enriched = enrich_with_inventory(order)
s.set_attribute("sku.count", len(enriched.items))
return jsonify(enriched.to_dict())Common Questions
Which Flask and Python versions are supported?
Flask 2.x and 3.x are fully supported. Python 3.9, 3.10, 3.11, and 3.12 are supported. The package works with both synchronous WSGI Flask and async ASGI Flask via asgiref. Flask-SQLAlchemy 3.x and standalone SQLAlchemy 1.4+ and 2.x are both supported.
How does TigerOps handle Flask application factory patterns?
Call TigerOps.init_app(app) inside your create_app() factory function after registering all blueprints and extensions. The TigerOps object supports the same lazy initialization pattern as Flask-SQLAlchemy and other Flask extensions.
Does TigerOps work with Flask running behind a reverse proxy?
Yes. TigerOps reads the X-Forwarded-For and X-Real-IP headers to capture the real client IP. For W3C trace context propagation from an upstream proxy or API gateway, set ProxyFix in your WSGI middleware stack before the TigerOps middleware.
Can I trace Flask CLI commands and background scripts?
Yes. Wrap CLI commands with the @tigerops.trace_command decorator. For standalone scripts that import your Flask app, call TigerOps.init_app(app) once and use the tigerops.span() context manager around the work you want to trace.
How are Celery task spans linked to the originating Flask request?
When a Flask request publishes a Celery task, TigerOps serializes the active trace context into the task headers. The Celery worker deserializes the context and creates a child span linked to the original request span, giving you end-to-end trace continuity.
Full Flask Observability in One pip Install
WSGI traces, SQLAlchemy spans, Celery task visibility, and cache instrumentation — no code changes required.