Suggested addition to Errsysw.prg

Post Reply
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Suggested addition to Errsysw.prg

Post by Roger Seiler »

Below is an addition that I made to my version of Errsysw.prg that I find very helpful. This addition retains info from any prior error.log, adding it to the end of the current cErrorlog, until the error.log file exceeds 50 K in size. If over 50 K, then just the most recent 5k chars of info are retained, and the file builds again.

This prevents losing important error info in a situation where different errors occur in quick succession before you have a chance to debug the first errors in the sequence. Especially important where a customer fails to tell you about an earlier error before they crash the app with something else.

Here it is, to be added just above existing Errsysw.prg comment,
"// Generates a file with an Error Log "

Code: Select all

   
   // If an Error.log already exists, add it to bottom of cErrorLog.
   // Added this to retain prior error messages up to limit of 25k...
   IF FILE("Error.log")
      cText := MEMOREAD("Error.log")
      cText := CRLF+CRLF+REPLICATE("*",50)+ ;
               CRLF+REPLICATE("*",50)+CRLF+CRLF+cText
      IF LEN(cText) < 50000
         cErrorLog += cText
      ELSE
         cErrorLog += SUBSTR(cText,1,5000)
      ENDIF
   ENDIF

   // Generates a file with an Error Log

   BEGIN SEQUENCE  // [ continue with existing PRG code... ]

- Roger
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Post by Roger Seiler »

Forgot to mention that cText := "" is declared as a local at the beginning of the function.

- Roger
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Post by Roger Seiler »

Just thought of a way to do this even better. As error.log file builds to more than 50k chars, instead of arbitrarily saving only the the most recent 5k chars from the prior error info, we can just cut out the oldest info equal to the size of the new cErrorlog. This minimizes the loss of useful prior error info.

So here it is again (to be inserted just above Memowrit() section)...

Code: Select all

   LOCAL cText := ""   // declare at top of function

   // Insert the following in Errsysw.prg just before Memowrit() section...

   // If an Error.log already exists, add it to bottom of cErrorLog.
   // Added this to retain prior error messages up to limit of 25k...
   IF FILE("Error.log")
      cText := MEMOREAD("Error.log")
      cText := CRLF+CRLF+REPLICATE("*",50)+ ;
               CRLF+REPLICATE("*",50)+CRLF+CRLF+cText
      IF LEN(cText) < 50000
         cErrorLog += cText
      ELSE
         cErrorLog += SUBSTR(cText,1,LEN(cText)-LEN(cErrorLog))
      ENDIF
   ENDIF

   // Generates a file with an Error Log    [ existing comment ]

   BEGIN SEQUENCE  // [ continue with existing PRG code... ]
- Roger
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Post by Roger Seiler »

Geez! Every time I look at this, I see a slightly better way to do it. This version lets the error.log file build up to just 55k, and keeps it at that size as it adds new error text to the top while deleting old error text at the bottom. If you want to retain more error text, then just increase the error.log max size in two places from 55000 to whatever...

Code: Select all

   LOCAL cText := ""   // declare at top of function

   // Insert the following in Errsysw.prg just before Memowrit() section...

   // If an Error.log already exists, add it to bottom of cErrorLog.
   // Added this to retain prior error messages up to limit of 55k...
   IF FILE("Error.log")
      cText := MEMOREAD("Error.log")
      cText := CRLF+CRLF+REPLICATE("*",50)+ ;
               CRLF+REPLICATE("*",50)+CRLF+CRLF+cText
      cErrorLog += cText
      IF LEN(cErrorLog) > 55000    // For 16 bits, must set limit at 35000
         cErrorLog := SUBSTR(cErrorLog, 1, 55000)  // For 16 bits, 35000
      ENDIF                                      // due to 64k limit.
   ENDIF

   // Generates a file with an Error Log    [ existing comment ]

   BEGIN SEQUENCE  // [ continue with existing PRG code... ]
- Roger
User avatar
ukoenig
Posts: 3981
Joined: Wed Dec 19, 2007 6:40 pm
Location: Germany
Contact:

Some changes in ERRORSYSW.prg

Post by ukoenig »

Hello Roger,

some month ago, there was a toppic, i added a few lines
because i needed error files with different timestamps :

Code: Select all


