/// <summary /> /// <param name="seriesCountLimit"></param> /// <param name="valuesPerDimensionLimit"></param> /// <param name="seriesConfig"></param> public MetricConfiguration( int seriesCountLimit, int valuesPerDimensionLimit, IMetricSeriesConfiguration seriesConfig) { if (seriesCountLimit < 1) { throw new ArgumentOutOfRangeException( nameof(seriesCountLimit), $"Metrics must allow at least one data series (but {seriesCountLimit} was specified)."); } if (valuesPerDimensionLimit < 0) { throw new ArgumentOutOfRangeException(nameof(valuesPerDimensionLimit)); } Util.ValidateNotNull(seriesConfig, nameof(seriesConfig)); SeriesCountLimit = seriesCountLimit; ValuesPerDimensionLimit = valuesPerDimensionLimit; SeriesConfig = seriesConfig; _hashCode = Util.CombineHashCodes( SeriesCountLimit.GetHashCode(), ValuesPerDimensionLimit.GetHashCode(), SeriesConfig.GetType().FullName.GetHashCode(), SeriesConfig.GetHashCode()); }
/// <summary>Gets the specified metric, or creates one if no such metric exists.</summary> /// <param name="metricIdentifier">The identity of the metric.</param> /// <param name="metricConfiguration">@The configutration of the metric.</param> /// <returns>A metric witht he specified identify and configuration.</returns> /// <exception cref="ArgumentException">If a metric with the specified identify exists, /// but its configuration does not match the specified configuration. /// You may not change a metric configurations once a metric was created for the first time. /// Either specify the same configuration every time, or specify <c>null</c> during every /// invocation except the first one. <c>null</c> will match against any previously specified /// configuration when retrieving existing metrics, or fall back to the default when /// creating new metrics.</exception> public Metric GetOrCreate( MetricIdentifier metricIdentifier, MetricConfiguration metricConfiguration) { Util.ValidateNotNull(metricIdentifier, nameof(metricIdentifier)); Metric metric = this.metrics.GetOrAdd( metricIdentifier, (key) => new Metric( this.metricManager, metricIdentifier, metricConfiguration ?? MetricConfigurations.Common.Default())); if (metricConfiguration != null && false == metric.configuration.Equals(metricConfiguration)) { throw new ArgumentException("A Metric with the specified Namespace, Id and dimension names already exists, but it has a configuration" + " that is different from the specified configuration. You may not change configurations once a" + " metric was created for the first time. Either specify the same configuration every time, or" + " specify 'null' during every invocation except the first one. 'Null' will match against any" + " previously specified configuration when retrieving existing metrics, or fall back to" + Invariant($" the default when creating new metrics. ({nameof(metricIdentifier)} = \"{metricIdentifier.ToString()}\".)")); } return(metric); }
/// <summary> /// We are working on adding a publically exposed method to a future version of the Core SDK so that the reflection employed here is not necesary. /// </summary> /// <param name="source"></param> /// <param name="target"></param> public static void CopyTelemetryContext(TelemetryContext source, TelemetryContext target) { Util.ValidateNotNull(source, nameof(source)); Util.ValidateNotNull(target, nameof(target)); // Copy internal tags: Action <TelemetryContext, TelemetryContext, string> initializeDelegate = GetDelegate_TelemetryContextInitialize(); initializeDelegate(target, source, null); // Copy public properties: IDictionary <string, string> sourceProperties = source.Properties; IDictionary <string, string> targetProperties = target.Properties; if (targetProperties != null && sourceProperties != null && sourceProperties.Count > 0) { foreach (KeyValuePair <string, string> property in sourceProperties) { if (!String.IsNullOrEmpty(property.Key) && !targetProperties.ContainsKey(property.Key)) { targetProperties[property.Key] = property.Value; } } } // Copy iKey: if (source.InstrumentationKey != null) { target.InstrumentationKey = source.InstrumentationKey; } }
internal object GetOrCreateExtensionStateUnsafe(Func <MetricManager, object> newExtensionStateInstanceFactory) { object extensionState = _extensionState; if (extensionState != null) { return(extensionState); } Util.ValidateNotNull(newExtensionStateInstanceFactory, nameof(newExtensionStateInstanceFactory)); object newExtensionState = null; try { newExtensionState = newExtensionStateInstanceFactory(this); } catch { newExtensionState = null; } if (newExtensionState != null) { object prevExtensionState = Interlocked.CompareExchange(ref _extensionState, newExtensionState, null); extensionState = prevExtensionState ?? newExtensionState; } return(extensionState); }
/// <summary>@ToDo: Complete documentation before stable release. {659}.</summary> /// <param name="source">@ToDo: Complete documentation before stable release. {688}.</param> /// <param name="target">@ToDo: Complete documentation before stable release. {859}.</param> public static void CopyTelemetryContext(TelemetryContext source, TelemetryContext target) { Util.ValidateNotNull(source, nameof(source)); Util.ValidateNotNull(target, nameof(target)); // Copy internal tags: target.Initialize(source, instrumentationKey: null); // Copy public properties: #pragma warning disable CS0618 // Type or member is obsolete Utils.CopyDictionary(source.Properties, target.Properties); #pragma warning restore CS0618 // Type or member is obsolete // This check avoids accessing the public accessor GlobalProperties // unless needed, to avoid the penalty of ConcurrentDictionary instantiation. if (source.GlobalPropertiesValue != null) { Utils.CopyDictionary(source.GlobalProperties, target.GlobalProperties); } // Copy iKey: if (source.InstrumentationKey != null) { target.InstrumentationKey = source.InstrumentationKey; } }
/// <summary>Creates a new instance of <c>MetricConfiguration</c>.</summary> /// <param name="seriesCountLimit">How many data time series a metric can contain as a maximum. /// Once this limit is reached, calls to <c>TrackValue(..)</c>, <c>TryGetDataSeries(..)</c> and similar /// that would normally result in new series will return <c>false</c>.</param> /// <param name="valuesPerDimensionLimit">How many different values each of the dimensions of a metric can /// have as a maximum. /// Once this limit is reached, calls to <c>TrackValue(..)</c>, <c>TryGetDataSeries(..)</c> and similar /// that would normally result in new series will return <c>false</c>.</param> /// <param name="seriesConfig">The configuration for how each series of this metric should be aggregated.</param> public MetricConfiguration( int seriesCountLimit, int valuesPerDimensionLimit, IMetricSeriesConfiguration seriesConfig) { if (seriesCountLimit < 1) { throw new ArgumentOutOfRangeException( nameof(seriesCountLimit), Invariant($"Metrics must allow at least one data series (but {seriesCountLimit} was specified).")); } this.SeriesCountLimit = seriesCountLimit; if (valuesPerDimensionLimit < 0) { throw new ArgumentOutOfRangeException(nameof(valuesPerDimensionLimit)); } for (int d = 0; d < this.valuesPerDimensionLimits.Length; d++) { this.valuesPerDimensionLimits[d] = valuesPerDimensionLimit; } Util.ValidateNotNull(seriesConfig, nameof(seriesConfig)); this.SeriesConfig = seriesConfig; this.hashCode = this.ComputeHashCode(); }
public MeasurementAggregator(MetricSeriesConfigurationForMeasurement configuration, MetricSeries dataSeries, MetricAggregationCycleKind aggregationCycleKind) : base(MetricValuesBufferFactory, configuration, dataSeries, aggregationCycleKind) { Util.ValidateNotNull(configuration, nameof(configuration)); this.restrictToUInt32Values = configuration.RestrictToUInt32Values; this.ResetAggregate(); }
public GaugeAggregator(GaugeMetricSeriesConfiguration configuration, MetricSeries dataSeries, MetricAggregationCycleKind aggregationCycleKind) : base(MetricValuesBufferFactory, configuration, dataSeries, aggregationCycleKind) { Util.ValidateNotNull(configuration, nameof(configuration)); _restrictToUInt32Values = configuration.RestrictToUInt32Values; ResetAggregate(); }
/// <summary>@ToDo: Complete documentation before stable release. {569}</summary> /// <param name="metricIdentifier">@ToDo: Complete documentation before stable release. {108}</param> /// <param name="dimensionNamesAndValues">@ToDo: Complete documentation before stable release. {785}</param> /// <param name="config">@ToDo: Complete documentation before stable release. {275}</param> /// <returns>@ToDo: Complete documentation before stable release. {908}</returns> public MetricSeries CreateNewSeries(MetricIdentifier metricIdentifier, IEnumerable <KeyValuePair <string, string> > dimensionNamesAndValues, IMetricSeriesConfiguration config) { Util.ValidateNotNull(metricIdentifier, nameof(metricIdentifier)); Util.ValidateNotNull(config, nameof(config)); var dataSeries = new MetricSeries(this.aggregationManager, metricIdentifier, dimensionNamesAndValues, config); return(dataSeries); }
/// <summary> /// /// </summary> /// <param name="metricId"></param> /// <param name="config"></param> /// <returns></returns> public MetricSeries CreateNewSeries(string metricId, IMetricSeriesConfiguration config) { Util.ValidateNotNull(metricId, nameof(metricId)); Util.ValidateNotNull(config, nameof(config)); var dataSeries = new MetricSeries(_aggregationManager, metricId, null, config); return(dataSeries); }
/// <summary> /// We are working on adding a publically exposed method to a future version of the Core SDK so that the reflection employed here is not necesary. /// </summary> /// <param name="telemetryClient"></param> /// <returns></returns> internal static TelemetryConfiguration GetTelemetryConfiguration(TelemetryClient telemetryClient) { Util.ValidateNotNull(telemetryClient, nameof(telemetryClient)); Func <TelemetryClient, TelemetryConfiguration> getTelemetryConfigurationDelegate = GetDelegate_TelemetryClientGetConfiguration(); TelemetryConfiguration pipeline = getTelemetryConfigurationDelegate(telemetryClient); return(pipeline); }
public DataSeriesAggregatorBase(IMetricSeriesConfiguration configuration, MetricSeries dataSeries, MetricAggregationCycleKind aggregationCycleKind) { Util.ValidateNotNull(configuration, nameof(configuration)); _dataSeries = dataSeries; _aggregationCycleKind = aggregationCycleKind; _isPersistent = configuration.RequiresPersistentAggregation; Reset(default(DateTimeOffset), default(IMetricValueFilter)); }
/// <summary> /// /// </summary> /// <param name="telemetryPipeline"></param> public MetricManager(IMetricTelemetryPipeline telemetryPipeline) { Util.ValidateNotNull(telemetryPipeline, nameof(telemetryPipeline)); _telemetryPipeline = telemetryPipeline; _aggregationManager = new MetricAggregationManager(); _aggregationCycle = new DefaultAggregationPeriodCycle(_aggregationManager, this); _aggregationCycle.Start(); }
internal MetricSeries( MetricAggregationManager aggregationManager, string metricId, IEnumerable <KeyValuePair <string, string> > dimensionNamesAndValues, IMetricSeriesConfiguration configuration) { Util.ValidateNotNull(aggregationManager, nameof(aggregationManager)); Util.ValidateNotNull(metricId, nameof(metricId)); Util.ValidateNotNull(configuration, nameof(configuration)); _aggregationManager = aggregationManager; _metricId = metricId; _configuration = configuration; _requiresPersistentAggregator = configuration.RequiresPersistentAggregation; var dimNameVals = new Dictionary <string, string>(); if (dimensionNamesAndValues != null) { int dimIndex = 0; foreach (KeyValuePair <string, string> dimNameVal in dimensionNamesAndValues) { if (dimNameVal.Key == null) { throw new ArgumentNullException($"The name for dimension at 0-based index '{dimIndex}' is null."); } if (String.IsNullOrWhiteSpace(dimNameVal.Key)) { throw new ArgumentException($"The name for dimension at 0-based index '{dimIndex}' is empty or white-space"); } if (dimNameVal.Value == null) { throw new ArgumentNullException($"The value for dimension '{dimNameVal.Key}' number is null."); } if (String.IsNullOrWhiteSpace(dimNameVal.Value)) { throw new ArgumentNullException($"The value for dimension '{dimNameVal.Key}' is empty or white-space."); } dimNameVals[dimNameVal.Key] = dimNameVal.Value; dimIndex++; } } _dimensionNamesAndValues = dimNameVals; _aggregatorPersistent = null; _aggregatorDefault = null; _aggregatorQuickPulse = null; _aggregatorCustom = null; }
/// <summary>Copies the contents of this collection to the specified array.</summary> /// <param name="array">An artay.</param> /// <param name="arrayIndex">Array index where to start the copy.</param> public void CopyTo(Metric[] array, int arrayIndex) { Util.ValidateNotNull(array, nameof(array)); if (arrayIndex < 0 || arrayIndex >= array.Length) { throw new ArgumentOutOfRangeException(nameof(arrayIndex)); } this.metrics.Values.CopyTo(array, arrayIndex); }
public DefaultAggregationPeriodCycle(MetricAggregationManager aggregationManager, MetricManager metricManager) { Util.ValidateNotNull(aggregationManager, nameof(aggregationManager)); Util.ValidateNotNull(metricManager, nameof(metricManager)); this.aggregationManager = aggregationManager; this.metricManager = metricManager; this.runningState = RunningState_NotStarted; this.workerTaskCompletionControl = new TaskCompletionSource <bool>(); this.aggregationThread = null; }
public DefaultAggregationPeriodCycle(MetricAggregationManager aggregationManager, MetricManager metricManager) { Util.ValidateNotNull(aggregationManager, nameof(aggregationManager)); Util.ValidateNotNull(metricManager, nameof(metricManager)); _workerMethod = this.Run; _aggregationManager = aggregationManager; _metricManager = metricManager; _runningState = RunningState_NotStarted; _workerTask = null; }
/// <summary> /// </summary> /// <param name="metricId"></param> /// <param name="aggregationKindMoniker"></param> public MetricAggregate(string metricId, string aggregationKindMoniker) { Util.ValidateNotNull(metricId, nameof(metricId)); Util.ValidateNotNull(aggregationKindMoniker, nameof(aggregationKindMoniker)); MetricId = metricId; AggregationKindMoniker = aggregationKindMoniker; _aggregationPeriodStart = default(DateTimeOffset); _aggregationPeriodDuration = default(TimeSpan); Dimensions = new ConcurrentDictionary <string, string>(); Data = new ConcurrentDictionary <string, object>(); }
/// <summary>Creates a new instance of <c>MetricConfiguration</c>.</summary> /// <param name="seriesCountLimit">How many data time series a metric can contain as a maximum. /// Once this limit is reached, calls to <c>TrackValue(..)</c>, <c>TryGetDataSeries(..)</c> and similar /// that would normally result in new series will return <c>false</c>.</param> /// <param name="valuesPerDimensionLimits">How many different values each of the dimensions of a metric can /// have as a maximum. If this enumeration contains less elements than the number of supported dimensions, /// then the last specified element is replicated for subsequent dimensions. If this enumeration contains /// too many elements, superflous elements are ignored. /// Once this limit is reached, calls to <c>TrackValue(..)</c>, <c>TryGetDataSeries(..)</c> and similar /// that would normally result in new series will return <c>false</c>.</param> /// <param name="seriesConfig">The configuration for how each series of this metric should be aggregated.</param> public MetricConfiguration( int seriesCountLimit, IEnumerable <int> valuesPerDimensionLimits, IMetricSeriesConfiguration seriesConfig) { if (seriesCountLimit < 1) { throw new ArgumentOutOfRangeException( nameof(seriesCountLimit), Invariant($"Metrics must allow at least one data series (but {seriesCountLimit} was specified).")); } this.SeriesCountLimit = seriesCountLimit; if (valuesPerDimensionLimits == null) { throw new ArgumentNullException(nameof(valuesPerDimensionLimits)); } int lastLim = 0, d = 0; foreach (int lim in valuesPerDimensionLimits) { lastLim = lim; if (lastLim < 0) { throw new ArgumentOutOfRangeException(nameof(valuesPerDimensionLimits) + "[" + d + "]"); } this.valuesPerDimensionLimits[d] = lastLim; d++; if (d >= MetricIdentifier.MaxDimensionsCount) { break; } } for (; d < this.valuesPerDimensionLimits.Length; d++) { this.valuesPerDimensionLimits[d] = lastLim; } Util.ValidateNotNull(seriesConfig, nameof(seriesConfig)); this.SeriesConfig = seriesConfig; this.hashCode = this.ComputeHashCode(); }
public MetricSeriesAggregatorBase( Func <MetricValuesBufferBase <TBufferedValue> > metricValuesBufferFactory, IMetricSeriesConfiguration configuration, MetricSeries dataSeries, MetricAggregationCycleKind aggregationCycleKind) { Util.ValidateNotNull(metricValuesBufferFactory, nameof(metricValuesBufferFactory)); Util.ValidateNotNull(configuration, nameof(configuration)); _dataSeries = dataSeries; _aggregationCycleKind = aggregationCycleKind; _isPersistent = configuration.RequiresPersistentAggregation; _metricValuesBufferFactory = metricValuesBufferFactory; _metricValuesBuffer = InvokeMetricValuesBufferFactory(); Reset(default(DateTimeOffset), default(IMetricValueFilter)); }
/// <summary>@ToDo: Complete documentation before stable release. {659}</summary> /// <param name="source">@ToDo: Complete documentation before stable release. {688}</param> /// <param name="target">@ToDo: Complete documentation before stable release. {859}</param> public static void CopyTelemetryContext(TelemetryContext source, TelemetryContext target) { Util.ValidateNotNull(source, nameof(source)); Util.ValidateNotNull(target, nameof(target)); // Copy internal tags: target.Initialize(source, instrumentationKey: null); // Copy public properties: #pragma warning disable CS0618 // Type or member is obsolete Utils.CopyDictionary(source.Properties, target.Properties); #pragma warning restore CS0618 // Type or member is obsolete Utils.CopyDictionary(source.GlobalProperties, target.GlobalProperties); // Copy iKey: if (source.InstrumentationKey != null) { target.InstrumentationKey = source.InstrumentationKey; } }
public SimpleUInt32DataSeriesAggregator(IMetricSeriesConfiguration configuration, MetricSeries dataSeries, MetricAggregationCycleKind aggregationCycleKind) : base(configuration, dataSeries, aggregationCycleKind) { Util.ValidateNotNull(configuration, nameof(configuration)); SimpleMetricSeriesConfiguration simpleSeriesConfig = configuration as SimpleMetricSeriesConfiguration; if (simpleSeriesConfig == null) { throw new ArgumentException( $"{nameof(SimpleUInt32DataSeriesAggregator)} expects a configuration of type {nameof(SimpleMetricSeriesConfiguration)}," + $" however the specified configuration is {configuration?.GetType()?.FullName ?? Util.NullString}.", nameof(configuration)); } if (false == simpleSeriesConfig.RestrictToUInt32Values) { throw new ArgumentException( $"{nameof(SimpleUInt32DataSeriesAggregator)} expects a configuration of type {nameof(SimpleMetricSeriesConfiguration)}" + $" where 'RestrictToUInt32Values' is TRUE, however it is False.", nameof(configuration)); } }
internal bool AddAggregator(IMetricSeriesAggregator aggregator, MetricAggregationCycleKind aggregationCycleKind) { Util.ValidateNotNull(aggregator, nameof(aggregator)); if (aggregator.DataSeries._configuration.RequiresPersistentAggregation) { return(AddAggregator(aggregator, _aggregatorsForPersistent)); } switch (aggregationCycleKind) { case CycleKind.Default: return(AddAggregator(aggregator, _aggregatorsForDefault)); case CycleKind.QuickPulse: return(AddAggregator(aggregator, _aggregatorsForQuickPulse)); case CycleKind.Custom: return(AddAggregator(aggregator, _aggregatorsForCustom)); default: throw new ArgumentException($"Unexpected value of {nameof(aggregationCycleKind)}: {aggregationCycleKind}."); } }
public void ValidateNotNull() { Util.ValidateNotNull("foo", "specified name"); Assert.ThrowsException <ArgumentNullException>(() => Util.ValidateNotNull(null, "specified name")); }
private MetricsCache(MetricManager metricManager) { Util.ValidateNotNull(metricManager, nameof(metricManager)); _metricManager = metricManager; }
/// <summary>Initializes a metric collection.</summary> /// <param name="metricManager">The manager that owns the scope of this metric collection.</param> internal MetricsCollection(MetricManager metricManager) { Util.ValidateNotNull(metricManager, nameof(metricManager)); this.metricManager = metricManager; }
/// <summary>Gets the metric with the specified identify, if it exists.</summary> /// <param name="metricIdentifier">A metric identity.</param> /// <param name="metric">The metric (if it exists) or <c>null</c>.</param> /// <returns><c>true</c> if the metric was retrieved, or <c>false</c> otherwise.</returns> public bool TryGet(MetricIdentifier metricIdentifier, out Metric metric) { Util.ValidateNotNull(metricIdentifier, nameof(metricIdentifier)); return(this.metrics.TryGetValue(metricIdentifier, out metric)); }
internal MetricSeries( MetricAggregationManager aggregationManager, MetricIdentifier metricIdentifier, IEnumerable <KeyValuePair <string, string> > dimensionNamesAndValues, IMetricSeriesConfiguration configuration) { // Validate and store aggregationManager: Util.ValidateNotNull(aggregationManager, nameof(aggregationManager)); this.aggregationManager = aggregationManager; // Validate and store metricIdentifier: Util.ValidateNotNull(metricIdentifier, nameof(metricIdentifier)); this.MetricIdentifier = metricIdentifier; // Copy dimensionNamesAndValues, validate values (keys are implicitly validated as they need to match the keys in the identifier): var dimNameVals = new Dictionary <string, string>(); if (dimensionNamesAndValues != null) { int dimIndex = 0; foreach (KeyValuePair <string, string> dimNameVal in dimensionNamesAndValues) { if (dimNameVal.Value == null) { throw new ArgumentNullException(Invariant($"The value for dimension '{dimNameVal.Key}' number is null.")); } if (String.IsNullOrWhiteSpace(dimNameVal.Value)) { throw new ArgumentNullException(Invariant($"The value for dimension '{dimNameVal.Key}' is empty or white-space.")); } dimNameVals[dimNameVal.Key] = dimNameVal.Value; dimIndex++; } } // Validate that metricIdentifier and dimensionNamesAndValues contain consistent dimension names: if (metricIdentifier.DimensionsCount != dimNameVals.Count) { throw new ArgumentException(Invariant($"The specified {nameof(metricIdentifier)} contains {metricIdentifier.DimensionsCount} dimensions,") + Invariant($" however the specified {nameof(dimensionNamesAndValues)} contains {dimNameVals.Count} name-value pairs with unique names.")); } foreach (string dimName in metricIdentifier.GetDimensionNames()) { if (false == dimNameVals.ContainsKey(dimName)) { throw new ArgumentException(Invariant($"The specified {nameof(metricIdentifier)} contains a dimension named \"{dimName}\",") + Invariant($" however the specified {nameof(dimensionNamesAndValues)} does not contain an entry for that name.")); } } // Store copied dimensionNamesAndValues: this.dimensionNamesAndValues = dimNameVals; // Validate and store configuration: Util.ValidateNotNull(configuration, nameof(configuration)); this.configuration = configuration; this.requiresPersistentAggregator = configuration.RequiresPersistentAggregation; // Init other instance vars: this.aggregatorPersistent = null; this.aggregatorDefault = null; this.aggregatorQuickPulse = null; this.aggregatorCustom = null; }