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 lastExchangeCreatedTimestamp; 052 private Statistic lastExchangeCompletedTimestamp; 053 private String lastExchangeCompletedExchangeId; 054 private Statistic lastExchangeFailureTimestamp; 055 private String lastExchangeFailureExchangeId; 056 private boolean statisticsEnabled = true; 057 058 @Override 059 public void init(ManagementStrategy strategy) { 060 super.init(strategy); 061 this.exchangesCompleted = new StatisticCounter(); 062 this.exchangesFailed = new StatisticCounter(); 063 this.exchangesInflight = new StatisticCounter(); 064 065 this.failuresHandled = new StatisticCounter(); 066 this.redeliveries = new StatisticCounter(); 067 this.externalRedeliveries = new StatisticCounter(); 068 069 this.minProcessingTime = new StatisticMinimum(); 070 this.maxProcessingTime = new StatisticMaximum(); 071 this.totalProcessingTime = new StatisticCounter(); 072 this.lastProcessingTime = new StatisticValue(); 073 this.deltaProcessingTime = new StatisticDelta(); 074 this.meanProcessingTime = new StatisticValue(); 075 076 this.firstExchangeCompletedTimestamp = new StatisticValue(); 077 this.firstExchangeFailureTimestamp = new StatisticValue(); 078 this.lastExchangeCreatedTimestamp = new StatisticValue(); 079 this.lastExchangeCompletedTimestamp = new StatisticValue(); 080 this.lastExchangeFailureTimestamp = new StatisticValue(); 081 } 082 083 @Override 084 public void reset() { 085 super.reset(); 086 exchangesCompleted.reset(); 087 exchangesFailed.reset(); 088 // do not reset exchangesInflight 089 failuresHandled.reset(); 090 redeliveries.reset(); 091 externalRedeliveries.reset(); 092 minProcessingTime.reset(); 093 maxProcessingTime.reset(); 094 totalProcessingTime.reset(); 095 lastProcessingTime.reset(); 096 deltaProcessingTime.reset(); 097 meanProcessingTime.reset(); 098 firstExchangeCompletedTimestamp.reset(); 099 firstExchangeCompletedExchangeId = null; 100 firstExchangeFailureTimestamp.reset(); 101 firstExchangeFailureExchangeId = null; 102 lastExchangeCreatedTimestamp.reset(); 103 lastExchangeCompletedTimestamp.reset(); 104 lastExchangeCompletedExchangeId = null; 105 lastExchangeFailureTimestamp.reset(); 106 lastExchangeFailureExchangeId = null; 107 } 108 109 @Override 110 public long getExchangesCompleted() { 111 return exchangesCompleted.getValue(); 112 } 113 114 @Override 115 public long getExchangesFailed() { 116 return exchangesFailed.getValue(); 117 } 118 119 @Override 120 public long getExchangesInflight() { 121 return exchangesInflight.getValue(); 122 } 123 124 @Override 125 public long getFailuresHandled() { 126 return failuresHandled.getValue(); 127 } 128 129 @Override 130 public long getRedeliveries() { 131 return redeliveries.getValue(); 132 } 133 134 @Override 135 public long getExternalRedeliveries() { 136 return externalRedeliveries.getValue(); 137 } 138 139 @Override 140 public long getMinProcessingTime() { 141 return minProcessingTime.getValue(); 142 } 143 144 @Override 145 public long getMeanProcessingTime() { 146 return meanProcessingTime.getValue(); 147 } 148 149 @Override 150 public long getMaxProcessingTime() { 151 return maxProcessingTime.getValue(); 152 } 153 154 @Override 155 public long getTotalProcessingTime() { 156 return totalProcessingTime.getValue(); 157 } 158 159 @Override 160 public long getLastProcessingTime() { 161 return lastProcessingTime.getValue(); 162 } 163 164 @Override 165 public long getDeltaProcessingTime() { 166 return deltaProcessingTime.getValue(); 167 } 168 169 @Override 170 public long getIdleSince() { 171 // must not have any inflight 172 if (getExchangesInflight() <= 0) { 173 // what is the last time since completed/failed 174 long max = Math.max(lastExchangeCompletedTimestamp.getValue(), lastExchangeFailureTimestamp.getValue()); 175 if (max > 0) { 176 long delta = System.currentTimeMillis() - max; 177 if (delta > 0) { 178 return delta; 179 } 180 } 181 } 182 return -1; 183 } 184 185 @Override 186 public Date getLastExchangeCreatedTimestamp() { 187 long value = lastExchangeCreatedTimestamp.getValue(); 188 return value > 0 ? new Date(value) : null; 189 } 190 191 @Override 192 public Date getLastExchangeCompletedTimestamp() { 193 long value = lastExchangeCompletedTimestamp.getValue(); 194 return value > 0 ? new Date(value) : null; 195 } 196 197 @Override 198 public String getLastExchangeCompletedExchangeId() { 199 return lastExchangeCompletedExchangeId; 200 } 201 202 @Override 203 public Date getFirstExchangeCompletedTimestamp() { 204 long value = firstExchangeCompletedTimestamp.getValue(); 205 return value > 0 ? new Date(value) : null; 206 } 207 208 @Override 209 public String getFirstExchangeCompletedExchangeId() { 210 return firstExchangeCompletedExchangeId; 211 } 212 213 @Override 214 public Date getLastExchangeFailureTimestamp() { 215 long value = lastExchangeFailureTimestamp.getValue(); 216 return value > 0 ? new Date(value) : null; 217 } 218 219 @Override 220 public String getLastExchangeFailureExchangeId() { 221 return lastExchangeFailureExchangeId; 222 } 223 224 @Override 225 public Date getFirstExchangeFailureTimestamp() { 226 long value = firstExchangeFailureTimestamp.getValue(); 227 return value > 0 ? new Date(value) : null; 228 } 229 230 @Override 231 public String getFirstExchangeFailureExchangeId() { 232 return firstExchangeFailureExchangeId; 233 } 234 235 @Override 236 public boolean isStatisticsEnabled() { 237 return statisticsEnabled; 238 } 239 240 @Override 241 public void setStatisticsEnabled(boolean statisticsEnabled) { 242 this.statisticsEnabled = statisticsEnabled; 243 } 244 245 @Override 246 public void processExchange(Exchange exchange, String type) { 247 exchangesInflight.increment(); 248 if ("route".equals(type)) { 249 long now = System.currentTimeMillis(); 250 lastExchangeCreatedTimestamp.updateValue(now); 251 } 252 } 253 254 @Override 255 public void completedExchange(Exchange exchange, long time) { 256 increment(); 257 exchangesCompleted.increment(); 258 exchangesInflight.decrement(); 259 260 if (ExchangeHelper.isFailureHandled(exchange)) { 261 failuresHandled.increment(); 262 } 263 if (exchange.isExternalRedelivered()) { 264 externalRedeliveries.increment(); 265 } 266 267 minProcessingTime.updateValue(time); 268 maxProcessingTime.updateValue(time); 269 totalProcessingTime.updateValue(time); 270 lastProcessingTime.updateValue(time); 271 deltaProcessingTime.updateValue(time); 272 273 long now = System.currentTimeMillis(); 274 if (!firstExchangeCompletedTimestamp.isUpdated()) { 275 firstExchangeCompletedTimestamp.updateValue(now); 276 } 277 278 lastExchangeCompletedTimestamp.updateValue(now); 279 if (firstExchangeCompletedExchangeId == null) { 280 firstExchangeCompletedExchangeId = exchange.getExchangeId(); 281 } 282 lastExchangeCompletedExchangeId = exchange.getExchangeId(); 283 284 // update mean 285 long mean = 0; 286 long completed = exchangesCompleted.getValue(); 287 if (completed > 0) { 288 mean = totalProcessingTime.getValue() / completed; 289 } 290 meanProcessingTime.updateValue(mean); 291 } 292 293 @Override 294 public void failedExchange(Exchange exchange) { 295 increment(); 296 exchangesFailed.increment(); 297 exchangesInflight.decrement(); 298 299 if (ExchangeHelper.isRedelivered(exchange)) { 300 redeliveries.increment(); 301 } 302 if (exchange.isExternalRedelivered()) { 303 externalRedeliveries.increment(); 304 } 305 306 long now = System.currentTimeMillis(); 307 if (!firstExchangeFailureTimestamp.isUpdated()) { 308 firstExchangeFailureTimestamp.updateValue(now); 309 } 310 311 lastExchangeFailureTimestamp.updateValue(now); 312 if (firstExchangeFailureExchangeId == null) { 313 firstExchangeFailureExchangeId = exchange.getExchangeId(); 314 } 315 lastExchangeFailureExchangeId = exchange.getExchangeId(); 316 } 317 318 @Override 319 public String dumpStatsAsXml(boolean fullStats) { 320 StringBuilder sb = new StringBuilder(); 321 sb.append("<stats "); 322 sb.append(String.format("exchangesCompleted=\"%s\"", exchangesCompleted.getValue())); 323 sb.append(String.format(" exchangesFailed=\"%s\"", exchangesFailed.getValue())); 324 sb.append(String.format(" failuresHandled=\"%s\"", failuresHandled.getValue())); 325 sb.append(String.format(" redeliveries=\"%s\"", redeliveries.getValue())); 326 sb.append(String.format(" externalRedeliveries=\"%s\"", externalRedeliveries.getValue())); 327 sb.append(String.format(" minProcessingTime=\"%s\"", minProcessingTime.getValue())); 328 sb.append(String.format(" maxProcessingTime=\"%s\"", maxProcessingTime.getValue())); 329 sb.append(String.format(" totalProcessingTime=\"%s\"", totalProcessingTime.getValue())); 330 sb.append(String.format(" lastProcessingTime=\"%s\"", lastProcessingTime.getValue())); 331 sb.append(String.format(" deltaProcessingTime=\"%s\"", deltaProcessingTime.getValue())); 332 sb.append(String.format(" meanProcessingTime=\"%s\"", meanProcessingTime.getValue())); 333 sb.append(String.format(" idleSince=\"%s\"", getIdleSince())); 334 335 if (fullStats) { 336 sb.append(String.format(" startTimestamp=\"%s\"", dateAsString(startTimestamp.getTime()))); 337 sb.append(String.format(" resetTimestamp=\"%s\"", dateAsString(resetTimestamp.getTime()))); 338 sb.append(String.format(" firstExchangeCompletedTimestamp=\"%s\"", 339 dateAsString(firstExchangeCompletedTimestamp.getValue()))); 340 sb.append(String.format(" firstExchangeCompletedExchangeId=\"%s\"", nullSafe(firstExchangeCompletedExchangeId))); 341 sb.append(String.format(" firstExchangeFailureTimestamp=\"%s\"", 342 dateAsString(firstExchangeFailureTimestamp.getValue()))); 343 sb.append(String.format(" firstExchangeFailureExchangeId=\"%s\"", nullSafe(firstExchangeFailureExchangeId))); 344 sb.append(String.format(" lastExchangeCreatedTimestamp=\"%s\"", 345 dateAsString(lastExchangeCreatedTimestamp.getValue()))); 346 sb.append(String.format(" lastExchangeCompletedTimestamp=\"%s\"", 347 dateAsString(lastExchangeCompletedTimestamp.getValue()))); 348 sb.append(String.format(" lastExchangeCompletedExchangeId=\"%s\"", nullSafe(lastExchangeCompletedExchangeId))); 349 sb.append(String.format(" lastExchangeFailureTimestamp=\"%s\"", 350 dateAsString(lastExchangeFailureTimestamp.getValue()))); 351 sb.append(String.format(" lastExchangeFailureExchangeId=\"%s\"", nullSafe(lastExchangeFailureExchangeId))); 352 } 353 sb.append("/>"); 354 return sb.toString(); 355 } 356 357 private static String dateAsString(long value) { 358 if (value <= 0) { 359 return ""; 360 } 361 return new SimpleDateFormat(TIMESTAMP_FORMAT).format(value); 362 } 363 364 private static String nullSafe(String s) { 365 return s != null ? s : ""; 366 } 367 368}