Logging and handling Java errors - Latest

Data360 Analyze Server Help

Product type
Software
Portfolio
Verify
Product family
Data360
Product
Data360 Analyze
Version
Latest
Language
English
Product name
Data360 Analyze
Title
Data360 Analyze Server Help
Copyright
2024
First publish date
2016
Last updated
2024-11-28
Published on
2024-11-28T15:26:57.181000

For information on the Java API, see the "laeJavaApi" Zip file which you will find in the following location: <Data360Analyze installation directory>/docs/lae

The Node interface defines an accessor to a Logger object. The Logger provides utility methods for writing to the log with varying LogLevels , as follows, in order of severity:

  • DEBUG
  • INFO
  • WARN
  • ERROR

The different log levels can be used by calling the logger().log(LogLevel level, …) method. Alternatively, the logger().debug, logger().info, logger().warn and logger().error methods can be used.

There are a large number of variants for these methods, taking different parameters. See the "laeJavaApi" Zip file (see <Data360Analyze installation directory>/docs/lae) for the full list of method variants on the Logger class.

The severity of the log level with which the message is logged, in comparison to the LogLevel property on the Java node determine whether or not the message is actually written to the log.

These log levels are outlined in the following table:

LogLevel When to use When written to log? Example

DEBUG

Used when logging information unrelated to any errors, just debugging information which may be useful to identify what is going on in the processing logic. The contents of these debug statements may only make sense to the node developer for troubleshooting purposes. In general, these should not be internationalized.

Node LogLevel = 0

logger().debug("Beginning to process records");

Record record = null

while ((record = read(0)) != RecordInput.EOF) {

//process record

}

logger().debug("Finished processing records");

INFO

Generally useful if an error occurs, but is handled, or an exception is being thrown that is part of the method contract (except for NodeFailedExceptions, which should generally only be thrown after a LogLevel.ERROR message has been logged).

Node LogLevel <= 1

public void myMethod() throws IOException {

try {

readFile();

}

catch (IOException ioe) {

logger().info(ioe, "IOException occurred reading file");

throw ioe;

}

}

WARN

Generally used when an error occurs, but the code is able to make some assumptions and continue. Is possible/likely to lead to an error later.

Node LogLevel <= 2

File dir =new File(dirName);

boolean madePath = dir.mkdirs();

if (!madePath) {

String msg =

"First choice path ("+madePath.getName()+") failed. ";

msg += "proceeding to backup location. ";

msg += "This may affect downstream processing. ";

logger().warn(msg);

dir = new File(backupDirPath);

}

ERROR

Used when the node is about to fail.

ALWAYS

int inputIdx = findInput("Data");

if (inputIdx == -1) {

logger().error("Expected node input \"Data\" does not exist");

throw fail();

}

The methods inherited by the Node that the node developer is expected to write (setup, processAll and cleanup) only declare to throw NodeFailedExceptions. When a NodeFailedException is thrown from the body of one of these methods, then will assume that the node has written all of the required information to the log, so will not automatically log any error information.

Therefore, it is the responsibility of the node developer to ensure that when any exception is thrown from within one of these methods, one of the following occurs:

  • The exception is caught, handled, and processing can continue.
  • The exception is caught, logged, the node status is set to fail (via calling the fail() method) and a NodeFailedException is thrown or the method returns normally.
  • The exception is caught, logged, the node status set to an appropriate non-failure state based on the exception and a NodeFailedException is thrown or the method returns normally.

The following example shows the correct mechanism for logging errors and failing the node:

try

{

//get the required properties

m_outputAsFloat = properties().getBoolean( propertyBase() + ".outputFloat");

m_inputColumnName = properties().getString( propertyBase() + ".inputColumnName");

m_outputColumnName = properties().getString( propertyBase() + ".outputColumnName");

}

catch (PropertyException ex)

{

logger().error(ex, Logger.CHAIN_END, "Error reading node properties.");

throw fail();

}

If a PropertyException occurs during this attempt, the code first obtains the Logger using the logger() accessor and writes an error to the log. The Logger.CHAIN_END argument simply tells the log that it shouldn’t expect any more error messages related to this error, and to end the error chain. This can be left off the call to error without ill-effects.

Following this, the code will set the state of the node to failed, using the fail() method defined on the Node interface. The fail method returns a NodeFailedException which is then thrown by the code within the setup method.

Java node logging properties

The logging behavior of the Java node is governed by the following properties:

  • LogConfig node property
  • LogLevel node property
  • LogType - Logger API

LogLevel

In the LogLevel property of a Java node, you can select a numeric value to determine the threshold of severity for capturing logging events. Choose from:

  • 0 - Debug
  • 1 - Info
  • 2 - Warn
  • 3 - Error
  • 4 - Error

The default value is 2.

A logging event whose severity meets or exceeds the value specified in the LogLevel property will be logged. To increase the detail that is logged, select a lower value in the LogLevel property.

LogConfig

In general, you do not need to specify a value in the LogConfig property. The Java node log file creates an XML formatted log in the temp directory. The log level is set by the value of ls.brain.node.java.logLevel.

When the LogLevel property within the Java node is set, this sets the property ls.brain.node.java.logLevel. If you do not specify a value in the LogLevel property, the value is instead taken from the configuration files.

If you want to customize Java node logging, you can modify the LogConfig property. You can specify that multiple logs are to be used, each of which filters log events by LogLevel and/or ErrorCode or another user-defined logic supplied as a Java class. A log can also subscribe to events generated by another log. For example:

<logging>

<log name='JavaNode'><levelEnabled level='WARN'>

<subscribe log='root'/>

<log name='childLog'><levelEnabled level='ERROR'>

<appender layout='text’ file='c:/BRAINscratch/nodeErrors.txt'/>

</log>

</log>

</logging>

childLog subscribes to the pre-defined JavaNode log, but only logs errors while JavaNode logs warnings and errors. Its layout is raw text (rather than XML) and is written to the specified file.

LogType

By default, Java nodes use the Logger API for logging. Logger entries provide more information and are easier to read.

Logger example:

2010-11-23 16:18:46.742; WARN: Accepted connection from /127.0.0.1:55926javaDetail:com.lavastorm.Example.handleAccept(Example.java@386)