From 041474fbda2f6db1b4a92e4d1c6d97b0431e36b4 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 2 Oct 2018 11:52:28 -0700 Subject: [PATCH 1/5] MetricExtractor info is set to a internal field, and copied to Properties in Properties Getter method. This should improve performance as MetricExtractor sits before sampling, and accessing Properties ConcurrentDictionary is avoided until later in the pipeline. With sampling most items are dropped and hence this gives perf boost. --- .../DataContracts/DependencyTelemetry.cs | 22 +++++++++-- .../DataContracts/RequestTelemetry.cs | 19 +++++++++- .../AutocollectedMetricsExtractor.cs | 38 ++++++++++++------- 3 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs b/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs index 0d9e6dee4c..aed80d212e 100644 --- a/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs +++ b/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs @@ -9,7 +9,7 @@ namespace Microsoft.ApplicationInsights.DataContracts using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.External; - + using Microsoft.ApplicationInsights.Extensibility.Implementation.Metrics; using static System.Threading.LazyInitializer; /// @@ -254,8 +254,15 @@ public override bool? Success /// Learn more /// public override IDictionary Properties - { - get { return this.InternalData.properties; } + { + get + { + if (!this.InternalData.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) + { + this.InternalData.properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = this.MetricExtractorInfo; + } + return this.InternalData.properties; + } } /// @@ -295,6 +302,15 @@ public string DependencyKind set { this.samplingPercentage = value; } } + /// + /// Gets or sets the MetricExtractorInfo. + /// + internal string MetricExtractorInfo + { + get; + set; + } + /// /// Gets the dependency operation details, if any. /// diff --git a/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs b/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs index 9915575db4..a62780c724 100644 --- a/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs +++ b/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs @@ -7,6 +7,7 @@ using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.External; + using Microsoft.ApplicationInsights.Extensibility.Implementation.Metrics; /// /// Encapsulates information about a web request handled by the application. @@ -165,7 +166,14 @@ public override TimeSpan Duration /// public override IDictionary Properties { - get { return this.Data.properties; } + get + { + if (!this.Data.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) + { + this.Data.properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = this.MetricExtractorInfo; + } + return this.Data.properties; + } } /// @@ -226,6 +234,15 @@ public string Source set { this.Data.source = value; } } + /// + /// Gets or sets the MetricExtractorInfo. + /// + internal string MetricExtractorInfo + { + get; + set; + } + /// /// Deeply clones a object. /// diff --git a/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs b/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs index 96877d42fa..b7fbeecad6 100644 --- a/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs +++ b/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs @@ -191,29 +191,39 @@ private static string GetExtractorInfo(ISpecificAutocollectedMetricsExtractor ex /// The string to be added to the item's properties. private static void AddExtractorInfo(ITelemetry item, string extractorInfo) { - var itemWithProperties = item as ISupportProperties; - if (itemWithProperties == null) + string extractionPipelineInfo = String.Empty; + if (item is RequestTelemetry) { - return; - } - - string extractionPipelineInfo; - bool hasPrevInfo = itemWithProperties.Properties.TryGetValue(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key, out extractionPipelineInfo); + var req = item as RequestTelemetry; + extractionPipelineInfo = req.MetricExtractorInfo; + if (extractionPipelineInfo.Length > 0) + { + extractionPipelineInfo = extractionPipelineInfo + "; "; + } + else + { + extractionPipelineInfo = String.Empty; + } - if (false == hasPrevInfo) - { - extractionPipelineInfo = String.Empty; + extractionPipelineInfo = extractionPipelineInfo + extractorInfo; + req.MetricExtractorInfo = extractorInfo; } - else + else if (item is DependencyTelemetry) { + var dep = item as DependencyTelemetry; + extractionPipelineInfo = dep.MetricExtractorInfo; if (extractionPipelineInfo.Length > 0) { extractionPipelineInfo = extractionPipelineInfo + "; "; } - } + else + { + extractionPipelineInfo = String.Empty; + } - extractionPipelineInfo = extractionPipelineInfo + extractorInfo; - itemWithProperties.Properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = extractionPipelineInfo; + extractionPipelineInfo = extractionPipelineInfo + extractorInfo; + dep.MetricExtractorInfo = extractorInfo; + } } /// From 9927f3fbde0b35a74fcea280bb3f8030309a2a11 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 2 Oct 2018 12:11:22 -0700 Subject: [PATCH 2/5] Null check for MetrixExtractorInfo --- .../DataContracts/DependencyTelemetry.cs | 1 + .../DataContracts/RequestTelemetry.cs | 3 ++- .../AutocollectedMetricsExtractor.cs | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs b/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs index aed80d212e..2aec9072e4 100644 --- a/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs +++ b/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs @@ -261,6 +261,7 @@ public override IDictionary Properties { this.InternalData.properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = this.MetricExtractorInfo; } + return this.InternalData.properties; } } diff --git a/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs b/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs index a62780c724..93b243f0e8 100644 --- a/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs +++ b/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs @@ -171,7 +171,8 @@ public override IDictionary Properties if (!this.Data.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) { this.Data.properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = this.MetricExtractorInfo; - } + } + return this.Data.properties; } } diff --git a/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs b/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs index b7fbeecad6..f2daf5f8d0 100644 --- a/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs +++ b/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs @@ -196,7 +196,7 @@ private static void AddExtractorInfo(ITelemetry item, string extractorInfo) { var req = item as RequestTelemetry; extractionPipelineInfo = req.MetricExtractorInfo; - if (extractionPipelineInfo.Length > 0) + if (extractionPipelineInfo?.Length > 0) { extractionPipelineInfo = extractionPipelineInfo + "; "; } @@ -212,7 +212,7 @@ private static void AddExtractorInfo(ITelemetry item, string extractorInfo) { var dep = item as DependencyTelemetry; extractionPipelineInfo = dep.MetricExtractorInfo; - if (extractionPipelineInfo.Length > 0) + if (extractionPipelineInfo?.Length > 0) { extractionPipelineInfo = extractionPipelineInfo + "; "; } From d31a38f8971f72168104808191a71a53d2c319fb Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 2 Oct 2018 13:18:47 -0700 Subject: [PATCH 3/5] Refactor --- .../AutocollectedMetricsExtractor.cs | 43 ++++++++----------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs b/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs index f2daf5f8d0..24602337ea 100644 --- a/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs +++ b/src/Microsoft.ApplicationInsights/Metrics/Extensibility/AutocollectedMetricsExtraction/AutocollectedMetricsExtractor.cs @@ -190,42 +190,33 @@ private static string GetExtractorInfo(ISpecificAutocollectedMetricsExtractor ex /// The telemetry item to be tagged. /// The string to be added to the item's properties. private static void AddExtractorInfo(ITelemetry item, string extractorInfo) - { - string extractionPipelineInfo = String.Empty; + { if (item is RequestTelemetry) { var req = item as RequestTelemetry; - extractionPipelineInfo = req.MetricExtractorInfo; - if (extractionPipelineInfo?.Length > 0) - { - extractionPipelineInfo = extractionPipelineInfo + "; "; - } - else - { - extractionPipelineInfo = String.Empty; - } - - extractionPipelineInfo = extractionPipelineInfo + extractorInfo; - req.MetricExtractorInfo = extractorInfo; + req.MetricExtractorInfo = ExtractionPipelineInfo(req.MetricExtractorInfo, extractorInfo); } else if (item is DependencyTelemetry) { var dep = item as DependencyTelemetry; - extractionPipelineInfo = dep.MetricExtractorInfo; - if (extractionPipelineInfo?.Length > 0) - { - extractionPipelineInfo = extractionPipelineInfo + "; "; - } - else - { - extractionPipelineInfo = String.Empty; - } - - extractionPipelineInfo = extractionPipelineInfo + extractorInfo; - dep.MetricExtractorInfo = extractorInfo; + dep.MetricExtractorInfo = ExtractionPipelineInfo(dep.MetricExtractorInfo, extractorInfo); } } + private static string ExtractionPipelineInfo(string extractionPipelineInfo, string extractorInfo) + { + if (extractionPipelineInfo?.Length > 0) + { + extractionPipelineInfo = extractionPipelineInfo + "; "; + } + else + { + extractionPipelineInfo = String.Empty; + } + + return extractionPipelineInfo + extractorInfo; + } + /// /// Calls all participating extractors to initialize themselves. /// From 205f23f6276d32d834f37829a935615c11856668 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 2 Oct 2018 14:35:44 -0700 Subject: [PATCH 4/5] Check null or empty --- .../DataContracts/DependencyTelemetry.cs | 2 +- .../DataContracts/RequestTelemetry.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs b/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs index 2aec9072e4..66bbd15f7c 100644 --- a/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs +++ b/src/Microsoft.ApplicationInsights/DataContracts/DependencyTelemetry.cs @@ -257,7 +257,7 @@ public override IDictionary Properties { get { - if (!this.InternalData.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) + if (!string.IsNullOrEmpty(this.MetricExtractorInfo) && !this.InternalData.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) { this.InternalData.properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = this.MetricExtractorInfo; } diff --git a/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs b/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs index 93b243f0e8..047287afcd 100644 --- a/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs +++ b/src/Microsoft.ApplicationInsights/DataContracts/RequestTelemetry.cs @@ -168,7 +168,7 @@ public override IDictionary Properties { get { - if (!this.Data.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) + if (!string.IsNullOrEmpty(this.MetricExtractorInfo) && !this.Data.properties.ContainsKey(MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key)) { this.Data.properties[MetricTerms.Extraction.ProcessedByExtractors.Moniker.Key] = this.MetricExtractorInfo; } From 306bb1778a4af1d6f61ce2e9cd00be22c910d535 Mon Sep 17 00:00:00 2001 From: Cijo Thomas Date: Tue, 2 Oct 2018 14:56:32 -0700 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f29c37116e..69fc821e25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ This changelog will be used to generate documentation on [release notes page](http://azure.microsoft.com/documentation/articles/app-insights-release-notes-dotnet/). ## Version 2.8.0 -- [Perf Improvement - Use TimeSpan instead of String for durations to avoid conversions.](https://github.com/Microsoft/ApplicationInsights-dotnet/issues/927) +- Perf Improvements + https://github.com/Microsoft/ApplicationInsights-dotnet/issues/927 + https://github.com/Microsoft/ApplicationInsights-dotnet/issues/930 ## Version 2.8.0-beta2 - [TelemetryProcessors (sampling, autocollectedmetricaggregator), TelemetryChannel (ServerTelemetryChannel) added automatically to the default ApplicationInsights.config are moved under the default telemetry sink.](https://github.com/Microsoft/ApplicationInsights-dotnet/issues/907)