private static void ProcessMetrics <TTelemetry>( CollectionConfigurationAccumulator configurationAccumulatorLocal, IEnumerable <CalculatedMetric <TTelemetry> > metrics, TTelemetry telemetry, out CollectionConfigurationError[] filteringErrors, ref string projectionError) { filteringErrors = new CollectionConfigurationError[] { }; foreach (CalculatedMetric <TTelemetry> metric in metrics) { if (metric.CheckFilters(telemetry, out filteringErrors)) { // the telemetry document has passed the filters, count it in and project try { double projection = metric.Project(telemetry); configurationAccumulatorLocal.MetricAccumulators[metric.Id].AddValue(projection); } catch (Exception e) { // most likely the projection did not result in a value parsable by double.Parse() projectionError = e.ToString(); } } } }
public void CollectionConfigurationAccumulatorPreparesMetricAccumulatorsTest() { // ARRANGE CollectionConfigurationError[] error; var metricInfo = new CalculatedMetricInfo() { Id = "Metric1", TelemetryType = TelemetryType.Request, Projection = "Name", Aggregation = AggregationType.Min, FilterGroups = new FilterConjunctionGroupInfo[0] }; var collectionConfigurationInfo = new CollectionConfigurationInfo() { Metrics = new[] { metricInfo } }; var collectionConfiguration = new CollectionConfiguration(collectionConfigurationInfo, out error, new ClockMock()); // ACT var accumulator = new CollectionConfigurationAccumulator(collectionConfiguration); // ASSERT Assert.AreSame(collectionConfiguration, accumulator.CollectionConfiguration); Assert.AreEqual("Metric1", accumulator.MetricAccumulators.Single().Key); }
private void ProcessTelemetry(ITelemetry telemetry) { // only process items that are going to the instrumentation key that our module is initialized with if (string.IsNullOrWhiteSpace(this.config?.InstrumentationKey) || !string.Equals(telemetry?.Context?.InstrumentationKey, this.config.InstrumentationKey, StringComparison.OrdinalIgnoreCase)) { return; } var telemetryAsRequest = telemetry as RequestTelemetry; var telemetryAsDependency = telemetry as DependencyTelemetry; var telemetryAsException = telemetry as ExceptionTelemetry; var telemetryAsEvent = telemetry as EventTelemetry; var telemetryAsTrace = telemetry as TraceTelemetry; // update aggregates bool?originalRequestTelemetrySuccessValue = null; if (telemetryAsRequest != null) { // special treatment for RequestTelemetry.Success originalRequestTelemetrySuccessValue = telemetryAsRequest.Success; telemetryAsRequest.Success = IsRequestSuccessful(telemetryAsRequest); this.UpdateRequestAggregates(telemetryAsRequest); } else if (telemetryAsDependency != null) { this.UpdateDependencyAggregates(telemetryAsDependency); } else if (telemetryAsException != null) { this.UpdateExceptionAggregates(); } // get a local reference, the accumulator might get swapped out at any time // in case we continue to process this configuration once the accumulator is out, increase the reference count so that this accumulator is not sent out before we're done CollectionConfigurationAccumulator configurationAccumulatorLocal = this.dataAccumulatorManager.CurrentDataAccumulator.CollectionConfigurationAccumulator; // if the accumulator is swapped out and a sample is created and sent out - all while between these two lines, this telemetry item gets lost // however, that is not likely to happen configurationAccumulatorLocal.AddRef(); try { // collect full telemetry items if (!this.disableFullTelemetryItems) { ITelemetryDocument telemetryDocument = null; IEnumerable <DocumentStream> documentStreams = configurationAccumulatorLocal.CollectionConfiguration.DocumentStreams; //!!! report runtime errors for filter groups? CollectionConfigurationError[] groupErrors; if (telemetryAsRequest != null) { telemetryDocument = this.CreateTelemetryDocument( telemetryAsRequest, documentStreams, documentStream => documentStream.RequestQuotaTracker, documentStream => documentStream.CheckFilters(telemetryAsRequest, out groupErrors), ConvertRequestToTelemetryDocument); } else if (telemetryAsDependency != null) { telemetryDocument = this.CreateTelemetryDocument( telemetryAsDependency, documentStreams, documentStream => documentStream.DependencyQuotaTracker, documentStream => documentStream.CheckFilters(telemetryAsDependency, out groupErrors), ConvertDependencyToTelemetryDocument); } else if (telemetryAsException != null) { telemetryDocument = this.CreateTelemetryDocument( telemetryAsException, documentStreams, documentStream => documentStream.ExceptionQuotaTracker, documentStream => documentStream.CheckFilters(telemetryAsException, out groupErrors), ConvertExceptionToTelemetryDocument); } else if (telemetryAsEvent != null) { telemetryDocument = this.CreateTelemetryDocument( telemetryAsEvent, documentStreams, documentStream => documentStream.EventQuotaTracker, documentStream => documentStream.CheckFilters(telemetryAsEvent, out groupErrors), ConvertEventToTelemetryDocument); } else if (telemetryAsTrace != null) { telemetryDocument = this.CreateTelemetryDocument( telemetryAsTrace, documentStreams, documentStream => documentStream.TraceQuotaTracker, documentStream => documentStream.CheckFilters(telemetryAsTrace, out groupErrors), ConvertTraceToTelemetryDocument); } if (telemetryDocument != null) { this.dataAccumulatorManager.CurrentDataAccumulator.TelemetryDocuments.Push(telemetryDocument); } this.dataAccumulatorManager.CurrentDataAccumulator.GlobalDocumentQuotaReached = this.globalQuotaTracker.QuotaExhausted; } // collect calculated metrics CollectionConfigurationError[] filteringErrors; string projectionError = null; if (telemetryAsRequest != null) { QuickPulseTelemetryProcessor.ProcessMetrics( configurationAccumulatorLocal, configurationAccumulatorLocal.CollectionConfiguration.RequestMetrics, telemetryAsRequest, out filteringErrors, ref projectionError); } else if (telemetryAsDependency != null) { QuickPulseTelemetryProcessor.ProcessMetrics( configurationAccumulatorLocal, configurationAccumulatorLocal.CollectionConfiguration.DependencyMetrics, telemetryAsDependency, out filteringErrors, ref projectionError); } else if (telemetryAsException != null) { QuickPulseTelemetryProcessor.ProcessMetrics( configurationAccumulatorLocal, configurationAccumulatorLocal.CollectionConfiguration.ExceptionMetrics, telemetryAsException, out filteringErrors, ref projectionError); } else if (telemetryAsEvent != null) { QuickPulseTelemetryProcessor.ProcessMetrics( configurationAccumulatorLocal, configurationAccumulatorLocal.CollectionConfiguration.EventMetrics, telemetryAsEvent, out filteringErrors, ref projectionError); } else if (telemetryAsTrace != null) { QuickPulseTelemetryProcessor.ProcessMetrics( configurationAccumulatorLocal, configurationAccumulatorLocal.CollectionConfiguration.TraceMetrics, telemetryAsTrace, out filteringErrors, ref projectionError); } //!!! report errors from string[] errors; and string projectionError; } finally { // special treatment for RequestTelemetry.Success - restore the value if (telemetryAsRequest != null) { telemetryAsRequest.Success = originalRequestTelemetrySuccessValue; } configurationAccumulatorLocal.Release(); } }