Terminology & Syntax

Groovy Tips & Tricks

LogicMonitor's Embedded Groovy Scripting engine provides a number of helper classes specifically selected to help get instrumentation data out of systems & devices. See the following tips & tricks:

Calling a Simple HTTP API

Many devices have their own HTTP APIs that you might need to access to get device performance data. For a simple example, see the following example, where we query a NetApp E-Series REST API for details about it's flash cache:

 
// import the logicmonitor http and jsonslurper classes
import com.santaba.agent.groovyapi.http.*;
import groovy.json.JsonSlurper;

// get the host, credentials, and mgmt station baseurl from the device property table
hostname = hostProps.get("system.hostname");
userid = hostProps.get("netapp.rest.user");
passwd = hostProps.get("netapp.rest.pass");
base_url = hostProps.get("netapp.rest.url");

// construct the full endpoint url
endpoint_url = base_url + "/devmgr/v2/storage-systems/" + hostname + "/flash-cache";

// fetch data from the API
http_body = HTTP.body(endpoint_url, userid, passwd);

// in this case, the http body is a json data structure
// let's use jsonslurper to turn the json text into an groovy object
json_slurper = new JsonSlurper();
response_obj = json_slurper.parseText(http_body);

// iterate over the response object, assigning key-value pairs
response_obj.each()
{ key, value ->
    // print each key-value pair
    println key + "=" + value;
}

// return with a response code that indicates we ran successfully
return (0);

In this case you'll want to create a datapoint for each of the key-value pairs you care about, using the key-value post-processor to separate the values as necessary.

Running an External Process

Some devices require that you run a CLI tool or some compiled binary to extract data. To do this in Groovy we do something like this:

 
// get the device hostname and cli credentials
hostname = hostProps.get("system.hostname");
cli_user = hostProps.get("cli.user");
cli_pass = hostProps.get("cli.pass");

// define the extnernal commmand you want to run
command = "/usr/local/bin/ipmiutil sensor -c -N " + hostname + " -U " + cli_user + " -P " + cli_pass;

// setup some buffers to hold process stdout & stderr
process_output = new StringBuffer();
process_errors = new StringBuffer();

// execute the command
process = command.execute();
// collect the stdout & stderr from the process
process.waitForProcessOutput(process_output, process_errors);

// kill the process if it runs for longer than we expect (30 seconds)
process.waitForOrKill(30000);

// did the process exit with a successful return code?
if (process.exitValue() == 0)
{
    // yes, the process ran successfully -- process the output as necessary and print it out 
    println process_output;

    // return with a response code that indicates we ran successfully
    return(0);
}
else
{
    // no, the process failed -- print some diagnostics and stderr
    println 'Execution of Process: "' + command + '" failed with an exit code of "' + process.exitValue() + '"';
    println process_errors;

    // return with a response code that indicates some failure
    return(1);
}

Interacting with DNS

The Collector includes the ability to allow scripting of DNS objects. This can be handy when you need to verify the operation of your local DNS resolvers.

Here's a simple example that would allow you to verify the resolution of a specific DNS record:

 
// import the xbill dns helper class
import org.xbill.DNS.*;

// do a DNS lookup, 
records = new Lookup("gmail.com", Type.MX).run()

// iterate through the records list
records.each() 
{ address ->
    // print the address record    
    println address;
}
// return with a response code that indicates we ran successfully
return(0);

You might use this in conjunction with a datapoint post-processor to look for the presence of a certain address and trigger an alert if it's not found.

See http://dnsjava.org/dnsjava-current/doc/ for complete class documentation of this class.