Пример #1
0
        /// <summary>Creates a new metric definition from the provided information, or returns an existing matching definition if found.</summary>
        /// <remarks>If the metric definition 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.
        /// Definitions are looked up and added to the provided definitions dictionary.</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="unitCaption">The display caption for the calculated values captured under this metric.</param>
        /// <param name="description">A description of what is tracked by this metric, suitable for end-user display.</param>
        public static CustomSampledMetricDefinition AddOrGet(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName, MetricSampleType metricSampleType, string unitCaption, string description)
        {
            //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 = GetKey(metricTypeName, categoryName, counterName);
            IMetricDefinition definition;

            //we need the try and create to be atomic in a multi-threaded environment
            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, unitCaption, description);
                }
            }

            return((CustomSampledMetricDefinition)definition);
        }
        /// <summary>Creates a new metric definition from the provided information, or returns an existing matching definition if found.</summary>
        /// <remarks>If the metric definition 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.
        /// Definitions are looked up and added to the provided definitions dictionary.</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>
        public static EventMetricDefinition AddOrGet(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName)
        {
            //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 = GetKey(metricTypeName, categoryName, counterName);
            IMetricDefinition definition;

            //We need to grab a lock so our try get & the create are done as one lock.
            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 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.
                }
            }
            return((EventMetricDefinition)definition);
        }
Пример #3
0
 /// <summary>
 /// Create a new sampled metric object from the provided raw data packet.
 /// </summary>
 /// <remarks>The metric definition <b>will</b> be automatically added to the provided collection.</remarks>
 /// <param name="definitions">The definitions dictionary this definition is a part of.</param>
 /// <param name="packet">The packet to create a definition from.</param>
 internal SampledMetricDefinition(MetricDefinitionCollection definitions, SampledMetricDefinitionPacket packet)
     : base(definitions, packet)
 {
     // After the base constructor, auto-add ourself to the definition collection
     SetReadOnly();         // Make sure we're read-only before we're added to the collection.
     definitions.Add(this); // ToDo: Determine whether to keep or discard this behavior for sampled metrics.
 }
Пример #4
0
        /// <summary>
        /// Create a new metric definition from the provided metric definition packet.
        /// </summary>
        /// <remarks>At any one time there should only be one metric definition with a given combination of
        /// metric type, category, and counter name.  These values together are used to correlate metrics
        /// between sessions.  The metric definition will <b>not</b> be automatically added to the provided collection.</remarks>
        /// <param name="definitions">The definitions dictionary this definition is a part of</param>
        /// <param name="packet">The packet to create a definition from.</param>
        internal MetricDefinition(MetricDefinitionCollection definitions, MetricDefinitionPacket packet)
        {
            //make sure our definitions dictionary isn't null
            if (definitions == null)
            {
                throw new ArgumentNullException(nameof(definitions));
            }

            //make sure our packet isn't null
            if (packet == null)
            {
                throw new ArgumentNullException(nameof(packet));
            }

            m_Definitions = definitions;
            m_Packet      = packet;

            //and create our metric dictionary
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            m_Metrics = OnMetricDictionaryCreate();
            // ReSharper restore DoNotCallOverridableMethodsInConstructor

            //finally, auto-add ourself to the definition
            //m_Definitions.Add(this); // Commented out for new EventMetricDefinition protocol with Register().
        }
        /// <summary>
        /// Create a new event metric object from the provided raw data packet
        /// </summary>
        /// <param name="definitions">The definitions dictionary this definition is a part of</param>
        /// <param name="packet">The packet to create a definition from.</param>
        internal EventMetricDefinition(MetricDefinitionCollection definitions, MetricDefinitionPacket packet)
            : base(definitions, packet)
        {
            m_MetricValues = new EventMetricValueDefinitionCollection(this);

            //and we need to set that to our packet, all part of our bogus reach-around to make persistence work
            Packet.MetricValues = m_MetricValues;
        }
        /// <summary>
        /// Create a new event metric definition.
        /// </summary>
        /// <remarks>At any one time there should only be one metric definition with a given combination of
        /// metric type, category, and counter name.  These values together are used to correlate metrics
        /// between sessions.  The metric definition will <b>not</b> be automatically added to the provided collection.</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>
        public EventMetricDefinition(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName)
            : base(definitions, new EventMetricDefinitionPacket(metricTypeName, categoryName, counterName))
        {
            m_MetricValues = new EventMetricValueDefinitionCollection(this);

            //and we need to set that to our packet, all part of our bogus reach-around to make persistence work
            Packet.MetricValues = m_MetricValues;
        }
        /// <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);
        }
Пример #8
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);
        }
        /// <summary>
        /// Register this instance as a completed definition and return the valid usable definition for this event metric.
        /// </summary>
        /// <remarks>This call is necessary to complete a new event metric definition (created by calls to AddValue) before
        /// it can be used, and it signifies that all desired value columns have been added to the definition.  Only the
        /// first registration of a metric definition with a given Key (metrics system, category name, and counter name)
        /// will be effective and return the same definition object; subsequent calls (perhaps by another thread) will
        /// instead return the existing definition already registered.  If a definition already registered with that Key
        /// can not be an event metric (e.g. a sampled metric is defined with that Key) or if this instance defined value
        /// columns not present as compatible value columns in the existing registered definition with that Key, then an
        /// ArgumentException will be thrown to signal your programming mistake.</remarks>
        /// <returns>The actual usable definition with the same metrics system, category name, and counter name as this instance.</returns>
        public EventMetricDefinition Register()
        {
            EventMetricDefinition      officialDefinition;
            MetricDefinitionCollection definitionCollection = (MetricDefinitionCollection)Definitions;

            // We need to lock the collection while we check for an existing definition and maybe add this one to it.
            lock (definitionCollection.Lock)
            {
                IMetricDefinition rawDefinition;
                if (definitionCollection.TryGetValue(MetricTypeName, CategoryName, CounterName, out rawDefinition) == false)
                {
                    // There isn't already one by that Key.  Great!  Register ourselves.
                    SetReadOnly(); // Mark this definition as completed.
                    officialDefinition = this;
                    definitionCollection.Add(this);
                }
                else
                {
                    // Oooh, we found one already registered.  We'll want to do some checking on this, but outside the lock.
                    officialDefinition = rawDefinition as EventMetricDefinition;
                }
            } // End of collection lock

            if (officialDefinition == null)
            {
                throw new ArgumentException(
                          string.Format(
                              "There is already a metric definition for the same metrics system ({0}), category name ({1}), and counter name ({2}), but it is not an event metric.",
                              MetricTypeName, CategoryName, CounterName));
            }
            else if (this != officialDefinition)
            {
                // There was one other than us, make sure it's compatible with us.
                IEventMetricValueDefinitionCollection officialValues = officialDefinition.Values;
                foreach (EventMetricValueDefinition ourValue in Values)
                {
                    IEventMetricValueDefinition officialValue;
                    if (officialValues.TryGetValue(ourValue.Name, out officialValue) == false)
                    {
                        // It doesn't have one of our value columns!
                        throw new ArgumentException(
                                  string.Format(
                                      "There is already an event metric definition for the same metrics system ({0}), category name ({1}), and counter name ({2}), but it is not compatible; it does not define value column \"{3}\".",
                                      MetricTypeName, CategoryName, CounterName, ourValue.Name));
                    }
                    else if (ourValue.SerializedType != ((EventMetricValueDefinition)officialValue).SerializedType)
                    {
                        throw new ArgumentException(
                                  string.Format(
                                      "There is already an event metric definition for the same metrics system ({0}), category name ({1}), and counter name ({2}), but it is not compatible; " +
                                      "it defines value column \"{3}\" with type {4} rather than type {5}.",
                                      MetricTypeName, CategoryName, CounterName, ourValue.Name, officialValue.Type.Name, ourValue.Type.Name));
                    }
                }

                // We got through all the values defined in this instance?  Then we're okay to return the official one.
            }
            // Otherwise, it's just us, so we're all good.

            return(officialDefinition);
        }
Пример #10
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)
 {
 }
Пример #11
0
 /// <summary>
 /// Create a new custom sampled metric object from the provided raw data packet
 /// </summary>
 /// <remarks>The metric definition will automatically be added to the provided collection.</remarks>
 /// <param name="definitions">The definitions dictionary this definition is a part of</param>
 /// <param name="packet">The raw data packet</param>
 internal CustomSampledMetricDefinition(MetricDefinitionCollection definitions, CustomSampledMetricDefinitionPacket packet)
     : base(definitions, packet)
 {
     m_RequiresMultipleSamples = SampledMetricTypeRequiresMultipleSamples(packet.MetricSampleType);
 }
Пример #12
0
 /// <summary>
 /// Create a new metric definition.
 /// </summary>
 /// <remarks>At any one time there should only be one metric definition with a given combination of
 /// metric type, category, and counter name.  These values together are used to correlate metrics
 /// between sessions.  The metric definition will automatically be added to the provided collection.</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="unitCaption">The display caption for the calculated values captured under this metric.</param>
 /// <param name="description">A description of what is tracked by this metric, suitable for end-user display.</param>
 public CustomSampledMetricDefinition(MetricDefinitionCollection definitions, string metricTypeName, string categoryName, string counterName, MetricSampleType metricSampleType, string unitCaption, string description)
     : base(definitions, new CustomSampledMetricDefinitionPacket(metricTypeName, categoryName, counterName, metricSampleType, unitCaption, description))
 {
     m_RequiresMultipleSamples = SampledMetricTypeRequiresMultipleSamples(metricSampleType);
 }
Пример #13
0
        private string[] m_CategoryNames;   //the parsed array of the category name hierarchy, period delimited

        /// <summary>
        /// Create a new metric definition.
        /// </summary>
        /// <remarks>At any one time there should only be one metric definition with a given combination of
        /// metric type, category, and counter name.  These values together are used to correlate metrics
        /// between sessions.  The metric definition will <b>not</b> be automatically added to the provided collection.</remarks>
        /// <param name="definitions">The definitions dictionary this definition is a part of</param>
        /// <param name="metricType">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="sampleType">The type of data sampling done for this metric.</param>
        public MetricDefinition(MetricDefinitionCollection definitions, string metricType, string categoryName, string counterName, SampleType sampleType)
            : this(definitions, new MetricDefinitionPacket(metricType, categoryName, counterName, sampleType))
        {
        }