Joe Williams

  • Content count

  • Joined

  • Last visited

  • Days Won


Community Reputation

3 Neutral

About Joe Williams

  • Rank
    Community Whiz Kid

Recent Profile Visitors

77 profile views
  1. 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;
  2. 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
  3. 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!
  4. 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.
  5. 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.
  6. 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.
  7. Discovery time PropertySource

    Looks like it is under security review.
  8. LogicMonitor Portal Metrics

    I can't seem to edit my post. It appears the paging parameters aren't working, most likely the offset.
  9. 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.
  10. 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.
  11. Add device to Collector with least devices in rest api

    Here is what I use to "report" on collectors and their versions. $status = $null $body = $null $response = $null <# Use TLS 1.2 #> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 <# account info #> $accessId = '' $accessKey = '' $company = 'SITE' <# request details #> $httpVerb = 'GET' $resourcePath = '/setting/collectors' $queryParams = '?size=1000&fields=id,description,hostname,platform,collectorGroupName,collectorSize,numberOfHosts,build' #$queryParams = '' $status = $null $body = $null $response = $null $data = '' <# Construct URL #> $url = 'https://' + $company + '' + $resourcePath + $queryParams <# Get current time in milliseconds #> $epoch = [Math]::Round((New-TimeSpan -start (Get-Date -Date "1/1/1970") -end (Get-Date).ToUniversalTime()).TotalMilliseconds) <# Concatenate Request Details #> $requestVars = $httpVerb + $epoch + $data + $resourcePath <# Construct Signature #> $hmac = New-Object System.Security.Cryptography.HMACSHA256 $hmac.Key = [Text.Encoding]::UTF8.GetBytes($accessKey) $signatureBytes = $hmac.ComputeHash([Text.Encoding]::UTF8.GetBytes($requestVars)) $signatureHex = [System.BitConverter]::ToString($signatureBytes) -replace '-' $signature = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($signatureHex.ToLower())) <# Construct Headers #> $auth = 'LMv1 ' + $accessId + ':' + $signature + ':' + $epoch $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization",$auth) $headers.Add("Content-Type",'application/json') <# Make Request #> $response = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers <# Print status and body of response #> $status = $response.status #$body = $| ConvertTo-Json -Depth 5 $body = $ | ConvertTo-Json -Depth 2 $Collectors = $body | ConvertFrom-Json #$Collectors.items | Sort collectorGroupName | format-table -AutoSize $Collectors.items | Sort collectorGroupName | Out-Gridview #$body The numberOfHosts would help you out in this case.
  12. Logic Monitor and Power BI

    I imagine you would have a better time offloading the data from LogicMonitor to a separate database using an Integration. Then using Power BI against that database.
  13. Updating Escalation Chains via REST

    I figured it out. You do need to have the name and destination fields. And I missed I didn't have everything inside of {}.
  14. How to transfer data from LogicMonitor to other tools?

    Another option (if you are staying with LogicMonitor) is to use an Integration. You can send the data to another source via an Escalation chain. Related, but not related, we used this to tie in Webex Teams and LogicMonitor, so certain alerts goto our ticketing system and the chat.