New Relic with Python on Cloud Foundry


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 Overview

New Relic Overview

 

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"

 

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.