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

com.onloupe.agent.metrics.EventMetricCollection Maven / Gradle / Ivy

package com.onloupe.agent.metrics;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import com.onloupe.core.util.OutObject;
import com.onloupe.core.util.TypeUtils;


/**
 * The collection of event metrics for a given event metric definition.
 */
public class EventMetricCollection {
    
    /** The dictionary by name. */
    private final Map dictionaryByName = new HashMap();
    
    /** The dictionary. */
    private final Map dictionary = new HashMap();
    
    /** The lock. */
    private final Object lock = new Object();
    
    /** The metric definition. */
    private final EventMetricDefinition metricDefinition;
    
	/**
	 * Create a new event metric dictionary for the provided definition.
	 * 
	 * This dictionary is created automatically by the Custom Sampled Metric
	 * Definition during its initialization.
	 * 
	 * @param metricDefinition The definition of the event metric to create a metric
	 *                         dictionary for
	 */
	public EventMetricCollection(EventMetricDefinition metricDefinition) {
		this.metricDefinition = metricDefinition;
	}

	/**
	 * Determines whether the collection contains an element with the specified key.
	 * 
	 * @param key The key to locate in the collection
	 * @return true if the collection contains an element with the key; otherwise,
	 *         false.
	 */
	public final boolean containsKey(UUID key) {
		// gateway to our inner dictionary
		return this.dictionary.containsKey(key);
	}

	/**
	 * Determines whether the collection contains an element with the specified key.
	 * 
	 * @param key The metric name to locate in the collection
	 * @return true if the collection contains an element with the key; otherwise,
	 *         false.
	 */
	public final boolean containsKey(String key) {
		// gateway to our alternate inner dictionary
		return this.dictionaryByName.containsKey(key);
	}

	/**
	 * Create a new metric object with the provided instance name and add it to the
	 * collection.
	 *
	 * @param instanceName The instance name to use, or blank or null for the
	 *                     default metric.
	 * @return The new metric object that was added to the collection
	 */
	public final EventMetric add(String instanceName) {
		synchronized (this.lock) {
			// Create a new metric object with the provided instance name (it will get added
			// to us automatically)
			EventMetric newMetric = new EventMetric(this.metricDefinition, instanceName);
			this.dictionary.put(newMetric.getId(), newMetric);
			this.dictionaryByName.put(newMetric.getInstanceName(), newMetric);
			// finally, return the newly created metric object to our caller
			return newMetric;
		}
	}

