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 Date getLastExchangeCreatedTimestamp() { 171 long value = lastExchangeCreatedTimestamp.getValue(); 172 return value > 0 ? new Date(value) : null; 173 } 174 175 @Override 176 public Date getLastExchangeCompletedTimestamp() { 177 long value = lastExchangeCompletedTimestamp.getValue(); 178 return value > 0 ? new Date(value) : null; 179 } 180 181 @Override 182 public String getLastExchangeCompletedExchangeId() { 183 return lastExchangeCompletedExchangeId; 184 } 185 186 @Override 187 public Date getFirstExchangeCompletedTimestamp() { 188 long value = firstExchangeCompletedTimestamp.getValue(); 189 return value > 0 ? new Date(value) : null; 190 } 191 192 @Override 193 public String getFirstExchangeCompletedExchangeId() { 194 return firstExchangeCompletedExchangeId; 195 } 196 197 @Override 198 public Date getLastExchangeFailureTimestamp() { 199 long value = lastExchangeFailureTimestamp.getValue(); 200 return value > 0 ? new Date(value) : null; 201 } 202 203 @Override 204 public String getLastExchangeFailureExchangeId() { 205 return lastExchangeFailureExchangeId; 206 } 207 208 @Override 209 public Date getFirstExchangeFailureTimestamp() { 210 long value = firstExchangeFailureTimestamp.getValue(); 211 return value > 0 ? new Date(value) : null; 212 } 213 214 @Override 215 public String getFirstExchangeFailureExchangeId() { 216 return firstExchangeFailureExchangeId; 217 } 218 219 @Override 220 public boolean isStatisticsEnabled() { 221 return statisticsEnabled; 222 } 223 224 @Override 225 public void setStatisticsEnabled(boolean statisticsEnabled) { 226 this.statisticsEnabled = statisticsEnabled; 227 } 228 229 @Override 230 public void processExchange(Exchange exchange, String type) { 231 exchangesInflight.increment(); 232 if ("route".equals(type)) { 233 long now = System.currentTimeMillis(); 234 lastExchangeCreatedTimestamp.updateValue(now); 235 } 236 } 237 238 @Override 239 public void completedExchange(Exchange exchange, long time) { 240 increment(); 241 exchangesCompleted.increment(); 242 exchangesInflight.decrement(); 243 244 if (ExchangeHelper.isFailureHandled(exchange)) { 245 failuresHandled.increment(); 246 } 247 if (exchange.isExternalRedelivered()) { 248 externalRedeliveries.increment(); 249 } 250 251 minProcessingTime.updateValue(time); 252 maxProcessingTime.updateValue(time); 253 totalProcessingTime.updateValue(time); 254 lastProcessingTime.updateValue(time); 255 deltaProcessingTime.updateValue(time); 256 257 long now = System.currentTimeMillis(); 258 if (!firstExchangeCompletedTimestamp.isUpdated()) { 259 firstExchangeCompletedTimestamp.updateValue(now); 260 } 261 262 lastExchangeCompletedTimestamp.updateValue(now); 263 if (firstExchangeCompletedExchangeId == null) { 264 firstExchangeCompletedExchangeId = exchange.getExchangeId(); 265 } 266 lastExchangeCompletedExchangeId = exchange.getExchangeId(); 267 268 // update mean 269 long mean = 0; 270 long completed = exchangesCompleted.getValue(); 271 if (completed > 0) { 272 mean = totalProcessingTime.getValue() / completed; 273 } 274 meanProcessingTime.updateValue(mean); 275 } 276 277 @Override 278 public void failedExchange(Exchange exchange) { 279 increment(); 280 exchangesFailed.increment(); 281 exchangesInflight.decrement(); 282 283 if (ExchangeHelper.isRedelivered(exchange)) { 284 redeliveries.increment(); 285 } 286 if (exchange.isExternalRedelivered()) { 287 externalRedeliveries.increment(); 288 } 289 290 long now = System.currentTimeMillis(); 291 if (!firstExchangeFailureTimestamp.isUpdated()) { 292 firstExchangeFailureTimestamp.updateValue(now); 293 } 294 295 lastExchangeFailureTimestamp.updateValue(now); 296 if (firstExchangeFailureExchangeId == null) { 297 firstExchangeFailureExchangeId = exchange.getExchangeId(); 298 } 299 lastExchangeFailureExchangeId = exchange.getExchangeId(); 300 } 301 302 @Override 303 public String dumpStatsAsXml(boolean fullStats) { 304 StringBuilder sb = new StringBuilder(); 305 sb.append("<stats "); 306 sb.append(String.format("exchangesCompleted=\"%s\"", exchangesCompleted.getValue())); 307 sb.append(String.format(" exchangesFailed=\"%s\"", exchangesFailed.getValue())); 308 sb.append(String.format(" failuresHandled=\"%s\"", failuresHandled.getValue())); 309 sb.append(String.format(" redeliveries=\"%s\"", redeliveries.getValue())); 310 sb.append(String.format(" externalRedeliveries=\"%s\"", externalRedeliveries.getValue())); 311 sb.append(String.format(" minProcessingTime=\"%s\"", minProcessingTime.getValue())); 312 sb.append(String.format(" maxProcessingTime=\"%s\"", maxProcessingTime.getValue())); 313 sb.append(String.format(" totalProcessingTime=\"%s\"", totalProcessingTime.getValue())); 314 sb.append(String.format(" lastProcessingTime=\"%s\"", lastProcessingTime.getValue())); 315 sb.append(String.format(" deltaProcessingTime=\"%s\"", deltaProcessingTime.getValue())); 316 sb.append(String.format(" meanProcessingTime=\"%s\"", meanProcessingTime.getValue())); 317 318 if (fullStats) { 319 sb.append(String.format(" startTimestamp=\"%s\"", dateAsString(startTimestamp.getTime()))); 320 sb.append(String.format(" resetTimestamp=\"%s\"", dateAsString(resetTimestamp.getTime()))); 321 sb.append(String.format(" firstExchangeCompletedTimestamp=\"%s\"", 322 dateAsString(firstExchangeCompletedTimestamp.getValue()))); 323 sb.append(String.format(" firstExchangeCompletedExchangeId=\"%s\"", nullSafe(firstExchangeCompletedExchangeId))); 324 sb.append(String.format(" firstExchangeFailureTimestamp=\"%s\"", 325 dateAsString(firstExchangeFailureTimestamp.getValue()))); 326 sb.append(String.format(" firstExchangeFailureExchangeId=\"%s\"", nullSafe(firstExchangeFailureExchangeId))); 327 sb.append(String.format(" lastExchangeCreatedTimestamp=\"%s\"", 328 dateAsString(lastExchangeCreatedTimestamp.getValue()))); 329 sb.append(String.format(" lastExchangeCompletedTimestamp=\"%s\"", 330 dateAsString(lastExchangeCompletedTimestamp.getValue()))); 331 sb.append(String.format(" lastExchangeCompletedExchangeId=\"%s\"", nullSafe(lastExchangeCompletedExchangeId))); 332 sb.append(String.format(" lastExchangeFailureTimestamp=\"%s\"", 333 dateAsString(lastExchangeFailureTimestamp.getValue()))); 334 sb.append(String.format(" lastExchangeFailureExchangeId=\"%s\"", nullSafe(lastExchangeFailureExchangeId))); 335 } 336 sb.append("/>"); 337 return sb.toString(); 338 } 339 340 private static String dateAsString(long value) { 341 if (value <= 0) { 342 return ""; 343 } 344 return new SimpleDateFormat(TIMESTAMP_FORMAT).format(value); 345 } 346 347 private static String nullSafe(String s) { 348 return s != null ? s : ""; 349 } 350 351}