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 */
017package org.apache.camel.management.mbean;
018
019import java.text.SimpleDateFormat;
020import java.util.Date;
021
022import org.apache.camel.Exchange;
023import org.apache.camel.api.management.ManagedResource;
024import org.apache.camel.api.management.mbean.ManagedPerformanceCounterMBean;
025import org.apache.camel.management.PerformanceCounter;
026import org.apache.camel.spi.ManagementStrategy;
027import org.apache.camel.support.ExchangeHelper;
028
029@ManagedResource(description = "Managed PerformanceCounter")
030public abstract class ManagedPerformanceCounter extends ManagedCounter
031        implements PerformanceCounter, ManagedPerformanceCounterMBean {
032
033    public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
034
035    private Statistic exchangesCompleted;
036    private Statistic exchangesFailed;
037    private Statistic exchangesInflight;
038    private Statistic failuresHandled;
039    private Statistic redeliveries;
040    private Statistic externalRedeliveries;
041    private Statistic minProcessingTime;
042    private Statistic maxProcessingTime;
043    private Statistic totalProcessingTime;
044    private Statistic lastProcessingTime;
045    private Statistic deltaProcessingTime;
046    private Statistic meanProcessingTime;
047    private Statistic firstExchangeCompletedTimestamp;
048    private String firstExchangeCompletedExchangeId;
049    private Statistic firstExchangeFailureTimestamp;
050    private String firstExchangeFailureExchangeId;
051    private Statistic lastExchangeCompletedTimestamp;
052    private String lastExchangeCompletedExchangeId;
053    private Statistic lastExchangeFailureTimestamp;
054    private String lastExchangeFailureExchangeId;
055    private boolean statisticsEnabled = true;
056
057    @Override
058    public void init(ManagementStrategy strategy) {
059        super.init(strategy);
060        this.exchangesCompleted = new StatisticCounter();
061        this.exchangesFailed = new StatisticCounter();
062        this.exchangesInflight = new StatisticCounter();
063
064        this.failuresHandled = new StatisticCounter();
065        this.redeliveries = new StatisticCounter();
066        this.externalRedeliveries = new StatisticCounter();
067
068        this.minProcessingTime = new StatisticMinimum();
069        this.maxProcessingTime = new StatisticMaximum();
070        this.totalProcessingTime = new StatisticCounter();
071        this.lastProcessingTime = new StatisticValue();
072        this.deltaProcessingTime = new StatisticDelta();
073        this.meanProcessingTime = new StatisticValue();
074
075        this.firstExchangeCompletedTimestamp = new StatisticValue();
076        this.firstExchangeFailureTimestamp = new StatisticValue();
077        this.lastExchangeCompletedTimestamp = new StatisticValue();
078        this.lastExchangeFailureTimestamp = new StatisticValue();
079    }
080
081    @Override
082    public void reset() {
083        super.reset();
084        exchangesCompleted.reset();
085        exchangesFailed.reset();
086        // do not reset exchangesInflight
087        failuresHandled.reset();
088        redeliveries.reset();
089        externalRedeliveries.reset();
090        minProcessingTime.reset();
091        maxProcessingTime.reset();
092        totalProcessingTime.reset();
093        lastProcessingTime.reset();
094        deltaProcessingTime.reset();
095        meanProcessingTime.reset();
096        firstExchangeCompletedTimestamp.reset();
097        firstExchangeCompletedExchangeId = null;
098        firstExchangeFailureTimestamp.reset();
099        firstExchangeFailureExchangeId = null;
100        lastExchangeCompletedTimestamp.reset();
101        lastExchangeCompletedExchangeId = null;
102        lastExchangeFailureTimestamp.reset();
103        lastExchangeFailureExchangeId = null;
104    }
105
106    @Override
107    public long getExchangesCompleted() {
108        return exchangesCompleted.getValue();
109    }
110
111    @Override
112    public long getExchangesFailed() {
113        return exchangesFailed.getValue();
114    }
115
116    @Override
117    public long getExchangesInflight() {
118        return exchangesInflight.getValue();
119    }
120
121    @Override
122    public long getFailuresHandled() {
123        return failuresHandled.getValue();
124    }
125
126    @Override
127    public long getRedeliveries() {
128        return redeliveries.getValue();
129    }
130
131    @Override
132    public long getExternalRedeliveries() {
133        return externalRedeliveries.getValue();
134    }
135
136    @Override
137    public long getMinProcessingTime() {
138        return minProcessingTime.getValue();
139    }
140
141    @Override
142    public long getMeanProcessingTime() {
143        return meanProcessingTime.getValue();
144    }
145
146    @Override
147    public long getMaxProcessingTime() {
148        return maxProcessingTime.getValue();
149    }
150
151    @Override
152    public long getTotalProcessingTime() {
153        return totalProcessingTime.getValue();
154    }
155
156    @Override
157    public long getLastProcessingTime() {
158        return lastProcessingTime.getValue();
159    }
160
161    @Override
162    public long getDeltaProcessingTime() {
163        return deltaProcessingTime.getValue();
164    }
165
166    @Override
167    public Date getLastExchangeCompletedTimestamp() {
168        long value = lastExchangeCompletedTimestamp.getValue();
169        return value > 0 ? new Date(value) : null;
170    }
171
172    @Override
173    public String getLastExchangeCompletedExchangeId() {
174        return lastExchangeCompletedExchangeId;
175    }
176
177    @Override
178    public Date getFirstExchangeCompletedTimestamp() {
179        long value = firstExchangeCompletedTimestamp.getValue();
180        return value > 0 ? new Date(value) : null;
181    }
182
183    @Override
184    public String getFirstExchangeCompletedExchangeId() {
185        return firstExchangeCompletedExchangeId;
186    }
187
188    @Override
189    public Date getLastExchangeFailureTimestamp() {
190        long value = lastExchangeFailureTimestamp.getValue();
191        return value > 0 ? new Date(value) : null;
192    }
193
194    @Override
195    public String getLastExchangeFailureExchangeId() {
196        return lastExchangeFailureExchangeId;
197    }
198
199    @Override
200    public Date getFirstExchangeFailureTimestamp() {
201        long value = firstExchangeFailureTimestamp.getValue();
202        return value > 0 ? new Date(value) : null;
203    }
204
205    @Override
206    public String getFirstExchangeFailureExchangeId() {
207        return firstExchangeFailureExchangeId;
208    }
209
210    @Override
211    public boolean isStatisticsEnabled() {
212        return statisticsEnabled;
213    }
214
215    @Override
216    public void setStatisticsEnabled(boolean statisticsEnabled) {
217        this.statisticsEnabled = statisticsEnabled;
218    }
219
220    @Override
221    public void processExchange(Exchange exchange) {
222        exchangesInflight.increment();
223    }
224
225    @Override
226    public void completedExchange(Exchange exchange, long time) {
227        increment();
228        exchangesCompleted.increment();
229        exchangesInflight.decrement();
230
231        if (ExchangeHelper.isFailureHandled(exchange)) {
232            failuresHandled.increment();
233        }
234        if (exchange.isExternalRedelivered()) {
235            externalRedeliveries.increment();
236        }
237
238        minProcessingTime.updateValue(time);
239        maxProcessingTime.updateValue(time);
240        totalProcessingTime.updateValue(time);
241        lastProcessingTime.updateValue(time);
242        deltaProcessingTime.updateValue(time);
243
244        long now = System.currentTimeMillis();
245        if (!firstExchangeCompletedTimestamp.isUpdated()) {
246            firstExchangeCompletedTimestamp.updateValue(now);
247        }
248
249        lastExchangeCompletedTimestamp.updateValue(now);
250        if (firstExchangeCompletedExchangeId == null) {
251            firstExchangeCompletedExchangeId = exchange.getExchangeId();
252        }
253        lastExchangeCompletedExchangeId = exchange.getExchangeId();
254
255        // update mean
256        long mean = 0;
257        long completed = exchangesCompleted.getValue();
258        if (completed > 0) {
259            mean = totalProcessingTime.getValue() / completed;
260        }
261        meanProcessingTime.updateValue(mean);
262    }
263
264    @Override
265    public void failedExchange(Exchange exchange) {
266        increment();
267        exchangesFailed.increment();
268        exchangesInflight.decrement();
269
270        if (ExchangeHelper.isRedelivered(exchange)) {
271            redeliveries.increment();
272        }
273        if (exchange.isExternalRedelivered()) {
274            externalRedeliveries.increment();
275        }
276
277        long now = System.currentTimeMillis();
278        if (!firstExchangeFailureTimestamp.isUpdated()) {
279            firstExchangeFailureTimestamp.updateValue(now);
280        }
281
282        lastExchangeFailureTimestamp.updateValue(now);
283        if (firstExchangeFailureExchangeId == null) {
284            firstExchangeFailureExchangeId = exchange.getExchangeId();
285        }
286        lastExchangeFailureExchangeId = exchange.getExchangeId();
287    }
288
289    @Override
290    public String dumpStatsAsXml(boolean fullStats) {
291        StringBuilder sb = new StringBuilder();
292        sb.append("<stats ");
293        sb.append(String.format("exchangesCompleted=\"%s\"", exchangesCompleted.getValue()));
294        sb.append(String.format(" exchangesFailed=\"%s\"", exchangesFailed.getValue()));
295        sb.append(String.format(" failuresHandled=\"%s\"", failuresHandled.getValue()));
296        sb.append(String.format(" redeliveries=\"%s\"", redeliveries.getValue()));
297        sb.append(String.format(" externalRedeliveries=\"%s\"", externalRedeliveries.getValue()));
298        sb.append(String.format(" minProcessingTime=\"%s\"", minProcessingTime.getValue()));
299        sb.append(String.format(" maxProcessingTime=\"%s\"", maxProcessingTime.getValue()));
300        sb.append(String.format(" totalProcessingTime=\"%s\"", totalProcessingTime.getValue()));
301        sb.append(String.format(" lastProcessingTime=\"%s\"", lastProcessingTime.getValue()));
302        sb.append(String.format(" deltaProcessingTime=\"%s\"", deltaProcessingTime.getValue()));
303        sb.append(String.format(" meanProcessingTime=\"%s\"", meanProcessingTime.getValue()));
304
305        if (fullStats) {
306            sb.append(String.format(" startTimestamp=\"%s\"", dateAsString(startTimestamp.getTime())));
307            sb.append(String.format(" resetTimestamp=\"%s\"", dateAsString(resetTimestamp.getTime())));
308            sb.append(String.format(" firstExchangeCompletedTimestamp=\"%s\"",
309                    dateAsString(firstExchangeCompletedTimestamp.getValue())));
310            sb.append(String.format(" firstExchangeCompletedExchangeId=\"%s\"", nullSafe(firstExchangeCompletedExchangeId)));
311            sb.append(String.format(" firstExchangeFailureTimestamp=\"%s\"",
312                    dateAsString(firstExchangeFailureTimestamp.getValue())));
313            sb.append(String.format(" firstExchangeFailureExchangeId=\"%s\"", nullSafe(firstExchangeFailureExchangeId)));
314            sb.append(String.format(" lastExchangeCompletedTimestamp=\"%s\"",
315                    dateAsString(lastExchangeCompletedTimestamp.getValue())));
316            sb.append(String.format(" lastExchangeCompletedExchangeId=\"%s\"", nullSafe(lastExchangeCompletedExchangeId)));
317            sb.append(String.format(" lastExchangeFailureTimestamp=\"%s\"",
318                    dateAsString(lastExchangeFailureTimestamp.getValue())));
319            sb.append(String.format(" lastExchangeFailureExchangeId=\"%s\"", nullSafe(lastExchangeFailureExchangeId)));
320        }
321        sb.append("/>");
322        return sb.toString();
323    }
324
325    private static String dateAsString(long value) {
326        if (value <= 0) {
327            return "";
328        }
329        return new SimpleDateFormat(TIMESTAMP_FORMAT).format(value);
330    }
331
332    private static String nullSafe(String s) {
333        return s != null ? s : "";
334    }
335
336}