-
Dec 8th, 2020, 04:36 PM
#1
Thread Starter
Fanatic Member
[RESOLVED] Logging Errors In Realtime
I have my standard Error Log routine in almost all procedures.
Depending on how the log call is set in a procedure it will generate:
1) Msg Only
2) Log Only
3) Msg and Log
What I've found in realtime, is that at times when an error occurs a particular procedure may be called multiple times. With "Msg Only", or "Msg and Log" this may generate multiple message boxes Until I run out of memory or App times out.
Using "Log Only" solves the above problems, but then one has to remember to check the log at the end each day or set a flag to trigger a reminder that the log has new data. It does not give immediate feedback an error has occurred.
Having a log error routine at the procedure level helps, but I've seen some programs which generate logs of almost everything that occurs within a procedure. I can't image each procedure has a "call log" after almost every line code, but maybe it does? However, going with this concept of generating a log for almost everything executed would generate a huge log in realtime.
Anyone have a suggestion to:
1) Trying to get as much error log data a possible in realtime
but keep the volume down?
2) Keep the App from running out of memory because of Msgbox calls when multiple calls are being made to a procedure that errors?
-
Dec 8th, 2020, 05:19 PM
#2
Re: Logging Errors In Realtime
I can't really tell what you are talking about here. Msgbox is modal and blocks code execution so only one can be displayed at a time.
Perhaps it would help if we were to see this routine you speak of.
-
Dec 8th, 2020, 06:10 PM
#3
Thread Starter
Fanatic Member
Re: Logging Errors In Realtime
DataMiser thanks for responding.
In MDI realtime, if the procedure is called multiple times and an Error occurs a MsgBox is generated.
Within Each Procedure
Code:
With TError
.Type = ERR_CRITICAL
.Src = mstrModule & "ProcName"
.Data = "Whatever if needed"
.Action = MsgAndLog
End With
Call DoError
Routine Called
Code:
Public Sub DoError()
'This is the Error Handling Routine
'It is implemented as a Structure but could be implemented as a Sub/Function
' like MsgBox
' Public Sub DoErrorNew(ErrorType As enmErrorType, ErrorAction As enmErrorAction, strErrorSource As String, strErrorInfo As String)
Dim strErrorType As String
Dim strPrompt As String
Dim strTitle As String
'---------------------------------
With TError
'1) Convert Error Type to String
Select Case .Type
Case ERR_CRITICAL
strErrorType = "CRITICAL"
Case ERR_WARNING
strErrorType = "WARNING"
Case ERR_INFORMATION
strErrorType = "INFORMATION"
Case ERR_IGNORE
Exit Sub
End Select
'2) Get Error
If Len(.Data) > 0 Then
'Use Mine
strPrompt = TError.Data
Else
'use Microsofts
strPrompt = "ErrorNo: " & Str$(Err.Number) & vbCrLf
strPrompt = strPrompt & " - " & Err.Description
End If
'3) Handle Error
Select Case .Action
Case MsgOnly
strTitle = strErrorType & "-" & .Src
MsgBox strPrompt, vbOKOnly, strTitle
Case LogOnly
Call DoLog(strErrorType)
Case MsgAndLog
Call DoLog(strErrorType)
strTitle = strErrorType & "-" & .Src
MsgBox strPrompt, vbOKOnly, strTitle
End Select
End With
End Sub
-
Dec 9th, 2020, 02:30 AM
#4
Re: Logging Errors In Realtime
Some modification of this may be useful to get real time error logging from the app.
https://www.vbforums.com/showthread....tentDebugPrint
Generally errors with msgbox should be reserved for the most critical only since they are annoying.
If possible, once an error is thrown try to abort whats happening to prevent an endless stream of errors after that.
logging levels are nice, since you can use them to later filter the log output to see only the critical things or things
from a certain module or error code. timestamps can also be very beneficial especially when filtering to find stuff, and then
going back to the full log to see the context around the error.
Logging to a database could also help, then using a secondary app to query/filter the results on interval.
You can also log to a debug pane inside the app to be visible on a certain tab or form for real time data.
Generally test data a lot, log on weird stuff, try to keep errors to a minimum, and abort early on error conditions
to keep logs as small and meaningful as possible. Capturing to much makes it a chore to go through and understand.
edit: related filter listview control: https://www.vbforums.com/showthread....w-User-control
Last edited by dz32; Dec 9th, 2020 at 08:32 AM.
-
Dec 9th, 2020, 02:47 AM
#5
Re: Logging Errors In Realtime
Originally Posted by dz32
logging levels are nice, since you can use them to later filter the log output to see only the critical things or things
from a certain module or error code..
This is not well understood IMO. Each DoError call has a .Type (like ERR_CRITICAL) in you implementation but you have to be able to *filter* log entry being create for this type. For instance when things break you enter, set log level to ERR_DEBUG and test failing part while it produces extremely detailed log so you can pinpoint the problem. After everything is fixed you reduce log level to ERR_CRITICAL and go on with your life with minimal to no log being created at client site.
The point is that most "professional" error logging solutions like (log4j, NLog, etc. packages in the free world of other languages) allow setting filtering options on namespaces/projects or classes in your solution. For instance you can set log level to ERR_DEBUG but silence this noisy class cFooBar which dumps useless warnings all the time. And then you can configure ERR_CRITICAL entries to send mail to admin or instant messages in Slack, SMS or whatever.
cheers,
</wqw>
-
Dec 9th, 2020, 09:11 AM
#6
Thread Starter
Fanatic Member
Re: Logging Errors In Realtime
dz32, wqweto thanks for responding.
Each error level (CRITICAL, WARNING, INFORMATION) is hardcoded (associated with) the DoError call.
This is based on what effect it has to keep App functioning.
dz32: FWIW: The call to DoLog puts on a TimeStamp and adds other info to the log file.
Thanks for the links, will go over them.
wqweto:
(1) Your post got me thinking, that I might be able to change (reassign) the Error Type once it triggers
which would be "log only" (or create new type such as your DEBUG suggestion) and bypass subsequent Msgbox generation. Not sure yet how I'm going accomplish that.
(2)
For instance when things break you enter, set log level to ERR_DEBUG and test failing part while it produces extremely detailed log so you can pinpoint the problem.
How one accomplishes this is the issue. (dz32 links may shed some light).
Never seen an example of procedure reentry to get more log info if I'm understanding correctly.
Take a standard VB procedure. Things my execute halfway through the procedure until an Error occurs. The Error routine (at the End of the Proc is then called). One can use a Resume Next (or Jump) to continue, but in order to flag where that Error occurred, one needs a line number of some type of reference (information) that got logged to ID where the error occurred. This means one would need to manually ID all "potential" critical points in every procedure and include them as a reference point when DoError is called. Doable -- BUT a lot of work.
Should be easier way unless I'm missing something.
Last edited by vb6forever; Dec 9th, 2020 at 09:20 AM.
-
Dec 9th, 2020, 09:26 AM
#7
Re: Logging Errors In Realtime
Originally Posted by vb6forever
Never seen an example of procedure reentry to get more log info if I'm understanding correctly.
Well, I meant you enter the room like in some theatrical appearance -- the hero to resolve the tough problem by turning logging level to 11 and wading through all those dumps :-))
cheers,
</wqw>
-
Dec 9th, 2020, 10:39 AM
#8
Re: Logging Errors In Realtime
dz32: FWIW: The call to DoLog puts on a TimeStamp and adds other info to the log file.
What if DoLog causes a MsgAndLog error?
Then you get it a loop
-
Dec 9th, 2020, 12:28 PM
#9
Thread Starter
Fanatic Member
Re: Logging Errors In Realtime
Arnoutdv:
Thanks for the thought (input), will test.
-
Dec 11th, 2020, 09:55 AM
#10
Re: Logging Errors In Realtime
Don't know if it will help, but I have used this simple routine to log errors in an executable.
Code:
Public Sub PrintDebug(msg As String)
Debug.Print msg
If DbgFlg Then Call LogError(msg)
End Sub
Instead of using Debug.Print, you use PrintDebug in the IDE. If you set the DbgFlg in the executable, those same errors are logged to file.
A MsgBox is not a very good tool to use for displaying errors because it halts processing until it is responded to. Design your own Message Box that flashes a message and then times out.
Code:
Option Explicit
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Sub Form_Click()
Hide
End Sub
Private Sub Form_KeyPress(KeyAscii As Integer)
If KeyAscii = 27 Then Hide
End Sub
Private Sub Form_Load()
Me.Left = (GetSystemMetrics(16) * Screen.TwipsPerPixelX) - Me.Width
Me.Top = (GetSystemMetrics(17) * Screen.TwipsPerPixelY) - Me.Height
'Set Icon = frmTray.Icon
End Sub
Private Sub Label1_Click()
Hide
End Sub
Private Sub Timer1_Timer()
frmNotify.Show
End Sub
J.A. Coutts
-
Dec 11th, 2020, 11:49 AM
#11
Thread Starter
Fanatic Member
Re: Logging Errors In Realtime
couttsj:
Thanks for your input and will take your comments under consideration.
The particular routine in questions works MOST of the time -- e.g. M$ controls or related supporting procedures I've written.
From what I've been able to determine (as occurs infrequently) is that when "the key" ActiveX event (the ActiveX is provided by the server company) is triggered and an error occurs either in that event or in one of my down stream procedures triggered by this call,
I get what I call a run of (multiples of the same) errors. If the routine that errors has LogOnly, while multiples occur in the log, the APP is not affected. However, if MsgOnly, or MsgandLog is used, then I end up with multiple Msgboxes being displayed until I run out of memory.
I can see where if one hasn't responded to the displayed Msgbox, before the next piece of server data invokes (calls made) to the downstream routines, that MAYBE(???), the OS says, still waiting on Msgbox response and so displays another of the same Msgbox. That is a pointer is set within the OS to the Error routine of the procedure that errored and each time a new piece of info arrives it ends up being routed to the same Error routine.
I can change all affected procedures to LogOnly and then either use a Statusbar and/or Msgbox to alert user at App End that an error(s) occurred and to check the log.
As you point out one can roll their own Notice and use a Timer which I'll give utmost consideration to. However, would really like to know what is going on in my code under the hood.
Last edited by vb6forever; Dec 11th, 2020 at 12:02 PM.
-
Dec 11th, 2020, 12:49 PM
#12
Re: Logging Errors In Realtime
Maybe you should add something to log the calling routine in there so you can see where the routine is being called from. This would let you know if you are getting caught in a loop of the routine calling itself endlessly when your error occurs.
-
Dec 11th, 2020, 02:33 PM
#13
Thread Starter
Fanatic Member
Re: Logging Errors In Realtime
DataMiser: THanks for responding.
I do currently have the ability to see code execution (tracing) that is invoked at the project level
as most every procedure contains:
Code:
#If kDEBUGON Then
Debug.Print "Begin BlankProc"
#End If
#If kDEBUGON Then
Debug.Print "End BlankProc"
#End If
THe problem is it creates a tremendous amount of Debug statements in Realtime.
I could narrow this down a bit by creating another constant (e.g. kDEBUGRT) for just those routines of interest (several modules worth) and also write out to a log rather than Debug.Print. I previously rejected this because errors occur infrequently, but combining this concept along with code to erase that log each day unless an error occurs (ie. set a flag), I think may work at this writing.
Looking down the road, if the problem is caused by the server triggering multiple calls, then resolving that might be a biggie since I have no control over the ActiveX.
Re: couttsj idea of using a timer and rolling ones own Msgbox, thinking about it a bit further, I believe it would experience the same issues I have now since just writing to the log using "LogOnly" generates multiples of the same error.
Last edited by vb6forever; Dec 11th, 2020 at 02:38 PM.
-
Dec 11th, 2020, 08:19 PM
#14
Re: Logging Errors In Realtime
One thing I have done in the past to let the user know to check the log is use the status bar on the MDI parent and display red text in it when an error has occurred during that session and then have the error log display by clicking on that panel.
btw what I was thinking about the logging of the calling routine would be added to the actual log routine, possibly passing a parameter to it to indicate where it was called from or setting up a global variable that gets set prior to any call to the dolog or whatever the routine is called. That way it only logs the routines when the error log is called which should not be all that often. If a ton of errors are happening then I would think it best to find and remove the source of the errors if at all possible.
-
Dec 12th, 2020, 10:59 AM
#15
Thread Starter
Fanatic Member
Re: Logging Errors In Realtime
DataMiser: Thanks again for your input.
the status bar on the MDI parent and display red text in it when an error has occurred
I do the same
then have the error log display by clicking on that panel.
Good idea, hadn't thought of that one.
logging of the calling routine
Been trying to get to this, but a toughie. For example multiple procs may call the one proc where the error occurs. One doesn't know an error occurred until it happened. I guess one could pass a "caller name" parameter into every down stream routine, but lot overhead and lot rewrite IMHO.
Going with a global variable that holds the callers name that is printed as part of the Error routine should do the same thing and save lot code (rewrite) effort. However, in either case, only gets one layer back.
As an alternative, thinking that by using a new project constant for those modules of interest, then writing out All calls to a log for a set period (say 5, 10 minutes, or 1/2 hour) which is set based on log size. If the error flag not set, then erase the log and start over. If the error flag set, then stop log and send message to troubleshoot.
Sounds like a "simple" plan that might work unless I'm missing something.
Otherwise -- unless you or other have some other ideas -- back to wqweto's
turning logging level to 11 and wading through all those dumps
Last edited by vb6forever; Dec 12th, 2020 at 11:03 AM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|