Results 1 to 15 of 15

Thread: [RESOLVED] Logging Errors In Realtime

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    Resolved [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?

  2. #2
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,205

    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.

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    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

  4. #4
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,056

    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.

  5. #5
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: Logging Errors In Realtime

    Quote Originally Posted by dz32 View Post
    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>

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    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.

  7. #7
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,120

    Re: Logging Errors In Realtime

    Quote Originally Posted by vb6forever View Post
    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>

  8. #8
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,872

    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

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    Re: Logging Errors In Realtime

    Arnoutdv:
    Thanks for the thought (input), will test.

  10. #10
    Frenzied Member
    Join Date
    Dec 2012
    Posts
    1,470

    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

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    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.

  12. #12
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,205

    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.

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    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.

  14. #14
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,205

    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.

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    858

    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
  •  



Click Here to Expand Forum to Full Width