Getting a Quick Overview of your Site’s Response Times

Creative Commons License Tidewater Muse
I promised you a couple weeks back to share some more code for building your own XFD (extreme feedback device). Embedding Munin graphs is child’s play, so I thought I’d give you a head-start with the Pingdom API. And we all know how critical site response times are to the success of your online business.

Why not just login to Pingdom?

Good question! My answer – because it’s slow & tedious. It takes me minutes to get the information I’m looking for – namely, the average response time of a few critical pages from yesterday and today. To not have to click through the various cities every day deselecting all the [European|American] sites in order to get a more accurate measurement – this alone is worth its weight in gold!

Don’t get me wrong. The graphs are wonderful for spotting trends, but I don’t need to look at these every day. I want to be able to tell within a second or two if my site is performant.

There’s a reason they made an API

The good folks at Pingdom are number crunchers at heart – they probably also avoid logging into the site when possible because they developed a nice API with which you can access all the info you need.

After requesting an API key, you’re just a few curl commands away from this :
pingdom

And here’s the corresponding code:

<?php
    define('SERVER_URL', 'https://ws.pingdom.com/soap/PingdomAPI.wsdl');
    define('USERNAME', '<username>');
    define('PASSWORD', '<password>');
    define('PINGDOM_API_KEY', '<api_key>');
    define('PINGDOM_API_STATUS_OK', 0);
    define('RESOLUTION', 'DAILY');
    define('GOOD_TIMING', 500);
    define('POOR_TIMING', 800);
    
    $client = new SoapClient(SERVER_URL, array( 'trace' => 1,'exceptions' => 0 ));
    
    $sessionId = loginPingdom($client);
    $responses = fetchPages($client, $sessionId);
    writeResponse($responses);
    logout($client, $sessionId);
    
function loginPingdom($client) {
    // Login
    $login_data->username = USERNAME;
    $login_data->password = PASSWORD;
    $sessionId = null;
    
    // Pingdom API function, see details on http://www.pingdom.com/services/api-documentation/
    $login_response = $client->Auth_login(PINGDOM_API_KEY, $login_data);

    // Check if everything is OK
    if (PINGDOM_API_STATUS_OK != $login_response->status) {
        echo'Unable to login to Pingdom';
    } else {
        // Without this value you wont be able to call any other Pingdom API function
        $sessionId = $login_response->sessionId;
    }
    
    return $sessionId;
}

function fetchPages($client, $sessionId) {
    $locs = array("Amsterdam, Holland","London, UK","Paris, France","Stockholm, Sweden");
    
    // Today - up through CURRENT_TIME
    $get_times_today->from = mktime("00", "00", "00", date("m"), date("d"), date("Y"));
    $get_times_today->to = CURRENT_TIME;
    $get_times_today->resolution = RESOLUTION;
    $get_times_today->locations = $locs;
    
    //Yesterday
    $get_times_yesterday->from = mktime("00", "00", "00", date("m") , date("d") - 1, date("Y"));
    $get_times_yesterday->to = mktime("23", "59", "59", date("m") , date("d") - 1, date("Y"));
    $get_times_yesterday->resolution = RESOLUTION;
    $get_times_yesterday->locations = $locs;
    
    // page names taken from how you entered them in Pingdom
    $pages_to_query = array('Homepage', 'Krankheiten', 'Asthma article');
    
    $responses = array();
    
    foreach ($pages_to_query as $checkName) {
        $response = null;
        
        $get_times_today->checkName = $checkName;
        $get_times_yesterday->checkName = $checkName;
        
        $times_today = $client->Report_getResponseTimes(PINGDOM_API_KEY, $sessionId, $get_times_today);
        $times_yesterday = $client->Report_getResponseTimes(PINGDOM_API_KEY, $sessionId, $get_times_yesterday);
        
        if (PINGDOM_API_STATUS_OK != $times_today->status || 
            PINGDOM_API_STATUS_OK != $times_yesterday->status) {
            echo('Error occurred while trying to get list of responsetimes');
        } else {
            $list_times_today = $times_today->responseTimesArray;
            $list_times_yesterday = $times_yesterday->responseTimesArray;
            
            $response->page = $checkName;
            $response->today = round($list_times_today[0]->responseTime);
            $response->yesterday = round($list_times_yesterday[0]->responseTime);
            
            $response->y_threshold = $response->yesterday < GOOD_TIMING ? 'green' : ($response->yesterday < POOR_TIMING ? 'orange' : 'red');
            $response->t_threshold = $response->today < GOOD_TIMING ? 'green' : ($response->today < POOR_TIMING ? 'orange' : 'red');
            
            $responses[] = $response;
        }
    }
    
    return $responses;
}

function writeResponse($responses) {
    $yesterday = date('d.m.Y', mktime(0, 0, 0, date("m") , date("d") - 1, date("Y")));
	$current = date('d.m.Y', CURRENT_TIME);
	
    echo "<br/><br/>";
    echo "<table class='responses' title='Response time (ms)' border='1'>";
    echo "    <tr>";
    echo "        <th> Response Times </th>";
    echo "        <th> $yesterday </th>";
    echo "        <th> $current </th>";
    echo "    </tr>";
    
    foreach ($responses as $response) { 
        $response_page = $response->page;
        $response_yest_thresh = $response->y_threshold;
        $response_toda_thresh = $response->t_threshold;
        $response_yesterday = $response->yesterday;
        $response_today = $response->today;
        
        echo "    <tr>";
        echo "        <td>$response_page</td>";
        echo "        <td><span style='color:$response_yest_thresh;'>$response_yesterday ms</span></td>";
        echo "        <td><span style='color:$response_toda_thresh;'>$response_today ms</span></td>";
        echo "    </tr>";
    }
    
    echo "</table>";
}

function logout($client, $sessionId) {
    $logout_response = $client->Auth_logout(PINGDOM_API_KEY, $sessionId);
    if (PINGDOM_API_STATUS_OK != $logout_response->status) {
        echo('Error occurred while closing connection');
    }
}
?>

Of course, there are a few customizations you should make – namely the $locs, $pages_to_query, GOOD_TIMING & POOR_TIMIING (both measured in msec) values. But, I hope I’ve gotten you off to a good start.

Questions, comments & criticisms happily taken!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

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