Monitor – Module to extract runtime information about Iguana from monitor_query data

So I was asked by a customer if I could suggest any good tricks to monitor a whole farm of Iguana servers.

As it happens there is a web-service API in Iguana which can be used to generate a very detailed XML summary.  It gives some information which could be useful like the number of open file handles, memory usage and so on.

Tip: As Eliot states in the comments: “In Iguana 5.6.5 you also get this same information from iguana.status() in Lua it’s handy since you don’t need to provide login credentials.”

However iguana.status() does have a limitation it only returns the status info for the local Iguana Instance that is running the code. So if you need to get the status info from a remote server you will still need to use monitor_query.

Using this API is a little tricky since the login mechanism is the same that Iguana’s GUI uses. We have to login and get back a session cookie. This cookie has to be used to do the authentication to get back the XML summary statistics from the Iguana server.

Note:  In Iguana 5.6 and above it’s a lot easier to call this API since it now supports HTTP basic authentication rather than having to use the cookie session magic. The code has been updated to use basic authentication, however we also included a status_with_cookie() function that will work with older Iguana versions (before 5.6.1).

I made a module called ‘monitor’ which wraps all this logic up.  This is how one can use it:

monitor = require 'monitor'

function main()
   local Report = monitor.status{user='admin', 
                                 password='password', 
                                 url='http://localhost:6543/'} 
   -- Report will have a XML node tree if successful of the stats from the target Iguana server
end

Now if you plan on using this module in a real monitoring script it pays to be paranoid.  There are a number of things which can fail.  For instance:

  1. The target Iguana service could be stopped.
  2. The webserver port of that the target Iguana server is listening on could be changed.
  3. The network might be unavailable.
  4. The username or password being used to login by the monitoring code could be changed.

These are all highly likely to happen over a long time in a real monitoring script.  So this is way one most likely would want to invoke this module using the pcall function to catch errors:

monitor = require 'monitor'

function main()
   -- Networks can fail so if you want to be cautious
   local Success, Report = pcall(monitor.status, {user='admin', 
                                 password='password', 
                                 url='http://localhost:6543/'} )
   if Success then
       --Process the data from the report   
   else
      -- It failed.  We might want to send an email 
   end
end

So what are some good ways to use this module?

One approach would be to:

  1. Put the code into a From Translator instance which is polled every 5 minutes.
  2. The code can then append to a daily CSV file with the server statistics.
  3. The CSV files can then be dropped into something like Excel and then we can graph the trends over time for things like number of file handles open, memory usage etc.

Here’s the source code to the monitor module:

local mon = {}

local function Split(s, d)              
   local t = {}        
   local i = 0          
   local f              
   local match = '(.-)' .. d .. '()'            
   if string.find(s, d) == nil then            
      return {s}                
   end          
   for sub, j in string.gfind(s, match) do              
      i = i + 1        
      t[i] = sub                
      f = j            
   end          
   if i~= 0 then                
      t[i+1]=string.sub(s,f)            
   end          
   return t            
end

-- Works with Iguana 5.6+
-- Uses basic authentication for monitor_query (added in 5.6.1)
function mon.status(T)
   local Url = T.url
   local User = T.user
   local Password = T.password
   if not Url or not User or not Password then
      error('Parameters url, user and password are required.',2)
   end
   
   -- We login first
   local Success, Report, Status = pcall(net.http.get,{url=Url..'monitor_query',
         auth={username=User, password=Password},live=true})
   if not Success or Status ~= 200 then
      error(Report, 2)
   end
   Report = xml.parse{data=Report}
   return Report
end

-- Use for Iguana 5.5 or earlier 
--   - rename this function mon.status() 
--   - and rename/delete the previous (above) mon.status()
-- Uses cookie with http.get{} (basic authentication for monitor_query added in 5.6.1)
function mon.status_with_cookie(T)
   local Url = T.url
   local User = T.user
   local Password = T.password
   if not Url or not User or not Password then
      error('Parameters url, user and password are required.',2)
   end
   
   -- We login first
   local Success,Result, _, Headers = pcall(net.http.get,{url=Url..'login.html',
         parameters={username=User, password=Password },live=true})
   if not Success then
      error(Result, 2)
   end
   -- That gives us our session cookie which we use for our
   -- login credentials.  The login interface was not quite
   -- meant for an API - but the problem is solvable.
   local SessionId = Headers["Set-Cookie"]
   if not SessionId then
      error('Username and/or password wrong',2)
   end
   SessionId = Split(SessionId,' ')[1]
   local Success, Report = pcall(net.http.get,{url=Url..'monitor_query',
         headers={Cookie=SessionId}, live=true})
  if not Success then
      error(Report, 2)
   end
   Report = xml.parse{data=Report}
   return Report
end

local monStatusHelp = {
   Title="monitor.status";
   Usage="local Report = monitor.status{url='http://localhost:6543/',user='admin', password='password'}",
   Desc=[[Under the hood this function does a web service call to Iguana to obtain many operational statistics about a server.
   Code using this library should expect that this web service call may periodically fail.
   ]];
   ["Returns"] = {
      {Desc="A XML node tree with the stats in it."},
   };
   ParameterTable= true,
   Parameters= {
      {url= {Desc='The root URL for the target Iguana server. i.e. http://localhost:6543/'}},
      {user= {Desc='User name to login with.'}},
      {password= {Desc='Password to login with'}},
   };
   Examples={
      "local Report = monitor.status{url='http://localhost:6543/', user='admin', password='password'}",
   };
   SeeAlso={
      {
         Title="Monitor module",
         Link="http://wiki.interfaceware.com/1479.html"
      }
   }
}

help.set{input_function=mon.status, help_data=monStatusHelp}

return mon

2 Comments

  1. Eliot Muir

    In Iguana 5.6.5 you also get this same information from iguana.status() in Lua it’s handy since you don’t need to provide login credentials.

  2. Eliot Muir

    Also in Iguana 5.6 and above it’s a lot easier to call this API since it support HTTP basic authentication rather than having to use the cookie session magic.

Leave A Comment?