All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.terracotta.statistics.StatisticsManager Maven / Gradle / Ivy

Go to download

Ehcache is an open source, standards-based cache used to boost performance, offload the database and simplify scalability. Ehcache is robust, proven and full-featured and this has made it the most widely-used Java-based cache.

There is a newer version: 2.10.9.2
Show newest version
/*
 * All content copyright Terracotta, Inc., unless otherwise indicated.
 *
 * Licensed 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.
 */
package org.terracotta.statistics;


import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;

import org.terracotta.context.ContextCreationListener;
import org.terracotta.context.ContextElement;
import org.terracotta.context.ContextManager;
import org.terracotta.context.TreeNode;
import org.terracotta.statistics.observer.OperationObserver;

public class StatisticsManager extends ContextManager {
  
  static {
    ContextManager.registerContextCreationListener(new ContextCreationListener() {
      @Override
      public void contextCreated(Object object) {
        parseStatisticAnnotations(object);
      }
    });
  }
  
  public static > OperationObserver createOperationStatistic(Object context, String name, Set tags, Class eventTypes) {
    return createOperationStatistic(context, name, tags, Collections.emptyMap(), eventTypes);
  }
  
  public static > OperationObserver createOperationStatistic(Object context, String name, Set tags, Map properties, Class resultType) {
    OperationStatistic stat = createOperationStatistic(name, tags, properties, resultType);
    associate(context).withChild(stat);
    return stat;
  }

  private static > OperationStatistic createOperationStatistic(String name, Set tags, Map properties, Class resultType) {
    return new GeneralOperationStatistic(name, tags, properties, resultType);
  }
  
  public static > OperationStatistic getOperationStatisticFor(OperationObserver observer) {
    TreeNode node = ContextManager.nodeFor(observer);
    if (node == null) {
      return null;
    } else {
      ContextElement context = node.getContext();
      if (OperationStatistic.class.isAssignableFrom(context.identifier())) {
        return (OperationStatistic) context.attributes().get("this");
      } else {
        throw new AssertionError();
      }
    }
  }
  
  public static  void createPassThroughStatistic(Object context, String name, Set tags, Callable source) {
    createPassThroughStatistic(context, name, tags, Collections.emptyMap(), source);
  }
  
  public static  void createPassThroughStatistic(Object context, String name, Set tags, Map properties, Callable source) {
    PassThroughStatistic stat = new PassThroughStatistic(context, name, tags, properties, source);
    associate(context).withChild(stat);
  }

  private static void parseStatisticAnnotations(final Object object) {
    for (final Method m : object.getClass().getMethods()) {
      Statistic anno = m.getAnnotation(Statistic.class);
      if (anno != null) {
        Class returnType = m.getReturnType();
        if (m.getParameterTypes().length != 0) {
          throw new IllegalArgumentException("Statistic methods must be no-arg: " + m);
        } else if (!Number.class.isAssignableFrom(returnType) && (!m.getReturnType().isPrimitive() || m.getReturnType().equals(Boolean.TYPE))) {
          throw new IllegalArgumentException("Statistic methods must return a Number: " + m);
        } else if (Modifier.isStatic(m.getModifiers())) {
          throw new IllegalArgumentException("Statistic methods must be non-static: " + m);
        } else {
          StatisticsManager.createPassThroughStatistic(object, anno.name(), new HashSet(Arrays.asList(anno.tags())), new MethodCallable(object, m));
        }
      } 
    }
  }
  
  static class MethodCallable implements Callable {

    private final WeakReference targetRef;
    private final Method method;
    
    MethodCallable(Object target, Method method) {
      this.targetRef = new WeakReference(target);
      this.method = method;
    }

    @Override
    public T call() throws Exception {
      return (T) method.invoke(targetRef.get());
    }
  }
}