mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-01-20 09:17:29 +07:00
Created StringMap class to manage thread context
Created StringMap class to manage thread context StringMap is ordered and optimized for my use-case Engineered compact encoding mode to track thread context
This commit is contained in:
parent
60d50fa15d
commit
d9232b3593
@ -1,20 +1,18 @@
|
||||
package com.riiablo.logger;
|
||||
|
||||
import org.apache.commons.collections4.map.UnmodifiableOrderedMap;
|
||||
|
||||
import com.riiablo.logger.message.Message;
|
||||
|
||||
public class LogEvent {
|
||||
private final Level level;
|
||||
private final Message message;
|
||||
private final StackTraceElement source;
|
||||
private final UnmodifiableOrderedMap<String, String> mdc;
|
||||
private final StringMap mdc;
|
||||
|
||||
LogEvent(
|
||||
Level level,
|
||||
Message message,
|
||||
StackTraceElement source,
|
||||
UnmodifiableOrderedMap<String, String> mdc) {
|
||||
StringMap mdc) {
|
||||
this.level = level;
|
||||
this.message = message;
|
||||
this.source = source;
|
||||
@ -33,7 +31,7 @@ public class LogEvent {
|
||||
return source;
|
||||
}
|
||||
|
||||
public UnmodifiableOrderedMap<String, String> mdc() {
|
||||
public StringMap mdc() {
|
||||
return mdc;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,13 @@
|
||||
package com.riiablo.logger;
|
||||
|
||||
import org.apache.commons.collections4.OrderedMap;
|
||||
import org.apache.commons.collections4.map.ListOrderedMap;
|
||||
import org.apache.commons.collections4.map.UnmodifiableOrderedMap;
|
||||
|
||||
public class MDC {
|
||||
private MDC() {}
|
||||
|
||||
private static final ThreadLocal<OrderedMap<String, String>> threadLocal
|
||||
= new ThreadLocal<OrderedMap<String, String>>() {
|
||||
private static final ThreadLocal<StringMap> threadLocal
|
||||
= new ThreadLocal<StringMap>() {
|
||||
@Override
|
||||
protected OrderedMap<String, String> initialValue() {
|
||||
return new ListOrderedMap<>(); // TODO: copy on write map
|
||||
protected StringMap initialValue() {
|
||||
return new StringMap();
|
||||
}
|
||||
};
|
||||
|
||||
@ -39,8 +35,7 @@ public class MDC {
|
||||
return threadLocal.get().size();
|
||||
}
|
||||
|
||||
public static UnmodifiableOrderedMap<String, String> freeze() {
|
||||
return (UnmodifiableOrderedMap<String,String>)
|
||||
UnmodifiableOrderedMap.unmodifiableOrderedMap(threadLocal.get());
|
||||
public static StringMap freeze() {
|
||||
return threadLocal.get().freeze();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.riiablo.logger;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import org.apache.commons.collections4.OrderedMap;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
|
||||
@ -12,8 +11,9 @@ public class RiiabloEncoder extends SimpleEncoder {
|
||||
|
||||
private final StringBuilder buffer = new StringBuilder(1024);
|
||||
|
||||
private Thread context;
|
||||
private boolean fullMode;
|
||||
private OrderedMap<String, String> mdc;
|
||||
private StringMap mdc;
|
||||
private int depth;
|
||||
|
||||
public boolean isFullMode() {
|
||||
@ -43,22 +43,28 @@ public class RiiabloEncoder extends SimpleEncoder {
|
||||
}
|
||||
|
||||
private void encodeFullMode(LogEvent event, StringBuilder buffer) {
|
||||
final OrderedMap<String, String> mdc = event.mdc();
|
||||
final StringMap mdc = event.mdc();
|
||||
encodeMessage(event, buffer);
|
||||
encodeFullMDC(mdc, buffer);
|
||||
}
|
||||
|
||||
private void encodeFullMDC(OrderedMap<String, String> mdc, StringBuilder buffer) {
|
||||
private void encodeFullMDC(StringMap mdc, StringBuilder buffer) {
|
||||
if (mdc.isEmpty()) return;
|
||||
buffer.append(' ');
|
||||
buffer.append(mdc.toString());
|
||||
}
|
||||
|
||||
private void encodeCompactMode(LogEvent event, StringBuilder buffer) {
|
||||
final OrderedMap<String, String> mdc = event.mdc();
|
||||
final StringMap mdc = event.mdc();
|
||||
final int depth = mdc.size();
|
||||
if (depth > 0) {
|
||||
if (!mdc.equals(this.mdc) || this.depth != depth) {
|
||||
final Thread currentThread = Thread.currentThread();
|
||||
if (context != currentThread) {
|
||||
context = currentThread;
|
||||
this.depth = 0;
|
||||
}
|
||||
|
||||
if (!mdc.equals(this.mdc)) {
|
||||
encodeCompactMDC(mdc, buffer, depth);
|
||||
this.mdc = mdc;
|
||||
this.depth = depth;
|
||||
@ -70,9 +76,14 @@ public class RiiabloEncoder extends SimpleEncoder {
|
||||
encodeMessage(event, buffer);
|
||||
}
|
||||
|
||||
private void encodeCompactMDC(OrderedMap<String, String> mdc, StringBuilder buffer, int depth) {
|
||||
buffer.append(spaces, 0, (depth - 1) * DEPTH_STEP);
|
||||
encodeFullMDC(mdc, buffer);
|
||||
buffer.append(lineSeparator);
|
||||
private void encodeCompactMDC(StringMap mdc, StringBuilder buffer, int depth) {
|
||||
for (int d = this.depth; d < depth; d++) {
|
||||
buffer.append(spaces, 0, d * DEPTH_STEP);
|
||||
buffer.append(' ');
|
||||
buffer.append('{');
|
||||
mdc.appendEntry(d, buffer);
|
||||
buffer.append('}');
|
||||
buffer.append(lineSeparator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
239
core/src/com/riiablo/logger/StringMap.java
Normal file
239
core/src/com/riiablo/logger/StringMap.java
Normal file
@ -0,0 +1,239 @@
|
||||
package com.riiablo.logger;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import com.badlogic.gdx.utils.ObjectIntMap;
|
||||
|
||||
public class StringMap {
|
||||
private static final int DEFAULT_CAPACITY = 4;
|
||||
private final ObjectIntMap<String> indexes;
|
||||
private String[] keys;
|
||||
private String[] vals;
|
||||
private int size;
|
||||
|
||||
private boolean immutable;
|
||||
private StringMap immutableCopy;
|
||||
private String toString;
|
||||
|
||||
public StringMap() {
|
||||
keys = ArrayUtils.EMPTY_STRING_ARRAY;
|
||||
vals = ArrayUtils.EMPTY_STRING_ARRAY;
|
||||
indexes = new ObjectIntMap<>(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
private StringMap(StringMap other) {
|
||||
assert other.keys.length == other.vals.length;
|
||||
assert other.size == other.indexes.size;
|
||||
size = other.size;
|
||||
keys = Arrays.copyOf(other.keys, size);
|
||||
vals = Arrays.copyOf(other.vals, size);
|
||||
indexes = new ObjectIntMap<>(other.indexes);
|
||||
immutable = true;
|
||||
}
|
||||
|
||||
private void inflateTable(final int size) {
|
||||
assert !immutable;
|
||||
assert this.size == 0;
|
||||
keys = new String[size];
|
||||
vals = new String[size];
|
||||
}
|
||||
|
||||
private void ensureCapacity(final int size) {
|
||||
assert !immutable;
|
||||
assert keys.length == vals.length;
|
||||
if (size >= this.size) {
|
||||
final int resize = Math.max(this.size * 2, DEFAULT_CAPACITY);
|
||||
assert resize > size;
|
||||
keys = Arrays.copyOf(keys, resize);
|
||||
vals = Arrays.copyOf(vals, resize);
|
||||
}
|
||||
}
|
||||
|
||||
private void assertMutable() {
|
||||
if (immutable) {
|
||||
throw new UnsupportedOperationException("StringMap has been frozen.");
|
||||
}
|
||||
}
|
||||
|
||||
public void put(String key, String value) {
|
||||
assertMutable();
|
||||
if (immutableCopy != null) {
|
||||
immutableCopy = null;
|
||||
}
|
||||
|
||||
assert keys.length == vals.length;
|
||||
if (keys.length == 0) {
|
||||
inflateTable(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
assert keys != null && vals != null;
|
||||
final int index = indexes.get(key, -1);
|
||||
if (index >= 0) {
|
||||
vals[index] = value;
|
||||
} else {
|
||||
ensureCapacity(size + 1);
|
||||
keys[size] = key;
|
||||
vals[size] = value;
|
||||
indexes.put(key, size);
|
||||
size++;
|
||||
}
|
||||
assert size == indexes.size;
|
||||
assert size > 0;
|
||||
}
|
||||
|
||||
public String get(String key) {
|
||||
assert keys.length == vals.length;
|
||||
if (keys.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int index = indexes.get(key, -1);
|
||||
return index >= 0 ? vals[index] : null;
|
||||
}
|
||||
|
||||
public void remove(String key) {
|
||||
assertMutable();
|
||||
if (immutableCopy != null) {
|
||||
immutableCopy = null;
|
||||
}
|
||||
|
||||
assert keys.length == vals.length;
|
||||
if (keys.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int index = indexes.get(key, -1);
|
||||
if (index < 0) return;
|
||||
System.arraycopy(keys, index + 1, keys, index, size - index - 1);
|
||||
System.arraycopy(vals, index + 1, vals, index, size - index - 1);
|
||||
keys[size] = vals[size] = null;
|
||||
indexes.remove(key, -1);
|
||||
size--;
|
||||
assert size == indexes.size;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
assert keys != null || keys == vals;
|
||||
if (keys == null) {
|
||||
assert size == 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Arrays.fill(keys, null);
|
||||
Arrays.fill(vals, null);
|
||||
indexes.clear();
|
||||
size = 0;
|
||||
assert size == indexes.size;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
assert size == indexes.size;
|
||||
return size;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
assert size == indexes.size;
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
public StringMap freeze() {
|
||||
if (immutableCopy == null) {
|
||||
return immutableCopy = new StringMap(this);
|
||||
} else {
|
||||
return immutableCopy;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (toString == null) {
|
||||
StringBuilder buffer = new StringBuilder(256);
|
||||
buffer.append('{');
|
||||
for (int i = 0, s = size; i < s; i++) {
|
||||
appendEntry(i, buffer).append(',');
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
buffer.setLength(buffer.length() - 1);
|
||||
}
|
||||
|
||||
buffer.append('}');
|
||||
toString = buffer.toString();
|
||||
}
|
||||
|
||||
return toString;
|
||||
}
|
||||
|
||||
StringBuilder appendEntry(int index, StringBuilder buffer) {
|
||||
assert index >= 0 && index < size;
|
||||
return buffer.append(keys[index]).append('=').append(vals[index]);
|
||||
}
|
||||
|
||||
private void assertImmutable() {
|
||||
if (!immutable) {
|
||||
throw new UnsupportedOperationException("StringMap has not been frozen.");
|
||||
}
|
||||
}
|
||||
|
||||
public StringMapIterator iterator() {
|
||||
return iterator(0);
|
||||
}
|
||||
|
||||
public StringMapIterator iterator(int startIndex) {
|
||||
if (startIndex < 0) {
|
||||
throw new IllegalArgumentException("startIndex(" + startIndex + ") < " + 0);
|
||||
}
|
||||
assertImmutable();
|
||||
return new StringMapIterator(startIndex);
|
||||
}
|
||||
|
||||
public class StringMapIterator implements Iterator<Entry> {
|
||||
final Entry entry = new Entry();
|
||||
int index;
|
||||
|
||||
StringMapIterator(int index) {
|
||||
assert immutable;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry next() {
|
||||
entry.key = keys[index];
|
||||
entry.value = vals[index];
|
||||
index++;
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Entry {
|
||||
String key;
|
||||
String value;
|
||||
|
||||
Entry() {}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return key + "=" + value;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user