Recent Discussions
Adding Arista AP's to LogicMonitor
There was a previous request about this, and I have been working on this my self, so I thought I would share what I have delivered. Required Custom Parameters. The Discovery and collection scripts are expecting the following custom properties to be present for each device I have added these at the folder (in our case "Networks") so they cascade down. AristaWIFI.api.endpoint - This is the endpoint within CV-Cue under advanced setting for configuration and management API integrations. AristaWIFI.api.key - The API Key for CV-CUE AristaWIFI.api.token - The API Token for CV-CUE If these are not provided then the collector and discovery scripts will fail. NetScan: I had issues getting the netscan to work in Groovy so wrote a pyhton script to do this which links to Arista CloudVision and LogicMonitor, I have something in my backlog now to migrate this to groovy, the biggest challenge I have is that the HTTP DELETE call in Groovy is expecting data which is not needed for the delete call to close the session. This also uses the Python Core Library we use for all of our LogicMonitor integrations, so sharing is a tad difficult as I would have share the script and our Core Library. If people think this is worth While I would add it in the future. I set a system category of "AristaWifi" to easily identify Arista AP's for the collection and discovery scripts. Finally I also include the AP's ID on discovery as this is used to pull the specific AP from CV-CUE as the custom Property "CVcueId". What Metrics can be collected. Currently I am collecting CPU and Memory which I have created a Arista WIFI General Metrics Data source, and Arista WIFI SSID Metrics which is collecting the Associated Clients and the SSID State which is whether it is Enabled (1) or Disabled (0), I also have unknown (3) if the information can not be retrieved from the JSON. Arista Wifi General Metrics: This data source is configured to use Script as the collection source, below is the script. Note: The logout is commented out until I can result the http delete issue mentioned above. /******************************************************************************* * Arista WIFI Integration with CUE for discovery of the AP's ******************************************************************************/ import com.santaba.agent.groovyapi.http.* import com.santaba.agent.groovy.utils.GroovyScriptHelper as GSH import com.logicmonitor.mod.Snippets import com.santaba.agent.AgentVersion import java.text.DecimalFormat import com.santaba.agent.util.Settings import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.json.JsonBuilder import java.util.concurrent.Executors import java.util.concurrent.TimeUnit // To run in debug mode, set to true Boolean debug = false // To enable logging, set to true Boolean log = false // Set props object based on whether or not we are running inside a netscan or debug console def props try { hostProps.get("system.hostname") props = hostProps debug = true // set debug to true so that we can ensure we do not print sensitive properties } catch (MissingPropertyException) { props = netscanProps } String key = props.get("AristaWIFI.api.key") String token = props.get("AristaWIFI.api.token") String AristaEndPoint = props.get("AristaWIFI.api.endpoint") //Get the Arista CV WIFI Node Node Id as discovered in the scanning script and submitted to the device.. String nodeId = props.get("CVcueId") String clientId = "logicmonitor" String wifiUrl = "https://"+AristaEndPoint+"/wifi/api/" if (!key) { throw new Exception("Must provide AristaWIFI.api.key to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!token) { throw new Exception("Must provide AristaWIFI.api.token credentials to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!clientId) { throw new Exception("Must provide AristaWIFI.api.clientId credentials to run this script. Verify necessary credentials have been provided in Netscan properties.") } //def logCacheContext = "${org}::arista-wifi-cloud" //Boolean skipDeviceDedupe = props.get("skip.device.dedupe", "false").toBoolean() String hostnameSource = props.get("hostname.source", "")?.toLowerCase()?.trim() Integer collectorVersion = AgentVersion.AGENT_VERSION.toInteger() // Bail out early if we don't have the correct minimum collector version to ensure netscan runs properly if (collectorVersion < 32400) { def formattedVer = new DecimalFormat("00.000").format(collectorVersion / 1000) throw new Exception("Upgrade collector running netscan to 32.400 or higher to run full featured enhanced netscan. Currently running version ${formattedVer}.") } httpClient = HTTP.open(AristaEndPoint,443); httpClient.setHTTPProxy('[YOUR Proxy]',8080); // Log in to arista loginurl = "https://"+AristaEndPoint+"/wifi/api/session" payloadstring = '{"type":"apiKeycredentials","keyId":"'+key+'","keyValue":"'+token+'","timeout":129,"clientIdentifier": "'+clientId+'"}'; def payload = payloadstring; //println payload; def loginResponse = httpClient.post(loginurl,payload,["Content-Type":"application/json"]); if ( !(httpClient.getStatusCode() =~ /20/) ) { // Error has occured println "Authentication Failure"; println httpClient.getStatusCode(); println loginResponse; return(1); } String RawCookie = httpClient.getHeader("Set-Cookie") //Have Kept but as yet not needed will remove if not needed.. String httpResponseBody = httpClient.getResponseBody() //Retrieve the Cookie to use from the header. AristaCookie = RawCookie.split(';')[0] //Retrieve AP data. deviceURL = 'manageddevices/aps?startindex=0&pagesize=1000&locationid=0&nodeid=0&boxid='+nodeId SendUrl = wifiUrl+deviceURL def header = ["Content-Type":"application/json","Cookie":AristaCookie] String deviceResponse = httpClient.get(SendUrl,header) if ( !(httpClient.getStatusCode() =~ /200/)) { println "Failed to retrieve data "+httpClient.getStatusCode return 1 } String deviceBody = httpClient.getResponseBody() def deviceJson = new JsonSlurper().parseText(deviceBody) def healthStats = deviceJson.managedDevices.healthStats def wildvalue = "" Integer rawminCPU = healthStats[0].minCpuUtilization Integer minCpu = rawminCPU/100 Integer rawavgCPU = healthStats[0].avgCpuUtilization Integer avgCpu = rawavgCPU/100 Integer rawmaxCPU = healthStats[0].maxCpuUtilization Integer maxCpu = rawmaxCPU/100 Integer rawminMem = healthStats[0].minMemoryUtilization Integer minMem = rawminCPU/100 Integer rawAvgMem = healthStats[0].avgMemoryUtilization Integer avgMem = rawAvgMem/100 Integer rawmaxMem = healthStats[0].maxMemoryUtilization Integer maxMem = rawmaxCPU/100 println "${wildvalue}.mincpu=${minCpu}" println "${wildvalue}.avgcpu=${avgCpu}" println "${wildvalue}.maxcpu=${maxCpu}" println "${wildvalue}.minMem=${minMem}" println "${wildvalue}.avgMem=${avgMem}" println "${wildvalue}.maxMem=${maxMem}" // Commented out log out process for now as will need to revisit currently reducing Timeout to 5 minutes for the session. /* String cookieString = '"'+AristaCookie+'"' def logoutheaders = ["Content-Type":"application/json","Cookie":AristaCookie] println logoutheaders def logoutResponse = httpClient.delete(loginurl,"{}",logoutheaders) logoutResult = httpClient.getStatusCode() if ( !(httpClient.getStatusCode() =~ /20/) ) { //Error has occured println "Logout Failure"; println httpClient.getStatusCode(); println loginResponse; return(1); } println logoutResponse;*/ def LMDebugPrint(message) { if (debug) { println(message.toString()) } } return 0 Arista WIFI SSID Metrics: This will collect the number of associated clients by Band (IE 2.4ghz) and SSID I have the created graphs to aggregate the data together for total number of associated clients. Discovery Script: /******************************************************************************* * Arista WIFI Integration with CUE for discovery of the AP's ******************************************************************************/ import com.santaba.agent.groovyapi.http.* import com.santaba.agent.groovy.utils.GroovyScriptHelper as GSH import com.logicmonitor.mod.Snippets import com.santaba.agent.AgentVersion import java.text.DecimalFormat import com.santaba.agent.util.Settings import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.json.JsonBuilder import java.util.concurrent.Executors import java.util.concurrent.TimeUnit // To run in debug mode, set to true Boolean debug = false // To enable logging, set to true Boolean log = false // Set props object based on whether or not we are running inside a netscan or debug console def props try { hostProps.get("system.hostname") props = hostProps debug = true // set debug to true so that we can ensure we do not print sensitive properties } catch (MissingPropertyException) { props = netscanProps } String key = props.get("AristaWIFI.api.key") String token = props.get("AristaWIFI.api.token") String AristaEndPoint = props.get("AristaWIFI.api.endpoint") //Get the Arista CV WIFI Node Node Id as discovered in the scanning script and submitted to the device.. String nodeId = props.get("CVcueId") String clientId = "logicmonitor" String wifiUrl = "https://"+AristaEndPoint+"/wifi/api/" if (!key) { throw new Exception("Must provide AristaWIFI.api.key to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!token) { throw new Exception("Must provide AristaWIFI.api.token credentials to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!clientId) { throw new Exception("Must provide AristaWIFI.api.clientId credentials to run this script. Verify necessary credentials have been provided in Netscan properties.") } //def logCacheContext = "${org}::arista-wifi-cloud" //Boolean skipDeviceDedupe = props.get("skip.device.dedupe", "false").toBoolean() String hostnameSource = props.get("hostname.source", "")?.toLowerCase()?.trim() Integer collectorVersion = AgentVersion.AGENT_VERSION.toInteger() // Bail out early if we don't have the correct minimum collector version to ensure netscan runs properly if (collectorVersion < 32400) { def formattedVer = new DecimalFormat("00.000").format(collectorVersion / 1000) throw new Exception("Upgrade collector running netscan to 32.400 or higher to run full featured enhanced netscan. Currently running version ${formattedVer}.") } httpClient = HTTP.open(AristaEndPoint,443); httpClient.setHTTPProxy('[Your Proxy]',8080); // Log in to arista loginurl = "https://"+AristaEndPoint+"/wifi/api/session" payloadstring = '{"type":"apiKeycredentials","keyId":"'+key+'","keyValue":"'+token+'","timeout":129,"clientIdentifier": "'+clientId+'"}'; def payload = payloadstring; //println payload; def loginResponse = httpClient.post(loginurl,payload,["Content-Type":"application/json"]); if ( !(httpClient.getStatusCode() =~ /20/) ) { // Error has occured println "Authentication Failure"; println httpClient.getStatusCode(); println loginResponse; return(1); } String RawCookie = httpClient.getHeader("Set-Cookie") //Have Kept but as yet not needed will remove if not needed.. String httpResponseBody = httpClient.getResponseBody() //Retrieve the Cookie to use from the header. AristaCookie = RawCookie.split(';')[0] //Retrieve AP data. deviceURL = 'manageddevices/aps?startindex=0&pagesize=1000&locationid=0&nodeid=0&boxid='+nodeId SendUrl = wifiUrl+deviceURL def header = ["Content-Type":"application/json","Cookie":AristaCookie] String deviceResponse = httpClient.get(SendUrl,header) if ( !(httpClient.getStatusCode() =~ /200/)) { println "Failed to retrieve data "+httpClient.getStatusCode return 1 } String deviceBody = httpClient.getResponseBody() def encoded_instance_props_array = [] def deviceJson = new JsonSlurper().parseText(deviceBody) def wildvalue = "" def wildalias = "" def description = "" def getOperatingBand = "" def getSSID = "" def radios = deviceJson.managedDevices.radios radios[0].each { RadioEntry -> // Build out wireless entries. getOperatingBand = RadioEntry.operatingBand RadioEntry.wirelessInterfaces.each { ssidEntry -> getssid = ssidEntry.ssid description = ssidEntry.bssid wildvalue = getOperatingBand+"_"+getssid wildalias = wildvalue def instance_props = [ "auto.opertating.band": RadioEntry.operatingBand, "auto.ssid": ssidEntry.ssid, "auto.bssid":ssidEntry.bssid, "auto.ssid.profileId":ssidEntry.ssidProfileId ] encoded_instance_props_array = instance_props.collect() { property, value -> URLEncoder.encode(property.toString()) + "=" + URLEncoder.encode(value.toString()) } println "${wildvalue}##${wildalias}##${description}####${encoded_instance_props_array.join("&")}" } } // Commented out log out process for now as will need to revisit currently reducing Timeout to 5 minutes for the session. /* String cookieString = '"'+AristaCookie+'"' def logoutheaders = ["Content-Type":"application/json","Cookie":AristaCookie] println logoutheaders def logoutResponse = httpClient.delete(loginurl,"{}",logoutheaders) logoutResult = httpClient.getStatusCode() if ( !(httpClient.getStatusCode() =~ /20/) ) { //Error has occured println "Logout Failure"; println httpClient.getStatusCode(); println loginResponse; return(1); } println logoutResponse;*/ def LMDebugPrint(message) { if (debug) { println(message.toString()) } } return 0 Collection Script: /******************************************************************************* * Arista WIFI Integration with CUE for discovery of the AP's ******************************************************************************/ import com.santaba.agent.groovyapi.http.* import com.santaba.agent.groovy.utils.GroovyScriptHelper as GSH import com.logicmonitor.mod.Snippets import com.santaba.agent.AgentVersion import java.text.DecimalFormat import com.santaba.agent.util.Settings import groovy.json.JsonOutput import groovy.json.JsonSlurper import groovy.json.JsonBuilder import java.util.concurrent.Executors import java.util.concurrent.TimeUnit // To run in debug mode, set to true Boolean debug = false // To enable logging, set to true Boolean log = false // Set props object based on whether or not we are running inside a netscan or debug console def props try { hostProps.get("system.hostname") props = hostProps debug = true // set debug to true so that we can ensure we do not print sensitive properties } catch (MissingPropertyException) { props = netscanProps } String key = props.get("AristaWIFI.api.key") String token = props.get("AristaWIFI.api.token") String AristaEndPont = props.get("AristaWIFI.api.endpoint") //Get the Arista CV WIFI Node Node Id as discovered in the scanning script and submitted to the device.. String nodeId = props.get("CVcueId") String clientId = "logicmonitor" String wifiUrl = "https://"+AristaEndPont+"/wifi/api/" if (!key) { throw new Exception("Must provide AristaWIFI.api.key to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!token) { throw new Exception("Must provide AristaWIFI.api.token credentials to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!clientId) { throw new Exception("Must provide AristaWIFI.api.clientId credentials to run this script. Verify necessary credentials have been provided in Netscan properties.") } if (!AristaEndPont) { throw new Exception("Must provide AristaWIFI.api.endpoint to run this script. Verify necessary variable is within your LogicMonitor instance before continuing.") } //def logCacheContext = "${org}::arista-wifi-cloud" //Boolean skipDeviceDedupe = props.get("skip.device.dedupe", "false").toBoolean() String hostnameSource = props.get("hostname.source", "")?.toLowerCase()?.trim() Integer collectorVersion = AgentVersion.AGENT_VERSION.toInteger() // Bail out early if we don't have the correct minimum collector version to ensure netscan runs properly if (collectorVersion < 32400) { def formattedVer = new DecimalFormat("00.000").format(collectorVersion / 1000) throw new Exception("Upgrade collector running netscan to 32.400 or higher to run full featured enhanced netscan. Currently running version ${formattedVer}.") } httpClient = HTTP.open(AristaEndPont,443); httpClient.setHTTPProxy('[Your Proxy]',8080); // Log in to arista loginurl = "https://"+AristaEndPont+"/wifi/api/session" payloadstring = '{"type":"apiKeycredentials","keyId":"'+key+'","keyValue":"'+token+'","timeout":129,"clientIdentifier": "'+clientId+'"}'; def payload = payloadstring; //println payload; def loginResponse = httpClient.post(loginurl,payload,["Content-Type":"application/json"]); if ( !(httpClient.getStatusCode() =~ /20/) ) { // Error has occured println "Authentication Failure"; println httpClient.getStatusCode(); println loginResponse; return(1); } String RawCookie = httpClient.getHeader("Set-Cookie") //Have Kept but as yet not needed will remove if not needed.. String httpResponseBody = httpClient.getResponseBody() //Retrieve the Cookie to use from the header. AristaCookie = RawCookie.split(';')[0] //Retrieve AP data. deviceURL = 'manageddevices/aps?startindex=0&pagesize=1000&locationid=0&nodeid=0&boxid='+nodeId SendUrl = wifiUrl+deviceURL def header = ["Content-Type":"application/json","Cookie":AristaCookie] String deviceResponse = httpClient.get(SendUrl,header) if ( !(httpClient.getStatusCode() =~ /200/)) { println "Failed to retrieve data "+httpClient.getStatusCode return 1 } String deviceBody = httpClient.getResponseBody() def encoded_instance_props_array = [] def deviceJson = new JsonSlurper().parseText(deviceBody) def wildvalue = "" def wildalias = "" def description = "" def getOperatingBand = "" def getSSID = "" def radios = deviceJson.managedDevices.radios def ssidActive = 3 radios[0].each { RadioEntry -> // Build out wireless entries. getOperatingBand = RadioEntry.operatingBand RadioEntry.wirelessInterfaces.each { ssidEntry -> getssid = ssidEntry.ssid description = ssidEntry.bssid wildvalue = getOperatingBand+"_"+getssid wildalias = wildvalue if (ssidEntry.active == true) { ssidActive = 1 } else { ssidActive = 0 } println "${wildvalue}.numAssocClients=${ssidEntry.numAssocClients}" println "${wildvalue}.active=${ssidActive}" } } // Commented out log out process for now as will need to revisit currently reducing Timeout to 5 minutes for the session. /* String cookieString = '"'+AristaCookie+'"' def logoutheaders = ["Content-Type":"application/json","Cookie":AristaCookie] println logoutheaders def logoutResponse = httpClient.delete(loginurl,"{}",logoutheaders) logoutResult = httpClient.getStatusCode() if ( !(httpClient.getStatusCode() =~ /20/) ) { //Error has occured println "Logout Failure"; println httpClient.getStatusCode(); println loginResponse; return(1); } println logoutResponse;*/ def LMDebugPrint(message) { if (debug) { println(message.toString()) } } return 098Views1like2CommentsLM / ServiceNow Integration
I'm working on some API commands for ServiceNow from LogicMonitor and am trying to see if there's a way to see further information from the return payload from ServiceNow when a ticket is generated via the integration. In particular, I'm trying to capture the sys_id field from ServiceNow so that I can use this to access the ticket in an escalation step using a custom HTTPS API command. I can see the payload includes sys_id in the integration logs, and indeed LogicMonitor uses it to generate the link to the ticket on the alert screens. Does anyone know if there's a token or such that can be used to access this info, or if there would be a way of storing it for access?Jason_Clemons6 hours agoNeophyte121Views0likes9CommentsAll my collectors are going down every 24 hours.
Hi, Starting last week Thursday, all my collectors, across two different LM portals, are going down approximately every 24 hours. Apparently the Watchdog is telling the Agent to reset itself which causes everything to die for 5-10 minutes. It's happening on almost every collector we have. Some do it every day, some skip a day here and there. They ALL started this last week Thursday. We didn't make any global changes and have no idea what the heck happened. Is anyone else dealing with this? There are entries like this that show the Watchdog service told the main Agent server to restart itself. [2025-05-06 20:05:47.876 GMT] [MSG] [CRITICAL] [statusmonitor:::] [StatusListener$1.run:135] Peer request to shutdown, CONTEXT=CAUSE=shutdown cmd, ACTION=quit [2025-05-06 20:05:47.876 GMT] [MSG] [CRITICAL] [statusmonitor:::] [StatusListener$1.run:151] Shutting self down by quit with 0, CONTEXT=MSG=all sockets closed, System.exit(0) now [2025-05-06 20:05:47.882 GMT] [MSG] [INFO] [statusmonitor:::] [RestartUtil._reportEvent:236] Reported restart reason successfully, CONTEXT=type=ReceivedShutdown, reason=Collector receives shutdown command from watchdog. Agent will restart. [2025-05-06 20:05:47.883 GMT] [MSG] [INFO] [statusmonitor:::] [RestartUtil._saveRestartReason:292] Save restart reason successfully, CONTEXT=file=C:\Program Files (x86)\LogicMonitor\Agent\conf\restart.conf [ These are the tickets that they generated showing that it delays a few minutes each day, but is happening almost by clockwork. I opened a ticket via Chat but was told that something is overload the agent and we need to up the collectors sizes. This doesn't really tell what happened last Thursday that started causing the problem so I'm posting here wondering if anyone is having the same issue. Thanks.Kelemvor2 days agoExpert390Views0likes14CommentsAutomate AWS device group creation
Hello, I'm trying to automate AWS account device group creation. The thing is I will not always have immediate access to the onboarded environment, so I wanted to reuse the external ID as it is possible in the UI (see the attached screenshot). I'm having difficulty finding the proper parameter in Python library, and the creation fails with error {"errorMessage":"No external ID assigned. Please request your external ID first","errorCode":1400,"errorDetail":null}. Is there any way to automate this? Thanks.6Views0likes0CommentsCould you please guide me on how I can manage the usage of LM logs?
It appears that our current usage of LogicMonitor logs storage has exceeded the allocated limit of 180GB. How could we address this over usage issue? Do you have ideas on how to prevent this from happening in the future?tuco2 days agoNeophyte69Views0likes2CommentsUIv4 - Instance Thresholds - Consecutive Polls
Good afternoon, Is it intentional that when you set an instance alert threshold, the consecutive polls is also overridden from the global threshold? For example, I'll set an instance level threshold in UIv3 which doesn't have the consecutive poll option and I assume it would just use the global threshold consecutive polls. But when I just checked in UIv4, the consecutive polls was just set to immediately and seemed to alert that way from my testing.Justin_Lanoue3 days agoAdvisor135Views0likes1CommentRename a collector?
I swore that in the old UIv3 you could rename a collector hostname. I dont mean the resource representation of the collector, when it monitors itself, I mean the actual name it has in the collector context. When I try to manage the collector on the collectors page, there is no option to change it. But we have a situation where we have to. Does this mean we need to rebuild and redeploy the collector to change it? The 2 collectors have similar collector names (collector hostnames), and while their respective resource names (for self-monitoring) have different displaynames etc, on the machines themselves, they have the same system.sysname. So this is causing some weird bug where alerts on either collector cause the alert to show on both. Kind of amusing. COLLECTOR "DEVICE NAME" /// RESOURCE DISPLAYNAME /// SYSTEM.SYSNAME ------------------------------------------------------------------- CORP\FF-FF01 /// FF-FF01.CompanyA.Com /// FF-FF01 WAN\FF-FF01 /// FF-FF01.CompanyB.Com /// FF-FF01 Because the sysnames are also the same (they sit in completely different networks) I think its confusing LogicMonitor, so I suspect the team that deploys there is going to have to honestly redo one of the collectors completely. But when fishing around in the UIv4 collectors page, I saw no way to change the "CORP\FF-FF01" or "WAN\FF-FF01" part. I think the sysname is going to force a complete redeploy on one, but its just weird I cant change the name.Lewis_Beard3 days agoProfessor70Views0likes1CommentHow to automate adding "Additional monitoring"
Hi, We have a requirement to run anti-virus software on all servers and need to monitor if it is running :-). Manually I can add this via "Additional monitoring" on our linux servers, but I don't want to do that every time a new server is deployed... Is there any way to automate this, so add it when a new server is deployd? Might be Terraform, Ansible, API-call or shell script. Have been searching on several places, but no luck until now. Any suggestion is highly appreciated. Kind regards, Jeroen5Views0likes1CommentBMC Remedy Integration
Hi all I'm looking to do an ITSM integration with BMC Helix/Remedy, which isn't natively supported. It looks as though we can create a new incident by making a POST request to their API. But, if we want to do an update, it seems their API requires that you first query the API for an internal ID for the Incident, then make a second call with the update referring to that internal ID. Apparently this behaviour in the API cannot be altered. I don't see any way to achieve this in LogicMonitor. Has anyone successfully integrated LM and BMC Helix/Remedy? I think we will likely need to build something to sit between and receive the updates from LM and then call the Helix API. Interested in hearing what others may have done to achieve this. DaveDave_Lee5 days agoAdvisor291Views0likes3Comments