/// <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); }
/// <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; }
/// <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. }
/// <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; }
/// <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)) { }
/// <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; }
/// <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) { }