Source Code Example: Using Twilio and Interzoid APIs Together for a Web Page (or other API) Global Monitoring and Alerting System

by Interzoid Team


Posted on August 7th, 2019


Twilio SMS Integration using Interzoid's Global Page Load and CDN Performance Monitoring API from Cities around the Globe

If you don't know Twilio, they have a set of communication APIs for SMS, Voice, and Messaging applications. They have 160,000 customers and an ecosystem of six million developers. Twilio's SMS API is ideal for sending system alert notifications to any device with a phone number, including coverage in 150 countries.

In this example, we will use Interzoid's Global Page Load API to measure load performance of a specified Web page from thirteen different physical locations around the globe. Then, when a certain measurement threshold is exceeded, we will use the Twilio SMS API to send an SMS alert notifying ourselves of the event. The example code just runs once, but of course in practice you would want this to run utilizing a scheduler at timed intervals.

The example code is written in Go, however the logic is easy enough to follow for the concepts to translate into any language. You will need a separate API key from both Interzoid and Twilio to execute the code, both of which provide free trials if you do not already have credentials.

The global locations used as sources from which to test performance are indicated in the array of strings labeled "locations" in the source code below. This list of course could be reduced if you did not want to test from each of the available global locations (a handful of dispersed locations would likely suffice). Available locations include Frankfurt, Sydney, Hong Kong, Sao Paulo, Montreal, London, Singapore, California, Paris, Tokyo, Mumbai, Virginia, and Stockholm. Internally, the API communicates with processes running on servers in those locations that perform the actual measuring.

Here is a walkthrough of the code:

First, the main package declaration and the importing of other packages we will make use of:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
    "strconv"
    "strings"
)

Next is the declaration of a type used as the basis to parse the returned JSON from the Interzoid API call.

// data type for the parsed JSON
type Payload struct {
    Origin string
    Seconds string
    PageResponseStatus string
    Contents string
    Code string
    Credits string
}

Next is the function to use the Twilio SMS API using your Twilio credentials. This will be called by the main function when a performance threshold is reached.

// function to send SMS notification through Twilio API
func smsNotify(s string) {

    // Set account keys & information
    accountSid := "YourTwilioAccountSid"
    authToken := "YourTwilioAuthToken"
    urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json"

    // Set data for the SMS notification message
    msgData := url.Values{}
    msgData.Set("To", "RecipientNumber")
    msgData.Set("From", "YourTwilioProvidedPhoneNumber")
    msgData.Set("Body", s)
    msgDataReader := *strings.NewReader(msgData.Encode())

    // Create HTTP request client and set headers
    client := &http.Client{}
    req, _ := http.NewRequest("POST", urlStr, &msgDataReader)
    req.SetBasicAuth(accountSid, authToken)
    req.Header.Add("Accept", "application/json")
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    // Make HTTP POST request, parse JSON response, and return the message SID
    resp, _ := client.Do(req)
    if (resp.StatusCode >= 200 && resp.StatusCode < 300) {
        var data map[string]interface{}
        decoder := json.NewDecoder(resp.Body)
        err := decoder.Decode(&data)
        if (err == nil) {
            fmt.Println("Twilio sid: ",data["sid"],"\r\n")
        }

        // Error handling
        } else {
        fmt.Println(resp.Status);
    }
}

Next declare the main function:

func main() {

Next declare an array that contains the names of each location where the performance measuring will occur from. These values will be passed one a time within the main loop to the Global Page Load API to perform the monitoring.

    // global physical locations to test performance from using Interzoid API
    locations := []string{"Frankfurt", "Sydney", "HongKong", "SaoPaulo", "Montreal", "London",         "Singapore",California", "Paris", "Tokyo", "Mumbai", "Virginia", "Stockholm"}

Next is the main loop, where the performance of a given Web page is tested from each location, and an SMS sent if the performance threshold is exceeded.

    for _, loc := range locations {
        url := "http://www.twilio.com" // any url you want to test for page load performance
        endpoint := "https://api.interzoid.com/globalpageload?
          license=YourInterzoidAPIKey&origin=" +
        loc + "&url=" + url
        response, _ := http.Get(endpoint)
        thePayload := Payload{}

        if response.StatusCode != 200 {
            fmt.Println("Error: ", response.Status)
            fmt.Println(loc, thePayload)
            fmt.Println("\r\n")
        } else {
            json.NewDecoder(response.Body).Decode(&thePayload)
            fmt.Println(url +
            "," + thePayload.Origin +
            "," + thePayload.Seconds +
            "," + thePayload.PageResponseStatus +
            "," + thePayload.Code +
            "," + thePayload.Credits +
            "\r\n")

            // convert from string to float for comparison
            elapsed, _ := strconv.ParseFloat(thePayload.Seconds, 64)
            if elapsed >= 2.0 { // two seconds - can be changed to anything.
                smsNotify("Warning! loc: " + loc + " seconds: " + thePayload.Seconds +
                  " -> " + url)
            }
        }
    }
}

And that's it! You can now test the performance, load times, and reliability of Web pages from around the world, alerting the appropriate personnel when an issue arises.


Measuring an API call instead of a Web page

You can measure an API call using the Interzoid Global Page Load API simply by using a URL query string as the url parameter passed to the API. For example, the following line:

url := "http://www.twilio.com"

can be changed to something like this:

url := "https://api.interzoid.com/getweatherzipcode?
    license=YourInterzoidAPIKey&zip=43210"

and the behavior will be the same, sending SMS messages if the API response time exceeds the performance threshold.

Here is the complete source code:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "net/url"
    "strconv"
    "strings"
)

// data type for the parsed JSON
type Payload struct {
    Origin string
    Seconds string
    PageResponseStatus string
    Contents string
    Code string
    Credits string
}

// function to send SMS notification through Twilio API
func smsNotify(s string) {

    // Set account keys & information
    accountSid := "YourTwilioAccountSid"
    authToken := "YourTwilioAuthToken"
    urlStr := "https://api.twilio.com/2010-04-01/Accounts/" + accountSid + "/Messages.json"

    // Set data for the SMS notification message
    msgData := url.Values{}
    msgData.Set("To", "RecipientNumber")
    msgData.Set("From", "YourTwilioProvidedPhoneNumber")
    msgData.Set("Body", s)
    msgDataReader := *strings.NewReader(msgData.Encode())

    // Create HTTP request client and set headers
    client := &http.Client{}
    req, _ := http.NewRequest("POST", urlStr, &msgDataReader)
    req.SetBasicAuth(accountSid, authToken)
    req.Header.Add("Accept", "application/json")
    req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

    // Make HTTP POST request, parse JSON response, and return the message SID
    resp, _ := client.Do(req)
    if (resp.StatusCode >= 200 && resp.StatusCode < 300) {
        var data map[string]interface{}
        decoder := json.NewDecoder(resp.Body)
        err := decoder.Decode(&data)
        if (err == nil) {
            fmt.Println("Twilio sid: ",data["sid"],"\r\n")
        }

        // Error handling
        } else {
        fmt.Println(resp.Status);
    }
}

func main() {

    // global physical locations to test performance from using Interzoid API
    locations := []string{"Frankfurt", "Sydney", "HongKong", "SaoPaulo", "Montreal", "London",         "Singapore",California", "Paris", "Tokyo", "Mumbai", "Virginia", "Stockholm"}

    for _, loc := range locations {
        url := "http://www.twilio.com" // any url you want to test for page load performance
        endpoint := "https://api.interzoid.com/globalpageload?
          license=YourInterzoidAPIKey&origin=" +
        loc + "&url=" + url
        response, _ := http.Get(endpoint)
        thePayload := Payload{}

        if response.StatusCode != 200 {
            fmt.Println("Error: ", response.Status)
            fmt.Println(loc, thePayload)
            fmt.Println("\r\n")
        } else {
            json.NewDecoder(response.Body).Decode(&thePayload)
            fmt.Println(url +
            "," + thePayload.Origin +
            "," + thePayload.Seconds +
            "," + thePayload.PageResponseStatus +
            "," + thePayload.Code +
            "," + thePayload.Credits +
            "\r\n")

            // convert from string to float for comparison
            elapsed, _ := strconv.ParseFloat(thePayload.Seconds, 64)
            if elapsed >= 2.0 { // two seconds - can be changed to anything.
                smsNotify("Warning! loc: " + loc + " seconds: " + thePayload.Seconds +
                  " -> " + url)
            }
        }
    }
}

Free API Credits
Register for an Interzoid API account and receive free trial credits
Global Page Load API
Measure Web asset performance from multiple locations around the globe.
More Info...