Java (im_java)

This module provides support for processing NXLog Agent log data with methods written in the Java language. The Java classes specified via the ClassPath directives may define one or more class methods which can be called from the Run or Exec directives of this module. Such methods must be declared with the public and static modifiers in the Java code to be accessible from NXLog Agent, and the first parameter must be of NXLog.Logdata type. See also the om_java and xm_java modules.

For the system requirements, installation details and environmental configuration requirements of Java, see the Installing Java section in the Java documentation.

The NXLog Java class provides access to the NXLog Agent functionality in the Java code. This class contains nested classes Logdata and Module with log processing methods, as well as methods for sending messages to the internal logger.

To have access to log processing methods, the public static method should accept an NXLog.Logdata or NXLog.Module object as a parameter.

class NXLog.Logdata

This Java class provides the methods to interact with an NXLog Agent event record object:

getField(name)

This method returns the value of the field name in the event.

setField(name, value)

This method sets the value of field name to value.

deleteField(name)

This method removes the field name from the event record.

getFieldnames()

This method returns an array with the names of all the fields currently in the event record.

getFieldtype(name)

This method retrieves the field type using the value from the name field.

post(module)

This method will submit the LogData event to NXLog Agent for processing by the next module in the route.

class NXLog.Module

The methods below allow setting and accessing variables associated with the module instance.

logdataNew()

This method returns a new NXLog.Logdata object.

setReadTimer(delay)

This method sets a trigger for another read after a specified delay in milliseconds.

saveCtx(key,value)

This method saves user data in the module data storage using values from the key and value fields.

loadCtx(key)

This method retrieves data from the module data storage using the value from the key field.

Below is the list of methods for sending messages to the internal logger.

NXLog.logInfo(msg)

This method sends the message msg to the internal logger at INFO log level. It does the same as the core log_info() procedure.

NXLog.logDebug(msg)

This method sends the message msg to the internal logger at DEBUG log level. It does the same as the core log_debug()procedure.

NXLog.logWarning(msg)

This method sends the message msg to the internal logger at WARNING log level. It does the same as the core log_warning() procedure.

NXLog.logError(msg)

This method sends the message msg to the internal logger at ERROR log level. It does the same as the core log_error() procedure.

Configuration

The NXLog Agent process maintains only one JVM instance for all im_java, om_java, or xm_java running instances. This means all Java classes loaded by the ClassPath directive will be available for all running instances.

The im_java module accepts the following directives in addition to the common module directives.

Required directives

The following directives are required for the module to start.

ClassPath

This mandatory directive defines the path to the .class files or a .jar file. This directive should be defined at least once within a module block.

Run

This mandatory directive specifies the static method inside the Classpath file which should be called.

Optional directives

JavaHome

This optional directive defines the path to the Java Runtime Environment (JRE). The path is used to search for the libjvm shared library. If this directive is not defined, the Java home directory will be set to the build-time value. Only one JRE can be defined for one or multiple NXLog Java instances. Defining multiple JRE instances causes an error.

VMOption

This optional directive defines a single Java Virtual Machine (JVM) option.

VMOptions

This optional block directive serves the same purpose as the VMOption directive, but also allows specifying multiple Java Virtual Machine (JVM) instances, one per line.

Example of Usage

Example 1. Using the im_java module for processing logs

This example parses the input, keeps only the entries that belong to the PATH type, and generates log records line-by-line. Using NXLog Agent facilities, these entries are divided into key-value pairs and converted to JSON format.

The doInput method of the Input Java class is used to run the processing.

Below is the NXLog Agent configuration.

nxlog.conf
<Input javain>
    Module        im_java
    # Path to the compiled class
    Classpath     Input.jar
    # Static method which will be called by the im_java module
    Run           Input.doInput
    # Path to Java Runtime
    #JavaHome      /usr/lib/jvm/java-11-openjdk-amd64
</Input>

<Output javaout>
    Module        om_file
    File          "/tmp/output.txt"
    <Exec>
        kvp->parse_kvp();
	      delete($EventReceivedTime);
        delete($SourceModuleName);
        delete($SourceModuleType);
        to_json();
    </Exec>
</Output>

Below is the Java class with comments.

Input.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Input {

    static String fileName = "/tmp/input.txt";
    static File file = Paths.get(fileName).toFile();
    static List<String> lines = null;
    static int currrent = 0;

    // This is a static method called by the Run directive in nxlog.conf
    // The NXLog.Module is a mandatory parameter
    static public void doInput(NXLog.Module module) {

        if (lines == null)
        {
            lines = new ArrayList<>();

            try(BufferedReader br = new BufferedReader(new FileReader(file))) {
                for(String line; (line = br.readLine()) != null; ) {
		    // Checks whether the entry belongs to the `PATH` type
		    if(line.contains("type=PATH")){
                    	lines.add(line);
		    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (currrent >= lines.size()) {
            return;
        }
        // Creats a new logdata record
        NXLog.Logdata ld = module.logdataNew();
        // Sets the $raw_event
        ld.setField("raw_event", lines.get(currrent));
        currrent ++;
        // Passes the record instance for further processing by other instances
        ld.post(module);
        // Scheduling the next read call
        module.setReadTimer(1);
    }
}

Below are the log samples before and after processing.

Input Sample
type=CWD msg=audit(1489999368.711:35724):  cwd="/root/nxlog"

type=PATH msg=audit(1489999368.711:35724): item=0 name="/root/test" inode=528869 dev=08:01 mode=040755 ouid=0 ogid=0 rdev=00:00

type=SYSCALL msg=audit(1489999368.711:35725): arch=c000003e syscall=2 success=yes exit=3 a0=12dcc40 a1=90800 a2=0 a3=0 items=1 ppid=15391 pid=12309 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts4 ses=583 comm="ls" exe="/bin/ls" key=(null)
Output Sample
{
  "type":"PATH",
  "msg":"audit(1489999368.711:35724):",
  "item":0,"name":"/root/test",
  "inode":528869,"dev":"08:01",
  "mode":040755,"ouid":0,
  "ogid":0,
  "rdev":"00:00"
}