Ejemplo n.º 1
0
        private long m_SampleSequence = 0; //used when adding sampled metrics to ensure order.

        /// <summary>
        /// Create a new metric with the provided metric definition and metric packet.
        /// </summary>
        /// <remarks>Most derived classes will provide a more convenient implementation that will automatically
        /// create the correct metric packet instead of the caller having to first create it.
        /// The new metric will automatically be added to the metric definition's metrics collection.</remarks>
        /// <param name="definition">The definition for this metric</param>
        /// <param name="packet">The metric packet to use for this metric</param>
        internal Metric(MetricDefinition definition, MetricPacket packet)
        {
            //verify and store off our input
            if (definition == null)
            {
                throw new ArgumentNullException(nameof(definition));
            }

            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet));
            }

            //one last safety check:  The definition and the packet better agree.
            if (definition.Id != packet.DefinitionId)
            {
                throw new ArgumentOutOfRangeException(nameof(packet), "The provided metric packet has a different definition Id than the provide metric definition.");
            }

            //and now that we know everything isn't null, go ahead and store things off
            m_MetricDefinition = definition;
            m_Packet           = packet;

            //and force our inheritor to create the samples collection so we get the right derived class.
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            m_Samples = OnSampleCollectionCreate();
            // ReSharper restore DoNotCallOverridableMethodsInConstructor

            //finally, add ourself to the metric definition's metrics collection
            m_MetricDefinition.Metrics.Add(this);
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Create a new metric dictionary for the provided definition.
 /// </summary>
 /// <remarks>This dictionary is created automatically by the Metric Definition during its initialization.</remarks>
 /// <param name="metricDefinition"></param>
 internal MetricCollection(MetricDefinition metricDefinition)
 {
     if (metricDefinition == null)
     {
         throw new ArgumentNullException(nameof(metricDefinition));
     }
     m_MetricDefinition = metricDefinition;
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Calculate the string key for a metric.
        /// </summary>
        /// <param name="metricDefinition">The existing metric definition object to generate a string key for</param>
        /// <param name="instanceName">The name of the performance counter category instance, or an empty string (""), if the category contains a single instance.</param>
        /// <returns>The unique string key for this item</returns>
        public static string GetKey(MetricDefinition metricDefinition, string instanceName)
        {
            //make sure the metric definition object isn't null
            if (metricDefinition == null)
            {
                throw new ArgumentNullException(nameof(metricDefinition));
            }

            return(GetKey(metricDefinition.MetricTypeName, metricDefinition.CategoryName, metricDefinition.CounterName, instanceName));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Takes an instance name or complete metric name and normalizes it to a metric name so it can be used to look up a metric
        /// </summary>
        /// <param name="metricDefinition">The metric definition to look for metrics within</param>
        /// <param name="metricKey">The instance name or complete metric name</param>
        /// <returns></returns>
        internal static string NormalizeKey(MetricDefinition metricDefinition, string metricKey)
        {
            string returnVal;
            string trueMetricKey;

            bool prependDefinitionName = false;

            //Did we get a null?  If we got a null, we know we need to pre-pend the definition (and it isn't safe to do any more testing)
            if (metricKey == null)
            {
                prependDefinitionName = true;
                trueMetricKey         = null;
            }
            else
            {
                //trim the input for subsequent testing to see what we get
                trueMetricKey = metricKey.Trim();

                if (string.IsNullOrEmpty(trueMetricKey))
                {
                    //we know we need to pre-pend the definition name
                    prependDefinitionName = true;
                }
                else
                {
                    //OK, a true key is a full name, so see if the key we got STARTS with our definition name
                    if (trueMetricKey.Length < metricDefinition.Name.Length)
                    {
                        //the key we got is shorter than the length of the metric definition name, so it can't include the metric definition name.
                        prependDefinitionName = true;
                    }
                    else
                    {
                        //now check the start of the string to see what we get
                        if (trueMetricKey.StartsWith(metricDefinition.Name, StringComparison.Ordinal) == false)
                        {
                            //they aren't the same at least as long as the metric definition name is, so we assume we need to pre-pend.
                            prependDefinitionName = true;
                        }
                    }
                }
            }

            //If the value we got was just the instance name, we need to put the metric definition's key in front of it.
            if (prependDefinitionName)
            {
                returnVal = GetKey(metricDefinition, trueMetricKey);
            }
            else
            {
                returnVal = trueMetricKey;
            }

            return(returnVal);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Determines whether the collection contains an element with the specified key.
        /// </summary>
        /// <param name="metricTypeName">The unique metric type</param>
        /// <param name="categoryName">The name of the category with which this definition is associated.</param>
        /// <param name="counterName">The name of the definition within the category.</param>
        /// <returns>true if the collection contains an element with the key; otherwise, false.</returns>
        public bool ContainsKey(string metricTypeName, string categoryName, string counterName)
        {
            //get the key for the provided values
            string key = MetricDefinition.GetKey(metricTypeName, categoryName, counterName);

            lock (m_Lock)
            {
                //gateway to our alternate inner dictionary
                return(m_DictionaryByName.ContainsKey(key));
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Determines whether the collection contains an element with the specified key.
        /// </summary>
        /// <param name="key">The metric name to locate in the collection</param>
        /// <returns>true if the collection contains an element with the key; otherwise, false.</returns>
        public bool ContainsKey(string key)
        {
            //we do a few cute tricks to normalize the key before checking it to be tolerant of what users do
            string trueKey = MetricDefinition.NormalizeKey(m_MetricDefinition, key);

            lock (m_Lock)
            {
                //gateway to our alternate inner dictionary
                return(m_DictionaryByName.ContainsKey(trueKey));
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Retrieve an item from the collection by its key if present.  If not present, the default value of the object is returned.
        /// </summary>
        /// <param name="key">The metric name to locate in the collection</param>
        /// <param name="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.</param>
        /// <returns>true if the collection contains an element with the specified key; otherwise false.</returns>
        public bool TryGetValue(string key, out IMetric value)
        {
            //we do a few cute tricks to normalize the key before checking it to be tolerant of what users do
            string trueKey = MetricDefinition.NormalizeKey(m_MetricDefinition, key);

            lock (m_Lock)
            {
                //gateway to our inner dictionary try get value
                return(m_DictionaryByName.TryGetValue(trueKey, out value));
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Retrieve an item from the collection by its key if present.  If not present, the default value of the object is returned.
        /// </summary>
        /// <param name="metricTypeName">The unique metric type</param>
        /// <param name="categoryName">The name of the category with which this definition is associated.</param>
        /// <param name="counterName">The name of the definition within the category.</param>
        /// <param name="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.</param>
        /// <returns>true if the collection contains an element with the specified key; otherwise false.</returns>
        /// <exception cref="ArgumentNullException">The provided metricsSystem, categoryName, or counterName was null.</exception>
        public bool TryGetValue(string metricTypeName, string categoryName, string counterName, out IMetricDefinition value)
        {
            //get the key for the provided values
            string key = MetricDefinition.GetKey(metricTypeName, categoryName, counterName);

            lock (m_Lock)
            {
                //gateway to our inner dictionary try get value
                return(m_DictionaryByName.TryGetValue(key, out value));
            }
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Retrieve metric object by its type, category, and counter names.
 /// </summary>
 /// <param name="metricTypeName">The unique metric type</param>
 /// <param name="categoryName">The name of the category with which this definition is associated.</param>
 /// <param name="counterName">The name of the definition within the category.</param>
 /// <returns></returns>
 public IMetricDefinition this[string metricTypeName, string categoryName, string counterName]
 {
     get
     {
         //create the key from the parts we got
         string key = MetricDefinition.GetKey(metricTypeName, categoryName, counterName);
         lock (m_Lock)
         {
             return(m_DictionaryByName[key]);
         }
     }
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Retrieve metric object by its name
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public IMetric this[string key]
        {
            get
            {
                //we do a few cute tricks to normalize the key before checking it to be tolerant of what users do
                string trueKey = MetricDefinition.NormalizeKey(m_MetricDefinition, key);

                lock (m_Lock)
                {
                    return(m_DictionaryByName[trueKey]);
                }
            }
        }
        /// <summary>Creates a new metric instance from the provided definition information, or returns any existing instance if found.</summary>
        /// <remarks>If the metric definition doesn't exist, it will be created.  If the metric doesn't exist, it will be created.
        /// If the metric definition does exist, but is not a Custom Sampled Metric (or a derived class) an exception will be thrown.</remarks>
        /// <param name="definitions">The definitions dictionary this definition is a part of</param>
        /// <param name="metricTypeName">The unique metric type</param>
        /// <param name="categoryName">The name of the category with which this definition is associated.</param>
        /// <param name="counterName">The name of the definition within the category.</param>
        /// <param name="metricSampleType">The type of data captured for each metric under this definition.</param>
        /// <param name="instanceName">The unique name of this instance within the metric's collection.</param>
        public static CustomSampledMetric AddOrGet(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName, MetricSampleType metricSampleType, string instanceName)
        {
            //we must have a definitions collection, or we have a problem
            if (definitions == null)
            {
                throw new ArgumentNullException(nameof(definitions));
            }

            //we need to find the definition, adding it if necessary
            string            definitionKey = MetricDefinition.GetKey(metricTypeName, categoryName, counterName);
            IMetricDefinition definition;

            //Establish a lock on the definitions collection so our lookup & create are atomic.
            lock (definitions.Lock)
            {
                if (definitions.TryGetValue(definitionKey, out definition))
                {
                    //if the metric definition exists, but is of the wrong type we have a problem.
                    if ((definition is CustomSampledMetricDefinition) == false)
                    {
                        throw new ArgumentException("A metric already exists with the provided type, category, and counter name but it is not compatible with being a custom sampled metric.  Please use a different counter name.", nameof(counterName));
                    }
                }
                else
                {
                    //we didn't find one, make a new one
                    definition =
                        new CustomSampledMetricDefinition(definitions, metricTypeName, categoryName, counterName,
                                                          metricSampleType);
                }
            }

            //now we have our definition, proceed to create a new metric if it doesn't exist
            string  metricKey = MetricDefinition.GetKey(metricTypeName, categoryName, counterName, instanceName);
            IMetric metric;

            //see if we can get the metric already.  If not, we'll create it
            lock (((MetricCollection)definition.Metrics).Lock)
            {
                if (definition.Metrics.TryGetValue(metricKey, out metric) == false)
                {
                    metric = new CustomSampledMetric((CustomSampledMetricDefinition)definition, instanceName);
                }
            }

            return((CustomSampledMetric)metric);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Add an existing metric packet object to our collection for the supplied packet.
        /// </summary>
        /// <param name="newDefinitionPacket">The new metric packet object to add.</param>
        internal MetricDefinition Add(MetricDefinitionPacket newDefinitionPacket)
        {
            //just do the null check - the rest of the checks (like dupe checks) are done in the normal add routine
            if (newDefinitionPacket == null)
            {
                throw new ArgumentNullException(nameof(newDefinitionPacket), "A metric packet object must be provided to add it to the collection.");
            }

            //create a new metric object to wrap the supplied metric packet
            MetricDefinition newDefinition = new MetricDefinition(this, newDefinitionPacket);

            //and call our mainstream add method which does the rest of our checks.
            Add(newDefinition);

            //return the newly added object so our caller doesn't have to go digging for it
            return(newDefinition);
        }
Ejemplo n.º 13
0
        /// <summary>Creates a new metric instance or returns an existing one from the provided definition information, or returns any existing instance if found.</summary>
        /// <remarks>If the metric definition doesn't exist, it will be created.  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.</remarks>
        /// <param name="definitions">The definitions dictionary this definition is a part of</param>
        /// <param name="metricTypeName">The unique metric type</param>
        /// <param name="categoryName">The name of the category with which this definition is associated.</param>
        /// <param name="counterName">The name of the definition within the category.</param>
        /// <param name="instanceName">The unique name of this instance within the metric's collection.</param>
        /// <returns>The event metric object for the specified event metric instance.</returns>
        public static EventMetric AddOrGet(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName, string instanceName)
        {
            //we must have a definitions collection, or we have a problem
            if (definitions == null)
            {
                throw new ArgumentNullException(nameof(definitions));
            }

            //we need to find the definition, adding it if necessary
            string            definitionKey = MetricDefinition.GetKey(metricTypeName, categoryName, counterName);
            IMetricDefinition definition;

            if (definitions.TryGetValue(definitionKey, out definition))
            {
                //if the metric definition exists, but is of the wrong type we have a problem.
                if ((definition is EventMetricDefinition) == false)
                {
                    throw new ArgumentException("A metric already exists with the provided type, category, and counter name but it is not compatible with being an event metric.  Please use a different counter name.", nameof(counterName));
                }
            }
            else
            {
                //we didn't find one, make a new one
                definition = new EventMetricDefinition(definitions, metricTypeName, categoryName, counterName);
                definitions.Add(definition); // Add it to the collection, no longer done in the constructor.
                // ToDo: Reconsider this implementation; putting incomplete event metric definitions in the collection is not ideal,
                // and creating a metric from an empty event metric definition is fairly pointless.
            }

            //now we have our definition, proceed to create a new metric if it doesn't exist
            string  metricKey = MetricDefinition.GetKey(metricTypeName, categoryName, counterName, instanceName);
            IMetric metric;

            //see if we can get the metric already.  If not, we'll create it
            lock (((MetricCollection)definition.Metrics).Lock) //make sure the get & add are atomic
            {
                if (definition.Metrics.TryGetValue(metricKey, out metric) == false)
                {
                    metric = new EventMetric((EventMetricDefinition)definition, instanceName);
                }
            }

            return((EventMetric)metric);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Retrieves the specified metric instance, or creates it if it doesn't exist
        /// </summary>
        /// <param name="instanceName"></param>
        /// <returns>The custom sampled metric object.</returns>
        private CustomSampledMetric EnsureMetricExists(string instanceName)
        {
            //Find the right metric sample instance, creating it if we have to.
            string  metricKey = MetricDefinition.GetKey(this, instanceName);
            IMetric ourMetric;

            //This must be protected in a multi-threaded environment
            lock (Metrics.Lock)
            {
                if (Metrics.TryGetValue(metricKey, out ourMetric) == false)
                {
                    //it doesn't exist - go ahead and add it
                    ourMetric = new CustomSampledMetric(this, instanceName);
                }
            }

            //and return the metric
            return((CustomSampledMetric)ourMetric);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Add the supplied Metric item to this collection.
        /// </summary>
        /// <remarks>Metrics automatically add themselves when they are created, so it isn't necessary (and will produce errors) to manually add them.</remarks>
        /// <param name="item">The new Metric item to add to this collection</param>
        public void Add(IMetric item)
        {
            //we really don't want to support this method, but we have to for ICollection<T> compatibility.  So we're going to ruthlessly
            //verify that the metric object was created correctly.

            if (item == null)
            {
                throw new ArgumentNullException(nameof(item), "A metric item must be provided to add it to the collection.");
            }

            //make sure the metric is for the right definition, namely our definition.
            if (MetricDefinition.GetKey(item) != m_MetricDefinition.Name)
            {
                throw new ArgumentOutOfRangeException(nameof(item), "The provided metric item is not related to the metric definition that owns this metrics collection.");
            }

            //we're about to modify the collection, get a lock.  We don't want the lock to cover the changed event since
            //we really don't know how long that will take, and it could be deadlock prone.
            lock (m_Lock)
            {
                //make sure we don't already have it
                if (m_Dictionary.ContainsKey(item.Id))
                {
                    throw new ArgumentException("The specified metric item is already in the collection.", nameof(item));
                }

                if (m_DictionaryByName.ContainsKey(item.Name))
                {
                    throw new ArgumentException("A metric item for the same metric is already in the collection.", nameof(item));
                }

                //add it to all of our collections, and to the definition metric cache.
                m_Dictionary.Add(item.Id, item);
                m_DictionaryByName.Add(item.Name, item);
                m_List.Add(item);
                ((MetricDefinitionCollection)m_MetricDefinition.Definitions).AddMetric(item);
            }

            //and fire our event
            OnCollectionChanged(new CollectionChangedEventArgs <IMetricCollection, IMetric>(this, item, CollectionAction.Added));
        }
Ejemplo n.º 16
0
 /// <summary>Creates a new event metric object from the metric definition looked up with the provided key information.</summary>
 /// <remarks>The metric definition must already exist or an exception will be raised.</remarks>
 /// <param name="definitions">The definitions dictionary this definition is a part of</param>
 /// <param name="metricTypeName">The unique metric type</param>
 /// <param name="categoryName">The name of the category with which this definition is associated.</param>
 /// <param name="counterName">The name of the definition within the category.</param>
 /// <param name="instanceName">The unique name of this instance within the metric's collection.</param>
 public EventMetric(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName, string instanceName)
     : this((EventMetricDefinition)definitions[MetricDefinition.GetKey(metricTypeName, categoryName, counterName)], instanceName)
 {
 }
Ejemplo n.º 17
0
        /// <summary>
        /// Determines if the provided object is identical to this object.
        /// </summary>
        /// <param name="obj">The object to compare this object to</param>
        /// <returns>True if the other object is also a MetricDefinition and represents the same data.</returns>
        public override bool Equals(object obj)
        {
            MetricDefinition otherMetricDefinition = obj as MetricDefinition;

            return(Equals(otherMetricDefinition)); // Just have type-specific Equals do the check (it even handles null)
        }