Foutenbeheer en log via Error klasse

Ik wil in mijn programma:

  • een vaste manier om met foutmeldingen te werken
  • nadien de foutmeldingen kunnen nazien

In allerlei Classes, Modules en Forms kunnen fouten ontstaan, ik hou altijd de laatste ter plaatse bij in een variabele sLastError.


PRIVATE sLastError AS String

PUBLIC SUB getLastError() AS String
  
  RETURN sLastError
  
END

In mijn FMain heb ik een procedure waar ik alle foutmeldingen naartoegooi:

FMain


PUBLIC SUB SetError(sTextline AS String) 
  
  lsbxError.Add(Str$(iErrCounter) & ": " & sTextline, MCommon.insertTop)
  IF MMain.bErrorFile 
    MMain.hError.writeError(Str$(iErrCounter) & ": " & sTextline)
  ENDIF 
  INC iErrCounter
  
END

Fouten zakken weg naar onder in het zichtbaar meldingen-schermdeel in de toepassing, de ListBox lsbxError.
De constante in MCommon die aangeeft dat bovenaan in de lijst wordt toegevoegd is misschien wat overdreven:

MCommon

PUBLIC CONST insertTop AS Integer = 0

In MMain heb ik mijn error object, wat alle foutmeldingen opvangt:

MMain

... 
hError = NEW CError  
  IF hError.sLastError
    bErrorFile = FALSE
    sLastError = "Error handling to file: " & hError.sLastError
  ELSE 
    bErrorFile = TRUE
  ENDIF 
...

Mijn foutklasse heet CError:

CError

PRIVATE $hErrorFile AS File
PUBLIC sLastError AS String
PRIVATE sErrorFileName AS String


PUBLIC SUB _new(OPTIONAL sFileName AS String)
  
  IF sFileName
    sErrorFileName = sFileName
    openErrorFile(sErrorFileName)
  ELSE 
    sErrorFileName = System.User.Home & "/.config/gambas" & "/" & Application.Name & "-error.txt"
    DEBUG sErrorFileName
    openErrorFile(sErrorFileName)
  ENDIF 
  
END

PUBLIC SUB getErrorFileName() AS String
  
  RETURN sErrorFileName

END


PUBLIC SUB openErrorFile(sErrorFile AS String) AS Boolean
  
  IF Exist(sErrorFile)
    'TRY $hErrorFile = OPEN sErrorFile FOR WRITE APPEND ' cannot append without maintenance
    TRY $hErrorFile = OPEN sErrorFile FOR WRITE CREATE  
  ELSE 
    TRY $hErrorFile = OPEN sErrorFile FOR WRITE CREATE 
  ENDIF 
  
  IF ERROR 
    sLastError = Error.Text
    RETURN FALSE
  ELSE 
    writeError("*** CError uses file: " & sErrorFileName)
    writeError("*** on: " & System.Host & " " & System.User.Name & " " & Application.Name & " " & Application.Version & " from " & Application.Path)
    sLastError = ""
    RETURN TRUE
  ENDIF 
  
END

PUBLIC SUB closeErrorFile()
  
  TRY CLOSE $hErrorFile
  TRY $hErrorFile.Close()
  
END


PUBLIC SUB writeError(sErrorText AS String) AS Boolean
  
  TRY PRINT #$hErrorFile, Date & "@" & Time & ":" & sErrorText
  IF ERROR 
    RETURN FALSE
  ELSE 
    RETURN TRUE
  ENDIF 
  
END

Upd 2018-04: ondertussen iets aangepaste versie:

' Gambas class file

' CError - help with formatting for display and storing to an error log

Public bLogToFile As Boolean

Private sPreviousError As String
Private sLastError As String
Private SErrorText As String

Private $hErrorFile As File
Private iErrorCount As Integer

Public Sub _new()
  
  Dim s As String
  
  ' rotate error log file
  If Exist(getErrorFileName() & "~")
    Try Kill getErrorFileName() & "~"
  Endif
  Try Copy getErrorFileName() To getErrorFileName() & "~"
  Try $hErrorFile = Open getErrorFileName() For Write Create
  If Not Error
    bLogToFile = True
    Exec ["gambas3", "-V"] To s
    s = "Error file for " & Application.Name & " " & Application.Version & " for " & System.User.Name & "@" & System.Host & ", gambas " & s
    Print #$hErrorFile, s 
    Print #$hErrorFile, " ----------------------------------------------------------------------------------------" 
    Try Close $hErrorFile
  Else
    Debug "try to open error file " & getErrorFileName() & ": " & Error.Text
    bLogToFile = False
  Endif
  iErrorCount = 0
  
End

Public Sub getErrorFileName() As String
  
  If Not Exist(System.User.Home &/ ".local/log")
    Mkdir System.User.Home &/ ".local/log/"
  Endif
  Return System.User.Home &/ ".local/log/" & Application.Name & "-err.txt"
  
End

Public Sub shiftError(sNewError As String)
 
  sPreviousError = sLastError
  sLastError = Stamp(sNewError)

End



Public Sub Stamp(s As String) As String
  
  Return Now() & ";" & Str(iErrorCount) & ": " & s
  
End


Public Sub setError(sError As String, Optional bForceLogToFile As Boolean) As String
  
  SErrorText = sError
  Inc iErrorCount
  shiftError(sError)
  If (bForceLogToFile Or bLogToFile)
    LogToFile(sLastError)
  Endif
  Return iErrorCount & " " & sError & " @" & Time(Now())
  
End


Public Sub getPreviousError() As String
  
  Return sPreviousError
  
End

Public Sub LogToFile(s As String)
  
  Try $hErrorFile = Open getErrorFileName() For Write Append
  If Error
    Debug Error.Text
  Endif
  Try Print #$hErrorFile, s
  If Error 
    Debug Error.Text
  Endif
  Try Close $hErrorFile
  If Error
    Debug Error.Text
  Endif
  
End