Logging using log4j

Post any questions you have about using the Verj.io Studio, including client and server-side programming with Javascript or FPL, and integration with databases, web services etc.

Moderators: Jon, Steve, Ian, Dave

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

Logging using log4j

#1

Postby Jon » Thu May 22, 2014 1:48 pm

This describes how to add log4j logging to your scripts. This is a very flexible Java logging package that provides many advantages including:

1. Ability to set the logging level dynamically at runtime without changing your scripts i.e. you can write debug logging into scripts then activate it when you need to, and only for selected scripts.
2. Ability to write to log files or the console or both.
3. Formatted log messages.
4. Multi-user access without file locking problems.
5. Once configured, it can be used by all scripts with the ability to control debugging messages by script, form, project etc.
6. The ability to wrap log files i.e. to stop them growing indefinitely.
7. It's pretty much a de facto standard and is used throughout the Java world.

See http://logging.apache.org/log4j for details.

Here are the steps to configure log4j for use by Ebase scripts:

Step 1: configure the log4j properties file
You only need to do this step once only, then it can be used by all scripts.

Edit file UfsServer/tomcat/webapps/xxx/WEB_INF/classes/log4j.xml on the server and add the following at the bottom, but before the ending </log4j:configuration> tag:

Code: Select all

<appender name="scriptsLog" class="org.apache.log4j.FileAppender">
    <param name="file" value="../logs/ebasescripts.log" />
    <param name="append" value="false" />
    <param name="threshold" value="debug" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d &#91;%t&#93; %-5p %c - %m%n"/>
    </layout>
</appender>

<logger name="ebforms" additivity="false">
    <level value="ALL" />
    <appender-ref ref="scriptsLog"/>
</logger>
This creates an appender, which specifies where the logs are written to; this example writes everything to file ebasescripts.log in the tomcat/logs folder. Note, if you start Ebase as a service you may need to change this to an absolute file path.

It also creates a logger, which is the component that actually does the logging - we will be using this logger from the scripts. The logger names are hierarchical: this one is named "ebforms" and it will be used by anything that requests a logger beginning with this name e.g. a request for a logger "ebforms.project1.script23" will also use this logger. This hierarchical behaviour is one of the features that makes log4j so flexible, hopefully it will become a bit clearer in a moment.

Step 2: restart the server
This is unfortunately necessary and activates the log4j configuration just created.

Step 3: add logging to your scripts
To do this, add the following two lines to each script where you want to use logging:

Code: Select all

importPackage&#40;org.apache.log4j&#41;;
var logger = Logger.getLogger&#40;"ebforms.project1.js1c"&#41;;
I suggest a naming convention of ebforms.<PROJECTNAME>.<SCRIPTNAME> but this can be anything you like. So long as this name begins with "ebforms." it will use the logger we configured above.

You can then create a log message with any of the following.

Code: Select all

logger.debug&#40;"A debug message"&#41;;
logger.info&#40;"An info message"&#41;;
logger.error&#40;"An error message"&#41;;
logger.log&#40;Level.INFO, "Another message"&#41;;
As you can see, log messages have a level - debug, info, error etc (there are quite a few more) - and these levels are also hierarchical. If you activate logging at debug level, all messages will be logged (as debug is the lowest level); but if you activate logging at info level, only info and higher messages (which includes error) will be logged. You specify what level you want to record at any time by changing the Level parameter in the log4j logger e.g.

<level value="INFO" />

That's all you need to start logging with log4j.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#2

Postby Jon » Thu May 22, 2014 2:03 pm

This is how to turn on debug logging for just one script, while leaving all others logging at error level. Add an additional logger like this:

Code: Select all

<logger name="ebforms" additivity="false">
    <level value="ERROR" />
    <appender-ref ref="scriptsLog"/>
</logger>

<logger name="ebforms.project1.script23" additivity="false">
    <level value="DEBUG" />
    <appender-ref ref="scriptsLog"/>
</logger>
The first logger is our default that applies to all scripts and specifies only ERROR message logging. The second logger specifies DEBUG message logging and is used by a logger requesting this explicit name:

Code: Select all

var logger = Logger.getLogger&#40;"ebforms.project1.script23"&#41;;
Last edited by Jon on Tue Jun 07, 2016 3:28 pm, edited 1 time in total.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#3

Postby Jon » Thu May 22, 2014 2:15 pm

Here's an example of a rolling file appender - it will wrap once the max size (50MB) is reached. Replace the file appender in the log4j.xml file with this one to implement.

Code: Select all

<appender name="scriptsLog" class="org.apache.log4j.RollingFileAppender">
    <param name="file" value="../logs/ebasescripts.log" />
    <param name="append" value="false" />
    <param name="MaxFileSize" value="50MB" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d &#91;%t&#93; %-5p %c - %m%n"/>
    </layout>
</appender> 
0 x

Steve James
Ebase User
Posts: 331
Joined: Mon Mar 10, 2014 8:34 am

#4

Postby Steve James » Fri May 23, 2014 8:08 am

Hi Jon, that's great thanks.

I've found that I need to restart Tomcat if I make a change to log level in log4j.xml, is there a way around this?

Couple of suggestions for future versions of Ebase.
1 - when creating a new js script it would be good to have the lines automatically imported including the default loggername.

Code: Select all

