1
2
3
4
5
6
7
8
9
10
11 package org.mule.management.stats;
12
13 import org.mule.api.MuleContext;
14 import org.mule.api.MuleSession;
15 import org.mule.api.construct.FlowConstruct;
16 import org.mule.util.concurrent.ThreadNameHelper;
17
18 import java.io.Serializable;
19 import java.lang.ref.ReferenceQueue;
20 import java.lang.ref.WeakReference;
21 import java.util.Map;
22
23 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
24 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicLong;
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27
28
29
30
31 public class ProcessingTime implements Serializable
32 {
33
34
35
36 private static final long serialVersionUID = 1L;
37
38 private static final Log logger = LogFactory.getLog(ProcessingTime.class);
39 private static volatile Thread referenceThread;
40 private static ReferenceQueue<ProcessingTime> queue = new ReferenceQueue<ProcessingTime>();
41 private static Map refs = new ConcurrentHashMap();
42
43 private AtomicLong accumulator = new AtomicLong();
44 private FlowConstructStatistics statistics;
45 private String threadName;
46
47
48
49
50
51 public static ProcessingTime newInstance(MuleSession session, MuleContext muleContext)
52 {
53 if (session != null)
54 {
55 FlowConstruct fc = session.getFlowConstruct();
56 if (fc != null)
57 {
58 FlowConstructStatistics stats = fc.getStatistics();
59 if (stats != null && fc.getStatistics().isEnabled())
60 {
61 return new ProcessingTime(stats, muleContext);
62 }
63 }
64
65 }
66
67 return null;
68 }
69
70
71
72
73
74
75 private ProcessingTime(FlowConstructStatistics stats, MuleContext muleContext)
76 {
77 this.statistics = stats;
78 this.threadName = String.format("%sprocessing.time.monitor", ThreadNameHelper.getPrefix(muleContext));
79 if (referenceThread == null)
80 {
81 startThread();
82 }
83 refs.put(new Reference(this), refs);
84 }
85
86
87
88
89
90 public void addFlowExecutionBranchTime(long startTime)
91 {
92 if (statistics.isEnabled())
93 {
94 long elapsedTime = getEffectiveTime(System.currentTimeMillis() - startTime);
95 statistics.addFlowExecutionBranchTime(elapsedTime, accumulator.addAndGet(elapsedTime));
96 }
97 }
98
99
100
101
102
103 public static long getEffectiveTime(long time)
104 {
105 return (time <= 0) ? 1L : time;
106 }
107
108
109
110
111 public void startThread()
112 {
113 synchronized (ProcessingTime.class)
114 {
115 if (referenceThread == null)
116 {
117 referenceThread = new Thread(new Runnable()
118 {
119
120
121
122 public void run()
123 {
124
125 try
126 {
127 while (true)
128 {
129 if (Thread.currentThread() != referenceThread)
130 {
131 break;
132 }
133 try
134 {
135
136
137
138 Object temp = queue.remove();
139 Reference ref = (Reference) temp;
140 refs.remove(ref);
141 FlowConstructStatistics stats = ref.getStatistics();
142 if (stats.isEnabled())
143 {
144 stats.addCompleteFlowExecutionTime(ref.getAccumulator().longValue());
145 }
146 }
147 catch (InterruptedException ex )
148 {
149 Thread.currentThread().interrupt();
150 break;
151 }
152 catch (Exception ex)
153 {
154
155 logger.error(this, ex);
156 }
157 }
158 }
159 finally
160 {
161 referenceThread = null;
162 }
163 }
164 }, this.threadName);
165 referenceThread.setDaemon(true);
166 referenceThread.start();
167 }
168 }
169 }
170
171
172
173
174 public synchronized static void stopTimer()
175 {
176 if (referenceThread != null)
177 {
178 referenceThread.interrupt();
179 referenceThread = null;
180 }
181 refs.clear();
182 }
183
184
185
186
187 static class Reference extends WeakReference<ProcessingTime>
188 {
189 private FlowConstructStatistics statistics;
190 private AtomicLong accumulator;
191
192 Reference(ProcessingTime time)
193 {
194 super(time, queue);
195 this.statistics = time.statistics;
196 this.accumulator = time.accumulator;
197 }
198
199 public AtomicLong getAccumulator()
200 {
201 return accumulator;
202 }
203
204 public FlowConstructStatistics getStatistics()
205 {
206 return statistics;
207 }
208 }
209 }