org.log4mongo.LoggingEventBsonifierImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.log4mongo.LoggingEventBsonifierImpl.java

Source

/*
 * Copyright (C) 2010 Robert Stewart (robert@wombatnation.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.log4mongo;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;
import org.bson.BSONObject;

import java.lang.management.ManagementFactory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Default implementation class for creating a BSON representation of a Log4J LoggingEvent.
 */
public class LoggingEventBsonifierImpl implements LoggingEventBsonifier {

    // Main log event elements
    private static final String KEY_TIMESTAMP = "timestamp";

    private static final String KEY_LEVEL = "level";

    private static final String KEY_THREAD = "thread";

    private static final String KEY_MESSAGE = "message";

    private static final String KEY_LOGGER_NAME = "loggerName";

    // Source code location
    private static final String KEY_FILE_NAME = "fileName";

    private static final String KEY_METHOD = "method";

    private static final String KEY_LINE_NUMBER = "lineNumber";

    private static final String KEY_CLASS = "class";

    // Class info
    private static final String KEY_FQCN = "fullyQualifiedClassName";

    private static final String KEY_PACKAGE = "package";

    private static final String KEY_CLASS_NAME = "className";

    // Exceptions
    private static final String KEY_THROWABLES = "throwables";

    private static final String KEY_EXCEPTION_MESSAGE = "message";

    private static final String KEY_STACK_TRACE = "stackTrace";

    // Host and Process Info
    private static final String KEY_HOST = "host";

    private static final String KEY_PROCESS = "process";

    private static final String KEY_HOSTNAME = "name";

    private static final String KEY_IP = "ip";

    // MDC Properties
    private static final String KEY_MDC_PROPERTIES = "properties";

    private final DBObject hostInfo = new BasicDBObject();

    public LoggingEventBsonifierImpl() {
        setupNetworkInfo();
    }

    private void setupNetworkInfo() {
        hostInfo.put(KEY_PROCESS, ManagementFactory.getRuntimeMXBean().getName());
        try {
            hostInfo.put(KEY_HOSTNAME, InetAddress.getLocalHost().getHostName());
            hostInfo.put(KEY_IP, InetAddress.getLocalHost().getHostAddress());
        } catch (UnknownHostException e) {
            LogLog.warn(e.getMessage());
        }
    }

    /**
     * BSONifies a single Log4J LoggingEvent object.
     *
     * @param loggingEvent
     *            The LoggingEvent object to BSONify <i>(may be null)</i>.
     *
     * @return The BSONified equivalent of the LoggingEvent object <i>(may be null)</i>.
     */
    public BSONObject bsonify(final LoggingEvent loggingEvent) {
        DBObject result = null;

        if (loggingEvent != null) {
            result = new BasicDBObject();

            result.put(KEY_TIMESTAMP, new Date(loggingEvent.getTimeStamp()));
            nullSafePut(result, KEY_LEVEL, loggingEvent.getLevel().toString());
            nullSafePut(result, KEY_THREAD, loggingEvent.getThreadName());
            nullSafePut(result, KEY_MESSAGE, loggingEvent.getRenderedMessage());
            nullSafePut(result, KEY_LOGGER_NAME, bsonifyClassName(loggingEvent.getLoggerName()));

            addMDCInformation(result, loggingEvent.getProperties());
            addLocationInformation(result, loggingEvent.getLocationInformation());
            addThrowableInformation(result, loggingEvent.getThrowableInformation());
            addHostnameInformation(result);
        }

        return (result);
    }

    /**
     * Adds MDC Properties to the DBObject.
     *
     * @param bson
     *            The root DBObject
     * @param props
     *            MDC Properties to be logged
     */
    protected void addMDCInformation(DBObject bson, final Map<Object, Object> props) {
        if (props != null && props.size() > 0) {

            BasicDBObject mdcProperties = new BasicDBObject();
            String key;
            // Copy MDC properties into document
            for (Map.Entry<Object, Object> entry : props.entrySet()) {
                key = (entry.getKey().toString().contains(".")) ? entry.getKey().toString().replaceAll("\\.", "_")
                        : entry.getKey().toString();
                nullSafePut(mdcProperties, key, entry.getValue().toString());
            }
            bson.put(KEY_MDC_PROPERTIES, mdcProperties);
        }
    }

    /**
     * Adds the LocationInfo object to an existing BSON object.
     *
     * @param bson
     *            The BSON object to add the location info to <i>(must not be null)</i>.
     * @param locationInfo
     *            The LocationInfo object to add to the BSON object <i>(may be null)</i>.
     */
    protected void addLocationInformation(DBObject bson, final LocationInfo locationInfo) {
        if (locationInfo != null) {
            nullSafePut(bson, KEY_FILE_NAME, locationInfo.getFileName());
            nullSafePut(bson, KEY_METHOD, locationInfo.getMethodName());
            nullSafePut(bson, KEY_LINE_NUMBER, locationInfo.getLineNumber());
            nullSafePut(bson, KEY_CLASS, bsonifyClassName(locationInfo.getClassName()));
        }
    }

    /**
     * Adds the ThrowableInformation object to an existing BSON object.
     *
     * @param bson
     *            The BSON object to add the throwable info to <i>(must not be null)</i>.
     * @param throwableInfo
     *            The ThrowableInformation object to add to the BSON object <i>(may be null)</i>.
     */
    @SuppressWarnings(value = "unchecked")
    protected void addThrowableInformation(DBObject bson, final ThrowableInformation throwableInfo) {
        if (throwableInfo != null) {
            Throwable currentThrowable = throwableInfo.getThrowable();
            List throwables = new BasicDBList();

            while (currentThrowable != null) {
                DBObject throwableBson = bsonifyThrowable(currentThrowable);

                if (throwableBson != null) {
                    throwables.add(throwableBson);
                }

                currentThrowable = currentThrowable.getCause();
            }

            if (throwables.size() > 0) {
                bson.put(KEY_THROWABLES, throwables);
            }
        }
    }

    /**
     * Adds the current process's host name, VM name and IP address
     *
     * @param bson
     *            A BSON object containing host name, VM name and IP address
     */
    protected void addHostnameInformation(DBObject bson) {
        nullSafePut(bson, KEY_HOST, hostInfo);
    }

    /**
     * BSONifies the given Throwable.
     *
     * @param throwable
     *            The throwable object to BSONify <i>(may be null)</i>.
     *
     * @return The BSONified equivalent of the Throwable object <i>(may be null)</i>.
     */
    protected DBObject bsonifyThrowable(final Throwable throwable) {
        DBObject result = null;

        if (throwable != null) {
            result = new BasicDBObject();

            nullSafePut(result, KEY_EXCEPTION_MESSAGE, throwable.getMessage());
            nullSafePut(result, KEY_STACK_TRACE, bsonifyStackTrace(throwable.getStackTrace()));
        }

        return (result);
    }

    /**
     * BSONifies the given stack trace.
     *
     * @param stackTrace
     *            The stack trace object to BSONify <i>(may be null)</i>.
     *
     * @return The BSONified equivalent of the stack trace object <i>(may be null)</i>.
     */
    protected DBObject bsonifyStackTrace(final StackTraceElement[] stackTrace) {
        BasicDBList result = null;

        if (stackTrace != null && stackTrace.length > 0) {
            result = new BasicDBList();

            for (StackTraceElement element : stackTrace) {
                DBObject bson = bsonifyStackTraceElement(element);

                if (bson != null) {
                    result.add(bson);
                }
            }
        }

        return (result);
    }

    /**
     * BSONifies the given stack trace element.
     *
     * @param element
     *            The stack trace element object to BSONify <i>(may be null)</i>.
     *
     * @return The BSONified equivalent of the stack trace element object <i>(may be null)</i>.
     */
    protected DBObject bsonifyStackTraceElement(final StackTraceElement element) {
        DBObject result = null;

        if (element != null) {
            result = new BasicDBObject();

            nullSafePut(result, KEY_FILE_NAME, element.getFileName());
            nullSafePut(result, KEY_METHOD, element.getMethodName());
            nullSafePut(result, KEY_LINE_NUMBER, element.getLineNumber());
            nullSafePut(result, KEY_CLASS, bsonifyClassName(element.getClassName()));
        }

        return (result);
    }

    /**
     * BSONifies the given class name.
     *
     * @param className
     *            The class name to BSONify <i>(may be null)</i>.
     *
     * @return The BSONified equivalent of the class name <i>(may be null)</i>.
     */
    @SuppressWarnings(value = "unchecked")
    protected DBObject bsonifyClassName(final String className) {
        DBObject result = null;

        if (className != null && className.trim().length() > 0) {
            result = new BasicDBObject();

            result.put(KEY_FQCN, className);

            List packageComponents = new BasicDBList();
            String[] packageAndClassName = className.split("\\.");

            packageComponents.addAll(Arrays.asList(packageAndClassName));
            // Requires Java 6
            // packageComponents.addAll(Arrays.asList(Arrays.copyOf(packageAndClassName,
            // packageAndClassName.length - 1)));

            if (packageComponents.size() > 0) {
                result.put(KEY_PACKAGE, packageComponents);
            }

            result.put(KEY_CLASS_NAME, packageAndClassName[packageAndClassName.length - 1]);
        }

        return (result);
    }

    /**
     * Adds the given value to the given key, except if it's null (in which case this method does
     * nothing).
     *
     * @param bson
     *            The BSON object to add the key/value to <i>(must not be null)</i>.
     * @param key
     *            The key of the object <i>(must not be null)</i>.
     * @param value
     *            The value of the object <i>(may be null)</i>.
     */
    protected void nullSafePut(DBObject bson, final String key, final Object value) {
        if (value != null) {
            if (value instanceof String) {
                String stringValue = (String) value;
                if (stringValue.trim().length() > 0) {
                    bson.put(key, stringValue);
                }
            } else if (value instanceof StringBuffer) {
                String stringValue = ((StringBuffer) value).toString();
                if (stringValue.trim().length() > 0) {
                    bson.put(key, stringValue);
                }
            } else {
                bson.put(key, value);
            }
        }
    }

}