....
....
cErrorLog += "   Dynamic memory consume :" + CRLF
cErrorLog += "      Actual  Value : " + Str( MemUsed() ) + " bytes" + CRLF
cErrorLog += "      Highest Value : " + Str( MemMax() ) + " bytes" + CRLF
// nSymNames() no longer returns a real value! 15/April/97
/*
cErrorLog += "   SYMBOLS segment" + CRLF
cErrorLog += "      " + LTrim( Str( nSymNames() ) ) + " SymbolNames:   " + ;
	                LTrim( Str( nSymNames() * 16 ) ) + " bytes"

// The changes :

// you can save max 10 Error-messages
// then it starts with 1 again
//  -------------------------        path of your EXE-file
c_dir := GetModuleFilename(GetInstance(),"YOUR_PROG.EXE" + CHR(0), 255)
c_pfad	:= left ( c_dir, rat( "\", c_dir) -1 )
// c_pfad   = Path of application
cERR := ""
cERR1 := ""
n := 0
BEGIN SEQUENCE
   oOldError = ErrorBlock( { || DoBreak() } )

   // ------------- NEW --------------------------------------

   FOR i := 1 TO 11
       n++ 
       xxx := lTRIM(str(n))
       cERR   := c_pfad + "\ERROR_" + xxx + ".log"
       // deletes the old error.log`s
       // ---------------------------------
       IF n = 11 
          cERR := c_pfad + "\ERROR_1.log"
          x := 1
          FOR x := 1 TO 10
               xxx := ltrim(str(x))
               cERR1 := "ERROR_" + xxx + ".log"
               DELETE FILE "&cERR1"
          NEXT	
          MemoWrit( "&cERR", cErrorLog )
          EXIT
       ELSE
          IF !FILE( "&cERR" )
               MemoWrit( "&cERR", cErrorLog )
               EXIT
          ENDIF
      ENDIF
NEXT
cERR3 := "ERROR_" + xxx + ".log"

// -------------------------------------------

END SEQUENCE
ErrorBlock( oOldError )

Best Regards
Uwe :lol:
Since 1995 ( the first release of FW 1.9 )
i work with FW.
If you have any questions about special functions, maybe i can help.
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Post by Roger Seiler »

The reason I prefer to keep the error messages in one file instead of a separate file for each, is to make it easier for customers to email to me the error.log that I need. They don't want to have to figure out which ERRnnn.log file to send to me. It is just simpler this way, and the single file usually goes back to cover about the last 3 errors - usually all that I need.

- Roger
User avatar
Otto
Posts: 4470
Joined: Fri Oct 07, 2005 7:07 pm
Contact:

Post by Otto »

Roger,
I think yours is a good idea.
Wouldn’t it be a good idea too to encode the file and also
give the file an other name maybe temp file.

I think it is not very clever to document an error in such a clear way.
You never know what people do with such files.
Otto
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Post by Roger Seiler »

Otto,

Yes, the text could be encrypted. However, with my types of apps and the types of customers I'm working with, I haven't yet felt the need to do this. I don't seem to have any customers yet who are capable of understanding what the info in the error.log file means, much less what they might be able to do with it that could be against my interests. Thus I prefer to keep the process of getting the error.log info from the customer as simple as possible (and as complete as possible) so that I can solve any problem as quickly as possible.

- Roger
Rochinha
Posts: 309
Joined: Sun Jan 08, 2006 10:09 pm
Location: Brasil - Sao Paulo
Contact:

Post by Rochinha »

Roger,

You can automate send error file,

I use Blat to this:

Code: Select all

...
   // Generates a file with an Error Log

   BEGIN SEQUENCE
         oOldError = ErrorBlock( { || DoBreak() } )
         MemoWrit( "Error.log", cErrorLog )
   END SEQUENCE
   ErrorBlock( oOldError )

    /* PANTALLA DE CONTROL DEL ERROR */
    DEFINE FONT oFont NAME "Ms Sans Serif" SIZE 0, -10

    DEFINE DIALOG oDlg RESOURCE "dlgMSRel"
    REDEFINE SAY oSay VAR "O seguinte erro foi encontrado:"+CRLF+"    "+TiraErrLixo(ErrorMessage( e ))+CRLF+StackMessage ID  99 OF oDlg COLOR RGB(000,000,000),RGB(255,255,255)
    REDEFINE SAY oSay ID 100 OF oDlg COLOR RGB(255,255,255),RGB(000,000,000)

    REDEFINE BUTTON oBtn1 ID 1 OF oDlg ;
                 ACTION Blat( "Cliente: " + M->CL_NOME,;
                      "smtp.isp.com",;
                      M->CL_EMAIL,;
                      "YourEmail@isp.com",;
                      "***** System Error Message *****",;
                      "UserName",;
                      "UserPassword",;
                      "error.log" )
    REDEFINE BUTTON oBtn2 ID 2 OF oDlg ACTION oDlg:End()
    REDEFINE BUTTON oBtn3 ID 3 OF oDlg ACTION WAITRUN("NOTEPAD ERROR.LOG") NOBORDER
    REDEFINE BUTTON oBtn4 ID 4 OF oDlg ACTION ( lRet  := .t., oDlg:End() ) // Retry
    REDEFINE BUTTON oBtn5 ID 5 OF oDlg ACTION ( lRet  := .f., oDlg:End() ) // Default

    ACTIVATE DIALOG oDlg CENTERED ;
             ON INIT ( iif(e:CanRetry,oBtn4:Enable(),oBtn4:Disable()), ;
                       iif(e:CanDefault,oBtn4:Enable(),oBtn4:Disable()) )
    oFont:End()

    BEGIN SEQUENCE
        oOldError = ErrorBlock( { || DoBreak() } )

        /*  CONTROL PERSONALIZADO DE ERRORES */
        if !lIsDir( "ERRORES" )    //CREAR CARPETA DE ERRORES DEL PROGRAMA
           lMkDir( "ERRORES" )
        endif
