|
Author: adrianc
Date: Sun Jul 15 16:07:59 2012 New Revision: 1361722 URL: http://svn.apache.org/viewvc?rev=1361722&view=rev Log: New feature - performance metrics. Basic code and services. Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/ ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java (with props) ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java (with props) Modified: ofbiz/trunk/framework/common/servicedef/services.xml ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java?rev=1361722&view=auto ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java (added) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java Sun Jul 15 16:07:59 2012 @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + Copyright (c) 2002 by Matt Welsh and The Regents of the University of California. All rights reserved. + + IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA + HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE + UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ +package org.ofbiz.base.metrics; + +/** + * An object that tracks service metrics. + * <p>This interface and its default implementation are based on the + * <code>seda.sandstorm.internal.StageStats</code> class written by + * Matt Welsh.</code> + * @see <a href="http://www.eecs.harvard.edu/~mdw/proj/seda/">SEDA</a> + */ +public interface Metrics { + + public static final int ESTIMATION_SIZE = 100; + public static final long ESTIMATION_TIME = 1000; + public static final double SMOOTHING = 0.7; + + /** + * Returns the name of the metric. + */ + String getName(); + + /** + * Returns a moving average of the service rate in milliseconds. The default + * implementation divides the total time by the total number of events and then + * applies a smoothing factor. + */ + double getServiceRate(); + + /** Returns the metric threshold. The meaning of the threshold is + * determined by client code. + * <p>The idea is for client code to compare {@link #getServiceRate()} to + * the threshold and perform some action based on the comparison.</p> + */ + double getThreshold(); + + /** Returns the total number of processed events. */ + long getTotalEvents(); + + /** + * Records the service time for <code>numEvents</code> taking + * <code>time</code> milliseconds to be processed. + */ + void recordServiceRate(int numEvents, long time); + + /** Resets all metrics. */ + void reset(); +} \ No newline at end of file Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/Metrics.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Added: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java?rev=1361722&view=auto ============================================================================== --- ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java (added) +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java Sun Jul 15 16:07:59 2012 @@ -0,0 +1,269 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + Copyright (c) 2002 by Matt Welsh and The Regents of the University of California. All rights reserved. + + IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA + HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE + UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ +package org.ofbiz.base.metrics; + +import java.util.ArrayList; +import java.util.List; + +import org.ofbiz.base.lang.LockedBy; +import org.ofbiz.base.lang.ThreadSafe; +import org.ofbiz.base.util.Assert; +import org.ofbiz.base.util.cache.UtilCache; +import org.w3c.dom.Element; + +/** + * A {@link org.ofbiz.base.metrics.Metrics} factory. + */ +@ThreadSafe +public final class MetricsFactory { + + private static final UtilCache<String, Metrics> METRICS_CACHE = UtilCache.createUtilCache("base.metrics", 0, 0); + /** + * A "do-nothing" <code>Metrics</code> instance. + */ + public static final Metrics NULL_METRICS = new NullMetrics(); + + /** + * Creates a <code>Metrics</code> instance based on <code>element</code> attributes. + * If an instance with the same name already exists, it will be returned. + * <p><strong>Element Attributes</strong> + * <table border="1"> + * <tr><th>Attribute Name</th><th>Requirements</th><th>Description</th><th>Notes</th></tr> + * <tr><td>name</td><td>Required</td><td>The metric name.</td><td> </td></tr> + * <tr><td>estimation-size</td><td>Optional</td><td>Positive integer number of events to include in the metrics calculation.</td><td>Defaults to "100".</td></tr> + * <tr><td>estimation-time</td><td>Optional</td><td>Positive integer number of milliseconds to include in the metrics calculation.</td><td>Defaults to "1000".</td></tr> + * <tr><td>smoothing</td><td>Optional</td><td>Smoothing factor - used to smooth the differences between calculations.</td><td>A value of "1" disables smoothing. Defaults to "0.7".</td></tr> + * <tr><td>threshold</td><td>Optional</td><td>The metric threshold. The meaning of the threshold is determined by client code.</td><td>Defaults to "0.0".</td></tr> + * </table></p> + * + * @param element The element whose attributes will be used to create the <code>Metrics</code> instance + * @return A <code>Metrics</code> instance based on <code>element</code> attributes + * @throws IllegalArgumentException if <code>element</code> is null or if the name attribute is empty + * @throws NumberFormatException if any of the numeric attribute values are unparsable + */ + public static Metrics getInstance(Element element) { + Assert.notNull("element", element); + String name = element.getAttribute("name"); + Assert.notEmpty("name attribute", name); + Metrics result = METRICS_CACHE.get(name); + if (result == null) { + int estimationSize = Metrics.ESTIMATION_SIZE; + String attributeValue = element.getAttribute("estimation-size"); + if (!attributeValue.isEmpty()) { + estimationSize = Integer.parseInt(attributeValue); + } + long estimationTime = Metrics.ESTIMATION_TIME; + attributeValue = element.getAttribute("estimation-time"); + if (!attributeValue.isEmpty()) { + estimationTime = Long.parseLong(attributeValue); + } + double smoothing = Metrics.SMOOTHING; + attributeValue = element.getAttribute("smoothing"); + if (!attributeValue.isEmpty()) { + smoothing = Double.parseDouble(attributeValue); + } + double threshold = 0.0; + attributeValue = element.getAttribute("threshold"); + if (!attributeValue.isEmpty()) { + threshold = Double.parseDouble(attributeValue); + } + result = new MetricsImpl(name, estimationSize, estimationTime, smoothing, threshold); + METRICS_CACHE.putIfAbsent(name, result); + result = METRICS_CACHE.get(name); + } + return result; + } + + /** + * Creates a <code>Metrics</code> instance. + * If an instance with the same name already exists, it will be returned. + * @param name The metric name. + * @param estimationSize Positive integer number of events to include in the metrics calculation. + * @param estimationTime Positive integer number of milliseconds to include in the metrics calculation. + * @param smoothing Smoothing factor - used to smooth the differences between calculations. + * @return A <code>Metrics</code> instance + */ + public static Metrics getInstance(String name, int estimationSize, long estimationTime, double smoothing, double threshold) { + Assert.notNull("name", name); + Metrics result = METRICS_CACHE.get(name); + if (result == null) { + result = new MetricsImpl(name, estimationSize, estimationTime, smoothing, threshold); + METRICS_CACHE.putIfAbsent(name, result); + result = METRICS_CACHE.get(name); + } + return result; + } + + /** + * Returns an existing <code>Metric</code> instance with the specified name. + * Returns <code>null</code> if the metric does not exist. + * @param name The metric name + */ + public static Metrics getMetric(String name) { + Assert.notNull("name", name); + return METRICS_CACHE.get(name); + } + + /** + * Returns all <code>Metric</code> instances. + */ + public static List<Metrics> getMetrics() { + return new ArrayList<Metrics>(METRICS_CACHE.values()); + } + + private static final class MetricsImpl implements Metrics { + @LockedBy("this") + private int count = 0; + @LockedBy("this") + private long lastTime = System.currentTimeMillis(); + @LockedBy("this") + private double serviceRate = 0.0; + @LockedBy("this") + private long totalServiceTime = 0; + @LockedBy("this") + private long totalEvents = 0; + @LockedBy("this") + private long cumulativeEvents; + private final String name; + private final int estimationSize; + private final long estimationTime; + private final double smoothing; + private final double threshold; + + private MetricsImpl(String name, int estimationSize, long estimationTime, double smoothing, double threshold) { + this.name = name; + this.estimationSize = estimationSize; + this.estimationTime = estimationTime; + this.smoothing = smoothing; + this.threshold = threshold; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + try { + MetricsImpl that = (MetricsImpl) obj; + return this.name.equals(that.name); + } catch (Exception e) {} + return false; + } + + @Override + public String getName() { + return name; + } + + @Override + public synchronized double getServiceRate() { + return serviceRate; + } + + @Override + public double getThreshold() { + return threshold; + } + + @Override + public synchronized long getTotalEvents() { + return cumulativeEvents; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public synchronized void recordServiceRate(int numEvents, long time) { + totalEvents += numEvents; + cumulativeEvents += numEvents; + totalServiceTime += time; + count++; + long curTime = System.currentTimeMillis(); + if ((count == estimationSize) || (curTime - lastTime >= estimationTime)) { + if (totalEvents == 0) { + totalEvents = 1; + } + double rate = totalServiceTime / totalEvents; + serviceRate = (rate * smoothing) + (serviceRate * (1.0 - smoothing)); + count = 0; + lastTime = curTime; + totalEvents = totalServiceTime = 0; + } + } + + @Override + public synchronized void reset() { + serviceRate = 0.0; + count = 0; + lastTime = System.currentTimeMillis(); + totalEvents = totalServiceTime = cumulativeEvents = 0; + } + + @Override + public String toString() { + return name; + } + } + + private static final class NullMetrics implements Metrics { + + @Override + public String getName() { + return "NULL"; + } + + @Override + public double getServiceRate() { + return 0; + } + + @Override + public double getThreshold() { + return 0.0; + } + + @Override + public long getTotalEvents() { + return 0; + } + + @Override + public void recordServiceRate(int numEvents, long time) { + } + + @Override + public void reset() { + } + } + + private MetricsFactory() {} +} Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/base/src/org/ofbiz/base/metrics/MetricsFactory.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Modified: ofbiz/trunk/framework/common/servicedef/services.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/servicedef/services.xml?rev=1361722&r1=1361721&r2=1361722&view=diff ============================================================================== --- ofbiz/trunk/framework/common/servicedef/services.xml (original) +++ ofbiz/trunk/framework/common/servicedef/services.xml Sun Jul 15 16:07:59 2012 @@ -787,4 +787,20 @@ under the License. <attribute name="encoding" mode="IN" type="String" optional="true" default-value="UTF-8"></attribute> </service> + <!-- Metrics services --> + <service name="getAllMetrics" auth="true" use-transaction="false" + engine="java" location="org.ofbiz.common.CommonServices" invoke="getAllMetrics"> + <description> + Get all metrics. Returns a List of Maps - one Map per metric. Each Map includes the following keys: + name, serviceRate, threshold, totalEvents. See org.ofbiz.base.metrics.Metrics. + </description> + <attribute name="metricsList" mode="OUT" type="java.util.List" optional="false" /> + </service> + + <service name="resetMetric" auth="true" use-transaction="false" + engine="java" location="org.ofbiz.common.CommonServices" invoke="resetMetric"> + <description>Resets a metric. See org.ofbiz.base.metrics.Metrics.</description> + <attribute name="name" mode="IN" type="String" optional="false"/> + </service> + </services> Modified: ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java?rev=1361722&r1=1361721&r2=1361722&view=diff ============================================================================== --- ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java (original) +++ ofbiz/trunk/framework/common/src/org/ofbiz/common/CommonServices.java Sun Jul 15 16:07:59 2012 @@ -18,11 +18,14 @@ *******************************************************************************/ package org.ofbiz.common; +import static org.ofbiz.base.util.UtilGenerics.checkList; +import static org.ofbiz.base.util.UtilGenerics.checkMap; + import java.io.BufferedReader; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.RandomAccessFile; @@ -43,14 +46,14 @@ import javolution.util.FastMap; import org.apache.log4j.Level; import org.apache.log4j.Logger; +import org.ofbiz.base.metrics.Metrics; +import org.ofbiz.base.metrics.MetricsFactory; import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.StringUtil; import org.ofbiz.base.util.UtilDateTime; -import org.ofbiz.base.util.UtilValidate; - -import static org.ofbiz.base.util.UtilGenerics.checkList; -import static org.ofbiz.base.util.UtilGenerics.checkMap; import org.ofbiz.base.util.UtilMisc; import org.ofbiz.base.util.UtilProperties; +import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.Delegator; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericValue; @@ -63,6 +66,7 @@ import org.ofbiz.service.ModelService; import org.ofbiz.service.ServiceUtil; import org.ofbiz.service.ServiceXaWrapper; import org.ofbiz.service.mail.MimeMessageWrapper; +import org.owasp.esapi.errors.EncodingException; /** * Common Services @@ -541,4 +545,35 @@ public class CommonServices { } } + public static Map<String, Object> getAllMetrics(DispatchContext dctx, Map<String, ?> context) { + List<Map<String, Object>> metricsMapList = FastList.newInstance(); + List<Metrics> metricsList = MetricsFactory.getMetrics(); + for (Metrics metrics : metricsList) { + Map<String, Object> metricsMap = FastMap.newInstance(); + metricsMap.put("name", metrics.getName()); + metricsMap.put("serviceRate", metrics.getServiceRate()); + metricsMap.put("threshold", metrics.getThreshold()); + metricsMap.put("totalEvents", metrics.getTotalEvents()); + metricsMapList.add(metricsMap); + } + Map<String, Object> result = ServiceUtil.returnSuccess(); + result.put("metricsList", metricsMapList); + return result; + } + + public static Map<String, Object> resetMetric(DispatchContext dctx, Map<String, ?> context) { + String name = (String) context.get("name"); + try { + name = StringUtil.defaultWebEncoder.decodeFromURL(name); + } catch (EncodingException e) { + return ServiceUtil.returnError("Exception thrown while decoding metric name \"" + name + "\""); + } + Metrics metric = MetricsFactory.getMetric(name); + if (metric != null) { + metric.reset(); + return ServiceUtil.returnSuccess(); + + } + return ServiceUtil.returnError("Metric \"" + name + "\" not found."); + } } |
| Free forum by Nabble | Edit this page |
