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