Email Alerts and Notifications

Email and SMS alerts

There are two kinds of alerts to consider: Notification Alerts and Custom Alerts.

Inactivity alerts

Notification alerts or rules are managed through Iguana Settings in the Settings > Monitoring section. Here’s some good advice for smart way to use them.

  1. Set up a Channel Group which has all your production channels. i.e. the ones you care about if they go down.
  2. Set up two channel inactivity rules:
    • One should be during working hours and should have a short time of inactivity.
    • The second should be out of working hours with a longer period for inactivity.

This means you end up with relatively little configuration work to do for these types of rules.

Custom alerts

Whenever you use an iguana.logInfo() statement from within a Lua Translator channel the output will get logged into the logs for that channel. This provides a great hook for implementing custom email notification logic.

The idea is this:

  1. Make yourself a helper function like this:
    function Alert(Message)
       iguana.logInfo("ALERT:n"..Message)
    end
  2. From your Lua code you can invoke this function based on any arbitrary rule you like. That’s dead easy to do since it’s a full language and you can access any part of the data. i.e.
    if ZID[3]:nodeValue() == 'VIP' then
       Alert("VIP patient - call the special team!")
    end
  3. Set up one standard notification rule that have the text query expression set to “ALERT” in an Informational message.

So now whenever the custom function is invoked it puts that into the logs which triggers the custom notification rule.

Soon there should be an interface for generating an email directly from Lua which will provide an alternative approach for doing this.

Sending an Email from Lua [top]

Sending an email using the Translator is easy with the built in SMTP facility:

function main(Data)
   -- Set up the parameters to be used with sending an email
   local smtpparams={
      header = {To = 'sales@interfaceware.com'; 
                From = 'testuser@mailserver.com'; 
                Date = 'Thu, 23 Aug 2001 21:27:04 -0400';
                Subject = 'Test Subject';},
      username = 'user',
      password = 'password',
      server = 'smtp://domain.mailserver.com:25',
      -- note that the "to" param is actually what is used to send the email, 
      -- the entries in header are only used for display. 
      -- For instance, to do Bcc, add the address in the  'to' parameter but 
      -- omit it from the header.
      to = {'sales@interfaceware.com','admin@interfaceware.com'},
      from = 'Test User <testuser@mailserver.com>',
      body = 'This is the test body of the email',
      use_ssl = 'try'
   } 

  net.smtp.send(smtpparams)
end

As always auto-completion and help are close at hand:

Some commonly used header fields are:

Header Field Description Comment
From: The email address, and optionally the name of the author(s). In many email clients this cannot be changed except by changing account settings. Mandatory
To: The email address(es), and optionally name(s) of the message’s recipient(s). Indicates primary recipients (multiple allowed), for secondary recipients see Cc: and Bcc: below.
Subject: A brief summary of the topic of the message.
Date: The local time and date when the message was written. Like the “From:” field, many email clients fill this in automatically when sending. The recipient’s client may then display the time in the format and time zone local to him/her. Mandatory
Message-ID: Also an automatically generated field; used to prevent multiple delivery and for reference in In-Reply-To: (see below).
Bcc: Blind Carbon Copy; addresses added to the SMTP delivery list but not (usually) listed in the message data, remaining invisible to other recipients.
Cc: Carbon copy; Many email clients will mark email in your inbox differently depending on whether you are in the To: or Cc: list.
Content-Type: Information about how the message is to be displayed, usually a MIME type. Non-standard
In-Reply-To: Message-ID of the message that this is a reply to. Often used to link related messages together.
Precedence: Commonly with values “bulk”, “junk”, or “list”; used to indicate that automated “vacation” or “out of office” responses should not be returned for this mail, e.g. to prevent vacation notices from being sent to all other subscribers of a mailing list. Non-standard
Received: Tracking information generated by mail servers that have previously handled a message, in reverse order (last handler first).
References: Message-ID of the message that this is a reply to, and the message-id of the message the previous was reply a reply to, etc.
Reply-To: Address that should be used to reply to the message.
Sender: Address of the actual sender acting on behalf of the author listed in the From: field (secretary, list manager, etc.).
Return-Path: When the delivery SMTP server makes the “final delivery” of a message, it inserts a return-path line at the beginning of the mail data. This use of return-path is required; mail systems MUST support it. The return-path line preserves the information in the from the MAIL command.
Errors-To: Indicates where error messages should be sent. In the absence of this line, they go to “Sender:”, and absent that, “From:”. Non-standard
X-* No standard header field will ever begin with the characters “X-“, so application developers are free to use them for their own purposes. Extensions

Tip: Fields like “X-Sender:” and “X-Mailer:” are common, but they are not part of the standard. In fact, any header fields not expressly defined in the RFC, is allowed, and ignored by most e-mail systems. So, we could have an e-mail message that uses headers like:

X-Sender: testuser@mailserver.com

X-Mailer: QUALCOMM Windows Eudora Version 4.3.2

Date: Thu, 23 Aug 2001 21:27:04 -0400

To: testuser@interfaceware.com
From: Test User <testuser@interfaceware.com>

Sender: <testuser@interfaceware.com>

In-Reply-To: <4.3.2.7.2.20010415150149.00b08080@mail.example.com>
Favorite-Color: Red

Cocktail: Martini, up, olive

Subject: test

Additional Information

  • Wikipedia: Email provides a good overview, with many links to RFCs etc.
  • RFC 5321 is the current email standard
  • RFC 5322 is the current email message standard, with header fields
  • RFC 4021 is a older standard containing mail and MIME header fields (including some fields omitted from 5322

Monitoring Queue Sizes [top]

One of the great things about the Translator is how easy it is to extend the functionality of Iguana. This is an example of writing a module in Iguana to monitor the queue count for a channel. This shows the usage of a queuemon module to check that the count of messages on a queue has not exceeded the given threshold.

If the queue count exceeds the threshold the script will log “ALERT:” followed by a description of the problem. That makes it very easy to detect this condition using a standard notification rule.

There are two examples given of calling this function. If no arguments are given then the script defaults to the current channel name and will raise an alert if the channel count exceeds 100.

These defaults can be overridden which is what the second example shows:

queue monitoring

Source Code

You can load the code into the Translator from this project zip file MonitorQueueSize-FromTranslator, or copy and paste from below.

main module:

require 'queuemon'

function main()
   -- Using default parameters
   queuemon.checkQueue()

   -- Setting the channel name and count explicitly
   queuemon.checkQueue{channel = '<your channel name>', count = 10000}   
end

queuemon module:

require 'iguanaconfig'

queuemon = {}

local function CheckChannel(Chan, Count, Name)
   if Chan.Name:nodeValue() == Name then
      local QC = tonumber(Chan.MessagesQueued:nodeValue())
      if QC > Count then
         iguana.logDebug('ALERT:\n Channel '..Name..' has '..QC..' messages queued.') 
         return true
      end   
   end
end

function queuemon.checkQueue(Param)
   -- We default to a queue count of 100
   if not Param then Param = {} end
   if not Param.count then Param.count = 100 end
   if not Param.channel then Param.channel= iguana.channelName() end

   local url = ''
   local webConfig = iguanaconfig.config().iguana_config.web_config
   -- use http or https for API query based on Iguana settings
   if webConfig.use_https:S() == 'true' then
      url = 'https://localhost:'
   else
      url = 'http://localhost:'    
   end
   url = url ..
   webConfig.port..'/status.html'
   iguana.logDebug(tostring(url))
   trace(url)

   -- We need a user login here - using *admin* for demo only  (as it usually works)
   -- Best to use a user with minimal permissions.
   local S = net.http.get{url=url, 
      parameters={UserName='admin',Password='password', Format='xml'}, 
      live=true}
   trace(S)
   S = xml.parse{data=S}

   for i = 1, S.IguanaStatus:childCount('Channel') do
      local Chan = S.IguanaStatus:child("Channel", i)
      local QC = CheckChannel(Chan, Param.count, Param.channel)
      if QC then return QC end
   end
   return
end

iguanaconfig module (used by the queuemon module):

-- This module does a lazy load of the Iguana Configuration file - it only loads the file once
iguanaconfig={}

-- relative path (from working directory) to the config file
-- you can substitute with the *absolute* path if you have problems
local CONFIG_FILE = 'IguanaConfigurationRepo/IguanaConfiguration.xml'

-- We open the configuration file once at compile time
local F = io.open(CONFIG_FILE, 'r')
local C = F:read('*a')
F:close() -- best practice to close (open filehandle can prevent Iguana updating config file on Win machines)

function iguanaconfig.config(A)
   return xml.parse{data=C}
end

The iguanaconfig module just loads the IguanaConfiguration.xml file and returns it as a XML document. It’s extremely useful for all sorts of things.

In this case we use it to pull back the port number that the Iguana instance is listening on.

This module uses the web monitoring URL to pull back the XML summary and parses it to find the queue counts for the channel. In this case we are only selecting one channel to check the queue count but there is no reason we could not check all the channels or even parse a group of channels and only check the queue counts on that channel group.

If you would like to see this script extended in that manner please contact support at support@interfaceware.com.

Leave A Comment?

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.