001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.management.mbean;
018    
019    import java.text.SimpleDateFormat;
020    import java.util.Date;
021    
022    import org.apache.camel.Exchange;
023    import org.apache.camel.api.management.ManagedResource;
024    import org.apache.camel.api.management.PerformanceCounter;
025    import org.apache.camel.api.management.mbean.ManagedPerformanceCounterMBean;
026    import org.apache.camel.spi.ManagementStrategy;
027    import org.apache.camel.util.ExchangeHelper;
028    
029    @ManagedResource(description = "PerformanceCounter")
030    public abstract class ManagedPerformanceCounter extends ManagedCounter implements PerformanceCounter, ManagedPerformanceCounterMBean {
031    
032        public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
033    
034        private Statistic exchangesCompleted;
035        private Statistic exchangesFailed;
036        private Statistic failuresHandled;
037        private Statistic redeliveries;
038        private Statistic externalRedeliveries;
039        private Statistic minProcessingTime;
040        private Statistic maxProcessingTime;
041        private Statistic totalProcessingTime;
042        private Statistic lastProcessingTime;
043        private Statistic meanProcessingTime;
044        private Statistic firstExchangeCompletedTimestamp;
045        private String firstExchangeCompletedExchangeId;
046        private Statistic firstExchangeFailureTimestamp;
047        private String firstExchangeFailureExchangeId;
048        private Statistic lastExchangeCompletedTimestamp;
049        private String lastExchangeCompletedExchangeId;
050        private Statistic lastExchangeFailureTimestamp;
051        private String lastExchangeFailureExchangeId;
052        private boolean statisticsEnabled = true;
053    
054        public void init(ManagementStrategy strategy) {
055            super.init(strategy);
056            this.exchangesCompleted = new Statistic("org.apache.camel.exchangesCompleted", this, Statistic.UpdateMode.COUNTER);
057            this.exchangesFailed = new Statistic("org.apache.camel.exchangesFailed", this, Statistic.UpdateMode.COUNTER);
058    
059            this.failuresHandled = new Statistic("org.apache.camel.failuresHandled", this, Statistic.UpdateMode.COUNTER);
060            this.redeliveries = new Statistic("org.apache.camel.redeliveries", this, Statistic.UpdateMode.COUNTER);
061            this.externalRedeliveries = new Statistic("org.apache.camel.externalRedeliveries", this, Statistic.UpdateMode.COUNTER);
062    
063            this.minProcessingTime = new Statistic("org.apache.camel.minimumProcessingTime", this, Statistic.UpdateMode.MINIMUM);
064            this.maxProcessingTime = new Statistic("org.apache.camel.maximumProcessingTime", this, Statistic.UpdateMode.MAXIMUM);
065            this.totalProcessingTime = new Statistic("org.apache.camel.totalProcessingTime", this, Statistic.UpdateMode.COUNTER);
066            this.lastProcessingTime = new Statistic("org.apache.camel.lastProcessingTime", this, Statistic.UpdateMode.VALUE);
067            this.meanProcessingTime = new Statistic("org.apache.camel.meanProcessingTime", this, Statistic.UpdateMode.VALUE);
068    
069            this.firstExchangeCompletedTimestamp = new Statistic("org.apache.camel.firstExchangeCompletedTimestamp", this, Statistic.UpdateMode.VALUE);
070            this.firstExchangeFailureTimestamp = new Statistic("org.apache.camel.firstExchangeFailureTimestamp", this, Statistic.UpdateMode.VALUE);
071            this.lastExchangeCompletedTimestamp = new Statistic("org.apache.camel.lastExchangeCompletedTimestamp", this, Statistic.UpdateMode.VALUE);
072            this.lastExchangeFailureTimestamp = new Statistic("org.apache.camel.lastExchangeFailureTimestamp", this, Statistic.UpdateMode.VALUE);
073        }
074    
075        @Override
076        public synchronized void reset() {
077            super.reset();
078            exchangesCompleted.reset();
079            exchangesFailed.reset();
080            failuresHandled.reset();
081            redeliveries.reset();
082            externalRedeliveries.reset();
083            minProcessingTime.reset();
084            maxProcessingTime.reset();
085            totalProcessingTime.reset();
086            lastProcessingTime.reset();
087            meanProcessingTime.reset();
088            firstExchangeCompletedTimestamp.reset();
089            firstExchangeCompletedExchangeId = null;
090            firstExchangeFailureTimestamp.reset();
091            firstExchangeFailureExchangeId = null;
092            lastExchangeCompletedTimestamp.reset();
093            lastExchangeCompletedExchangeId = null;
094            lastExchangeFailureTimestamp.reset();
095            lastExchangeFailureExchangeId = null;
096        }
097    
098        public long getExchangesCompleted() throws Exception {
099            return exchangesCompleted.getValue();
100        }
101    
102        public long getExchangesFailed() throws Exception {
103            return exchangesFailed.getValue();
104        }
105    
106        public long getFailuresHandled() throws Exception {
107            return failuresHandled.getValue();
108        }
109    
110        public long getRedeliveries() throws Exception {
111            return redeliveries.getValue();
112        }
113    
114        public long getExternalRedeliveries() throws Exception {
115            return externalRedeliveries.getValue();
116        }
117    
118        public long getMinProcessingTime() throws Exception {
119            return minProcessingTime.getValue();
120        }
121    
122        public long getMeanProcessingTime() throws Exception {
123            return meanProcessingTime.getValue();
124        }
125    
126        public long getMaxProcessingTime() throws Exception {
127            return maxProcessingTime.getValue();
128        }
129    
130        public long getTotalProcessingTime() throws Exception {
131            return totalProcessingTime.getValue();
132        }
133    
134        public long getLastProcessingTime() throws Exception {
135            return lastProcessingTime.getValue();
136        }
137    
138        public Date getLastExchangeCompletedTimestamp() {
139            long value = lastExchangeCompletedTimestamp.getValue();
140            return value > 0 ? new Date(value) : null;
141        }
142    
143        public String getLastExchangeCompletedExchangeId() {
144            return lastExchangeCompletedExchangeId;
145        }
146    
147        public Date getFirstExchangeCompletedTimestamp() {
148            long value = firstExchangeCompletedTimestamp.getValue();
149            return value > 0 ? new Date(value) : null;
150        }
151    
152        public String getFirstExchangeCompletedExchangeId() {
153            return firstExchangeCompletedExchangeId;
154        }
155    
156        public Date getLastExchangeFailureTimestamp() {
157            long value = lastExchangeFailureTimestamp.getValue();
158            return value > 0 ? new Date(value) : null;
159        }
160    
161        public String getLastExchangeFailureExchangeId() {
162            return lastExchangeFailureExchangeId;
163        }
164    
165        public Date getFirstExchangeFailureTimestamp() {
166            long value = firstExchangeFailureTimestamp.getValue();
167            return value > 0 ? new Date(value) : null;
168        }
169    
170        public String getFirstExchangeFailureExchangeId() {
171            return firstExchangeFailureExchangeId;
172        }
173    
174        public boolean isStatisticsEnabled() {
175            return statisticsEnabled;
176        }
177    
178        public void setStatisticsEnabled(boolean statisticsEnabled) {
179            this.statisticsEnabled = statisticsEnabled;
180        }
181    
182        public synchronized void completedExchange(Exchange exchange, long time) {
183            increment();
184            exchangesCompleted.increment();
185    
186            if (ExchangeHelper.isFailureHandled(exchange)) {
187                failuresHandled.increment();
188            }
189            Boolean externalRedelivered = exchange.isExternalRedelivered();
190            if (externalRedelivered != null && externalRedelivered) {
191                externalRedeliveries.increment();
192            }
193    
194            minProcessingTime.updateValue(time);
195            maxProcessingTime.updateValue(time);
196            totalProcessingTime.updateValue(time);
197            lastProcessingTime.updateValue(time);
198    
199            long now = new Date().getTime();
200            if (firstExchangeCompletedTimestamp.getUpdateCount() == 0) {
201                firstExchangeCompletedTimestamp.updateValue(now);
202            }
203    
204            lastExchangeCompletedTimestamp.updateValue(now);
205            if (firstExchangeCompletedExchangeId == null) {
206                firstExchangeCompletedExchangeId = exchange.getExchangeId();
207            }
208            lastExchangeCompletedExchangeId = exchange.getExchangeId();
209    
210            // update mean
211            long count = exchangesCompleted.getValue();
212            long mean = count > 0 ? totalProcessingTime.getValue() / count : 0;
213            meanProcessingTime.updateValue(mean);
214        }
215    
216        public synchronized void failedExchange(Exchange exchange) {
217            increment();
218            exchangesFailed.increment();
219    
220            if (ExchangeHelper.isRedelivered(exchange)) {
221                redeliveries.increment();
222            }
223            Boolean externalRedelivered = exchange.isExternalRedelivered();
224            if (externalRedelivered != null && externalRedelivered) {
225                externalRedeliveries.increment();
226            }
227    
228            long now = new Date().getTime();
229            if (firstExchangeFailureTimestamp.getUpdateCount() == 0) {
230                firstExchangeFailureTimestamp.updateValue(now);
231            }
232    
233            lastExchangeFailureTimestamp.updateValue(now);
234            if (firstExchangeFailureExchangeId == null) {
235                firstExchangeFailureExchangeId = exchange.getExchangeId();
236            }
237            lastExchangeFailureExchangeId = exchange.getExchangeId();
238        }
239    
240        public String dumpStatsAsXml(boolean fullStats) {
241            StringBuilder sb = new StringBuilder();
242            sb.append("<stats ");
243            sb.append(String.format("exchangesCompleted=\"%s\"", exchangesCompleted.getValue()));
244            sb.append(String.format(" exchangesFailed=\"%s\"", exchangesFailed.getValue()));
245            sb.append(String.format(" failuresHandled=\"%s\"", failuresHandled.getValue()));
246            sb.append(String.format(" redeliveries=\"%s\"", redeliveries.getValue()));
247            sb.append(String.format(" externalRedeliveries=\"%s\"", externalRedeliveries.getValue()));
248            sb.append(String.format(" minProcessingTime=\"%s\"", minProcessingTime.getValue()));
249            sb.append(String.format(" maxProcessingTime=\"%s\"", maxProcessingTime.getValue()));
250            sb.append(String.format(" totalProcessingTime=\"%s\"", totalProcessingTime.getValue()));
251            sb.append(String.format(" lastProcessingTime=\"%s\"", lastProcessingTime.getValue()));
252            sb.append(String.format(" meanProcessingTime=\"%s\"", meanProcessingTime.getValue()));
253    
254            if (fullStats) {
255                sb.append(String.format(" firstExchangeCompletedTimestamp=\"%s\"", dateAsString(firstExchangeCompletedTimestamp.getValue())));
256                sb.append(String.format(" firstExchangeCompletedExchangeId=\"%s\"", nullSafe(firstExchangeCompletedExchangeId)));
257                sb.append(String.format(" firstExchangeFailureTimestamp=\"%s\"", dateAsString(firstExchangeFailureTimestamp.getValue())));
258                sb.append(String.format(" firstExchangeFailureExchangeId=\"%s\"", nullSafe(firstExchangeFailureExchangeId)));
259                sb.append(String.format(" lastExchangeCompletedTimestamp=\"%s\"", dateAsString(lastExchangeCompletedTimestamp.getValue())));
260                sb.append(String.format(" lastExchangeCompletedExchangeId=\"%s\"", nullSafe(lastExchangeCompletedExchangeId)));
261                sb.append(String.format(" lastExchangeFailureTimestamp=\"%s\"", dateAsString(lastExchangeFailureTimestamp.getValue())));
262                sb.append(String.format(" lastExchangeFailureExchangeId=\"%s\"", nullSafe(lastExchangeFailureExchangeId)));
263            }
264            sb.append("/>");
265            return sb.toString();
266        }
267    
268        private static String dateAsString(long value) {
269            if (value == 0) {
270                return "";
271            }
272            return new SimpleDateFormat(TIMESTAMP_FORMAT).format(value);
273        }
274        
275        private static String nullSafe(String s) {
276            return s != null ? s : "";
277        }
278    
279    }