It is now easier than ever to build command-line probes. Here is a fun example that retrieves temperature data from the US NOAA weather feed for a particular city. It's at: http://www.weather.gov/xml/current_obs/
How does this probe work? The customer opens the probe picker, selects the Weather Service-Temp probe (it's in the Miscellaneous/Test category). Enter the city code for the closest weather station (KLEB is at Lebanon Municipal Airport, about a half mile to the south of us.) The Status window shows the name of the weather station, and there's a chartable value for the temperature reading.
Under the covers, InterMapper launches a Python program to contact the weather service, retrieve the meteorological conditions for the indicated city, and parses out the XML response to retrieve the temperature. (There's lots more information in the Weather Service feed - the program could easily be extended to display more information.) Here are some of the features of this probe:
- It's now easy to write cross-platform Python probes. The ${PYTHON} macro gives the path to the built-in python interpreter of InterMapper DataCenter no matter what platform you're using. For example, the probe can now use ${PYTHON} program.py and InterMapper will substitute the proper path to invoke Python, whether on Windows, OSX, or Linux/Unix.
- Probe writers can now include the script directly in the text of the probe file. (Earlier versions of InterMapper required that the script be saved separately in the Tools directory or elsewhere.) This makes it much easier to write scripts and keep the probe file in sync. To do this, use the new <tool:program-name> section in your probe file. The example file contains a program named noaa-weather.py. When InterMapper loads the probe, it parses out this section and saves it in a folder within the Tools directory of InterMapper Settings. Programs in the <tool:program-name> section may also save private files in that directory.
- The example probe file uses a couple interesting Python libraries. First is urllib2 that makes it easy to make queries from web services. It's a few straightforward calls to build a url, issue it, and retrieve the results.
- The probe also uses the xml.dom.minidom library to parse out XML data returned from the NOAA web service. This library is particularly well-explained in Chapter 9 of Dive into Python.
References
Developer Guide: General information about building Custom Probes
${PYTHON} macro
Python Documentation:
urllib2
xml.dom.minidom
Dive into Python: Chapter 12 provides a very readable discussion of XML processing in Python. The book is at:
The NOAA Temperature Probe
To use this probe, copy the text below, save it to a text editor, then use File->Import->Probe... in InterMapper.
Code: |
<!-- Weather Service Temperature - Retrieve the temperature from the NOAA weather XML (com.dartware.tool.noaa.txt) Copyright (c) 2009 Dartware, LLC. Please feel free to use this as a base for further development. 11Jun2010 - Updated to include a "m" in the closing tag of the display so that the outages are monospaced. -->
<header> type = "cmd-line" package = "com.dartware" probe_name = "tool.noaa" human_name = "Weather Service-Temperature" version = "1.2" address_type = "IP" display_name = "Miscellaneous/Test/Weather Service-Temp" </header>
<description> \GB\Retrieve the current temperature\p\
This probe retrieves the current temperature from the NOAA weather feed. To see the proper city code, visit:
\u4=http://www.weather.gov/xml/current_obs/\http://www.weather.gov/xml/current_obs/\p0\ </description>
<parameters> "Weather Station" = "KLEB" </parameters>
<command-line> path="" cmd="${PYTHON} noaa-weather.py" arg="${Weather Station}" </command-line>
<command-exit> -- These are the exit codes used by Nagios plugins down: ${EXIT_CODE}=4 critical: ${EXIT_CODE}=3 alarm: ${EXIT_CODE}=2 warn: ${EXIT_CODE}=1 okay: ${EXIT_CODE}=0 </command-exit>
<autorecord> $temp, 'tempNOAA', "NOAA Temp" </autorecord>
<command-display> \b5\ Temperature for $loc\p0\ Temperature: $temp \3g\degrees F\p0m\ </command-display>
<tool:noaa-weather.py>
# noaa-weather.py # Scan the XML results from NOAA's XML feeds # e.g., http://www.weather.gov/xml/current_obs/KLEB.xml # for relevant weather-related information. # 25 Mar 2009 -reb
import os import re import sys import getopt import urllib import urllib2 import htmllib from xml.dom import minidom
# httplib.HTTPConnection.debuglevel = 1 # force debugging....
# options are: station
try: opts, args = getopt.getopt(sys.argv[1:], "") except getopt.GetoptError, err: searchString = "getopt error %d" % (err)
station = args[0]
userAgent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; en-us) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1" noaaString = "http://www.weather.gov/xml/current_obs/%s.xml"
noaaString = noaaString % (urllib.quote_plus(station))
# print noaaString;
retcode = 4; try: request = urllib2.Request(noaaString) opener = urllib2.build_opener() request.add_header('User-Agent', userAgent) usock= opener.open(request) # print buf except IOError, e: if hasattr(e, 'reason'): resp = 'We failed to reach a server. ' reason = 'Reason: ' + 'Wrong host name?' # e.reason[1] elif hasattr(e, 'code'): resp = 'The server couldn\'t fulfill the request. ' reason = 'Error code: '+ str(e.code) print "\{ $temp := '%s', $loc := 'Unknown' } %s" % (0, resp + reason) sys.exit(retcode) # make it look down retcode = 0 # looks like it'll succeed
xmldoc = minidom.parse(usock)
tempList = xmldoc.getElementsByTagName('temp_f') tempElem = tempList[0] tempval = tempElem.firstChild.data
loclist = xmldoc.getElementsByTagName('location') locval = loclist[0].firstChild.data
print "\{ $temp := '%s', $loc := '%s' }%s" % (tempval, locval, tempval + ' degrees at ' + locval)
sys.exit(retcode) </tool:noaa-weather.py> |