Adding Weather to Map Widgets
LogicMonitor's Map widgets are a great and easy way to plot resources/groupsgeographically, including their status. A question that comes up occasionally is if it's possible to show weather information on top of these maps. While there's currently not a native option to show weather on a Map widget, it is possible to inject a weather layer onto an existing map with a bit of JavaScript. Below is a link to a sample dashboard that can insert various types of weather info onto Map widgets.Simply save the linked JSON file to your local workstation, then in your LogicMonitor portal go to Dashboards and click Add > From File. Dynamic_Weather_Overlay.json The magic happens in JavaScript embedded in the source of the Text widget. Feel free to explore the source code by entering the Text widget's Configure dialog and clicking the 'Source' button. In typical overkill fashion, I included the option for several differenttypes of weather information. The script looks for the following text (regardless of case) in the Map widget's title and adds the appropriate weather/info layer: "Radar" or "Precip" "NEXRAD Base" "NEXRAD Echo Tops" "MRMS" "Temperature" (OpenWeatherMap.org API key required) "Wind Speed" (OpenWeatherMap.org API key required) "Cloud Cover" or "Satellite" (OpenWeatherMap.org API key required) "fire"(for including perimeters of active wildfires) Prerequisites If you want to use one of the map types noted above as needing an API key (the other types use free APIs that don't require a key), you'll need to register for a free account on OpenWeatherMap.org. Once you've obtained an API key, just add a new dashboard token named 'OpenWeatherAPIKey' and paste your key into its value field.Alternatively, you can also hard-code the key directlyin the 'openWeatherMapsAPIKey' variable near the top of the script. The weather overlays should auto-update when the widgets performtheir regular timed refresh. For instance, new radar imagery is made available every 10 minutes and will update automatically. Weather sources currently defined within this script: RainViewer.com- Excellent source of global weather imaging data. Updates approx. every 10 minutes. Used by the script for radar/precipitation maps. Open Geospatial Consortium- Hosted by Iowa State University, an excellent free source of weather data. Since it sources data from the US National Weather Service, its data is local just US and Canada. Used by the script for NEXRAD and MRMS data. OpenWeatherMap.org- Good source for some weather data such as wind speed, temperature, and cloud cover. Requires use of an API key, which is available for free. National Interagency Fire Center - For data about active US wildfires. Known Issues: When switching to a different dashboard containing a Map widget, it's possible weather may still be visible on the new dashboard. If that happensjust refresh the page.389Views23likes3CommentsDashboard Audit
Hello, Has anyone been auditing on Dashboard usage. We have a lot of dashboards and we want to know dashboard which weren't used for over 30 days. I do not see an API for this, is there another to get this info. Essentially we need find dashboard not being used for over 30 days then, we will mark them private for next 10 days and then remove them. Thanks, AshishSolved115Views6likes10CommentsNOC Rollup Status Dashboards for MSPs
LM doesn't come with it out of the box, so I built the NOC Dashboard I've wanted. It provides high level, at-a-glance health indicators for each of our client environments we manage. This makes a great "big board" for a NOC room or a second screen status board for work from home NOC/Support folks. I do have three examples in this code for ways to filter for specific teams/purposes. This all collapses for ease of reference correctly in Powershell ISE on windows. Line 282 references a dataSource I wrote that counts frequency of specific eventlog events to illustrate potential brute force attempts (CTM are my initials, we tag our scripts to make finding the best source of answers faster in the future - old habit from pen & paper change logs from a previous job). As any screenshots would contain client names, I'm unable to post any screen shots of the results of this, but my current settings for my Main dashboard are (This is the first Dashboard I've made that looks better in UIv4 than 3): ... #!!! These two need to be changed. First is a string, second an integer #!!! See the comment block below for instructions # The first chunk of your company's logicmonitor URL $company = "yourCompanyNameHere" # ID of the group to be used as a source for the NOC widget items $parentGroupID = <parentGroupID> <# Netgain Technology, llc ( https://netgaincloud.com ) 2/26/2024 - Developed by Cole McDonald Disclaimer: Neither Netgain nor Cole McDonald are not responsible for any unexpected results this script may cause in your environment. To deploy this: - COLLECTOR: you will need a collector for scripting, this will be the single applies to target. You may need to increase the script timeout depending on the size of your device deployment. - DASHBOARD: you will need a Dashboard with a NOC widget on it. The name can be whatever you'd like, there will be a name change in the "name" property for the initial array. In the case of the first example here, "NOC - Master" - PARENT GROUP: you will need to identify the ID# of the group you wish to use as the source for the subgroup list and set the $parentGroupID to the appropriate ID# Purpose: Create an auto-updating high level NOC dashboard that can show - Rollup state for a list of client subgroups from our \Clients group - Group Indicators for a specific dataSource - Group indicators for a subset of devices within each group After the API region, there are three separate dashboards referenced to illustrate the 3 methods for using this dataSource. NOTE: my code uses backticks for line continuation. Where possible in my code, each line indicates a single piece of information about the script's algorithm and the first character in each line from a block indicates the line's relationship to the one above it. #> #region Rest API Initialization and Functions # Init variables used in the RESTApi functions $URLBase = "https://$company.logicmonitor.com/santaba/rest" $accessID = "##ApiAccessID.key##" $accessKey = "##ApiAccessKey.key##" #-------- The Functions ---------- function Send-Request { param ( $cred , $URL , $accessid = $null, $accesskey = $null, $data = $null, $version = '3' , $httpVerb = "GET" ) if ( $accessId -eq $null) { exit 1 } <# Use TLS 1.2 #> [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 <# 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' ) # uses version 2 of the API $headers.Add( "X-version" , $version ) <# Make Request #> $response = Invoke-RestMethod ` -Uri $URL ` -Method $httpVerb ` -Body $data ` -Header $headers ` -erroraction SilentlyContinue ` -warningaction SilentlyContinue Return $response } function Get-LMRestAPIObjectListing { param ( $URLBase , $resourcePathRoot , # "/device/devices" $size = 1000 , $accessKey , $accessId , $version = '2' ) $output = @() $looping = $true $counter = 0 while ($looping) { #re-calc offset based on iteration $offset = $counter * $size $resourcePath = $resourcePathRoot $queryParam = "?size=$size&offset=$offset" $url = $URLBase + $resourcePath + $queryParam # Make Request $response = Send-Request ` -accesskey $accessKey ` -accessid $accessId ` -URL $url ` -version $version if ( $response.items.count -eq $size ) { # Return set is full, more items to retrieve $output += $response.items $counter++ } elseif ( $response.items.count -gt 0 ) { # Return set is not full, store date, end loop $output += $response.items $looping = $false } else { # Return set is empty, no data to store, end loop $looping = $false } } write-output $output } # Get Dashboards $resourcePath = "/dashboard/dashboards" $dashboards = Get-LMRestAPIObjectListing ` -resourcePathRoot $resourcePath ` -accessKey $accessKey ` -accessId $accessID ` -URLBase $URLBase # Get Widgets $resourcePath = "/dashboard/widgets" $widgets = Get-LMRestAPIObjectListing ` -resourcePathRoot $resourcePath ` -accessKey $accessKey ` -accessId $accessID ` -URLBase $URLBase # Get Groups $resourcePath = "/device/groups" $Groups = Get-LMRestAPIObjectListing ` -resourcePathRoot $resourcePath ` -accessKey $accessKey ` -accessId $accessID ` -URLBase $URLBase #endregion function generateJSON { param( $dashInfo, $clientnames, $deviceDisplayName = "*", $DSDisplayName = "*" ) $itemArray = @() foreach ($name in $clientnames) { $itemArray += @{ "type" = "device" "deviceGroupFullPath" = "Clients/$name" "deviceDisplayName" = $deviceDisplayName "dataSourceDisplayName" = $DSDisplayName "instanceName" = "*" "dataPointName" = "*" "groupBy" = "deviceGroup" "name" = "`#`#RESOURCEGROUP`#`#" } } # Write JSON back to the API for that widget $outputJSON = "`n`t{`n`t`t`"items`" : [`n" foreach ($item in $itemArray) { $elementJSON = @" { `"type`" : `"$($item.type)`", `"dataPointName`" : `"$($item.dataPointName)`", `"instanceName`" : `"$($item.instanceName)`", `"name`" : `"$($item.name)`", `"dataSourceDisplayName`" : `"$($item.dataSourceDisplayName)`", `"groupBy`" : `"$($item.groupBy)`", `"deviceGroupFullPath`" : `"$($item.deviceGroupFullPath)`", `"deviceDisplayName`" : `"$($item.deviceDisplayName)`" } "@ if ($item -ne $itemArray[-1]) { $outputJSON += "$elementJSON,`n" } else { # Last Item $outputJSON += "$elementJSON`n`t`t]`n`t}" } } write-output $outputJSON } # Get Client Names from groups $clientnames = ( $groups ` | where parentid -eq $parentGroupID ` | where name -notmatch "^\." ).name | sort #ID Master Dashboard # declare dashboard name and set default id and widgetid to use in the loop later $masterDash = @{ id=0; widgetid=0; name="NOC - Master" } $master = $dashboards | ? name -eq $masterDash.name if (($master.name).count -eq 1) { $masterDash.id = $master.id $masterDash.widgetid = $master.widgetsConfig[0].psobject.Properties.name $outputJSON = generateJSON ` -dashInfo $masterDash ` -clientnames $clientnames $resourcePath = "/dashboard/widgets/$($masterDash.widgetid)" $url = $URLBase + $resourcePath $widget = Send-Request ` -accessKey $accessKey ` -accessId $accessID ` -data $outputJSON ` -URL $URL ` -httpVerb "PATCH" } #ID Network Dashboard # declare dashboard name and set default id and widgetid to use in the loop later $networkDash = @{ id=0; widgetid=0; name="NOC - Network" } # preset filters for specific dashboard targeting by device $networkDeviceDisplayNameString = "*(meraki|kemp)*" $network = $dashboards | ? name -eq $networkDash.name if (($network.name).count -eq 1) { $networkDash.id = $network.id $networkDash.widgetid = $network.widgetsConfig[0].psobject.Properties.name $outputJSON = generateJSON ` -dashInfo $networkDash ` -clientnames $clientnames ` -deviceDisplayName $networkDeviceDisplayNameString $resourcePath = "/dashboard/widgets/$($networkDash.widgetid)" $url = $URLBase + $resourcePath $widget = Send-Request ` -accessKey $accessKey ` -accessId $accessID ` -data $outputJSON ` -URL $URL ` -httpVerb "PATCH" } #ID Security Dashboard # declare dashboard name and set default id and widgetid to use in the loop later $securityDash = @{ id=0; widgetid=0; name="NOC - Security" } # preset filters for specific dashboard targeting by datasource $securityDataSourceDisplayNameString = "Event Frequency Sec:4625 CTM" $security = $dashboards | ? name -eq $securityDash.name if (($security.name).count -eq 1) { $securityDash.id = $security.id $securityDash.widgetid = $security.widgetsConfig[0].psobject.Properties.name $outputJSON = generateJSON ` -dashInfo $securityDash ` -clientnames $clientnames ` -DSDisplayName $securityDataSourceDisplayNameString $resourcePath = "/dashboard/widgets/$($securityDash.widgetid)" $url = $URLBase + $resourcePath $widget = Send-Request ` -accessKey $accessKey ` -accessId $accessID ` -data $outputJSON ` -URL $URL ` -httpVerb "PATCH" }154Views2likes3CommentsREST API Device SLA Widget
Hi Portal I am currently automating our SLA reporting and have come across the following issue. When I create a device SLA widget via REST API, I do not have the option "displayPercentageBar". When I make an Inspect in Chrome, for example, I see this setting: However, when I set it via REST API, nothing happens. Has anyone ever had to deal with this? Greetings DorianSolved117Views9likes5CommentsAlert List Dashboard, not a Widget on a Dashboard
Does anyone else have a Dashboard that contains just a single widget, anAlert List widget, so show every alert? It’s really annoying having the double scrollbar: We should have a special Dashboard thatisan Alert List to avoid this problem.78Views6likes10Commentsdashboard display user timeout override
We have several ( hundreds of ) dashboards which show pertinent data to the relevant teams here. Each set of teams sit in separate areas, and they all need to see their dashboards. As such, we have set up dashboard stations ( computers with a bunch of screens attached ) so they can put all their dashboards in their own areas on a specific wall etc.. The only portal which is timing out is the LogicMonitor portal. Is there any way to override a specific account to not be bound by the portal settings for idle logons? We need to keep our. timeout settings as 4 hrs for all other users, but these specific screens need to remain forever not being logged out ( as much as is possible ) Is it possible to have a per-account override for “user session timeout” ?77Views7likes2CommentsAccess to Group or Device properties from a text widget
I’m looking for a way to display custom properties from an arbitrary group. We have a dashboard that shows widgets from a specific client group using the group/device pulldown text widget built by @Kevin Ford :Dynamic Dashboards | Community (logicmonitor.com). I’m trying to figure out how to get to custom properties set at the group to display info about that particular client for our staff to have easy reference to. Something like ##defaultResourceGroup##/##example.property## We have our client’s groups tagged with specific contact and support links (KB, Azure Portal, etc...) that would be useful to have direct access to.62Views8likes1CommentIssues with new dynamic filtering feature of UIv4 Dashboards
I really like the new dynamic filtering feature in the UIv4 Dashboards page, I think it really adds a lot more usability/flexibility to dashboards and its probably my favorite thing so far about Uiv4. Having said that, I did notice a few issues after playing around with it: only System and Auto properties are available for filtering. Would be great to allow custom properties to be available as well Would like to be able to save filter “Views” across multiple dashboards, instead of having them need to be created for each dashboard Would like to have saved filter Views available to all users once created, not just the user which created the filter View Internal Websites are being shown on the dashboards, even when filters are set for properties which do not exist on those internal website checks filtering works fine for Resources, but unintended Website checks are being included Only seems to be including Internal Website checks, not External checksSolved75Views4likes4CommentsSLA Widget instance limit in UIv4 Dashboards - no error message when exceeded
The SLA widget (unfortunately) has a 2000-instance limit. In UIv3, when the limit is exceeded the widget will show an error message saying “instance limit of 2000 is exceeded”. So this at least tells me what the issue is. In UIv4, when the instance limit is exceeded for an SLA widget it just says “NaN” with no specific error message. It should at least show the same error message as before so users know why the widget is not populating.54Views7likes0Comments