Flask
Instrument your Flask application with OpenTelemetry to send traces, metrics, and logs to Last9
Use OpenTelemetry to instrument your Flask application and send telemetry data to Last9. This integration provides automatic instrumentation for HTTP requests, database queries, templating, and other operations in your Flask application.
You can either run OpenTelemetry Collector as a separate service or send telemetry directly from your application to Last9.
Prerequisites
Before setting up Flask monitoring, ensure you have:
- Python 3.7 or higher installed
- Flask application running
- Last9 account with integration credentials
pippackage manager available
-
Install OpenTelemetry Packages
Install the required OpenTelemetry packages for Flask instrumentation:
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp opentelemetry-distroYou can also add these packages to your
requirements.txtfile and install them using:pip install -r requirements.txt -
Bootstrap Automatic Instrumentation
Run the following command to detect and install the required instrumentation packages for your Flask application:
opentelemetry-bootstrap -a requirementsThis command analyzes your application dependencies and suggests relevant OpenTelemetry instrumentation packages. Common packages for Flask applications include:
opentelemetry-instrumentation-asyncioopentelemetry-instrumentation-dbapiopentelemetry-instrumentation-loggingopentelemetry-instrumentation-sqlite3opentelemetry-instrumentation-threadingopentelemetry-instrumentation-urllibopentelemetry-instrumentation-wsgiopentelemetry-instrumentation-flaskopentelemetry-instrumentation-grpcopentelemetry-instrumentation-jinja2opentelemetry-instrumentation-requestsopentelemetry-instrumentation-urllib3 -
Install Instrumentation Packages
Install all the recommended instrumentation packages automatically:
opentelemetry-bootstrap -a installThis command installs all the necessary instrumentation packages based on your application’s dependencies.
-
Set Environment Variables
Configure OpenTelemetry environment variables for your Flask application. Replace the placeholder values with your actual Last9 credentials:
export OTEL_SERVICE_NAME=<service_name>export OTEL_EXPORTER_OTLP_ENDPOINT={{ .Logs.WriteURL }}export OTEL_EXPORTER_OTLP_HEADERS="Authorization={{ .Logs.AuthValue }}"export OTEL_TRACES_EXPORTER=otlpexport OTEL_TRACES_SAMPLER="always_on"export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=local"export OTEL_LOG_LEVEL=errorEnvironment Variables Explained:
OTEL_SERVICE_NAME: Name of your Flask serviceOTEL_EXPORTER_OTLP_ENDPOINT: Last9 endpoint URL for telemetry dataOTEL_EXPORTER_OTLP_HEADERS: Authentication header for Last9OTEL_RESOURCE_ATTRIBUTES: Service metadata including environment
-
Run Your Flask Application
Choose the deployment method that matches your setup:
For development or simple deployments, start your Flask application with OpenTelemetry instrumentation:
opentelemetry-instrument python app.pyThis starts your Flask application with automatic OpenTelemetry instrumentation enabled.
For production deployments using Gunicorn, you need to use a pre-fork hook to initialize OpenTelemetry instrumentation correctly.
Create a new file named
last9_gunicorn.py:from opentelemetry import metrics, tracefrom opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (OTLPMetricExporter,)from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (OTLPSpanExporter,)from opentelemetry.sdk.metrics import MeterProviderfrom opentelemetry.sdk.metrics.export import PeriodicExportingMetricReaderfrom opentelemetry.sdk.resources import Resourcefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom flask import Flask, g, current_appapp = Flask(__name__)# Configurationapp.config.setdefault('OTEL_METRIC_EXPORT_INTERVAL', 60000)# Initialize OpenTelemetry on application startup@app.before_first_requestdef setup_telemetry():# Initialize tracingtracer_provider = TracerProvider()trace.set_tracer_provider(tracer_provider)trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))# Initialize metricsmetric_reader = PeriodicExportingMetricReader(OTLPMetricExporter(),export_interval_millis=app.config['OTEL_METRIC_EXPORT_INTERVAL'])meter_provider = MeterProvider(metric_readers=[metric_reader])metrics.set_meter_provider(meter_provider)current_app.logger.info("OpenTelemetry initialized")Start the application with Gunicorn:
opentelemetry-instrument gunicorn -c last9_gunicorn.py application:applicationIf you’re using Docker, update your Dockerfile’s CMD instruction:
CMD ["opentelemetry-instrument", "gunicorn", "-c", "last9_gunicorn.py", "application:application"]For development server in Docker:
CMD ["opentelemetry-instrument", "python", "app.py"]
What Gets Instrumented
When you use automatic instrumentation with Flask, OpenTelemetry automatically captures:
HTTP Requests
- Request method, URL, and headers
- Response status codes and timing
- Route parameters and query strings
- Request and response body sizes
Template Rendering
- Jinja2 template compilation and rendering
- Template names and render duration
- Template context and variables
Database Operations
- SQL queries and execution times
- Database connection details
- Query parameters and result counts
External API Calls
- HTTP client requests (using
requests,urllib, etc.) - Request/response details and timing
- Error handling and retry attempts
WSGI Middleware
- WSGI application lifecycle
- Middleware processing times
- Request routing and dispatching
Advanced Configuration
Custom Service Metadata
Enhance your service metadata by updating the OTEL_RESOURCE_ATTRIBUTES environment variable:
export OTEL_RESOURCE_ATTRIBUTES="service.name=flask-api,service.version=1.5.0,deployment.environment=production,service.instance.id=web-server-1,team=backend"Sampling Configuration
Control trace sampling to manage data volume:
# Always sample (development)export OTEL_TRACES_SAMPLER="always_on"
# Sample 10% of traces (production)export OTEL_TRACES_SAMPLER="traceidratio"export OTEL_TRACES_SAMPLER_ARG="0.1"Custom Span Attributes
Add custom attributes to your spans programmatically:
from opentelemetry import tracefrom flask import Flask, request
app = Flask(__name__)tracer = trace.get_tracer(__name__)
@app.route('/users/<user_id>')def get_user(user_id): with tracer.start_as_current_span("get_user") as span: span.set_attribute("user.id", user_id) span.set_attribute("operation.type", "user_lookup") span.set_attribute("request.remote_addr", request.remote_addr)
# Your Flask logic here return {"user_id": user_id}Error Handling and Logging
Integrate OpenTelemetry with Flask’s error handling:
from opentelemetry import tracefrom flask import Flaskimport logging
app = Flask(__name__)tracer = trace.get_tracer(__name__)
# Configure logginglogging.basicConfig(level=logging.INFO)logger = logging.getLogger(__name__)
@app.errorhandler(500)def handle_internal_error(error): span = trace.get_current_span() if span: span.set_status(trace.Status(trace.StatusCode.ERROR)) span.set_attribute("error.type", type(error).__name__) span.set_attribute("error.message", str(error))
logger.error(f"Internal server error: {error}", exc_info=True) return "Internal Server Error", 500Verification
-
Check Application Startup
When you start your Flask application, you should see OpenTelemetry initialization messages in the console output.
-
Generate Test Traffic
Make some requests to your Flask application to generate telemetry data:
curl http://localhost:5000/curl http://localhost:5000/healthcurl http://localhost:5000/api/users/123 -
Verify Data in Last9
Log into your Last9 account and check that traces and metrics are being received in Grafana.
Look for:
- HTTP request traces with timing information
- Template rendering spans
- Database query spans
- Error traces for failed requests
Troubleshooting
Common Issues
Missing Flask Instrumentation If Flask routes aren’t being traced, ensure the Flask instrumentation package is installed:
pip install opentelemetry-instrumentation-flaskGunicorn Worker Issues If using Gunicorn with multiple workers, ensure each worker initializes OpenTelemetry correctly. The pre-fork hook approach ensures consistent initialization.
Environment Variables Not Set Verify your environment variables are properly configured:
env | grep OTEL_Template Rendering Not Traced Install Jinja2 instrumentation for template tracing:
pip install opentelemetry-instrumentation-jinja2Performance Considerations
- Use sampling in production to control trace volume
- Monitor the instrumentation overhead on your application performance
- Consider using async patterns for high-throughput applications
- Use the OpenTelemetry Collector as a buffer for high-traffic applications
Best Practices
- Set meaningful service names that reflect your Flask application’s purpose
- Use consistent environment naming across services
- Include version information in resource attributes
- Add custom spans for critical business operations
- Implement proper error handling with span status updates
- Use Flask’s application context for span correlation
Supported Libraries
OpenTelemetry provides automatic instrumentation for many popular Python libraries commonly used with Flask:
- HTTP Clients:
requests,urllib,urllib3 - Databases:
sqlalchemy,psycopg2,pymysql,sqlite3 - Template Engines:
jinja2 - Message Queues:
celery,pika(RabbitMQ) - Cloud Services:
boto3(AWS),google-cloud - WSGI Servers:
gunicorn,uwsgi,waitress
For a complete list of supported libraries, visit the OpenTelemetry Python Contrib documentation.
Need Help?
If you encounter any issues or have questions:
- Join our Discord community for real-time support
- Contact our support team at support@last9.io