package org.simpleframework.demo.trace;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.channels.SelectableChannel;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.log4j.Logger;
import org.simpleframework.common.thread.Daemon;
import org.simpleframework.transport.trace.TraceAnalyzer;
import org.simpleframework.transport.trace.Trace;
public class LogAnalyzer extends Daemon implements TraceAnalyzer {
private static final Logger LOG = Logger.getLogger(LogAnalyzer.class);
private final Queue<TraceRecord> queue;
private final AtomicLong count;
private final String filter;
public LogAnalyzer() {
this(null);
}
public LogAnalyzer(String filter) {
this.queue = new ConcurrentLinkedQueue<TraceRecord>();
this.count = new AtomicLong();
this.filter = filter;
}
@Override
public Trace attach(SelectableChannel channel) {
return new TraceFeeder(channel);
}
public void run() {
try {
while(isActive()) {
Thread.sleep(1000);
while(!queue.isEmpty()) {
TraceRecord record = queue.poll();
if(filter != null) {
Object event = record.event;
Class type = event.getClass();
String name = type.getName();
if(name.contains(filter)) {
LOG.info(record);
}
} else {
LOG.info(record);
}
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
private class TraceFeeder implements Trace {
private final SelectableChannel channel;
private final long sequence;
public TraceFeeder(SelectableChannel channel) {
this.sequence = count.getAndIncrement();
this.channel = channel;
}
@Override
public void trace(Object event) {
trace(event, null);
}
@Override
public void trace(Object event, Object value) {
TraceRecord record = new TraceRecord(channel, event, value, sequence);
if(isActive()) {
queue.offer(record);
}
}
}
private class TraceRecord {
private final SelectableChannel channel;
private final String thread;
private final Object event;
private final Object value;
private final long sequence;
public TraceRecord(SelectableChannel channel, Object event, Object value, long sequence) {
this.thread = Thread.currentThread().getName();
this.sequence = sequence;
this.channel = channel;
this.event = event;
this.value = value;
}
public String toString() {
StringWriter builder = new StringWriter();
PrintWriter writer = new PrintWriter(builder);
writer.print(sequence);
writer.print(" [");
writer.print(channel);
writer.print("]");
writer.print(" ");
writer.print(thread);
writer.print(": ");
writer.print(event);
if(value != null) {
if(value instanceof Throwable) {
writer.print(" -> ");
((Throwable)value).printStackTrace(writer);
} else {
writer.print(" -> ");
writer.print(value);
}
}
writer.close();
return builder.toString();
}
}
}