Package org.erlide.runtime.rpc

Source Code of org.erlide.runtime.rpc.RpcMonitor$RpcData

package org.erlide.runtime.rpc;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.erlide.util.ErlLogger;
import org.erlide.util.erlang.OtpErlang;

import com.ericsson.otp.erlang.OtpErlangAtom;
import com.ericsson.otp.erlang.OtpErlangObject;
import com.ericsson.otp.erlang.OtpErlangRef;
import com.ericsson.otp.erlang.OtpNode;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class RpcMonitor {
    private static final boolean DISABLED = System.getProperty("erlide.rpcmonitor") == null;
    private static final int COUNT = Integer.parseInt(System.getProperty(
            "erlide.rpcmonitor.count", "50"));
    private static final boolean FULL = System.getProperty("erlide.rpcmonitor.full") != null;

    private static class RpcData {
        public final long startTime;
        public final String node;
        public final String module;
        public final String fun;
        public final SoftReference<Collection<OtpErlangObject>> args;
        public final long size;

        public RpcData(final long startTime, final String node, final String module,
                final String fun, final OtpErlangObject[] args, final long size) {
            this.startTime = startTime;
            this.node = node;
            this.module = module;
            this.fun = fun;
            this.args = new SoftReference<Collection<OtpErlangObject>>(
                    Collections.unmodifiableCollection(Lists.newArrayList(args)));
            this.size = size;
        }
    }

    private static class RpcInfo {
        public final String node;
        public final String module;
        public final String fun;
        public final SoftReference<Collection<OtpErlangObject>> args;
        public final long callSize;
        public final SoftReference<OtpErlangObject> result;
        public final long answerSize;
        public final long callTime;
        public final long answerTime;
        private final int argsSize;

        public RpcInfo(final RpcData data, final OtpErlangObject result,
                final long answerTime) {
            node = data.node;
            module = data.module;
            fun = data.fun;
            args = data.args;
            final Collection<OtpErlangObject> collection = args.get();
            argsSize = collection == null ? 0 : collection.size();
            this.result = new SoftReference<OtpErlangObject>(result);
            callTime = data.startTime;
            this.answerTime = answerTime;
            callSize = data.size;
            answerSize = OtpErlang.sizeOf(result);
        }

        public void dump(final PrintStream out, final boolean full) {
            Collection<OtpErlangObject> myArgs = args.get();
            myArgs = myArgs == null ? new ArrayList<OtpErlangObject>() : myArgs;
            final String argsString = full ? args.toString().replaceAll("\n|\r", " ")
                    : "...";
            OtpErlangObject val = result.get();
            val = val == null ? new OtpErlangAtom("null") : val;
            String resultString = full ? val.toString().replaceAll("\n|\r", " ") : "...";
            if (resultString.length() > 100) {
                resultString = new String(resultString.substring(0, 99) + "...");
            }
            out.format(
                    "%30s|%25s:%-20s/%d in=%9d, out=%9d, t=%6d, args=%s -> result=%s%n",
                    node.substring(0, Math.min(29, node.length() - 1)), module, fun,
                    argsSize, callSize, answerSize, answerTime - callTime, argsString,
                    resultString);
        }
    }

    private static int callCount = 0;
    private static final Map<OtpErlangRef, RpcData> ongoing = Maps.newHashMap();
    private static Comparator<RpcInfo> timeComparator = new Comparator<RpcInfo>() {
        @Override
        public int compare(final RpcInfo o1, final RpcInfo o2) {
            return (int) (o2.answerTime - o2.callTime - (o1.answerTime - o1.callTime));
        }
    };
    private static Comparator<RpcInfo> sizeComparator = new Comparator<RpcInfo>() {
        @Override
        public int compare(final RpcInfo o1, final RpcInfo o2) {
            return (int) (o2.callSize + o2.answerSize - (o1.callSize + o1.answerSize));
        }
    };
    private static final List<RpcInfo> slowest = Lists.newLinkedList();
    private static final List<RpcInfo> largest = Lists.newLinkedList();

    public static synchronized void recordResponse(final OtpErlangRef ref,
            final OtpErlangObject result) {
        if (DISABLED) {
            return;
        }
        final RpcData data = ongoing.remove(ref);
        final long now = System.currentTimeMillis();
        final RpcInfo info = new RpcInfo(data, result, now);
        add(largest, sizeComparator, info);
        add(slowest, timeComparator, info);
    }

    private static void add(final List<RpcInfo> list,
            final Comparator<RpcInfo> comparator, final RpcInfo info) {
        final int index = Collections.binarySearch(list, info, comparator);
        if (index < 0) {
            // Add the non-existent item to the list
            list.add(-index - 1, info);
        } else {
            list.add(index, info);
        }
        if (list.size() > COUNT) {
            list.remove(list.size() - 1);
        }
    }

    public static OtpErlangRef recordRequest(final OtpNode node, final String peer,
            final String module, final String fun, final OtpErlangObject[] args,
            final long callSize) {
        callCount++;
        if (DISABLED) {
            return null;
        }
        final RpcData data = new RpcData(System.currentTimeMillis(), peer, module, fun,
                args, callSize);
        final OtpErlangRef ref = node.createRef();
        ongoing.put(ref, data);
        return ref;
    }

    public static void dump() {
        dump(System.out, COUNT, FULL);
    }

    public static void dump(final String file) {
        dump(file, COUNT, FULL);
    }

    public static void dump(final String file, final int n) {
        dump(file, n, FULL);
    }

    public static void dump(final String file, final boolean full) {
        dump(file, COUNT, full);
    }

    public static void dump(final String fileName, final int n, final boolean full) {
        try {
            dump(new PrintStream(fileName), n, full);
        } catch (final FileNotFoundException e) {
            ErlLogger.error(e);
        }
    }

    public static synchronized void dump(final PrintStream out, final int n,
            final boolean full) {
        out.format("*** RpcMonitor statistics%n - %d calls%n", callCount);
        if (DISABLED) {
            out.println("\nRpcMonitor was not enabled.\n\nUse -Derlide.rpcmonitor to enable it.");
            return;
        }
        final String delim = "----------------------------------------------------------------------------------------";
        out.println(delim);
        out.println();
        out.format("Slowest %d calls%n", slowest.size());
        out.println(delim);
        for (final RpcInfo info : slowest) {
            info.dump(out, full);
        }
        out.println(delim);
        out.println();
        out.format("Largest %d calls%n", largest.size());
        out.println(delim);
        for (final RpcInfo info : largest) {
            if (info != null) {
                info.dump(out, full);
            }
        }
        out.println(delim);
        out.close();
    }

    public static void cleanupOldLogs(final String dirName, final String prefix) {
        final File dir = new File(dirName);
        for (final File f : dir.listFiles()) {
            final long now = System.currentTimeMillis();
            final int aWeek = 7 * 24 * 3600 * 1000;
            if (f.getName().startsWith(prefix) && now - f.lastModified() > aWeek) {
                f.delete();
            }
        }
    }

}
TOP

Related Classes of org.erlide.runtime.rpc.RpcMonitor$RpcData

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.