All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kdgregory.logback.aws.JsonLayout Maven / Gradle / Ivy

There is a newer version: 3.2.1
Show newest version
// Copyright (c) Keith D Gregory
//
// 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 com.kdgregory.logback.aws;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.kdgregory.logback.aws.internal.AbstractJsonLayout;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;


/**
 *  Formats an ILoggingEvent as a JSON string. This supports Elasticsearch
 *  without the need for Logstash (as well as any other JSON-consuming endpoint).
 *  

* The JSON object will always contain the following properties: *

    *
  • timestamp: the date/time that the message was logged. *
  • thread: the name of the thread where the message was logged. *
  • logger: the name of the logger. *
  • level: the level of this log message. *
  • message: the message itself. *
  • hostname: the name of the machine where the logger is running, if * available (this is currently retrieved from * RuntimeMxBean and may not be available on * all platforms). *
  • processId: the PID of the invoking process, if available (this is * retrieved from RuntimeMxBean and may not be * available on all platforms). *
*

* The following properties will only appear if they are present in the event: *

    *
  • exception: an exception with stack trace. This is an array, with the * first element identifying the exception and message, and * subsequent elements identifying the stack trace. *
  • mdc: the mapped diagnostic context. This is a child object. *
*

* The following properties are potentially expensive to compute, so will only * appear if specifically enabled via configuration: *

    *
  • locationInfo: the location where the logger was invoked. This is a * child object with the following components: *
      *
    • className *
    • methodName *
    • fileName *
    • lineNumber *
    *
  • instanceId: the EC2 instance ID of the machine where the logger is * running. WARNING: do not enable this elsewhere, as the * operation to retrieve this value may take a long time. *
*

* Lastly, you can define a set of user tags, which are written as a child object with * the key tags. These are intended to provide program-level information, * in the case where multiple programs send their logs to the same stream. They are set * as a single comma-separate string, which may contain substitution values (example: * appName=Fribble,startedAt={startupTimestamp}). *

* WARNING: you should not rely on the order in which elements are output. Any apparent * ordering is an implementation artifact and subject to change without notice. */ public class JsonLayout extends AbstractJsonLayout { //---------------------------------------------------------------------------- // Configuration //---------------------------------------------------------------------------- private boolean enableLocation; public void setEnableLocation(boolean value) { enableLocation = value; } public boolean getEnableLocation() { return enableLocation; } //---------------------------------------------------------------------------- // Layout Overrides //---------------------------------------------------------------------------- @Override public String doLayout(ILoggingEvent event) { Map map = new TreeMap(); map.put("timestamp", new Date(event.getTimeStamp())); map.put("thread", event.getThreadName()); map.put("logger", event.getLoggerName()); map.put("level", event.getLevel().toString()); map.put("message", event.getFormattedMessage()); List exceptionInfo = extractExceptionInfo(event); if (exceptionInfo != null) { map.put("exception", exceptionInfo); } if ((event.getMDCPropertyMap() != null) && ! event.getMDCPropertyMap().isEmpty()) { map.put("mdc", event.getMDCPropertyMap()); } if (enableLocation) { StackTraceElement[] callerData = event.getCallerData(); if ((callerData != null) && (event.getCallerData().length > 0)) { StackTraceElement info = callerData[0]; Map location = new TreeMap(); location.put("className", info.getClassName()); location.put("methodName", info.getMethodName()); location.put("fileName", info.getFileName()); location.put("lineNumber", info.getLineNumber()); map.put("locationInfo", location); } } return addCommonAttributesAndConvert(map); } /** * Extracts the exception information from an event, returning either null * or a list of strings. */ private static List extractExceptionInfo(ILoggingEvent event) { return (event.getThrowableProxy() == null) ? null : appendThrowable(new ArrayList(), event.getThrowableProxy()); } /** * Appends exception info from the current throwable to the passed list, * including its cause. */ private static List appendThrowable(List entries, IThrowableProxy throwable) { String optCausedBy = entries.isEmpty() ? "" : "Caused by: "; String initialLine = optCausedBy + throwable.getClassName() + ": " + throwable.getMessage(); entries.add(initialLine); for (StackTraceElementProxy ste : throwable.getStackTraceElementProxyArray()) { entries.add(ste.getSTEAsString()); } return (throwable.getCause() == null) ? entries : appendThrowable(entries, throwable.getCause()); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy