This post describes the required steps to leverage New Relic application monitoring with Python on Cloud Foundry. For the following I assume that you have a Cloud Foundry account with a New Relic service in the marketplace. (I’m using Pivotal Web Services)
To get started with Python, or more specific Django, on Cloud Foundry please read my former post: “Deploying a Django Application to Cloud Foundry“.
New Relic
New Relic is an Application Performance Management and Monitoring provider who deliver its products in a software as a service (SaaS) model. It allows you to get deep insights into your application.
In this post I will only focus on New Relic APM, a SaaS-based Application Performance Monitoring solution, which has a wide range of agents: Java, .NET, Node.js, PHP, Python and Ruby.
As usual, a picture is worth a thousands words:
New Relic APM gives you great details about transaction times, response times and more. The cool thing is that you don’t have to modify anything in your application code to leverage these deep insights.
Installation and Configuration for Pyhton
Though we are going to use New Relic in Cloud Foundry I give a short introduction how to minimal install and configure it for a “normal” server environment.
First you have to install the New Relic Agent:
pip install newrelic
New Relic is a commercial product therefore you need to specify the license key:
newrelic-admin generate-config LICENSE-KEY newrelic.ini
To validate your installation you can use following command:
newrelic-admin validate-config newrelic.ini
For python you just have to use the New Relic agent to start your e.g. “gunicorn” application server.
newrelic-admin run-program gunicorn emcforum.wsgi --workers 2
After a few minutes you should see your new application popping up in the New Relic Web UI, shown above.
Here you find the New Relic documentation for the python agent installation and configuration.
Python Buildpack
In my former post I already described the Cloud Foundry python buildpack and the VCAP_SERVICES environment variable in greater detail.
To make a long story short, the Cloud Foundry buildpack is based on the Heroku buildpack and the biggest difference is that Cloud Foundry handles all the information about bound services in a JSON formatted environment variable called VCAP_SERVICES . In contrary does Heroku add multiple simple environment variables to an app instance.
An example for an VCAP_SERVICES variable for a Cloud Foundry app with an ElephantSQL (PostgreSQL) database and New Relic bound to it:
{ "elephantsql":[ { "name":"vLab_DB", "label":"elephantsql", "tags":[ "New Product", "Data Stores", "relational", "Data Store", "postgresql" ], "plan":"turtle", "credentials":{ "uri":"postgres://mrsajkmm:HtcCdLBFsBeLHOdE2OqAmJWZUfRnPKeE@babar.elephantsql.com:5432/mrsijkmm", "max_conns":"5" } } ], "newrelic":[ { "name":"vLab_newrelic", "label":"newrelic", "tags":[ "Monitoring" ], "plan":"standard", "credentials":{ "licenseKey":"25sdcaa37583f73d0d76c9da43a8931f796e6978" } } ] }
New Relic variables
So why am I talking about VCAP_SERVICES in this post at all?
You need to pass the New Relic license to newrelic-admin in some way and in Cloud Foundry this license is stored in the VCAP_SERVICES variable.
But using newrelic-admin generate-config to generate the newrelic.ini is not reasonable and would still require to read the license from the VCAP_SERVICES variable. Looking at the documentation for configuring the python agent on Heroku there is another way to configure the newrelic agent: environment variables.
newrelic-admin does support among others following environment variables:
- NEW_RELIC_LOG
- the log path
- NEW_RELIC_LICENSE_KEY
- the New Relic license key
- NEW_RELIC_APP_NAME
- the name of the application to be shown in APM
On Heroku are these variables automatically added to an app instance but on Cloud Foundry they aren’t configured!
Profile.d
After researching, how to create the New Relic variables in an easy and flexible way, I found in the Heroku documentation “Profile.d“.
All bash scripts in a folder named .profile.d are run before the Procfile is executed.
Please note:
“The scripts must be bash
scripts, and their filenames must end in .sh
.”
To generate the New Relic variables I created three files, which are stored in the .profile.d folder.
The first os_vars.sh is executed by the buildpack and exports the variables after extracting them from the VCAP_SERVICES JSON variable, using Python. The export has to be done in the bash script to make the environment variable available in the current bash session.
os_vars.sh
#!/bin/sh #New Relic export NEW_RELIC_LICENSE_KEY="$(python $HOME/.profile.d/newrelic_license.py)" echo "added environment variable NEW_RELIC_LICENSE_KEY with value: $NEW_RELIC_LICENSE_KEY" export NEW_RELIC_APP_NAME="$(python $HOME/.profile.d/app_name.py)" echo "added environment variable NEW_RELIC_APP_NAME with value: $NEW_RELIC_APP_NAME" export NEW_RELIC_LOG="stdout" echo "added environment variable NEW_RELIC_LOG with value: $NEW_RELIC_LOG"
The second script, app_name.py , extracts from a not yet mentioned environment variable, VCAP_APPLICATION, the name of the Cloud Foundry application. The variable does store more information like IP address or limits.
app_name.py:
import os import json if 'VCAP_APPLICATION' in os.environ: VCAP_APPLICATION = json.loads(os.environ['VCAP_APPLICATION']) if 'application_name' in VCAP_APPLICATION: APPLICATION_NAME = VCAP_APPLICATION['application_name'] print(APPLICATION_NAME)
The last script, newrelic_license.py , extracts from the VCAP_SERVICES environmnet variable finally the license for New Relic.
newrelic_license.py:
import os import json if 'VCAP_SERVICES' in os.environ: vcap_services = json.loads(os.environ['VCAP_SERVICES']) if 'newrelic' in vcap_services: NEW_RELIC_LICENSE_KEY = vcap_services['newrelic'][0]['credentials']['licenseKey'] print(NEW_RELIC_LICENSE_KEY)
New Relic
After finding a way to create the New Relic variables we need to configure our application to use New Relic.
The first step is to add newrelic to the requirements.txt This instructs Cloud Foundry to install the required software. The file below is taken from my sample application on GitHub, which also includes all the other modifications for New Relic.
requirements.txt:
Django==1.7.1 WhiteNoise==1.0.6 gunicorn==19.1.1 mysql-connector-python==2.0.2 psycopg2==2.5.4 dj-database-url==0.3.0 newrelic==2.40.0.34
Finally we instruct Cloud Foundry to use newrelic-admin to launch our application.
Procfile:
web: newrelic-admin run-program gunicorn emcforum.wsgi --workers 2
A couple of minutes after pushing your appllcation to Cloud Foundy and accessing it, to generate some load, you should see some nice data in the New Relic UI!
Manual configuration
If you have a Cloud Foundry installation without a New Relic service in the marketplace, you can also create an account on newrelic.org and add the license manually.
This can be simply done by modifying the manifest.yml .
manifist.yml:
--- applications: - name: vLab instances: 1 memory: 128M command: null services: - vLab_DB - vLab_newrelic env: SECRET_KEY: 'aadc-t8j*i5a7^y9@d^$at#g0!j_h=h++5stj=nb7z8u#l_y#&' DEBUG: 'False' NEW_RELIC_LICENSE_KEY: '25sdcaa37583f73d0d76c9da43a8931f796e6978'
Troubleshoot
If you have an issue with New Relic and don’t see any data, you can push your application using a custom command. This command is the same we used in the section “Installation and Configuration for Python”, but this time we don’t specify a configuration file and send the output to the console. This way we will see the output in the log for our application.
cf push --no-route -c "newrelic-admin validate-config - stdout"