/*
* Copyright 2007-2011 Brian S O'Neill
*
* 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 org.cojen.dirmi.trace;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* TraceHandler which prints method trace information to standard out.
*
* @author Brian S O'Neill
*/
public class SimpleHandler extends ScopedTraceHandler {
private static Constructor cDateTimeCtor;
static {
try {
cDateTimeCtor = Class.forName("org.joda.time.DateTime").getConstructor(long.class);
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
}
}
private static volatile SimpleHandler cHandler;
/**
* Call to set an arbitrary message into the currently traced scope.
*/
public static void setMessage(String message) {
SimpleHandler handler = cHandler;
if (handler != null) {
handler.scopePut("message", message);
}
}
private static String formatDate(long millis) {
if (cDateTimeCtor != null) {
try {
return cDateTimeCtor.newInstance(millis).toString();
} catch (Exception e) {
cDateTimeCtor = null;
}
}
return new Date(millis).toString();
}
public SimpleHandler(TraceToolbox toolbox) {
super(toolbox);
cHandler = this;
}
protected void report(Scope scope) {
List<MethodData> mdList = scope.getMethodData();
StringBuilder b = new StringBuilder(500);
b.append(">>> BEGIN TRACE\n");
MethodData root = mdList.get(0);
TracedMethod rootMethod = root.getTracedMethod();
if (rootMethod.getOperation() != null) {
b.append("operation: ").append(rootMethod.getOperation()).append('\n');
} else {
b.append("operation: ").append(rootMethod).append('\n');
}
b.append("start: ").append(formatDate(scope.getStartTimeMillis())).append('\n');
b.append("thread: ").append(scope.getThread()).append('\n');
Object message = scope.getExtraData().get("message");
if (message != null) {
b.append("message: ").append(message).append('\n');
}
if (scope.getArguments() != null) {
b.append("args: ").append(Arrays.deepToString(scope.getArguments())).append('\n');
}
if (scope.hasResult()) {
b.append("result: ").append(scope.getResult()).append('\n');
}
if (scope.getException() != null) {
b.append("exception: ").append(scope.getException()).append('\n');
}
b.append("details...").append('\n');
for (MethodData md : mdList) {
b.append(" ").append(md.getTracedMethod()).append('\n');
int calls = md.getCallCount();
long time = md.getTotalTimeNanos();
b.append(" invocations: ").append(calls).append('\n');
if (md.hasTotalTimeNanos()) {
b.append(" total time: ").append(time).append("ns\n");
double dTime = time;
if (calls == 1) {
b.append(" average time: ").append(time).append("ns\n");
} else {
double average = dTime / calls;
b.append(" average time: ").append(average).append("ns\n");
}
if (time == root.getTotalTimeNanos()) {
b.append(" percent time: 100\n");
} else {
double percent = 100.0 * (dTime / root.getTotalTimeNanos());
b.append(" percent time: ").append(percent).append('\n');
}
}
}
b.append("<<< END TRACE");
System.out.println(b);
}
}