All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.extendj.Trace Maven / Gradle / Ivy

/* Copyright (c) 2016, Jesper Öqvist 
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package org.extendj;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.zip.DeflaterOutputStream;

/**
 * General purpose event tracing framework.
 *
 * 

Events are logged by pushEvent() and popEvent(). The resulting trace * can be sent via a socket to a profiling tool. */ public class Trace { private long start; // Start of time scale in nanoseconds. private static final int TRACE_FORMAT_VERSION = 2; // Version 2: switched child count from int to short. public Stack events = new Stack(); public static class Event { public String name; public final long start; public final String metadata; public long end; public List children = new ArrayList(); public Event(String name, long start) { this(name, start, ""); } public Event(String name, long start, String metadata) { this.name = name; this.start = start; this.metadata = metadata; } } public Trace(String name) { start = System.nanoTime(); Date timestamp = new Date(); events.push(new Event(String.format("%s %tF %tT", name, timestamp, timestamp), System.nanoTime())); } /** * Sets the start time, in nanoseconds. */ public void setStart(long start) { this.start = start; } /** * Adds a new event to the trace. * The new event should be popped by a later call to popEvent(). */ public void pushEvent(String name) { pushEvent(name, ""); } /** * Adds a new event to the trace. * The new event should be popped by a later call to popEvent(). */ public void pushEvent(String name, String metadata) { Event event = new Event(name, System.nanoTime(), metadata); events.peek().children.add(event); events.push(event); } /** * Pop the current event from the trace stack and update the end time. */ public void popEvent() { events.pop().end = System.nanoTime(); } /** * Write trace to file. * Log all collected trace information. * @param prefix the prefix to give the trace files */ public void dumpTrace(String prefix) { if (events.size() != 1) { System.err.format("Warning: tracing event stack has unexpected size %d. " + "Only the top event will be reported.%n", events.size()); } int suffix = 0; File dest; Date timestamp = new Date(); String filename = String.format("%s.%tF.trace", prefix, timestamp); do { dest = new File(filename); suffix += 1; filename = String.format("%s.%tF.%d.trace", prefix, new java.util.Date(), suffix); } while (dest.exists()); try { System.err.format("Writing trace to %s%n", dest.getAbsolutePath()); writeTrace(new DataOutputStream(new DeflaterOutputStream(new FileOutputStream(dest))), start); } catch (IOException ignored) { } } private void writeTrace(OutputStream output, long t0) throws IOException { DataOutputStream out = new DataOutputStream(output); out.writeInt(-TRACE_FORMAT_VERSION); Event root = events.peek(); root.end = System.nanoTime(); Set eventNames = getEventNames(root); Map nameMap = new HashMap(); out.writeInt(eventNames.size()); int id = 0; for (String name : eventNames) { nameMap.put(name, id++); out.writeUTF(name); } writeEvent(out, root, nameMap, t0); out.close(); } private static void writeEvent(DataOutputStream out, Event event, Map nameMap, long t0) throws IOException { out.writeInt(nameMap.get(event.name)); out.writeUTF(event.metadata); out.writeLong(event.start - t0); out.writeLong(event.end - t0); if (event.children.size() > Short.MAX_VALUE) { throw new Error(String.format("Event has too many children to serialize (%d)!", event.children.size())); } out.writeShort(event.children.size()); for (Event child : event.children) { writeEvent(out, child, nameMap, t0); } } private static Set getEventNames(Event root) { Set names = new HashSet(); Queue queue = new LinkedList(); queue.add(root); while (!queue.isEmpty()) { Event event = queue.poll(); names.add(event.name); queue.addAll(event.children); } return names; } public void sendTo(String host, int port) throws IOException { System.err.format("Sending trace to: %s:%d%n", host, port); Socket socket = new Socket(host, port); writeTrace(socket.getOutputStream(), start); //socket.close(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy