/// <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);
        }
Пример #2
0
 /// <summary>
 /// Create a new event metric object from the provided raw data packet
 /// </summary>
 /// <remarks>The new metric will automatically be added to the metric definition's metrics collection.</remarks>
 /// <param name="definition">The object that defines this metric</param>
 /// <param name="packet">The raw data packet</param>
 internal EventMetric(EventMetricDefinition definition, EventMetricPacket packet)
     : base(definition, packet)
 {
     // We created an EventMetricSampleCollection when base constructor called our OnSampleCollectionCreate().
     m_Samples          = (EventMetricSampleCollection)base.Samples;
     m_MetricDefinition = definition;
     m_Packet           = packet;
 }
Пример #3
0
        /// <summary>
        /// Create a new value definition from the provided information.
        /// </summary>
        /// <param name="definition">The metric definition that owns this value definition</param>
        /// <param name="packet">The prepopulated value definition packet.</param>
        internal EventMetricValueDefinition(EventMetricDefinition definition, EventMetricValueDefinitionPacket packet)
        {
            m_Definition = definition;
            m_Packet     = packet;

            //and determine if it is trendable or not
            m_Trendable = EventMetricDefinition.IsTrendableValueType(m_Packet.Type);
            MyIndex     = -1; // Mark it as unknown.
        }
Пример #4
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>
        /// Records a value to the values array of this sample given its value definition.
        /// </summary>
        /// <remarks>The value must be defined as part of the event metric definition associated with this sample
        /// or an exception will be thrown.  The data type must also be compatible with the data type configured
        /// on the event metric definition or no data will be recorded.
        /// If called more than once for the same value, the prior value will be replaced.</remarks>
        /// <param name="valueDefinition">The metric value definition object of the value to be recorded.</param>
        /// <param name="value">The value to be recorded.</param>
        public void SetValue(EventMetricValueDefinition valueDefinition, object value)
        {
            //make sure we got a value definition
            if (valueDefinition == null)
            {
                throw new ArgumentNullException(nameof(valueDefinition));
            }

            //look up the numerical index in the collection so we know what offset to put it in the array at
            int valueIndex = Metric.Definition.Values.IndexOf(valueDefinition);

            //if we didn't find it, we're hosed
            if (valueIndex < 0)
            {
#if DEBUG
                //if we're compiled in debug mode, tell the user they blew it.
                throw new ArgumentOutOfRangeException(nameof(valueDefinition), valueDefinition.Name);
#else
                //log and return, nothing we can do.
                if (!Log.SilentMode)
                {
                    Log.Write(LogMessageSeverity.Warning, LogCategory, "Unable to add metric value to the current sample due to missing value definition",
                              "There is no value definition named {1} for metric definition {0}",
                              Metric.Definition.Name, valueDefinition.Name);
                }
                return;
#endif
            }

            //coerce it into the right type
            object storedValue;
            if (value == null)
            {
                //you can always store a null.  And we can't really check it more, so there.
                storedValue = null;
            }
            else
            {
                //get the type so we can verify it
                Type valueType = value.GetType();

                //is it close enough to what we're expecting?
                if (valueDefinition.IsTrendable)
                {
                    if (EventMetricDefinition.IsTrendableValueType(valueType))
                    {
                        storedValue = value;
                    }
                    else
                    {
                        //no, it should be trendable and it isn't.  store null.
                        storedValue = null;
                    }
                }
                else
                {
                    //we don't care what it is because we're going to coerce it to a string.
                    storedValue = value.ToString();
                }
            }

            //now write out the value to the correct spot in the array
            Packet.Values[valueIndex] = storedValue;
        }
Пример #6
0
 /// <summary>
 /// Create a new event metric object from the provided metric definition
 /// </summary>
 /// <remarks>The new metric will automatically be added to the metric definition's metrics collection.</remarks>
 /// <param name="definition">The metric definition for the metric instance</param>
 /// <param name="instanceName">The unique name of this instance within the metric's collection.</param>
 public EventMetric(EventMetricDefinition definition, string instanceName)
     : this(definition, new EventMetricPacket(definition.Packet, instanceName))
 {
 }
Пример #7
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.
 /// Definitions are looked up and added to the active logging metrics collection (Log.Metrics)</remarks>
 /// <param name="definition">The metric definition for the metric instance</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(EventMetricDefinition definition, string instanceName)
 {
     //just forward into our call that requires the definition to be specified
     return(AddOrGet(Log.Metrics, definition.MetricTypeName, definition.CategoryName, definition.CounterName, instanceName));
 }
 /// <summary>
 /// Create a new values dictionary for the specified metric definition
 /// </summary>
 /// <param name="definition">The parent metric definition object that will own this dictionary.</param>
 internal EventMetricValueDefinitionCollection(EventMetricDefinition definition)
 {
     m_Definition = definition;
 }
Пример #9
0
 /// <summary>
 /// Create a new event metric dictionary for the provided definition.
 /// </summary>
 /// <remarks>This dictionary is created automatically by the Custom Sampled Metric Definition during its initialization.</remarks>
 /// <param name="metricDefinition">The definition of the custom sampled metric to create a metric dictionary for</param>
 public EventMetricCollection(EventMetricDefinition metricDefinition)
     : base(metricDefinition)
 {
 }