	/*
	 * /// Creates a new metric instance or returns an existing one by
	 * inspecting the provided object for EventMetricDefinition
	 * attributes. /// If the metric doesn't exist, it will be
	 * created. /// If the metric definition does exist, but is not an Event Metric
	 * (or a derived class) an exception will be thrown. /// If the metric
	 * definition isn't bound to an object type, the default metric will be
	 * returned. /// The provided object must not be null and must be of the type
	 * the metric definition owning this dictionary is bound to. ///
	 * The object to create a metric from. ///
	 * The event metric object for the specified event metric
	 * instance. public EventMetric AddOrGet(object userDataObject) {
	 * EventMetric newMetric;
	 * 
	 * //we need a live object, not a null object or we'll fail if (userDataObject
	 * == null) { throw new ArgumentNullException("userDataObject"); }
	 * 
	 * //great. We now know a lot - namely that it has to have the right attributes,
	 * etc. to define a metric so we can //now go and find all of the information we
	 * need to create a new metric. string instanceName = null; if
	 * (Definition.NameBound) { //we don't even need to get it - we just care that
	 * it's defined. try { //To be righteous, we need to only invoke the member
	 * we're looking at BindingFlags methodBinding; switch
	 * (Definition.NameMemberType) { case MemberTypes.Field: methodBinding =
	 * BindingFlags.GetField; break; case MemberTypes.Method: methodBinding =
	 * BindingFlags.InvokeMethod; break; case MemberTypes.Property: methodBinding =
	 * BindingFlags.GetProperty; break; default: throw new
	 * ArgumentOutOfRangeException(); }
	 * 
	 * //invoke the bound instance name from the type our definition is associated
	 * with. This way if the object provided //has multiple implementations that are
	 * metric-enabled, we use the correct one. object rawValue =
	 * Definition.BoundType.InvokeMember(Definition.NameMemberName, methodBinding,
	 * null, userDataObject, null, Locale.ROOT);
	 * 
	 * //and the raw value is either null or something we're going to convert to a
	 * string if (rawValue == null) { instanceName = null; } else { instanceName =
	 * rawValue.ToString(); } } catch (Exception ex) { //just trace log this - we
	 * can continue, they'll just get the default instance until they fix their
	 * code. Trace.
	 * TraceWarning("Unable to retrieve the instance name to create a specific %s metric because an exception occurred while accessing the member {1}: {2}"
	 * , Definition.Key, Definition.NameMemberName, ex.ToString()); } }
	 * 
	 * //now that we have our instance name, we go ahead and see if there is already
	 * an instance with the right name or just add it lock (this.Lock) //make sure
	 * the try & add are atomic { if (TryGetValue(instanceName, out newMetric) ==
	 * false) { //there isn't one with the right name, we need to create it.
	 * newMetric = Add(instanceName); } }
	 * 
	 * //return what we got - we have an object one way or another, or we threw an
	 * exception. return newMetric; }
	 */

	/**
	 * The definition of all of the metrics in this collection.
	 *
	 * @return the definition
	 */
	public final EventMetricDefinition getDefinition() {
		return this.metricDefinition;
	}

	/**
	 * Retrieve an item from the collection by its key if present. If not present,
	 * the default value of the object is returned.
	 * 
	 * @param key   The key of the value to get.
	 * @param value When this method returns, contains the value associated with the
	 *              specified key, if the key is found; otherwise, the default value
	 *              for the type of the value parameter. This parameter is passed
	 *              uninitialized.
	 * @return true if the collection contains an element with the specified key;
	 *         otherwise false.
	 */
	public final boolean tryGetValue(UUID key, OutObject value) {
		synchronized (this.lock) {
			// We are playing a few games to get native typing here.
			// Because it's an out value, we have to swap types around ourselves so we can
			// cast.
			return dictionary.containsKey(key);
		}
	}

	/**
	 * Retrieve an item from the collection by its key if present. If not present,
	 * the default value of the object is returned.
	 * 
	 * @param key   The metric name to locate in the collection
	 * @param value When this method returns, contains the value associated with the
	 *              specified key, if the key is found; otherwise, the default value
	 *              for the type of the value parameter. This parameter is passed
	 *              uninitialized.
	 * @return true if the collection contains an element with the specified key;
	 *         otherwise false.
	 */
	public final boolean tryGetValue(String key, OutObject value) {
		synchronized (this.lock) {
			// We are playing a few games to get native typing here.
			// Because it's an out value, we have to swap types around ourselves so we can
			// cast.
			value.argValue = dictionaryByName.get(TypeUtils.trimToNull(key));
			return value.argValue != null;
		}
	}

	/**
	 * Retrieve event metric object by its Id.
	 *
	 * @param id the id
	 * @return the event metric
	 */
	public final EventMetric get(UUID id) {
		synchronized (this.lock) {
			return this.dictionary.get(id);
		}
	}

	/**
	 * Retrieve event metric object by its name.
	 *
	 * @param key the key
	 * @return the event metric
	 */
	public final EventMetric get(String key) {
		synchronized (this.lock) {
			return this.dictionaryByName.get(TypeUtils.trimToNull(key));
		}
	}

	/**
	 * Object Change Locking object.
	 *
	 * @return the lock
	 */
	public final Object getLock() {
		return this.lock;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy