The New Relic Python agent can automatically instrument your Django and Flask applications, providing deep visibility into their performance.

Let’s see it in action with a simple Flask app.

from flask import Flask, request
import time

app = Flask(__name__)

@app.route('/')
def hello_world():
    # Simulate some work
    time.sleep(0.5)
    return 'Hello, World!'

@app.route('/user/<username>')
def show_user_profile(username):
    # Simulate more work
    time.sleep(0.7)
    return f'User {username}'

if __name__ == '__main__':
    app.run(debug=True)

To instrument this with New Relic, you first need to install the agent:

pip install newrelic

Then, create a newrelic.ini file in the same directory as your application script. For a Flask app, it would look like this:

[newrelic]
app_name = My Flask App
license_key = YOUR_LICENSE_KEY

[logging]
level = info
file = /tmp/newrelic.log

Replace YOUR_LICENSE_KEY with your actual New Relic license key.

Now, you need to run your Flask application using the New Relic Python agent. This is typically done by setting the NEW_RELIC_CONFIG_FILE environment variable and then executing your application script:

export NEW_RELIC_CONFIG_FILE=newrelic.ini
python app.py

When you access http://127.0.0.1:5000/ and http://127.0.0.1:5000/user/alice in your browser a few times, you’ll start seeing data appear in your New Relic account.

In the New Relic UI, you’ll see a new application named "My Flask App". Clicking into it will reveal transaction traces, showing the breakdown of time spent within each request. You’ll see distinct transactions for the / route and the /user/<username> route.

For a Django application, the setup is similar. Install the agent and create a newrelic.ini file. The app_name and license_key are the same. For Django, you typically add 'newrelic' to your INSTALLED_APPS in settings.py and then run your Django development server:

pip install newrelic
# In settings.py
INSTALLED_APPS = [
    # ... other apps
    'newrelic',
]

# In your terminal
export NEW_RELIC_CONFIG_FILE=newrelic.ini
python manage.py runserver

The New Relic agent works by using Python’s sys.setprofile or threading.setprofile functions to hook into function calls. When a request comes in, the agent starts profiling. It identifies framework-specific entry points (like Flask’s route decorators or Django’s URL dispatcher) and begins timing the execution. As your code calls other functions, the agent records these calls, their durations, and their relationships, building a detailed trace of the request’s execution path. This includes time spent in your application code, external calls (like database queries or HTTP requests), and even time spent in the Python interpreter itself.

The core mechanism for instrumentation involves wrappers. The New Relic agent wraps key functions within the web framework (e.g., the WSGI callable for Flask, or Django’s request handling pipeline) and potentially other libraries (like database drivers or HTTP clients). When these wrapped functions are called, the agent’s wrapper code executes first, starting a timer and recording context. It then calls the original function, and after it returns, the wrapper stops the timer, records the duration, and marks the segment as complete. This process is recursive, allowing the agent to build a nested tree of operations for each transaction.

One of the most powerful aspects of the New Relic agent is its ability to automatically detect and instrument many common libraries. For instance, when it sees a database query being executed via psycopg2 or mysql.connector, it automatically captures that query and its duration as a separate segment within the transaction trace. Similarly, outbound HTTP requests made with requests are also automatically instrumented. This means you get visibility into external dependencies without needing to write any custom instrumentation code for them.

This automatic instrumentation is driven by a combination of entry point detection within the frameworks and pattern matching against known library calls. The agent looks for specific function signatures or class methods that indicate the start of a framework request or a specific library operation.

The agent’s newrelic.ini configuration file is quite extensive, allowing fine-grained control over what gets monitored. You can disable automatic instrumentation for specific libraries, set custom thresholds for error reporting, and even define custom transaction naming rules. For example, to disable instrumentation for the requests library, you would add:

[disable_auto_instrumentation]
requests = true

This level of control is crucial for optimizing performance and ensuring that only relevant data is collected.

The next step in understanding New Relic’s Python agent is exploring custom instrumentation using decorators and newrelic.agent.record_exception.

Want structured learning?

Take the full Newrelic course →