Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.nextop.log.LogEntry Maven / Gradle / Ivy
package io.nextop.log;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import io.nextop.WireValue;
import javax.annotation.Nullable;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
// log call to be written upstream
// this is the foundation of network logging in nextop
public final class LogEntry {
/////// FACTORIES ///////
/* these correspond to message types in {@link Log} */
public static LogEntry count(Level level, String key, long d) {
return new LogEntry(Type.COUNT, level, key, d,
null, null, null);
}
public static LogEntry metric(Level level, String key, long value, Log.Unit unit) {
return new LogEntry(Type.METRIC, level, key, value, unit,
null, null);
}
public static LogEntry message(Level level, String key, @Nullable String message) {
return new LogEntry(Type.MESSAGE, level, key,
0L, null,
message,
null);
}
public static LogEntry handled(Level level, String key, Throwable t, @Nullable String message) {
return new LogEntry(Type.HANDLED, level, key,
0L, null,
message,
LogThrowable.valueOf(t));
}
public static LogEntry unhandled(Level level, String key, Throwable t, @Nullable String message) {
return new LogEntry(Type.UNHANDLED, level, key,
0L, null,
message,
LogThrowable.valueOf(t));
}
/////// SERIALIZATION ///////
private static final int S_VERSION = 1;
private static final String S_KEY_VERSION = "version";
private static final String S_KEY_TYPE = "type";
private static final String S_KEY_LEVEL = "level";
private static final String S_KEY_KEY = "key";
private static final String S_KEY_VALUE = "value";
private static final String S_KEY_UNIT = "unit";
private static final String S_KEY_MESSAGE = "message";
private static final String S_KEY_THROWABLE = "throwable";
private static final String S_THROWABLE_KEY_CLASS_NAME = "className";
private static final String S_THROWABLE_KEY_MESSAGE = "message";
private static final String S_THROWABLE_KEY_STACK_TRACE = "stackTrace";
private static final String S_THROWABLE_KEY_CAUSE = "cause";
private static final String S_TRACE_CLASS_NAME = "className";
private static final String S_TRACE_FILE_NAME = "fileName";
private static final String S_TRACE_LINE_NUMBER = "lineNumber";
private static final String S_TRACE_METHOD_NAME = "methodName";
public static WireValue toWireValue(LogEntry entry) {
Map map = new HashMap(32);
map.put(S_KEY_VERSION, S_VERSION);
// v1
map.put(S_KEY_TYPE, entry.type.toString());
map.put(S_KEY_LEVEL, entry.level.getName());
map.put(S_KEY_KEY, entry.key);
switch (entry.type) {
case COUNT:
case METRIC:
map.put(S_KEY_VALUE, entry.value);
break;
default:
// no value
break;
}
switch (entry.type) {
case METRIC:
map.put(S_KEY_UNIT, entry.unit.toString());
break;
default:
// no unit
break;
}
if (null != entry.message) {
map.put(S_KEY_MESSAGE, entry.message);
}
if (null != entry.t) {
map.put(S_KEY_THROWABLE, throwableToWireValue(entry.t));
}
return WireValue.of(map);
}
public static LogEntry fromWireValue(WireValue value) {
Map map = value.asMap();
int version = map.get(S_KEY_VERSION).asInt();
switch (version) {
default:
// from the future
// attempt to parse it as the last known version
// (if fails, the parsing will error out)
if (version < S_VERSION) {
throw new IllegalArgumentException();
} // else fall through
case 1:
Type type = Type.valueOf(map.get(S_KEY_TYPE).asString());
Level level = Level.parse(map.get(S_KEY_LEVEL).asString());
String key = map.get(S_KEY_KEY).asString();
long v;
if (map.containsKey(S_KEY_VALUE)) {
v = map.get(S_KEY_VALUE).asLong();
} else {
v = 0L;
}
@Nullable Log.Unit unit;
if (map.containsKey(S_KEY_UNIT)) {
unit = Log.Unit.valueOf(map.get(S_KEY_UNIT).asString());
} else {
unit = null;
}
@Nullable String message;
if (map.containsKey(S_KEY_MESSAGE)) {
message = map.get(S_KEY_MESSAGE).asString();
} else {
message = null;
}
@Nullable LogThrowable t;
if (map.containsKey(S_KEY_THROWABLE)) {
t = throwableFromWireValue(map.get(S_KEY_THROWABLE), version);
} else {
t = null;
}
return new LogEntry(type, level, key, v, unit, message, t);
}
}
private static WireValue throwableToWireValue(LogThrowable t) {
// version is pinned to containing log entry (see #toWireValue)
Map map = new HashMap(8);
map.put(S_THROWABLE_KEY_CLASS_NAME, t.className);
if (null != t.message) {
map.put(S_THROWABLE_KEY_MESSAGE, t.message);
}
map.put(S_THROWABLE_KEY_STACK_TRACE, stackTraceToWireValue(t.stackTrace));
if (null != t.cause) {
map.put(S_THROWABLE_KEY_CAUSE, throwableToWireValue(t.cause));
}
return WireValue.of(map);
}
private static LogThrowable throwableFromWireValue(WireValue value, int version) {
switch (version) {
default:
// see notes in #fromWireValue
if (version < S_VERSION) {
throw new IllegalArgumentException();
} // else fall through
case 1:
Map map = value.asMap();
String className = map.get(S_THROWABLE_KEY_CLASS_NAME).asString();
@Nullable String message;
if (map.containsKey(S_THROWABLE_KEY_MESSAGE)) {
message = map.get(S_THROWABLE_KEY_MESSAGE).asString();
} else {
message = null;
}
ImmutableList stackTrace = ImmutableList.copyOf(
stackTraceFromWireValue(map.get(S_THROWABLE_KEY_STACK_TRACE), version));
@Nullable LogThrowable cause;
if (map.containsKey(S_THROWABLE_KEY_CAUSE)) {
cause = throwableFromWireValue(map.get(S_THROWABLE_KEY_CAUSE), version);
} else {
cause = null;
}
return new LogThrowable(className, message, stackTrace, cause);
}
}
private static WireValue stackTraceToWireValue(List stackTrace) {
return WireValue.of(Lists.transform(stackTrace, new Function() {
@Override
public WireValue apply(@Nullable StackTraceElement input) {
return stackTraceElementToWireValue(input);
}
}));
}
private static WireValue stackTraceElementToWireValue(StackTraceElement stackTraceElement) {
// version is pinned to containing log entry (see #toWireValue)
Map map = new HashMap(8);
map.put(S_TRACE_CLASS_NAME, stackTraceElement.getClassName());
map.put(S_TRACE_FILE_NAME, stackTraceElement.getFileName());
map.put(S_TRACE_LINE_NUMBER, stackTraceElement.getLineNumber());
map.put(S_TRACE_METHOD_NAME, stackTraceElement.getMethodName());
return WireValue.of(map);
}
private static List stackTraceFromWireValue(WireValue value, final int version) {
switch (version) {
default:
// see notes in #fromWireValue
if (version < S_VERSION) {
throw new IllegalArgumentException();
} // else fall through
case 1:
return Lists.transform(value.asList(), new Function() {
@Override
public StackTraceElement apply(@Nullable WireValue input) {
return stackTraceElementFromWireValue(input, version);
}
});
}
}
private static StackTraceElement stackTraceElementFromWireValue(WireValue value, int version) {
switch (version) {
default:
// see notes in #fromWireValue
if (version < S_VERSION) {
throw new IllegalArgumentException();
} // else fall through
case 1:
Map map = value.asMap();
String className = map.get(S_TRACE_CLASS_NAME).asString();
String fileName = map.get(S_TRACE_FILE_NAME).asString();
int lineNumber = map.get(S_TRACE_LINE_NUMBER).asInt();
String methodName = map.get(S_TRACE_METHOD_NAME).asString();
return new StackTraceElement(className, methodName, fileName, lineNumber);
}
}
//
public static enum Type {
COUNT,
METRIC,
MESSAGE,
HANDLED,
UNHANDLED
}
public final Type type;
public final Level level;
public final String key;
public final long value;
@Nullable
public final Log.Unit unit;
@Nullable
public final String message;
@Nullable
public final LogThrowable t;
LogEntry(Type type, Level level, String key, long value, @Nullable Log.Unit unit, @Nullable String message, @Nullable LogThrowable t) {
this.type = type;
this.level = level;
this.key = key;
this.value = value;
this.unit = unit;
this.message = message;
this.t = t;
}
public void writeTo(Log log) {
switch (type) {
case COUNT:
log.count(level, key, value);
break;
case METRIC:
log.metric(level, key, value, unit);
break;
case MESSAGE:
log.message(level, key, message);
break;
case HANDLED:
log.handled(level, key, t.toThrowable(), message);
break;
case UNHANDLED:
log.unhandled(level, key, t.toThrowable(), message);
break;
default:
throw new IllegalStateException();
}
}
public static final class LogThrowable {
public static LogThrowable valueOf(Throwable t) {
@Nullable LogThrowable cause;
if (null != t.getCause()) {
cause = valueOf(t.getCause());
} else {
cause = null;
}
return new LogThrowable(t.getClass().getCanonicalName(), t.getMessage(),
ImmutableList.copyOf(t.getStackTrace()), cause);
}
public final String className;
@Nullable
public final String message;
public final ImmutableList stackTrace;
@Nullable
public final LogThrowable cause;
LogThrowable(String className, @Nullable String message, ImmutableList stackTrace, @Nullable LogThrowable cause) {
this.className = className;
this.message = message;
this.stackTrace = stackTrace;
this.cause = cause;
}
public Throwable toThrowable() {
Throwable t = _toThrowable();
t.setStackTrace(stackTrace.toArray(new StackTraceElement[stackTrace.size()]));
return t;
}
private Throwable _toThrowable() {
Throwable ct;
if (null != cause) {
ct = cause.toThrowable();
} else {
ct = null;
}
try {
Class extends Throwable> clazz = (Class extends Throwable>) Class.forName(className);
try {
Constructor extends Throwable> c = clazz.getConstructor(String.class, Throwable.class);
return c.newInstance(message, ct);
} catch (NoSuchMethodException e) {
if (null == message && null == ct) {
Constructor extends Throwable> c = clazz.getConstructor();
return c.newInstance();
} else if (null == message) {
Constructor extends Throwable> c = clazz.getConstructor(Throwable.class);
return c.newInstance(ct);
} else if (null == ct) {
Constructor extends Throwable> c = clazz.getConstructor(String.class);
return c.newInstance(message);
} else {
// no compatible constructor
return new LogThrowableMissingImplementation(className, message, ct);
}
}
} catch (Exception e) {
return new LogThrowableMissingImplementation(className, message, ct);
}
}
}
public static final class LogThrowableMissingImplementation extends Throwable {
private final String className;
private final String message;
public LogThrowableMissingImplementation(String className, @Nullable String message, @Nullable Throwable cause) {
super(concat(className, message), cause);
this.className = className;
this.message = message;
}
private static String concat(String className, @Nullable String message) {
String prefix = String.format("Missing \"%s\"", className);
if (null != message) {
return String.format("%s: %s", prefix, message);
} else {
return message;
}
}
}
}