Re: Retrieving line number of error with err_get
Posted in 1993
There are two ways to get file names and line numbers into an error log file in Informix 4GL. One is to use SCCS to insert the line numbers when you check code out. The other is to user cpp and the DEFINES _LINE_ and _FILE_. The following is an articule on the topic that I am working on for the next issue of our local Informix User Group that uses SCCS to get the file names, line numbers and release of code into your log files. ############################################################################ Informix 4GL Application Error Logging by Lester B. Knutsen In every major application that I have developed, one requirement has been to have some way of logging what is going on inside the program to be able to support it. There are three types of application logging I like to use. One is to log what the user is doing so that when they call with a question or problem its easier to figure out what went on. This is also a good way to find out what actually gets used in an application and what does not get used. A second is to log all errors within the program, and finally while a program is under development, more detailed debugging information is needed. The log could be to a file, to a network messaging system, or to a backup device. It is also very useful to log the 4GL module name, the version, and line number in the source code that caused the error. Informix 4GL has a function to write to a log file. First you need to create an error log with the function startlog("logname"). Then the function errorlog() can be used to save SQL error messages, informational messages about the application, and debugging messages. Informix will automatically print to an open error log the Informix error that causes a program to abort unless you have the statement "whenever error continue" in your code. It will include the source code line number and module name. However, because the program aborts, it does not allow you to do any clean-up that may be required. The function I have created includes the same information, and by setting the option "whenever error continue" in your code it allows you to program to handle and recover from errors. The following is an example function I have created using the errorlog function. In combination with the SCCS you can get the module name, SCCS version, and line number of the program that generated the function call. # error logging function when checked out of SCCS for editing (get -e filename) call dtlog( code, "MOD:%M% REL:%I% LINE:%C% :",message ) # error logging function when checked out of SCCS for compiling ( get filename) call dtlog( code, "MOD:dtlog.4gl REL:1.5 LINE:52 :",message ) There are three types of message calls to the function dtlog which writes the log file. The first argument passed is a number code for the type of message. The first type of message is a program error. If the number is negative then it is assumed it is an Informix error message. By replacing the variable "code" in the above function with the sql error code (sqlca.sqlcode) or status an error message will always print in the log if there is an error, and nothing will print if there is no error. The second type of message is informational. I use the number 1000 for messages that must be written to the log to indicate what is happening in the program. The third type of message is for debugging only. I use the number 0 to code messages that only get written to the log when debugging is turned on. To turn debugging on a off, one variable in the function, debug_flag needs to be changed. The second argument is a string containing the SCCS module name, version and line number. When the source code is checked out of SCCS using the get command, the %M% is replaced by the module file name, the %I% by the SCCS version, and the %C% by the line number within the file. This allows you to quickly find the file and line number that caused an error. See your unix documentation for more information on SCCS. The third argument is a user supplied message. This allows you to put messages like "preparing.." or "open form new.frm" in the log file to track what you are doing. The following are some examples: 1) I like to start and end a program with a message to the log saying that the program started or ended with a function call like: call dtlog(1000,"MOD:%M% REL:%I% LINE:%C% :","Starting Program") 2) After every sql statement I put a function call to check for errors in additional to whatever error handling I have in the program. If debugging is turned off these will only print if their is an error. call dtlog(status,"MOD:%M% REL:%I% LINE:%C% :","SQL Error ") or call dtlog(sqlca.sqlcode,"MOD:%M% REL:%I% LINE:%C% :","SQL Error ") 3) For debugging you can put the following type of statement anywhere in your program that a message would be helpful. It will only print when debugging is turned on. call dtlog(0,"MOD:%M% REL:%I% LINE:%C% :","Debugging Message") This is the code for the function. ############################################################################# # Copyright 1993 Advanced DataTools Corporation # Module: %W% Date: %D% # Author: Lester B. Knutsen # Description: General Informix 4GL Logging function ############################################################################# function dtlog(code,relid,msg) define code integer, # message type relid char(40), # SCCS filename, release and line number msg char(60), # application message passed to function msgline char(200),# message output to log debug_flag integer # set level of error logging whenever error continue # keep going if there is an error # set the level of debugging for messages to appear in the log # one of the following must be uncommented let debug_flag = true # turn on debugging - all messages will # appear in the log #let debug_flag = false # turn off debugging - only sql error # messages or messages when code is 1000 # will appear in the log case when ( code = 1000 ) # always write messages to the log let msgline = "MESSG: ",code using "------& ", relid , msg clipped call errorlog(msgline) return when ( code < 0 ) # always write errors to the log let msgline = "ERROR: ",code using "------& ", relid , msg clipped, "\\n", err_get(code) call errorlog(msgline) return when ( code >= 0 and debug_flag = true ) # only when debugging let msgline = "DEBUG: ",code using "------& ", relid , msg clipped call errorlog(msgline) end case end function ############################################################################# #################################################