This discussion has been locked. The information referenced herein may be inaccurate due to age, software updates, or external references.
You can no longer post new replies to this discussion. If you have a similar question you can start a new discussion in this forum.

Help with Best Way to Retrieve a List of Objects Based on Alert Trigger Condition Scopes (Summary Report)

Before I spend anymore time working on this, I wanted to post this to see if there is a better way.  I need a report that will tell me what objects each configured Alert can trigger on based on an alert's Trigger Condition Scope (Kind of like a big Summary Report of the "All Objects this Alert Can Trigger but instead of being for one object, I want it for all objects and all alerts.)  Since I can't find whatever Query drives the "All Objects this Alert Can Trigger" and use that to just build a SWQL/SQL statement, I figured I could just parse the XML from the "Trigger" field in the AlertConfigurations table.  The problem there is that while I'm pretty good with SQL/SWQL, I'm more comfortable with PowerShell and feel like it'd be easier to parse the XML using that instead of some complex LIKE statement in SQL/SWQL.  Especially since PowerShell can navigate through the XML in that Trigger field so well.

Even though XML is pretty easy to manipulate in PowerShell, I feel like there is probably a better way, so I'm hoping somebody can advise me on this (especially aLTeReGo​ or tdanner​, but anyone knowledgeable is fine) before I waste a bunch of time creating the PowerShell script or learning how to work with and parse XML in SQL/SWQL and creating a complex query to evaluate all of these.  I want to say I found the SWQL query that the "All Objects this Alert Can Trigger" uses once a few months ago either in a log file (due to a "Long Running Query" warning message in the SWIS or OrionWebsite log file), but even with Verbose logging turned on I don't see anything about that resource's backend code.  I found the files that drive that resource in the InetPub folder but they don't have the query in there at all either, so I'm guessing it's buried in a DLL file somewhere.

  • Unfortunately, the code that computes this set of objects and applicable alerts (or vice versa) is pretty complex and not currently exposed through SWIS.

  • Any suggestions on how to tackle this then?  Is parsing the Scope element of the XML condition via PowerShell the best way you can think of, or do you have some other ideas that might be easier?  I was thinking of creating a custom property called AlertsInScope and having the PowerShell script output to that property by putting a comma separated value of the Alert Names that each Node could be triggered on based on the Scope sections of the alerts. 

  • Parsing and correctly applying all of the possible scope conditions from the xml would be very challenging. There's no great solution to this.

    One way you might be able to tackle it would be borrow the web service that populates the "all alerts this object can trigger" resource. Use your browser's dev tools to look at the XHR generated by that resource. This is easiest to isolate if you click on the resource's title to pop it out onto a page by itself. There are several issues with this approach:

    1. These web calls are not part of the public API. They may change without notice in a future version.

    2. Because this web call is part of the website and not SWIS, it expects cookie authentication and not HTTP Basic auth. You will need to provide the same cookies that the browser sends or you will just get an error.

    3. This call gives you a list of alerts for one object. To build a complete "all alerts, all objects" report, you will have to call it separately for every object you care about. I don't know how big your system is - this might be a very large number of separate calls.

    However if I were in your shoes and needed to produce that report, this is how I would tackle it.

  • Well I was a bit curious about how to get the data from the webservice for your purposes as there are several technical obstacles (like problematic passthrough authentication absence for the service) and finally managed to do it. I believe this may help you, however as Tim mentioned... This is internal API, so may cause you some troubles in case it will be changed in future.

    I hope it's well readable.

    Code: Enjoy

    $requestUrl = "http://10.140.2.182"

    $username = "user1"

    $password = "123"

    ##As the webapi doesn't support the in-url authentication (or I didn't figure out how to :-)) we need to get the authentication cookie first

    $helperSession = Invoke-WebRequest -Uri ($requestUrl + '?accountId=' + $username + '&password=' + $password) -Method Get -SessionVariable websession

    $cookies = $websession.Cookies.GetCookies($requestUrl)

    $authCookie = $cookies | Where-Object {$_.Name -eq '.ASPXAUTH'} ##For authentication to the web service we need this cookie

    function getAlertsThisObjectCanTrigger($cookie, $requestUrl, $objectUri)

    {

      $session = New-Object Microsoft.PowerShell.Commands.WebRequestSession

      

      $session.Cookies.Add($cookie); ##add the auth. cookie to the session

      $RequestUri = $requestUrl + "/api/AllAlertThisObjectCanTrigger/GetAlerts"

      ##I don't think AlertDefId has any special meaning here. Just it's here in the webrequest, but doesn't limit the results. Haven't tested yet if the paging is mandatory

      $payload='{"AlertDefId":1,"EntityName":"Orion.Nodes","TriggeringObjectEntityUri":"' + $objectUri + '","CurrentPageIndex":0,"PageSize":"100"}'

      $response = Invoke-Webrequest -uri $RequestUri -Body $payload -Method Post -ContentType application/json  -WebSession $session

      $contentObject = $response.Content |ConvertFrom-Json

      [System.Array]$alertList=$null

      $contentObject.DataTable.Rows|%{$alertList+=$_[0]} ##Filter just alert name

      return $alertList

    }

    ##So here just you can get the objects uri you need...

    $objectUri = "swis://qa-brn-jpel-02.swdev.local/Orion/Orion.Nodes/NodeID=76"

    ##and here iterate through them and do appropriate actions

    $alertScopeForObject = getAlertsThisObjectCanTrigger $authCookie $requestUrl $objectUri

  • This is fantastic Jan.  I was really dreading working on this today and now I'm excited.  I assume the $requestUrl variable should be changed to our SolarWinds server?  I also like how you wrapped it all in a function already, so that really makes my job easier.  I REALLY appreciate this.  I'm sure it wasn't easy, so thank you very much.

  • Yes, this can be changed of course to your server as well as the access credentials. The $objectUri you'll then feed oviously in the foreach loop of needed uris. I'm glad it helps you (Hehe. It took some time as I several times went the wrong way to get the session cookie :-) ). The variable  returned by function is the array, so you can serialize it per your needs.

  • Yeah, while I'm getting decent with powershell, I still know almost nothing about .Net and C# and, well, pretty much anything that isn't PowerShell...  I spent almost my entire day yesterday with .Net Reflector breaking into and browsing around the SolarWinds DLL's on our Dev server trying to figure out how the dang resource worked and came to the conclusion that yes, tdanner is right, the code is complex.  So when I came in this morning and saw your post I jumped for joy.  Thanks again.

  • Yes, as far as I remember the code needs to count with many types of alerts (simple, more conditional, event driven) as well as to filter out the transitive conditions (e.g. CPU value is changing often, so to evaluate if this is the case for the function, you need to skip that condition), then the Alert owner conditions + there are some performance optimizations so the function can be reasonably faster (but can't be really fast as it needs to go through all conditions for given object type), so usage of the method "as is" via webcontroller sounds as better choice. DLL reflection can be the way as well, but I expect too many dependencies here, so it could be quite pain + you'll need to run the script directly from the Orion server. This way is kind of "simplier" and also executable remotely ;-)