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}