If you are looking for a way to ping an IP address or a URL’s domain using ICMP Ping, like you would from the OS command line, here’s some code for an Synthetic API monitor that works well.
Please note that builtin New Relic Synthetic “Ping” monitor actually tries to do an HTTP request, whereas this code does an actual ICMP ping, recording latency and failure rates, which you can graph in Insights.
To use this, create an Synthetic API monitor, paste in the code, and edit the first two variables. The targetName is just a string used in the console output. The target is the thing you want to ping, and it can be an IP address or a URL.
Down towards the bottom you will see where I insert data into Insights for graphing. I have a couple of variables consistent across all my Synthetic monitors called authTime and appTime so that I can separate out the time to authenticate into an application versus the time to load it’s home page. For this monitor, authTime is always zero, since no authentication takes place. Feel free to rename or delete these insights calls to make them work in your monitoring setup.
This code is based on some other ICMP ping code floating around the blogs, and fixes various bugs related to the asynchronous-ness of calls returning promises, and pretties it up a bit.
// **********************************************************
// SNMP ping monitor settings
// **********************************************************
var targetName = "India-PA3020-PRT01" // Name of device
var target = "14.141.80.162"; // IP address or URL
// **********************************************************
// You should not need to change anything below this line
// unless you want to tune an individual monitor in some manner.
// **********************************************************
// Standard settings
$http.head('https://google.com'); // Perform a HTTP HEAD so the NR monitor does not error out. We do not use this data.
var pingInterval = 1000; // How many ms between pings
var numberofruns = 12; // How many pings you want to perform for each monitor run
var runcount = 0; // How many pings were done so far
var failedcount = 0; // How many failures were seen so far
var alertOnFailedPercent = 10; // The maximum percentage of pings that can fail before alerting
var alertOnHighLatency = 700; // The max average latency in ms you will tolerate - gather metrics for a while, then tune this value if needed
var latencyarray = []; // Record the latency for each ping in an array
// Required modules
var ping = require ("net-ping"); // Gives us the ability to SNMP ping
var assert = require('assert'); // Gives us the ability to throw an alert+msg based on a condition
var dns = require('dns'); // Gives us the ability to do a dns lookup
// URL to IP
var regex = /.*:\/\/.*/; // Examine target to see if we need to convert a url to an IP
if (regex.test(target)) { // does target look like a URL?
var domain = target.split('/')[2]; // Get domain from the Url
var targetIP = ''; // IP address to ping
dns.lookup(domain, function (err, addresses, family) { // Do a DNS lookup
var msg = "Unable to resolve '" + domain + "' to an IP."; // Assert error message
assert.ok(addresses.length > 0, msg); // Assert that we got an ip address
targetIP = addresses; // Got an IP address
console.log("Pinging",domain,targetIP); // Progress message
}); // end DNS lookup
} else { // else we already have an IP address
targetIP = target; // just use the IP
console.log("Pinging",targetIP); // Progress message
} // Done getting the IP address to ping
// Ping Interval Timer
var runpings = setInterval(function(){ // Do this many pings using a timer
if (runcount < numberofruns) { // If not done yet
performping(); // Do a ping
} else { // Else we are done
clearInterval(runpings); // Stop the timer
calculateresult(); // Record the results
}
}, pingInterval); // Do a ping every pingInterval ms
// Ping
var performping = function() { // Do a single ping
if (targetIP == '') { return; } // Don't start until DNS resolves the domain to a targetIP
var session = ping.createSession (); // Create a ping session
session.pingHost (targetIP, function (error, targetIP, sent, rcvd) { // Ping the host
var ms = rcvd - sent; // Calculate the latency of the ping
if (error) { // If the ping errored
failedcount++; // Increment the failure count
console.log('Ping failed for',targetIP); // Log a failure to the console
} else { // Else
console.log('Reply from',targetIP,'time =',ms,'ms'); // Log the latency to the console - uncomment for debugging
latencyarray.push(ms); // Record the latency
}
runcount++; // Increment the count of pings done
});
};
// Results
var calculateresult = function() { // Calculate results and issue alerts
// Progress message
var latencies = latencyarray.toString(); // Progress message - latency array to a string
console.log("Latencies: " + latencies); // Progress message - latency array
// Average latency
var sum = 0; // Sum of latencies ignoring failures
for( var i = 0; i < latencyarray.length; i++ ){ // Walk through the latency array
sum += parseInt( latencyarray[i], 10 ); // Add them up
} // To get the total
var latencyavg = sum/latencyarray.length; // And divide by the number of latencies to get the average
console.log("Average latency: " + latencyavg,"ms"); // Progress Message
// Falure rates
var failedpercent = Math.round((failedcount/runcount)*100); // Round failedPercent to an integer
console.log("Failed count:",failedcount, "out of",runcount); // Progress Message
console.log("Failed percentage: " + failedpercent); // Progress Message
// Insights data
$util.insights.set("failed",failedcount); // Add to insights - failed is unique to this type of monitor
$util.insights.set("failed_percent",failedpercent); // Add to insights - failedPercent is unique to this type of monitor
$util.insights.set('authTime',0); // Add to insights - authTime is standard across all apps
$util.insights.set('appTime',latencyavg); // Add to insights - appTime is standard across all apps
// Failure Alerts
var msg = targetName + ' ' + targetIP + ' ' + failedpercent + '% ping failure rate exceeds threshold of ' + alertOnFailedPercent
assert.ok(failedpercent <= alertOnFailedPercent, msg) // Throw an error on unacceptably high failure rates
// Latency alerts
var msg = targetName + ' ' + targetIP + ' ' + failedpercent + '% ping latency exceeds threshold of ' + alertOnHighLatency
assert.ok(latencyavg <= alertOnHighLatency, msg) // Throw an error on unacceptably high average latency
};