...
Dialog .RC File:

Code: Select all

dlgMSRel DIALOG 20, 28, 245, 138
STYLE 0x4L | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Mensagem de Erro"
FONT 8, "MS Sans Serif"
{
 DEFPUSHBUTTON "&Não enviar", 2, 120, 121, 52, 14
 PUSHBUTTON "&Enviar relatório de erros", 1, 4, 121, 114, 14
 PUSHBUTTON "Clique aqui.", 3, 188, 96, 55, 14
 PUSHBUTTON "&Denovo", 4, 173, 121, 34, 14, WS_DISABLED | WS_TABSTOP
 PUSHBUTTON "&Padrão", 5, 209, 121, 34, 14, WS_DISABLED | WS_TABSTOP
 LTEXT "Para visualizar os dados contidos neste relatório de erros.", -1, 5, 99, 181, 9
 CONTROL "", 100, "static", SS_WHITERECT | WS_CHILD | WS_VISIBLE, -8, -1, 261, 30
 ICON "icon_info", -1, 4, 3, 18, 20
 LTEXT "Evento de detecção de erros", 99, 28, 3, 224, 24
 LTEXT "O programa não responde.", -1, 4, 35, 247, 9
 LTEXT "Informe este problema à 5Volution.", -1, 5, 52, 247, 9
 LTEXT "Foi criado um relatório detalhando o erro ocorrido que voce pode nos enviar para ajudar a melhorar o 5Volution. Esse relatório será considerado confidencial e anônimo.", -1, 5, 66, 241, 29
 GROUPBOX "", -1, -5, 25, 256, 93, BS_GROUPBOX
}
Blat function:

Code: Select all

function blat( cbody ,;
               cserver ,;
               cto ,;
               cf ,;
               csubject ,;
               cu ,;
               cpw ,;
               cattach )
     BlatCMD := [ blat.txt] + ;
                [ -server ]   + alltrim(cserver) + ;
                [ -to ]       + alltrim(cto) + ;
                [ -f ]        + alltrim(cf) + ;
                [ -mailfrom ] + alltrim(cf) + ;
                [ -subject "] + alltrim(csubject) + ["] + ;
                [ -r ]        + ;
                [ -u ]        + alltrim(cu) + ;
                [ -pw ]       + alltrim(cpw) + ;
                [ -log "email.log" -debug ] + ;
                iif( empty( cAttach ),[],[ -attach "] + alltrim(cattach) + ["])
     cMacro="BLAT.EXE " + BlatCMD
     fErase( "email.log" )
     cBody := FormHtml( cSubject, cBody )
     memowrit( "blat.txt", cbody )
     //memowrit( "blat.bat", cMacro )
     WinExec( cMacro, 0 )
     if file( "blat.log" )
        BlatLOG := memoread( "email.log" )
        if "ERROR" $ Upper(BlatLOG)
            Mensagem( "Erro: arquivo de BLAT.LOG foi criado" )
            return .f.
        endif
     endif
     RETURN .T.

Function FormHtml( cSubject, cBody )
   Local cOpen := "", cClose := ""
   cHTML := ;
      '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"' + CRLF + ;
      '                      "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">' + CRLF + ;
      '<html>' + CRLF + ;
      '<head>' + CRLF + ;
      '   <title>' + cSubject + '</title>' + CRLF + ;
      '   <meta http-equiv="Content-Type"' + CRLF + ;
      '         content="text/html; charset=iso-8859-1">' + CRLF + ;
      '</head>' + CRLF + ;
      '<body>' + CRLF + ;
      cBody + CRLF + ;
      '</body>' + CRLF + ;
      '</html>'
   Return cOpen + cHTML + cClose
On error occurrency, this routine send the email with error.log to you.
MOISES
Posts: 824
Joined: Wed Aug 22, 2007 10:09 am

Post by MOISES »

Antonio,

Why not to add this features to errosrsyw?.
Saludos / Regards,

FWH 20.04, Harbour 3.2.0 dev (r1909261630) y BCC 7.40
MOISES
Posts: 824
Joined: Wed Aug 22, 2007 10:09 am

Post by MOISES »

Hi,

For sending the email, I think it will be better to use MAPI.
Saludos / Regards,

FWH 20.04, Harbour 3.2.0 dev (r1909261630) y BCC 7.40
User avatar
Roger Seiler
Posts: 223
Joined: Thu Dec 01, 2005 3:34 pm
Location: Nyack, New York, USA
Contact:

Post by Roger Seiler »

Rochinha,

Thank you! Great idea!

- Roger
Rochinha
Posts: 309
Joined: Sun Jan 08, 2006 10:09 pm
Location: Brasil - Sao Paulo
Contact:

Post by Rochinha »

Roger,

Thanks too!

Moises,

I´m using Blat because MAPI fails with Outlook or Outlook 2000 security.

MAPI works fine with Eudora.

See more examples in http://www.fivetechsoft.com/forums/view ... blat+class
Post Reply