Sweet. I don't think it get's much easier than that. Nice work!
[5] Manning Clark @ 04:05PM | 2004-02-13
Could this be adapted to record messages like the agent log with LogAction? I use the AL to see both messages and errors from agents. It would be cool if both types could be stored in your database. Thanks again for sharing!
Thanks guys! Hopefully it'll be out there for download this weekend.
Manning: yes, it does this too. I even include parameters for a severity level and a NotesDocument, in case you want to automatically add a doclink to the message (these are default parameters for event logging -- which you can leave blank if you don't want to use them, and there's also a LogErrorEx function that has these parameters as well).
Well done. I *just* had a conversation with two developers over what constitutes the #1 programming tip, and I insisted on an agent log. So, I was actually going to write up a class and then you roll out this beautiful utility.
Thanks. Very appreciated.
can i leave messages on my answering machine with this? also, i'd like to be able to check the log to see what my wife wants me to pick up from the grocery store.
trace with ND6 is nice. With R5 I usually add 2 undocumented calls that seems to work throughout all releases:
lsi_info(2) = "current function name" and
lsi_info(12) = "called from" -- sort of simplified a call stack. Also it could be mighty useful to obtain a class name if the code is class {say Typename(Me)}, but that unfortunately leads to 2 syntaxes - one for class methods/properties and other for plain functions. But I think it's worth the pain.
As for Java code with additional object -- could it be handled with a static method of a class, so that you do not need to instantiate beforehand?
Another subject in this context could be adding of "tracing" facility. Say each opening block becomes:
On Error goto logError
Dim nsfTools_trace As String
...
nsfTools_trace = "code 1"
...
nsfTools_trace = "code 2"
logError:
Call LogErrorClassTrace Typename(Me), lsi_info(2),lsi_info(12), nsfTools_trace
Exit Sub
or:
%include "c:\lss\nsftools.logging\initErrorLog"
...
%include "c:\lss\nsftools.logging\catchErrorLogClassSubTrace"
End Sub
The naming of directory structure could be another issue - to allow development of code "packages". With eventual advent of Domino designer plugin for Eclipse it may be handy (or not, probably depends on how it can be implemented)
Thanks Julian, this is a brilliant idea. I'm a big believer in not allowing scheduled agents to run without logging themselves to a central logging db, and I've got some really ugly logging code that handles it. I'm off to take a look at yours
In LS you can retreive errors from deeply nested function/sub calls and pass them up the stack to get a stack trace of all function/sub names and the line # in each. Like this from my log:
16/02/2004 13:09:21 WebQuerySave-InvoiceHistory: Object variable not set (91)
> INVOICE.ADDKEYWORD (in module: BASEDOCUMENT) line: 316
> INVOICE.GETDOCUMENTKEYWORDS (in module: INVOICE) line: 396
> INVOICE.WRITETODOCUMENT (in module: BASEDOCUMENT) line: 540
> INVOICE.SAVE (in module: BASEDOCUMENT) line: 158
> INVOICE.SAVEANDCLOSE (in module: BASEDOCUMENT) line: 181
> INITIALIZE (in module: 23DEA868) line: 64
Julians log is awsome because it's friendly looking and so simple to use. The LogError couls easily become nested-enabled or have a nested variant available for use as well. The concept is simple your LogError call, simply makes another 'Error' call after processing, which passes the error up the stack.
Normunds: Thanks. I'm actually using lsi_info(12) in my functions, and I agree that it's a nice little trick. As for the static methods in Java...well, I probably need to write a whole article on that one. It gets tricky.
Johan: I need to take another look at that. I've got Log2LS on my hard drive somewhere, but haven't looked in a while. I appreciate the reminder (I know you write good code, so I know I need to read through it all again).
Andrew: Actually, in ND6 you can just call lsi_info(14) and get the stack trace with one call, without any nested error handling. For R5 that might be a necessary technique though. I'll have to see about adding that to the documentation in the database. Thanks.
probably I should write too much because I haven't looke at your code again, but it's clear that even if you use lsi_info(12) in your logError call, you loose info that lsi_info(12) would have returned in "current subroutine". When you have trouble in a function that can be called almost by everything then it's darn helpful to know what has called it.
And building stack trace by raising errors is another possibility for R5 (but of course you can't implement it with a single call to logging function). So probably there could be a number of logError routines you provide. From dirt simple logError, no parameters, to something similar that I suggested that provides Class, calling routine and optionally trace variables(s).
Still another thing -- a large part of "errors" at least for me are "data or logic" errors. Sort of "assert that the result is positive, else log meaningless-data-error". Probably you've provided a good way to log them.
[19] tony palmer @ 04:17AM | 2004-02-18
I also created a logging tool around the log4j format for both LS and Java. This was before I saw Johan's. doh!
I've posted it on openntf. It's quite basic but way better than the standard agent log.