DEV Community

Anthony Bloomer
Anthony Bloomer

Posted on

Building a Fitness Insights Dashboard

Introduction

As a motivator to maintain a healthy diet and to get into a routine of daily workouts, I have started to track my intake and exercise habits using MyFitnessPal and other mobile applications. Pulling data from those sources and creating custom events in New Relic Insights allows me to keep track of my progress and provides a way for me to query my data using NRQL and to create visualizations.

Data Sources

The two main applications I use for tracking is MyFitnessPal and MapMyWalk. MyFitnessPal allows you to track your diet and exercise to determine optimal caloric intake and nutrients for your overall goal. MapMyWalk allows you to track cardiovascular activities such as running, walking, and even stationary bike exercises.

Although MyFitnessPal does have an API, it is private-access only. To get around this, I found a Python library called python-myfitnesspal which allows you to scrape your data from MyFitnessPal. See the example below:

import myfitnesspal

client = myfitnesspal.Client('my_username')
day = client.get_date(2013, 3, 2)
day
# >> <03/02/13 {'sodium': 3326, 'carbohydrates': 369, 'calories': 2001, 'fat': 22, 'sugar': 103, 'protein': 110}>
Enter fullscreen mode Exit fullscreen mode

For a daily summary of your nutrition information, you can use a Day object's totals property:

day.totals
# >> {'calories': 2001,
#     'carbohydrates': 369,
#     'fat': 22,
#     'protein': 110,
#     'sodium': 3326,
#     'sugar': 103}
Enter fullscreen mode Exit fullscreen mode

If you want to see the amount of water you've recorded:

day.water
# >> 1
Enter fullscreen mode Exit fullscreen mode

Perfect. These are exactly the data points I am interested in. So, once a day, I call the API to get those values and record a custom event using the Python Agent API:

def send_intake_data():
    client = myfitnesspal.Client(USERNAME, PASSWORD)
    day = client.get_date(datetime.datetime.now())
    totals = day.totals
    totals.update({'water': day.water})
    newrelic.agent.record_custom_event('Meal', totals, application)
Enter fullscreen mode Exit fullscreen mode

Similarly to MyFitnessPal, MapMyWalk does have an API but it is private access only. To address this issue, I wrote a simple script using Selenium which logs into the MapMyWalk website and then goes to a JSON resource which holds my workout data. Once every day, I call this script to get workout data for that day and then record a custom event in Insights:

def login():
    logger.info("Logging into MapMyWalk")
    driver = webdriver.Chrome(options=chrome_options)
    driver.get(LOGIN_URL)
    driver.find_element_by_id('email').send_keys(USERNAME)
    driver.find_element_by_id('password').send_keys(PASSWORD)
    driver.find_element_by_id('password').send_keys(Keys.ENTER)
    return driver

def get_workout_data():
    d = login()
    time.sleep(3)
    today = datetime.date.today()
    d.get(WORKOUTS % (today.month, today.year))
    time.sleep(3)
    pre = d.find_element_by_tag_name("pre").text
    data = json.loads(pre)
    logger.info("JSON response: %s" % data)
    wd = data['workout_data']['workouts']
    d.close()
    d.quit()
    today = str(today)
    if today not in wd:
        logger.info("No workouts found for today.")
        return None
    else:
        return wd[today]

def send_workout_data():
    workout_data = get_workout_data()
    if workout_data is not None:
        for w in workout_data:
            logger.info(w)
            newrelic.agent.record_custom_event('Workout', w, application)
Enter fullscreen mode Exit fullscreen mode

You can find the complete source code on my GitHub. The documentation covers project setup and deployment instructions.

Insights Dashboard

Image

Installation

This project uses python-myfitnesspal to programmatically interact with and analyze the information I have entered into MyFitnessPal. To authenticate, you'll need to export your username and password as environment variables:

export FITNESS_PAL_USERNAME='YOUR_USERNAME'
export FITNESS_PAL_PASSWORD='YOUR_PASSWORD'
Enter fullscreen mode Exit fullscreen mode

I'm using Selenium and the ChromeDriver to automate data retrieval from the MapMyWalk website. You will need to have Google Chrome and ChromeDriver installed. If you are using macOS, you can install ChromeDriver using Homebrew:

brew cask install chromedriver
Enter fullscreen mode Exit fullscreen mode

To send metrics to New Relic Insights, you will also need to export your application name and license key:

export NEW_RELIC_LICENSE_KEY='YOUR_LICENSE_KEY'
export NEW_RELIC_APP_NAME='YOUR_APP_NAME'
Enter fullscreen mode Exit fullscreen mode

Then, create a new Virtual Environment and install the project requirements:

virtualenv env
source env/bin/activate
pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Finally, launch the worker:

python fitnesspal.py
Enter fullscreen mode Exit fullscreen mode

The program uses schedule to send metrics once a day at 23:30pm.

Deploying to Heroku

Since I'm using Selenium to automate data retrieval from MapMyWalk, you'll need to install the following buildpacks:

You will also need to configure the environment variables outlined in the installation above, for example:

heroku config:set NEW_RELIC_LICENSE_KEY=YOUR_LICENSE_KEY
Enter fullscreen mode Exit fullscreen mode

Querying Insights Data

This tool creates two custom events, Meal and Workout, which you can query using NRQL in Insights.

Examples

Get your average calorie intake since 1 week ago:

SELECT average(calories) FROM Meal SINCE 1 week AGO TIMESERIES 1 day 
Enter fullscreen mode Exit fullscreen mode

Get the total number of steps walked since 1 week ago:

SELECT sum(steps) FROM Workout SINCE 1 week AGO TIMESERIES 1 day 
Enter fullscreen mode Exit fullscreen mode

Get the total amount of water consumed:

SELECT sum(water) FROM Meal SINCE 1 week AGO TIMESERIES 1 day 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)