importPackage&#40;org.apache.log4j&#41;; 
var logger = Logger.getLogger&#40;"ebforms.project.script"&#41;;
2 - Most of our forms still have FPL scripts so tracing logs isn't too time consuming. Our form writers have started using JS and use log('blurb'); a lot. It would be good if the log statement automatically adds the scriptname to the log entry. This would make tracing easier.

Thanks
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#5

Postby Jon » Tue May 27, 2014 7:29 am

Steve,

Unfortunately the restart is unavoidable at the moment. We are planning to introduce some sort of log4j built-in support in V5.0, and at that point we'll try and avoid the restart. We'll also try and add the script name to each log entry in V5.0.

Regards
Jon
0 x

LKirby
Ebase User
Posts: 37
Joined: Wed Mar 13, 2013 11:33 am
Contact:

#6

Postby LKirby » Wed May 13, 2015 2:21 pm

Hi Jon,

I was just thinking about what Steve said about including

Code: Select all

importPackage&#40;org.apache.log4j&#41;; 
var logger = Logger.getLogger&#40;"ebforms.project.script"&#41;;

on every new script created and I was wondering if something like this was possible in v5 if there was an option to further Steve's idea by being able to customise the default 2 lines added to every script as I'd think many people are always adding a few common lines to every script created. For example, I usually find myself having something this at the start of every script:

Code: Select all

importPackage&#40;com.ebasetech.xi.api&#41;;
importPackage&#40;com.ebasetech.xi.services&#41;;
importPackage&#40;org.apache.log4j&#41;;

var logger = Logger.getLogger&#40;"ebforms.project.script"&#41;;

var eo = event.owner,
sm = system.securityManager;

// Script comment on what what it does
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#7

Postby Jon » Wed May 13, 2015 5:51 pm

OK noted. We haven't gotten around to looking at more logging options in V5 but it hasn't been forgotten.

Regards
Jon
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#8

Postby Segi » Wed May 13, 2015 6:36 pm

I added that code at the bottom of UfsServer/tomcat/webapps/UFS/WEB_INF/classes/log4j.xml right before the closing /log4j:configuration tag and restarted eBase. I get this warning when starting up the server and logging doesn't work:

Code: Select all

log4j&#58;WARN Continuable parsing error 54 and column 23
log4j&#58;WARN The content of element type "log4j&#58;configuration" must match "&#40;renderer*,throwableRenderer?,appender*,plugin*,&#40;category|logger&#41;*,root?,&#40;categoryFactory|loggerFactory&#41;?&#41;".
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#9

Postby Jon » Thu May 14, 2015 9:36 am

I don't think the warning messages on the server log stop it from working - I have these on my system too. If you can't get it to work can you add your script code to this log. Add the log4j config as well if it's not the same as the example.

Regards
Jon
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#10

Postby Segi » Thu May 14, 2015 4:22 pm

Jon,

I used the log4j code exactly as provided above

Code: Select all

<appender>
    <param>
    <param>
    <param>
    <layout>
        <param>
    </layout>
</appender>

<logger>
    <level>
    <appender>
</logger>
I used this in a script:

Code: Select all

importPackage&#40;org.apache.log4j&#41;;

var logger = Logger.getLogger&#40;"ebforms.project1.js1c"&#41;;
logger.debug&#40;"A debug message"&#41;; 
logger.info&#40;"An info message"&#41;; 
no output is written to the file
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#11

Postby Jon » Thu May 14, 2015 4:56 pm

OK, I assume that your log4j looks like this:

<appender name="scriptsLog" class="org.apache.log4j.FileAppender">
<param name="file" value="../logs/ebasescripts.log" />
<param name="append" value="false" />
<param name="threshold" value="debug" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
</layout>
</appender>

<logger name="ebforms" additivity="false">
<level value="ALL" />
<appender-ref ref="scriptsLog"/>
</logger>

Can you check that the ebasescripts.log file is created in UfsServer/tomcat/logs as soon as you start the server - it will be empty initially. On my Windows system this file is created in UfsServer/tomcat/logs because the home directory is UfsServer/tomcat/bin and the file location in log4j.xml is ../logs/ebasescripts.log. If this file does not exist in UfsServer/tomcat/logs on your system, I suggest you have a look around and see if it's been created somewhere else - this will be the case if your home directory is different. In particular if you start Ebase as a service, the home directory will be different.

If this is indeed the problem, you can always change the log4j.xml file to provide an absolute file path instead of a relative path.

Everything else looks OK.

Regards
Jon
0 x

Segi
Ebase User
Posts: 649
Joined: Mon Dec 09, 2013 6:37 pm

#12

Postby Segi » Thu May 14, 2015 4:57 pm

Jon,

The file is created in logs/ebasescripts.log when I start the server and is empty, even after I write to it

Update: I figured out why it wasn't working and it is fixed now.
0 x

Jon
Moderator
Moderator
Posts: 1342
Joined: Wed Sep 12, 2007 12:49 pm

#13

Postby Jon » Thu May 14, 2015 5:47 pm

Hmm, well there isn't much else that can go wrong.

The name specified in the Logger.getLogger() statement must begin with the string specified in the log4j.xml logger i.e. ebforms.
Other than that the level specified in the logger in log4j.xml should be All.

One more thing you might try. Change the appender-ref in log4j.xml so it says ref="SYSLOG" instead of ref= "scriptsLog", then restart the server. Your logging messages should now come out in the console window instead of going to the file. This tests that your script code is correct and that log4j is working OK.

Regards
Jon
0 x


Who is online

Users browsing this forum: No registered users and 12 guests