At my work, we had several issues/needs related to agents in different Domino databases. I tried to come up with a quick and lean solution, that gave us the functionality we needed, nothing more and nothing less. Yes, I am aware of Julian Robichaux’s excellent OpenLog. But we had some needs that I did not feel were addressed in that project.
What I wanted was a database where the agents could be documented, and also where the log data was stored. So I created a Agent Log database where one document is stored per agent. The form let me document the actions of the agent, as well as what server it is running on, in what database, when it is triggered, etc. When the document is opened, I also read the last time the agent was run and if the agent is enabled or not.
This is a sample document for an agent. It is scheduled to run at 11am every day:
This is what the actual database looks like.
I plan to release the database on OpenNTF.org when I get the time.
Nothing complicated this far. The next step was to create a small script library, doing the actual logging. I created a script library called Class.AgentLog with the following code:
Public Const THREAD_TICKS=6 Public Const THREAD_TICKS_PER_SEC=7 Class AgentLog Private session As NotesSession Private logdb As NotesDatabase Private agentdoc As NotesDocument ' Main doc in Agent Log db Private logdoc As NotesDocument Private running As Integer Private tstart As Long ' Ticks at start Private tend As Long ' Ticks at end Private tps As Long ' Ticks per second (system dependant) Public Sub New( agentname As String ) Dim view As NotesView Dim key As String running = True tstart = GetThreadInfo( THREAD_TICKS ) tps = GetThreadInfo( THREAD_TICKS_PER_SEC ) Set session = New NotesSession Set logdb = New NotesDatabase( session.CurrentDatabase.Server, "IT/AgentLog.nsf" ) Set view = logdb.GetView( "(LookupAgent)" ) If agentname = "" Then agentname = session.CurrentAgent.Name End If key = session.CurrentDatabase.FilePath & "~" & agentname Set agentdoc = view.GetDocumentByKey( key ) If agentdoc Is Nothing Then Print "AgentLog: Failed to locate agent document for " & agentname & "." Exit Sub End If Set logdoc = New NotesDocument( logdb ) logdoc.Form = "LogItem" Call logdoc.MakeResponse( agentdoc ) Call logdoc.ReplaceItemValue("AgentName", agentname ) Call logdoc.ReplaceItemValue("StartTime", Now() ) If session.IsOnServer = True Then Call logdoc.ReplaceItemValue("RunBy", session.CurrentDatabase.Server ) Else Call logdoc.ReplaceItemValue("RunBy", session.CommonUserName ) End If End Sub Public Sub Finish() running = False End Sub Public Sub Terminate() Dim seconds As Integer If logdoc Is Nothing Then Exit Sub End If tend = GetThreadInfo( THREAD_TICKS ) seconds = (tend - tstart) / tps Call logdoc.ReplaceItemValue("EndTime", Now() ) Call logdoc.ReplaceItemValue("Seconds", seconds ) If running = True Then ' Check if not terminated gracefully Call logdoc.ReplaceItemValue("Terminated", "Yes" ) End If Call logdoc.Save(True,True) End Sub End Class
All code goes in the (Declarations) section of the script library.
There are a few things to notice. I actually make each log item a child (response) document to the main document. By doing this, I can easily later create reports for each agent about all the times it was executed, etc.
When the object is instantiated, a blank string is normally passed. This will set the agent name variable to the actual agent name. The agent name is listed in the agent log document. If for some reason you want to use a different agent name in the document (e.g. the agent is a manually triggered agent called AdminUpdateSelectedDocuments and you want it listed just as UpdateSelectedDocuments).
The only thing left now is to update every agent you want to log as follows:
In the (Options) section:
Use "Class.AgentLog"
In the (Declarations) section:
Dim agent As AgentLog
In the Initialize event, I put one line at the beginning and one right at the end. The first line instantiate the agent log object and. set a flag indicating that the agent is running. The second line will clear that flag, so the final function knows that the agent ended gracefully.
Sub Initialize Set agent = New AgentLog("") ' *** Do stuff here Call agent.Finish() End Sub
The last thing is to add one line to the Terminate event. This line is where the logging is actually done. If the flag running is set, we know the agent was terminated before it actually reached the end.
Sub Terminate Call agent.Terminate() End Sub
Happy logging!