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 = "Managed 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 deltaProcessingTime;
044        private Statistic meanProcessingTime;
045        private Statistic firstExchangeCompletedTimestamp;
046        private String firstExchangeCompletedExchangeId;
047        private Statistic firstExchangeFailureTimestamp;
048        private String firstExchangeFailureExchangeId;
049        private Statistic lastExchangeCompletedTimestamp;
050        private String lastExchangeCompletedExchangeId;
051        private Statistic lastExchangeFailureTimestamp;
052        private String lastExchangeFailureExchangeId;
053        private boolean statisticsEnabled = true;
054    
055        public void init(ManagementStrategy strategy) {
056            super.init(strategy);
057            this.exchangesCompleted = new Statistic("org.apache.camel.exchangesCompleted", this, Statistic.UpdateMode.COUNTER);
058            this.exchangesFailed = new Statistic("org.apache.camel.exchangesFailed", this, Statistic.UpdateMode.COUNTER);
059    
060            this.failuresHandled = new Statistic("org.apache.camel.failuresHandled", this, Statistic.UpdateMode.COUNTER);
061            this.redeliveries = new Statistic("org.apache.camel.redeliveries", this, Statistic.UpdateMode.COUNTER);
062            this.externalRedeliveries = new Statistic("org.apache.camel.externalRedeliveries", this, Statistic.UpdateMode.COUNTER);
063    
064            this.minProcessingTime = new Statistic("org.apache.camel.minimumProcessingTime", this, Statistic.UpdateMode.MINIMUM);
065            this.maxProcessingTime = new Statistic("org.apache.camel.maximumProcessingTime", this, Statistic.UpdateMode.MAXIMUM);
066            this.totalProcessingTime = new Statistic("org.apache.camel.totalProcessingTime", this, Statistic.UpdateMode.COUNTER);
067            this.lastProcessingTime = new Statistic("org.apache.camel.lastProcessingTime", this, Statistic.UpdateMode.VALUE);
068            this.deltaProcessingTime = new Statistic("org.apache.camel.deltaProcessingTime", this, Statistic.UpdateMode.DELTA);
069            this.meanProcessingTime = new Statistic("org.apache.camel.meanProcessingTime", this, Statistic.UpdateMode.VALUE);
070    
071            this.firstExchangeCompletedTimestamp = new Statistic("org.apache.camel.firstExchangeCompletedTimestamp", this, Statistic.UpdateMode.VALUE);
072            this.firstExchangeFailureTimestamp = new Statistic("org.apache.camel.firstExchangeFailureTimestamp", this, Statistic.UpdateMode.VALUE);
073            this.lastExchangeCompletedTimestamp = new Statistic("org.apache.camel.lastExchangeCompletedTimestamp", this, Statistic.UpdateMode.VALUE);
074            this.lastExchangeFailureTimestamp = new Statistic("org.apache.camel.lastExchangeFailureTimestamp", this, Statistic.UpdateMode.VALUE);
075        }
076    
077        @Override
078        public synchronized void reset() {
079            super.reset();
080            exchangesCompleted.reset();
081            exchangesFailed.reset();
082            failuresHandled.reset();
083            redeliveries.reset();
084            externalRedeliveries.reset();
085            minProcessingTime.reset();
086            maxProcessingTime.reset();
087            totalProcessingTime.reset();
088            lastProcessingTime.reset();
089            deltaProcessingTime.reset();
090            meanProcessingTime.reset();
091            firstExchangeCompletedTimestamp.reset();
092            firstExchangeCompletedExchangeId = null;
093            firstExchangeFailureTimestamp.reset();
094            firstExchangeFailureExchangeId = null;
095            lastExchangeCompletedTimestamp.reset();
096            lastExchangeCompletedExchangeId = null;
097            lastExchangeFailureTimestamp.reset();
098            lastExchangeFailureExchangeId = null;
099        }
100    
101        public long getExchangesCompleted() throws Exception {
102            return exchangesCompleted.getValue();
103        }
104    
105        public long getExchangesFailed() throws Exception {
106            return exchangesFailed.getValue();
107        }
108    
109        public long getFailuresHandled() throws Exception {
110            return failuresHandled.getValue();
111        }
112    
113        public long getRedeliveries() throws Exception {
114            return redeliveries.getValue();
115        }
116    
117        public long getExternalRedeliveries() throws Exception {
118            return externalRedeliveries.getValue();
119        }
120    
121        public long getMinProcessingTime() throws Exception {
122            return minProcessingTime.getValue();
123        }
124    
125        public long getMeanProcessingTime() throws Exception {
126            return meanProcessingTime.getValue();
127        }
128    
129        public long getMaxProcessingTime() throws Exception {
130            return maxProcessingTime.getValue();
131        }
132    
133        public long getTotalProcessingTime() throws Exception {
134            return totalProcessingTime.getValue();
135        }
136    
137        public long getLastProcessingTime() throws Exception {
138            return lastProcessingTime.getValue();
139        }
140    
141        public long getDeltaProcessingTime() throws Exception {
142            return deltaProcessingTime.getValue();
143        }
144    
145        public Date getLastExchangeCompletedTimestamp() {
146            long value = lastExchangeCompletedTimestamp.getValue();
147            return value > 0 ? new Date(value) : null;
148        }
149    
150        public String getLastExchangeCompletedExchangeId() {
151            return lastExchangeCompletedExchangeId;
152        }
153    
154        public Date getFirstExchangeCompletedTimestamp() {
155            long value = firstExchangeCompletedTimestamp.getValue();
156            return value > 0 ? new Date(value) : null;
157        }
158    
159        public String getFirstExchangeCompletedExchangeId() {
160            return firstExchangeCompletedExchangeId;
161        }
162    
163        public Date getLastExchangeFailureTimestamp() {
164            long value = lastExchangeFailureTimestamp.getValue();
165            return value > 0 ? new Date(value) : null;
166        }
167    
168        public String getLastExchangeFailureExchangeId() {
169            return lastExchangeFailureExchangeId;
170        }
171    
172        public Date getFirstExchangeFailureTimestamp() {
173            long value = firstExchangeFailureTimestamp.getValue();
174            return value > 0 ? new Date(value) : null;
175        }
176    
177        public String getFirstExchangeFailureExchangeId() {
178            return firstExchangeFailureExchangeId;
179        }
180    
181        public boolean isStatisticsEnabled() {
182            return statisticsEnabled;
183        }
184    
185        public void setStatisticsEnabled(boolean statisticsEnabled) {
186            this.statisticsEnabled = statisticsEnabled;
187        }
188    
189        public synchronized void completedExchange(Exchange exchange, long time) {
190            increment();
191            exchangesCompleted.increment();
192    
193            if (ExchangeHelper.isFailureHandled(exchange)) {
194                failuresHandled.increment();
195            }
196            Boolean externalRedelivered = exchange.isExternalRedelivered();
197            if (externalRedelivered != null && externalRedelivered) {
198                externalRedeliveries.increment();
199            }
200    
201            minProcessingTime.updateValue(time);
202            maxProcessingTime.updateValue(time);
203            totalProcessingTime.updateValue(time);
204            lastProcessingTime.updateValue(time);
205            deltaProcessingTime.updateValue(time);
206    
207            long now = new Date().getTime();
208            if (firstExchangeCompletedTimestamp.getUpdateCount() == 0) {
209                firstExchangeCompletedTimestamp.updateValue(now);
210            }
211    
212            lastExchangeCompletedTimestamp.updateValue(now);
213            if (firstExchangeCompletedExchangeId == null) {
214                firstExchangeCompletedExchangeId = exchange.getExchangeId();
215            }
216            lastExchangeCompletedExchangeId = exchange.getExchangeId();
217    
218            // update mean
219            long count = exchangesCompleted.getValue();
220            long mean = count > 0 ? totalProcessingTime.getValue() / count : 0;
221            meanProcessingTime.updateValue(mean);
222        }
223    
224        public synchronized void failedExchange(Exchange exchange) {
225            increment();
226            exchangesFailed.increment();
227    
228            if (ExchangeHelper.isRedelivered(exchange)) {
229                redeliveries.increment();
230            }
231            Boolean externalRedelivered = exchange.isExternalRedelivered();
232            if (externalRedelivered != null && externalRedelivered) {
233                externalRedeliveries.increment();
234            }
235    
236            long now = new Date().getTime();
237            if (firstExchangeFailureTimestamp.getUpdateCount() == 0) {
238                firstExchangeFailureTimestamp.updateValue(now);
239            }
240    
241            lastExchangeFailureTimestamp.updateValue(now);
242            if (firstExchangeFailureExchangeId == null) {
243                firstExchangeFailureExchangeId = exchange.getExchangeId();
244            }
245            lastExchangeFailureExchangeId = exchange.getExchangeId();
246        }
247    
248        public String dumpStatsAsXml(boolean fullStats) {
249            StringBuilder sb = new StringBuilder();
250            sb.append("<stats ");
251            sb.append(String.format("exchangesCompleted=\"%s\"", exchangesCompleted.getValue()));
252            sb.append(String.format(" exchangesFailed=\"%s\"", exchangesFailed.getValue()));
253            sb.append(String.format(" failuresHandled=\"%s\"", failuresHandled.getValue()));
254            sb.append(String.format(" redeliveries=\"%s\"", redeliveries.getValue()));
255            sb.append(String.format(" externalRedeliveries=\"%s\"", externalRedeliveries.getValue()));
256            sb.append(String.format(" minProcessingTime=\"%s\"", minProcessingTime.getValue()));
257            sb.append(String.format(" maxProcessingTime=\"%s\"", maxProcessingTime.getValue()));
258            sb.append(String.format(" totalProcessingTime=\"%s\"", totalProcessingTime.getValue()));
259            sb.append(String.format(" lastProcessingTime=\"%s\"", lastProcessingTime.getValue()));
260            sb.append(String.format(" deltaProcessingTime=\"%s\"", deltaProcessingTime.getValue()));
261            sb.append(String.format(" meanProcessingTime=\"%s\"", meanProcessingTime.getValue()));
262    
263            if (fullStats) {
264                sb.append(String.format(" resetTimestamp=\"%s\"", dateAsString(resetTimestamp.getValue())));
265                sb.append(String.format(" firstExchangeCompletedTimestamp=\"%s\"", dateAsString(firstExchangeCompletedTimestamp.getValue())));
266                sb.append(String.format(" firstExchangeCompletedExchangeId=\"%s\"", nullSafe(firstExchangeCompletedExchangeId)));
267                sb.append(String.format(" firstExchangeFailureTimestamp=\"%s\"", dateAsString(firstExchangeFailureTimestamp.getValue())));
268                sb.append(String.format(" firstExchangeFailureExchangeId=\"%s\"", nullSafe(firstExchangeFailureExchangeId)));
269                sb.append(String.format(" lastExchangeCompletedTimestamp=\"%s\"", dateAsString(lastExchangeCompletedTimestamp.getValue())));
270                sb.append(String.format(" lastExchangeCompletedExchangeId=\"%s\"", nullSafe(lastExchangeCompletedExchangeId)));
271                sb.append(String.format(" lastExchangeFailureTimestamp=\"%s\"", dateAsString(lastExchangeFailureTimestamp.getValue())));
272                sb.append(String.format(" lastExchangeFailureExchangeId=\"%s\"", nullSafe(lastExchangeFailureExchangeId)));
273            }
274            sb.append("/>");
275            return sb.toString();
276        }
277    
278        private static String dateAsString(long value) {
279            if (value == 0) {
280                return "";
281            }
282            return new SimpleDateFormat(TIMESTAMP_FORMAT).format(value);
283        }
284        
285        private static String nullSafe(String s) {
286            return s != null ? s : "";
287        }
288    
289    }