Joe Williams

  • Content Count

  • Joined

  • Last visited

  • Days Won


Community Reputation

3 Neutral

About Joe Williams

  • Rank
    Community Whiz Kid

Recent Profile Visitors

102 profile views
  1. Joe Williams

    Complex Datapoint and limit

    I am writing a custom datasource for a temperature monitor. We want to alert on if the temperature falls to high or to low. I figured limit would be what we want. This is what I have so far, no matter what it returns 0 tho. I have adjusted the numbers so Temperature falls outside and inside the range and it always returns 0. if(limit(Temperature, 46, 60), 0, 1) Is my understanding of this wrong? Eventually I would chain this to return different numbers based on Error and Critical thresholds, but can't get this even started lol.
  2. As a MSP this would be nice considering we have to name things like ESXI01 - CustomerName.
  3. Joe Williams

    Widget exceeds the instance limit

    We see the issue when we attempt to get aggregate bandwidth across a customers environment. We also see it when we attempt to show VM status. Even if we filter it to Error and Critical it will say the 2k limit.
  4. Joe Williams

    SNMP Trap Event Consolidation

    SYSLOG is another where we have this issue. We have received 1000s of duplicate alerts in the span of minutes. We had to create special escalation chains just to throttle it properly when it does it.
  5. Joe Williams

    Custom ConfigSource Issues

    And of course I kept plugging away and go it. It isn't pretty but it works. // import the logicmonitor expect helper class import com.santaba.agent.groovyapi.expect.Expect; // get the hostname and credentials from the device property table hostname = hostProps.get("system.hostname"); userid = hostProps.get("config.user"); passwd = hostProps.get("config.pass"); // initiate an ssh connection to the host using the provided credentials ssh_connection =, userid, passwd); // wait for the cli prompt, which indicates we've connected ssh_connection.expect("> "); // send a command to show the tomcat log file size, along with the newline [enter] character ssh_connection.send("enable\n"); // wait for the cli prompt to return, which indicates the command has completed ssh_connection.expect("# "); ssh_connection.send("terminal length 0\n"); ssh_connection.expect("# "); // capture all the text up to the expected string. this should look something like ssh_connection.send("show configuration\n"); ssh_connection.expect(" # "); cmd_output = ssh_connection.before(); // now that we've capture the data we care about lets exit from the cli ssh_connection.send("exit\n"); // wait until the external process finishes then close the connection ssh_connection.expectClose(); println cmd_output;
  6. Joe Williams

    Custom ConfigSource Issues

    I am having to write a custom configsource for Steelhead Riverbeds. There isn't a way to sftp a file off so I am having to write an expect script in groovy. I am trying to cobble together something using the Cisco Generic RunningConfig as a stepping stone, but I just can't get it off the ground. If I run it via the ConfigSources page with Test Script I get this. If I run it via collector debug and !groovy I get Any help would appreciated. Oh yeah the formatting of the cli. And what I have so far. import com.santaba.agent.groovyapi.expect.Expect; host = hostProps.get("system.hostname"); user = hostProps.get("config.user"); pass = hostProps.get("config.pass"); // open an ssh connection and wait for the prompt, user, pass); cli.expect("#"); // ensure the page-by-page view doesn't foul the config output cli.send("terminal length 0\n"); cli.expect("#"); // display the config cli.send("show configuration\n"); cli.expect("##\n") // logout from the device cli.send("exit\n"); cli.expect("#exit"); // collect the output config=cli.before(); // close the ssh connection handle then print the config cli.expectClose(); println config; And now what I have so far
  7. Joe Williams

    Issues With Creating A Datasource

    This was it. Thank you! Next yeah I will work on using the encoder to fix future issues. @Michael Rodrigues I went with MIke's suggestion and yeah that worked. Thanks!
  8. Joe Williams

    Issues With Creating A Datasource

    It is the > in the filter. I tried converting to htmlentities and that didn't work. I tried escaping it and that didn't work either. Any ideas? I am still learning Groovy.
  9. Joe Williams

    Issues With Creating A Datasource

    I took a working groovy script datasource and am now trying to adjust it to some needs we have. This data will end up giving us alert totals for each month so we can build reports. Any ideas? Here is what I have so far. import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Hex; import groovy.json.JsonSlurper; //define credentials and url def accessId = hostProps.get(''); def accessKey = hostProps.get('lmaccess.key'); def account = hostProps.get('lmaccount'); def alertgroup = hostProps.get(''); def collectionFailures = 0 def failures = [:] def client = new LogicMonitorRestClient(accessId, accessKey, account, this.&println) try { def alerts = client.get("/device/groups/" + alertgroup + "/alerts", fields: "severity", filter: "startEpoch>:1538370000,endEpoch<:1541048399,cleared:*") //warnings = alerts.findAll {it.severity == 2}.size() println "WarningCount: ${alerts.findAll {it.severity == 2}.size()}" println "ErrorCount: ${alerts.findAll { it.severity == 3 }.size()}" println "CriticalCount: ${alerts.findAll { it.severity == 4 }.size()}" println "TotalAlerts: ${alerts.size()}" } catch (Throwable e) { failures["alerts"] = e.toString() collectionFailures += 1 } // Do error reporting println "CollectionFailures:${collectionFailures}" failures.each{ query, exception -> println "Exception while querying $query:" println exception } return 0 ////////////////////// // HELPER FUNCTIONS // ////////////////////// class LogicMonitorRestClient { String userKey String userId String account int maxPages = 20 int itemsPerPage = 1000 def println LogicMonitorRestClient(userId, userKey, account, printFunction) { this.userId = userId this.userKey = userKey this.account = account this.println = printFunction } def generateHeaders(verb, path) { def headers = [:] def epoch = System.currentTimeMillis() def requestVars = verb + epoch + path // Calculate signature def hmac = Mac.getInstance('HmacSHA256') def secret = new SecretKeySpec(userKey.getBytes(), 'HmacSHA256') hmac.init(secret) // Sign the request def hmac_signed = Hex.encodeHexString(hmac.doFinal(requestVars.getBytes())) def signature = hmac_signed.bytes.encodeBase64() headers["Authorization"] = "LMv1 " + userId + ":" + signature + ":" + epoch headers["Content-Type"] = "application/json" return headers } def packParams(params) { def pairs = [] params.each{ k, v -> pairs << ("${k}=${v}")} return pairs.join("&") } // Non paginating, raw version of the get function def _rawGet(path, params) { def baseUrl = 'https://' + account + '' + '/santaba/rest' + path def packedParams = "" if(params) { packedParams = "?"+packParams(params) } def query = baseUrl+packedParams def url = query.toURL() def response = url.getText(useCaches: true, allowUserInteraction: false, requestProperties: generateHeaders("GET", path)) return response } // Public interface for getting stuff. def get(Map args=[:], path) { def itemsReceived = [] def pageReads = 0 // Impose our own paging parameters. args.size = itemsPerPage args.offset = 0 while(true) { // Do da nastieh def response = new JsonSlurper().parseText(_rawGet(path, args)) if (response.errmsg == "OK") { // Catch individual items if ( == null) { return } itemsReceived += // Check if there are more items // if ( > itemsReceived.size()) // { args.offset = args.size + args.offset // } // else // { // break // we are done // } } else { // Throw an exception with whatever error message we got. throw new Exception(response.errmsg) } pageReads += 1 // Check that we don't exceed max pages. if (pageReads >= maxPages) { break } if ( > 0) { break } } return itemsReceived } } If I run the URL with the API creds in my test powershell script, it works perfectly. When I test it in LM as a datasource, I get the attached error.
  10. Joe Williams

    LogicMonitor Portal Metrics

    @AnthonyH That was it. if ( > 0) { break } With that at the bottom instead of the original and I took out another portion it now works flawlessly.
  11. Joe Williams

    Discovery time PropertySource

    Looks like it is under security review.
  12. Joe Williams

    LogicMonitor Portal Metrics

    I can't seem to edit my post. It appears the paging parameters aren't working, most likely the offset.
  13. Joe Williams

    LogicMonitor Portal Metrics

    This datasource is exactly what we are looking for, but there is one problem. It isn't returning the proper counts for alerts. I tried adjusting the two variables int maxPages = 5 int itemsPerPage = 800 But the most I could get is 1000. Our current count is 9079 Warnings, 415 Errors and 284 Criticals, but everything gets moved to all equal 1000. Even when I adjust the two variables to a much higher rate.
  14. Joe Williams

    Alert Test Report

    We have a a Group that we onboard devices into. That group has an alert rule/escalation chain associated with it. That rule forwards the alerts to nowhere. This allows us to accomplish what you are looking to do.