001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021package org.nuxeo.ecm.core.management.events; 022 023import java.util.Collections; 024import java.util.Map; 025import java.util.Map.Entry; 026import java.util.concurrent.ConcurrentHashMap; 027 028import org.nuxeo.ecm.core.event.impl.EventListenerDescriptor; 029 030/** 031 * Helper class to store statistics about listeners calls. 032 * 033 * @author Thierry Delprat 034 */ 035public class EventStatsHolder { 036 037 protected static boolean collectAsyncHandlersExecTime = false; 038 039 protected static boolean collectSyncHandlersExecTime = false; 040 041 protected static Map<String, CallStat> syncStats = new ConcurrentHashMap<>(); 042 043 protected static Map<String, CallStat> aSyncStats = new ConcurrentHashMap<>(); 044 045 private EventStatsHolder() { 046 } 047 048 public static boolean isCollectAsyncHandlersExecTime() { 049 return collectAsyncHandlersExecTime; 050 } 051 052 public static void setCollectAsyncHandlersExecTime(boolean collectAsyncHandlersExecTime) { 053 EventStatsHolder.collectAsyncHandlersExecTime = collectAsyncHandlersExecTime; 054 } 055 056 public static boolean isCollectSyncHandlersExecTime() { 057 return collectSyncHandlersExecTime; 058 } 059 060 public static void setCollectSyncHandlersExecTime(boolean collectSyncHandlersExecTime) { 061 EventStatsHolder.collectSyncHandlersExecTime = collectSyncHandlersExecTime; 062 } 063 064 /** 065 * @since 5.6 066 */ 067 public static void clearStats() { 068 syncStats.clear(); 069 aSyncStats.clear(); 070 } 071 072 public static void logAsyncExec(EventListenerDescriptor desc, long delta) { 073 if (!collectAsyncHandlersExecTime) { 074 return; 075 } 076 String name = desc.getName(); 077 synchronized (aSyncStats) { 078 CallStat stat = aSyncStats.get(name); 079 if (stat == null) { 080 String label = desc.asPostCommitListener().getClass().getSimpleName(); 081 if (desc.getIsAsync()) { 082 label += "(async)"; 083 } else { 084 label += "(sync)"; 085 } 086 stat = new CallStat(label); 087 aSyncStats.put(name, stat); 088 } 089 stat.update(delta); 090 } 091 } 092 093 public static void logSyncExec(EventListenerDescriptor desc, long delta) { 094 if (!collectSyncHandlersExecTime) { 095 return; 096 } 097 String name = desc.getName(); 098 syncStats.computeIfAbsent(name, k -> new CallStat(desc.asEventListener().getClass().getSimpleName())) 099 .update(delta); 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 long totalTime = 0; 126 for (CallStat stat : stats.values()) { 127 totalTime += stat.getAccumulatedTime(); 128 } 129 if (totalTime == 0) { 130 totalTime = 1; 131 } 132 StringBuilder sb = new StringBuilder(); 133 for (Entry<String, CallStat> en : stats.entrySet()) { 134 String name = en.getKey(); 135 CallStat stat = en.getValue(); 136 sb.append(name); 137 sb.append(" - "); 138 sb.append(stat.getLabel()); 139 sb.append(" - "); 140 sb.append(stat.getCallCount()); 141 sb.append(" calls - "); 142 sb.append(stat.getAccumulatedTime()); 143 sb.append("ms - "); 144 String pcent = String.format("%.2f", 100.0 * stat.getAccumulatedTime() / totalTime); 145 sb.append(pcent); 146 sb.append("%\n"); 147 } 148 return sb.toString(); 149 } 150 151 public static void resetHandlersExecTime() { 152 clearStats(); 153 } 154 155}