groovy code library support
I just cannot bring myself to paste the same complex code into multiple LogicModule scripts, leaving little land mines scattered randomly. I was working today on a general template for using the API from within LogicModules using code I found scattered around different modules (we keep backups of everything, making it somewhat easy to search for those). Just a few things I noticed: * all the code is different * nothing I found so far accounts for API rate limiting * various inefficiencies exist in at least some of what I found The correct solution to all of this is to make a library feature available so we can maintain Groovy functions and such in one place, calling them from LogicModule scripts. It is very sad to see how little re-use is possible within the framework at all levels, and this one is especially bad in terms of maintenance and things breaking easily when changes are made in the API backend.7Views1like2CommentsProperty-based Windows service monitoring
I recently published CGYKT4. In this DataSource, a groovy script checks for the presence of the custom.MonitoredServices property. If the value is "SYN_Windows_Basic_Services" then the script replaces that with a hard-coded set of standard services. If custom.MonitoredServices contains any comma-spearated list of services, then the script just uses those. Finally, if custom.MonitoredServices contains "SYN_Windows_Basic_Services" and a comma-separated list of services, then the standard list of services is added to the values from the property. Once the list of services is determined, the script checks if those services exist on the target device. If so, an instance is created and the script generates an alert if the service is not running.9Views0likes2CommentsGroovy Expect Scripting -- "]$" prompts
Most of the Linux environments I work with are RHEL or CentOS and our prompts look like: [username@hostname ~]$ I can't seem to find a prompt pattern that works for both the closing square bracketand the dollar sign when writing a script using thecom.santaba.agent.groovyapi.expect.Expectpackage. No amount of escaping seems to work like '\\]\\$' or ']\\$'. I do need the multi-character prompt because the output I want to parse will include errant $, but not ]$. Multi-character prompts are generally not a problem because I often have to expect a sudo password prompt using a 'username:' pattern and this works without issue. Any ideas on how to tackle this?Solved11Views0likes1CommentIssues 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('lmaccess.id'); def accessKey = hostProps.get('lmaccess.key'); def account = hostProps.get('lmaccount'); def alertgroup = hostProps.get('lmaccess.group'); 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 + '.logicmonitor.com' + '/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 (response.data.items == null) { return response.data } itemsReceived += response.data.items // Check if there are more items // if (response.data.total > 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 (response.data.total > 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. Quote Exception while querying alerts: java.io.IOException: Server returned HTTP response code: 400 for URL https://XXX.logicmonitor.com/santaba/rest/device/groups/224/alerts?fields=severity&filter=startEpoch>:1538370000,endEpoch<:1541048399,cleared:*Solved13Views0likes5CommentsUse of per collector http proxy settings for PropertySource scripts using Groovy HTTP helper methods.
I have created a Groovy script based PropertySource, that uses a REST call to contact an external site using the included HTTP helper methods in order to fill some information fields. This works fine in itself. The issue I have is the need to set the proxy details on the object after it is instantiated in the script. As far as I know, the collector properties/settings are not exposed in any way to a scripted PropertySource, despite the script running locally on the collector. Nor does the HTTP connection use the existing proxy as set on the collector. Unless I am missing something, it seems exceptionally convoluted to get those details, and then propagate them into property fields for all devices on that collector. to then be able to reference them properly inside the script. Is there any way to call the equivalent of getHostProps(), but for the collector properties? This would also be useful in cases of say, independent customer sites that use separate API keys for the same script.3Views0likes1CommentGroovy hostProps method to fetch device properties using wildcard/glob/regex
I've setup a few custom properties that define if an Oracle database exists and the port it listens on in a key-value pair/JSON syntax. These properties are named in <ApplicationName>.databases format (e.g. app1.databases & app2.databases). Not wanting to repeat myself, I have a set of datasources that query the common Oracle datapoints, but I would like a way to combine all of these *.databases properties together without having to constantly update the datasources or a propertysource whenever I have a new application to monitor. It would be nice to have a method in the hostProps class that supports getting device properties using a wildcard, glob, or regular expression.10Views0likes2CommentsLogicModule Development Recipes
Hello LogicMonitor Community ! Andrey here from LM's Monitoring EngineerTeam. To supplement the suite of scripted LogicModules provided in the LM Support Center, mycolleagues and I havecreated a public GitHub repository with many more examples. Have a look at theLogicMonitor GitHub Repo, where you'll find various recipes for solving common monitoring script problems. Both Groovy and PowerShell examples are included Feel free to comment below with requests and/orsuggestedimprovements. Happy scripting !4Views0likes9CommentsInternal Scripted Service Check "test script" button and debug
Although a TEST step button is available in service checks (external and internal) this only shows the request made and the response output windows. Neither type gives you any kind of output from the post-processing of the response i.e. JSONPATH results. For the Internal service check that has the scripted option (rather than settings) this is even more noticeable as there is no obvious way to put any println or debug in your response script to make sure it is doing the write thing or work out why it is not doing the right thing. The addition of a stdout/output window that shows response (or request) script output would be really helpful. Also possiblythe addition of a Test Script button for the response script that would run the script and show output as per datasources would also be great. I ran these ideas past support and they suggested raising a feature request so I have. They did also suggest I could test my scripts (request or response) in the console debug window which is possible but not obvious ways to mock LMRequest/LMResponse objects so that the script can run the same way as it would normally as a service check. If there are examples or ways to do this then this may be a good subject to create a support page explaining how to do it.7Views0likes0CommentsScript/API to automate phone call to IVR server
Hi all, I'm trying to find ideas, scripts, processes for a function our customer approached us with. In short, they want LM to place a call once per hour to the Interactive Voice Response application to ensure the IVR system answers the call, prompts are being displayed, and host database connection is established. My only is guess is to somehow create a Datasource that runs a script to interact with an API that somehow makes a phone call and then displays information as a result. I would like to know if this already part of LM or would need to be heavily developed in-house or is even remotely possible to implement. If you have had any success with this type of monitoring, I'd appreciate your insight. Thanks much7Views0likes4CommentsClear an alert with a NaN value
I recently wrote a datasource that pulled an API and alerted when the return value was greater than0 The problem I ran intois the API never returned a 0, instead it would return NaN. I worked around this issue by using Key = Value datapoints and a "if (strv.isEmpty) {" statement. Basically, if their is a value returned the output in the script will be "events=[returned value]" the same as most key=value datapoints. If the returned value is empty, the script will fill out the entire string returning "events=0" which puts a 0 in the datapoint and allows the alert to clear. This a nice workaround for a LogicMonitor Admin's bag of tricks. //Print KeyValue strv = response_obj['results']['2']; if ( strv.isEmpty() ) { println "events=0" } else { println "events=" + strv; } return(0);9Views0likes1Comment