001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     Nuxeo - initial API and implementation
011 *
012 * $Id$
013 */
014package org.nuxeo.ecm.core.management.events;
015
016import java.util.Collections;
017import java.util.HashMap;
018import java.util.Map;
019
020import org.nuxeo.ecm.core.event.impl.EventListenerDescriptor;
021
022/**
023 * Helper class to store statistics about listeners calls.
024 *
025 * @author Thierry Delprat
026 */
027public class EventStatsHolder {
028
029    protected static boolean collectAsyncHandlersExecTime = false;
030
031    protected static boolean collectSyncHandlersExecTime = false;
032
033    protected static Map<String, CallStat> syncStats = new HashMap<String, CallStat>();
034
035    protected static Map<String, CallStat> aSyncStats = new HashMap<String, CallStat>();
036
037    private EventStatsHolder() {
038    }
039
040    public static boolean isCollectAsyncHandlersExecTime() {
041        return collectAsyncHandlersExecTime;
042    }
043
044    public static void setCollectAsyncHandlersExecTime(boolean collectAsyncHandlersExecTime) {
045        EventStatsHolder.collectAsyncHandlersExecTime = collectAsyncHandlersExecTime;
046    }
047
048    public static boolean isCollectSyncHandlersExecTime() {
049        return collectSyncHandlersExecTime;
050    }
051
052    public static void setCollectSyncHandlersExecTime(boolean collectSyncHandlersExecTime) {
053        EventStatsHolder.collectSyncHandlersExecTime = collectSyncHandlersExecTime;
054    }
055
056    /**
057     * @since 5.6
058     */
059    public static void clearStats() {
060        synchronized (aSyncStats) {
061            EventStatsHolder.aSyncStats.clear();
062        }
063    }
064
065    public static void logAsyncExec(EventListenerDescriptor desc, long delta) {
066        if (!collectAsyncHandlersExecTime) {
067            return;
068        }
069        String name = desc.getName();
070        synchronized (aSyncStats) {
071            CallStat stat = aSyncStats.get(name);
072            if (stat == null) {
073                String label = desc.asPostCommitListener().getClass().getSimpleName();
074                if (desc.getIsAsync()) {
075                    label += "(async)";
076                } else {
077                    label += "(sync)";
078                }
079                stat = new CallStat(label);
080                aSyncStats.put(name, stat);
081            }
082            stat.update(delta);
083        }
084    }
085
086    public static void logSyncExec(EventListenerDescriptor desc, long delta) {
087        if (!collectSyncHandlersExecTime) {
088            return;
089        }
090        String name = desc.getName();
091        synchronized (syncStats) {
092            CallStat stat = syncStats.get(name);
093            if (stat == null) {
094                String label = desc.asEventListener().getClass().getSimpleName();
095                stat = new CallStat(label);
096                syncStats.put(name, stat);
097            }
098            stat.update(delta);
099        }
100    }
101
102    public static String getAsyncHandlersExecTime() {
103        return getStringSummary(aSyncStats);
104    }
105
106    /**
107     * @since 5.6
108     */
109    public static Map<String, CallStat> getAsyncHandlersCallStats() {
110        return Collections.unmodifiableMap(aSyncStats);
111    }
112
113    public static String getSyncHandlersExecTime() {
114        return getStringSummary(syncStats);
115    }
116
117    /**
118     * @since 5.6
119     */
120    public static Map<String, CallStat> getSyncHandlersCallStats() {
121        return Collections.unmodifiableMap(syncStats);
122    }
123
124    protected static String getStringSummary(Map<String, CallStat> stats) {
125        StringBuffer sb = new StringBuffer();
126        synchronized (stats) {
127
128            long totalTime = 0;
129            for (String name : stats.keySet()) {
130                totalTime += stats.get(name).getAccumulatedTime();
131            }
132
133            for (String name : stats.keySet()) {
134                CallStat stat = stats.get(name);
135                sb.append(name);
136                sb.append(" - ");
137                sb.append(stat.getLabel());
138                sb.append(" - ");
139                sb.append(stat.getCallCount());
140                sb.append(" calls - ");
141                sb.append(stat.getAccumulatedTime());
142                sb.append("ms - ");
143                String pcent = String.format("%.2f", 100.0 * stat.getAccumulatedTime() / totalTime);
144                sb.append(pcent);
145                sb.append("%\n");
146            }
147        }
148        return sb.toString();
149    }
150
151    public static void resetHandlersExecTime() {
152        synchronized (syncStats) {
153            syncStats = new HashMap<String, CallStat>();
154        }
155        synchronized (aSyncStats) {
156            aSyncStats = new HashMap<String, CallStat>();
157        }
158    }
159
160}