Instead, use the log() method of GenericHandler to write debugging information to the Locomotive server log. This method takes two parameters:
log_message is whatever information you want to write to the log. log_level is a number which is meant to represent the "seriousness" of the information that you're logging. A log_level of 0 is the highest severity; as the log_level increases, it becomes less and less severe. If you use a log_level higher than the Locomotive configuration variable LOG_LEVEL (from the file loco.conf), then your message will be suppressed from being written to the log. So, a good way to turn on or off debugging statements is to change LOG_LEVEL in loco.conf. For your convenience, we've provided some default log_level values in the GenericHandler class:public void log (int log_level, String log_message)
When you are writing debugging information to the log, you might say:public static final int ERROR = 0; public static final int WARNING = 1; public static final int NORMAL = 6; public static final int DEBUG = 9;
So, to turn on debugging, make sure that LOG_LEVEL has a value greater than 9 in the file loco.conf:log (DEBUG, "reached line 312");
LOG_LEVEL 10And, to turn off debugging, make LOG_LEVEL 9 or less:
LOG_LEVEL 9Because you can turn debugging on or off so easily, a good strategy when you first write your code is to put debugging statements in key parts of your code, so that you can "follow" your code by looking at the server log. You can even have more than one debugging log_level, if you'd like, so that you always log the important junctures in your code. A good way to follow the log is by using the "tail -f" option of the Unix "tail" command to continuously display the newest additions to the log file. (You can also tail -f the Event Log, too.)
A word of caution: after you have sufficiently tested and debugged your code, it may be wise to completely remove the debugging statements, because, even if they are not written to the log, they still take up resources to execute.
An alternative to removing the debugging statements is to have a static variable in your Handler which specifies whether to write debugging variables or not. You can then say:
if (IS_DEBUGGING) log(...)You can turn this static variable on or off as a global configuration variable, to be loaded when the Locomotive first starts up. Or, instead of having a static variable, you can have two different versions of the Handler, invoked by two different line entries in the Handler Routing Table; one entry would be the normal Handler, while the other would be the "debugging" version, thus:
Then, in your LoginHandler code, you can turn on a debugging variable (not a static variable) if the first url token is login_dbg:// normal version of the login handler: login org.locomotive.loco.base.LoginHandler // debugging version of the login handler: login_dbg org.locomotive.loco.base.LoginHandler
boolean IS_DEBUGGING; ... if (url_tokens[1].equals("login_dbg")) { IS_DEBUGGING = true; }
There has been a Locomotive Error Errormsg: There was a Locomotive error, code: login_lue. RequestID: 114604 System Tag: LEVERAGE_DEV InstanceID: sv_one Date: Jul 09, 1998 11:47 AM Please mail a copy of this page to our site administrator, ben@leverage.com. |
And the line that threw the Exception must be line 82:handleException (lue, "There was a Locomotive error, code: " + "login_lue.");
This tells us that there may be something wrong with this particular user's data in the database, or with the loco_users table, or with the database itself. Then, we can take action to find out exactly what was wrong. Having a short, unique identifier code such as login_lue thus helps you pinpoint where the errors are occurring in your code.user = new User (conn, form_username, false);
By the way, the handleException() method of GenericHandler also writes to the Locomotive Server Log file. It uses a log_level of 0, or ERROR. For any given Exception, handleException() will write a "stack trace", which is a list of all the methods that have called each other to reach the specific line in the program where the Exception was thrown. In the previous example of the error Web page, the handleException() method would also write the following stack trace to the server log:
From this stack trace, we would know to go to line 83 in the file LoginHandler.java to see what caused this Exception:1998-07-09 11:47:04 PDT REQ(114604) ERROR: There was a Locomotive error, code: login_lue. java.loco.LoadUserException at org.locomotive.module.base.LoginHandler.handleRequest(LoginHandler.java:83) at org.locomotive.module.base.BaseHandler.handleRequest(BaseHandler.java:44) at org.locomotive.loco.RequestManager.handoff(RequestManager.java:127) at org.locomotive.loco.RequestManager.run(RequestManager.java:75) at org.locomotive.server.PooledThread.run(PooledThread.java:38) at java.lang.Thread.run(Thread.java:490)
So, the stack trace in the log file is another way to find out exactly which line caused a particular error. Because users might report incomplete information about the error -- for example, they might only say what they were doing, and maybe give an approximate time when the error occurred, instead of sending the entire error Web page -- having a full stack trace in the log file can be very useful to track down a problem that a user has reported.user = new User (conn, form_username, false);
Note that the word "ERROR" always precedes a stack trace for an Exception
in the log file. This word is added by handleException(). At Leverage,
we have a convention that whenever serious Exceptions are thrown, we always
put the word ERROR at the beginning of the line in the log file. This way,
it makes it easy to find all serious errors in the log file. For example,
you can use the "grep" command in Unix to search for "ERROR" in the log
files. In fact, it's a good habit to periodically scan for lines containing
"ERROR" in your log files, to find out what kinds of problems might be
happening in your code or in the Locomotive.
LOCO_CHECK_NEW_TEMPLATE_FREQ 1When you run a Locomotive on the live site, you can make this value higher, in order to save time, because you know that the templates won't change very often on the live site. (There is also a way to force the Locomotive to reload all templates once, whether they've changed or not; see The Locomotive Administrators Guide.)
[if [and [USERNAME] [= USERS_AGE 21]] [quote Hi, [USERNAME], you're legal!! :^)]]You can check whether USERS_AGE = 21 directly by saying [= USERS_AGE 21], which will evaluate to "true" if it is true. Better yet, we can simply find out the value of the USERS_AGE variable by saying [USERS_AGE].