I hate not being able to sleep even though I am dog tired. Oh well. I will continue the saga of Informant development. I've been thinking about a redesign of it the last little while. When the code base is this small and the functionality is contained within just a few classes, it makes throwing the code out a lot easier. Not to mention that Python allows for this so easily as well.
I am trying my best to temper my own desires and plans for Informant with the view that this could be something that would be of general use in a project like Gnome. This design work I am doing now isn't so much necessary for Gnome, but it is very useful in my long term (and even immediate) plans for Informant. Therefore I shall press forward.
Hopefully this ASCII art thing will come out, diagramming the process:
whisper(alertObj) alert(alertObj
Source -----------------> Listener -------------->
(PBListener or
DBusListener)
access alert info
---> Informant <-----------
- alertObjs = [...] \ Informers
- informers = [...]--\ - Tray Icon
\ newAlert() - Alert Window
\ - E-mail informer
\--------> - IRC/IM bot Informer
- Auto-Action Informer
- Web display
I hope this makes sense. This is how I see the system working. As always, there are any number of sources that provide notification of particular conditions, events, etc. Each of these sources will be able to talk to one of the Listeners in the particular protocol it understands. These Listeners are objects that "listen" for the alerts to be "whispered" to them and then pass it on to the main Informant object. This makes Informant at this level protocol agnostic. Each of the Listener objects, when initialized, is given a reference to the main Informant object. They call the alert method on this object. It stores a list of the available alert objects, which store thing such as the time sent, the message, the priority of the message, the source of the message, and the action to be taken. Registered with the Informant object are any number of Informers, objects that implement the IInformer interface. The Informant will call newAlert() method on each of the Informers that it has registered with it. Each then will take an appropriate action.
The Informers I envision are these: First, I am unsure of this separation, but I will leave it like this for now. There is the notification area icon. All this will do when receiving the newAlert message is increment the number of new alerts data member, and display itself in the notification area if not already. Otherwise, update the display. The second is the alertsWindow(). If the window is visible, it will ask the Informant for the information on the new alert and update itself accordingly. Otherwise, it will do nothing until displayed. At display time. it requests info on all alerts currently stored and displays them as proper. The part I am unsure about is the separation of these two objects. How do I tell the alerts window to display when the tray icon is clicked? Perhaps there can be a special kind of informer that is display only. The tray icon will call the display method on the Informant and it will call the corresponding method on the methods that implement IDisplayInformer.
There are other types that use the information right away. Another design decision is this: I can imagine for very high priority alerts -- such as a major error found by the log file watcher source -- I would want to be alerted if I am away from my computer. I can use SMTP to send an e-mail/text message to my phone. Or an IRC bot can alert someone in an IRC channel, etc. Do I automatically send all alerts notifications to all Informers, and let them decide what to do with them? Or do I have them tell the Informant "Only give me items that are above this priority or from this source." Add two more possible informers to the list. An auto-action informer would automatically perform the action associated with the alert. Back to the log file alert. A possible action would be to run a script that launches a terminal with an ssh session to the machine with the problem. That would force you to take care of it now. The last one would be a web viewer. The user could go to a web page and view the history of alerts.
I think this design allows for some flexibility and puts of the decision of how alerts are received and how they are given to the user until deployment time. A standard script could be written for standard configurations, with command line options to add others.
Does this sound reasonable or too much overhead? For the next release, I will only have the PB Listener and the Tray Icon and Alerts Window Informers. When Moshe finishes D-BUS in Twisted, I will add that listener. I hope to add other Informers, such as a gdesklets informer or a Windows System Tray or OS X menu bar Informer later. I want to get this all set up and going, work hard on the UI in the Alerts Window, and then get back to focusing on my sources and making them easy to write. They are the reason that I started this in the first place.
Man, I feel too verbose. I guess I take a risk in doing my design out in public. Oh well.