Created
March 14, 2018 13:52
-
-
Save aerobless/e81c9e0de7f2bb1ed4d99897af16fa29 to your computer and use it in GitHub Desktop.
Fluent Key Value Log Fromatter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LogEntry { | |
private LogKey key; | |
private String value; | |
public LogEntry(LogKey key, String value) { | |
this.key = key; | |
this.value = value; | |
} | |
public LogKey getKey() { | |
return key; | |
} | |
public String getValue() { | |
return value; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import java.util.ArrayList; | |
import java.util.List; | |
import java.util.Optional; | |
import java.util.stream.Collectors; | |
import LogKey.customKey; | |
/** | |
* LogFormatter is used to fluidly write a log statement containing key=value entries. | |
* E.g. "This is a sample, someValue=123, otherThing=HelloWorld" | |
* <p> | |
* A LogFormatter chain should always be ended either by .build() to get the string value or by | |
* .logInfo(), .logError() etc. so that the log statement is written with the specified log level. | |
*/ | |
public class LogFormatter { | |
private String description = ""; | |
private List<LogEntry> logEntries = new ArrayList<>(); | |
/** | |
* Please use newLog() instead. | |
* | |
* @return new LogFormatter | |
*/ | |
@Deprecated | |
public static LogFormatter newLogStatement() { | |
return newLog(); | |
} | |
/** | |
* Creates a new LogFormatter. | |
* | |
* @return new LogFormatter | |
*/ | |
public static LogFormatter newLog() { | |
return new LogFormatter(); | |
} | |
/** | |
* Creates a new LogFormatter. | |
* | |
* @param description a human readable description | |
* @return new LogFormatter | |
*/ | |
public static LogFormatter newLog(String description) { | |
final LogFormatter logFormatter = new LogFormatter(); | |
return logFormatter.description(description); | |
} | |
/** | |
* Creates a new LogFormatter. | |
* | |
* @param description a human readable description. Can contain {} which will be replaced by args | |
* @param args arguments are used to replace {} in the description. Args are nullsafe, if null is provided "null" is logged. | |
* @return new LogFormatter | |
*/ | |
public static LogFormatter newLog(String description, Object... args) { | |
final LogFormatter logFormatter = new LogFormatter(); | |
return logFormatter.description(description, args); | |
} | |
/** | |
* Adds a human readable description. The description may contain {} which will be replaced by the provided args. | |
* Be sure to also add any values with .add(key, value). | |
* | |
* @param description a human readable description. Can contain {} which will be replaced by args | |
* @return the provided LogFormatter which can be used for further chaining | |
*/ | |
public LogFormatter description(String description) { | |
this.description = description + ", "; | |
return this; | |
} | |
/** | |
* Adds a human readable description. The description may contain {} which will be replaced by the provided args. | |
* Be sure to also add any values with .add(key, value). | |
* | |
* @param description a human readable description. Can contain {} which will be replaced by args | |
* @param args arguments are used to replace {} in the description. Args are nullsafe, if null is provided "null" is logged. | |
* @return the provided LogFormatter which can be used for further chaining | |
*/ | |
public LogFormatter description(String description, Object... args) { | |
String replacedDescription = description; | |
Object[] arguments = args; | |
if (arguments == null) { | |
arguments = new Object[]{null}; | |
} | |
for (Object argument : arguments) { | |
replacedDescription = replacedDescription.replaceFirst("\\{}", nullSafeToString(argument)); | |
} | |
return description(replacedDescription); | |
} | |
/** | |
* Adds a key value pair. The log will contain "key=value, ". | |
* | |
* @param key a LogKey or String | |
* @param value an Object. Value is nullsafe, if null is provided "null" is logged. | |
* @return the provided LogFormatter which can be used for further chaining | |
*/ | |
public LogFormatter add(LogKey key, Object value) { | |
logEntries.add(new LogEntry(key, nullSafeToString(value))); | |
return this; | |
} | |
/** | |
* Adds a key value pair. The log will contain "key=value, ". | |
* | |
* @param key a LogKey or String | |
* @param value an Object. Value is nullsafe, if null is provided "null" is logged. | |
* @return the provided LogFormatter which can be used for further chaining | |
*/ | |
public LogFormatter add(String key, Object value) { | |
return add(customKey(key), value); | |
} | |
/** | |
* Ends the LogFormatter chain and returns the log statement as a string. | |
* | |
* @return the log statement as a string | |
*/ | |
public String build() { | |
return description + logEntries.stream() | |
.map(entry -> entry.getKey().toString() + "=" + entry.getValue()) | |
.collect(Collectors.joining(", ")); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level info. | |
*/ | |
public void logInfo() { | |
getLoggerForCallerClass().info(build()); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level warn. | |
*/ | |
public void logWarn() { | |
getLoggerForCallerClass().warn(build()); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level warn. | |
* | |
* @param throwable a throwable | |
*/ | |
public void logWarn(Throwable throwable) { | |
getLoggerForCallerClass().warn(build(), throwable); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level error. | |
*/ | |
public void logError() { | |
getLoggerForCallerClass().error(build()); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level error. | |
* | |
* @param throwable a throwable | |
*/ | |
public void logError(Throwable throwable) { | |
getLoggerForCallerClass().error(build(), throwable); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level trace. | |
*/ | |
public void logTrace() { | |
getLoggerForCallerClass().trace(build()); | |
} | |
/** | |
* Ends the LogFormatter chain and logs the statement with level debug. | |
*/ | |
public void logDebug() { | |
getLoggerForCallerClass().debug(build()); | |
} | |
//https://stackoverflow.com/questions/421280/how-do-i-find-the-caller-of-a-method-using-stacktrace-or-reflection | |
private Logger getLoggerForCallerClass() { | |
StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); | |
return LoggerFactory.getLogger(stackTraceElements[3].getClassName()); | |
} | |
private String nullSafeToString(Object value) { | |
return Optional.ofNullable(value).orElse("null").toString(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class LogKey { | |
//DATE | |
public static final LogKey VALID_FROM = new LogKey("validFrom"); | |
public static final LogKey VALID_TO = new LogKey("validTo"); | |
//EVENTS | |
public static final LogKey EVENT_AGE = new LogKey("eventAge"); | |
public static final LogKey EVENT_TYPE = new LogKey("eventType"); | |
public static final LogKey EVENT_LOCAL_ID = new LogKey("eventLocalId"); | |
public static final LogKey CALL_TIMEOUT = new LogKey("callTimeout"); | |
//JOBS | |
public static final LogKey JOB_NAME = new LogKey("jobName"); | |
public static final LogKey JOB_STATE = new LogKey("jobState"); | |
//Basic Logging | |
public static final LogKey DESCRIPTION = new LogKey("description"); | |
//REST / Networking | |
public static final LogKey CORRELATION_ID = new LogKey("cid"); | |
public static final LogKey ORIGIN_APPLICATION_ID = new LogKey("originApplicationId"); | |
public static final LogKey REQUEST_COUNT = new LogKey("requestCount"); | |
//... others | |
private String keyName; | |
private LogKey(String keyName) { | |
this.keyName = keyName.replace(" ", ""); | |
} | |
public static LogKey customKey(String keyName) { | |
return new LogKey(keyName); | |
} | |
@Override | |
public String toString() { | |
return keyName; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment