Monitoring OS X with AppleScript and Monitis

As a system administrator, you will often need to get information about the health and performance of your systems, using only whatever tools are available. Monitis, and its REST API, give you the utmost in flexibility, allowing you to use whatever tools you have, on any system. In this article, we’ll take a look at how AppleScript can be used to invoke REST API calls, using a system load monitor as an example.

Getting Started

To begin, you should read some of the previous articles discussing monitoring Linux or OS X with bash scripts. There are details of using the API covered there that we won’t cover again in this article. At a minimum, you should have your API key and secret key handy.

AppleScript is a language and programming environment used in OS X to automate tasks that need to interact with applications. For a system administrator with a UNIX background, using shell scripts will usually be the first choice, but AppleScript offers the ability to take advantage of special interfaces built into many OS X applications. It can also use the output of any UNIX command line programs. For this example, we’ll just use system load averages to illustrate the concept.

Before we dive into the AppleScript code, let’s create the monitor where we can report the results, using the shell script from the previous article.

$ export APIKEY="your API key"
$ export SECRETKEY="your API secret"

# create the monitor
$ ./

Keep track of the number labeled “data” in the response from, as you will want to add that to the configuration in the AppleScript monitor that we create.

The AppleScript code

To make the script easier to read, modify, and maintain, the steps of the process are separated out into “handlers”, which are groups of multiple statements with a common purpose. These are roughly analogous to functions and methods in other programming languages. The main steps of our system load monitor are gathering information from the system, manipulating it to work with the Monitis API, and ultimately posting it to the custom monitor we created.

Getting the system load

This step is the simplest. It calls the uptime command, and parses out the load averages. A string containing the resulting values is formatted for posting to the Monitis API and then returned from the handler.

-- get the 1, 5, and 15 minutes load averages using the uptime command
to getLoadAvgsResult()
    return do shell script "uptime | egrep -o \"averages: (.*)\" | while read a b c d; do echo 1m:$b\\;5m:$c\\;15m:$d; done"
end getLoadAvgsResult


Format data for the Monitis API

In this step, we take the values returned in the previous step, and combine it with the information needed to use the Monitis API, including calculating a checksum, timestamp, and adding in the monitor ID and API key.

-- generates a timestamp in the format required by the Monitis REST API
to getTimeStamp()
    return do shell script "date -u +\"%F %T\""
end getTimeStamp

-- calculates the check time in the format required by the Monitis REST API
to getCheckTime()
    return do shell script "date -u +\"%s\"000"
end getCheckTime

-- calculates the checksum for the Monitis API
-- note that the key-value parameters are (and must be) sorted alphabetically by key
-- OpenSSL is used to do the actual HMAC calculation
to calcChecksum(secretkey, action, apikey, checktime, monitorId, result, timestamp, version)
    set checksumString to "action" & action
    set checksumString to checksumString & "apikey" & apikey
    set checksumString to checksumString & "checktime" & checktime
    set checksumString to checksumString & "monitorId" & monitorId
    set checksumString to checksumString & "results" & result
    set checksumString to checksumString & "timestamp" & timestamp
    set checksumString to checksumString & "version" & version
    set checksumScript to "printf '%s' '" & checksumString & "' | openssl dgst -sha1 -hmac " & secretkey & " -binary | openssl enc -base64"
    set checksum to do shell script checksumScript
    return checksum
end calcChecksum


Post the result to the Monitis custom monitor

Finally, with the data collected, and ready to post, we send it off to the Monitis API, and display the result to the user.

-- post a previously calculated result to the Monitis REST API
-- uses curl to make the actual connection to the Monitis URL
to postResult(apikey, secretkey, monitis_url, output, monitorId, result)
    set checktime to getCheckTime()
    set timestamp to getTimeStamp()
    set checksum to calcChecksum(secretkey, "addResult", apikey, checktime, monitorId, result, timestamp, "2")
    set postData to buildPostString("addResult", apikey, checktime, monitorId, result, timestamp, "2", checksum)
    set returnValue to do shell script "curl " & postData & " " & monitis_url
end postResult

-- helper handler for postResult
-- builds the post string that will be passed to curl
to buildPostString(action, apikey, checktime, monitorId, result, timestamp, version, checksum)
    set postData to "--data-urlencode 'action=addResult' "
    set postData to postData & "--data-urlencode 'apikey=" & apikey & "' "
    set postData to postData & "--data-urlencode 'checktime=" & checktime & "' "
    set postData to postData & "--data-urlencode 'monitorId=" & monitorId & "' "
    set postData to postData & "--data-urlencode 'results=" & result & "' "
    set postData to postData & "--data-urlencode 'timestamp=" & timestamp & "' "
    set postData to postData & "--data-urlencode 'version=" & "2" & "' "
    set postData to postData & "--data-urlencode 'checksum=" & checksum & "' "
    return postData
end buildPostString

Once the results have been sent, we display the result of the HTTP POST with the AppleScript command “display dialog”, which will pop up a dialog box with the result. In previous bash and python examples, this result was displayed via standard output. In the context of AppleScript, it works better to do this with a dialog box, because it is unlikely that standard output will be available, i.e. in the situation where the user double-clicks on the script icon to run it. Here’s how the pieces above are called at the top level of the script.

-- get the load average, and submit it to Monitis
set loadAvgsResult to getLoadAvgsResult()
set apiresult to postResult(apikey, secretkey, monitis_url, output, monitorId, loadAvgsResult)
display dialog "Monitis API Result: " & apiresult buttons {"OK"}

Then, the output looks like this:

Try it out

If you haven’t already downloaded the code for this example, now is a great time to get the code and try it out. Everything you need to get started is available in the Monitis Exchange GitHub Repository. You can retrieve the code like this.

$ git clone
Cloning into Monitis-Mac-OS-scripts...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (7/7), done.
remote: Total 8 (delta 1), reused 8 (delta 1)
Unpacking objects: 100% (8/8), done.

With the code in place, work your way through the example and try it out. When you open the file “monitis_record_load.scpt”, it will launch the AppleScript Editor application, if it isn’t already running. This is a basic integrated development environment (IDE), which will allow you to edit, compile, run, and debug your script.

To start, open the example script in the AppleScript Editor. You will need to make a few modifications to the configuration, so it will work with your own custom monitor. Specifically, change the following lines, so that they contain your own API key, secret key, and custom monitor ID. The monitor ID is the value obtained from earlier.

-- monitor configuration, replace these with your own keys and ID
set apikey to "your API key"
set secretkey to "your secret key"
set monitorId to "845"

Then, you should be able to click on the run button (green button with a black arrow), and see the result, as in the screen shot above. You can also use the Event Log pane at the bottom of the editor window to watch the code in progress.

Create an application

With a working script for your custom monitor, the last step in this example is to turn it into a application that can run outside of the editor. To do this, simply select “Save as…” from the File menu, and choose the file format “Application.” When saved, this file can be run by double-clicking on its icon.

Next steps

Now you have a custom monitor for system load in AppleScript. From here, you can modify the script to monitor other system metrics, including application status that is only accessible via AppleScript APIs. Suppose, for example, that you want to monitor the idle time of Jabber contacts, using the Adium instant messaging client popular on OS X. The code to get that value into a monitor would look like this:

tell application "Adium"
    set idleTime to idle time of contact ""
end tell

By using this value in place of loadAvgsResult, and creating an appropriate custom monitor, monitoring a Jabber contact becomes easy. That’s it for this article. Now, go try it out for yourself.

Monitis Monitoring Platform