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 SubThe 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!
