diff --git a/BASE/src/Microsoft.ApplicationInsights/TelemetryClient.cs b/BASE/src/Microsoft.ApplicationInsights/TelemetryClient.cs index 6935d0ba7..63f2686ce 100644 --- a/BASE/src/Microsoft.ApplicationInsights/TelemetryClient.cs +++ b/BASE/src/Microsoft.ApplicationInsights/TelemetryClient.cs @@ -153,7 +153,7 @@ public bool IsEnabled() /// Named string values you can use to search and classify events. public void TrackEvent(string eventName, IDictionary properties = null) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackEvent); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackEvent); if (string.IsNullOrEmpty(eventName)) { CoreEventSource.Log.TrackEventInvalidName(); @@ -176,7 +176,7 @@ public void TrackEvent(string eventName, IDictionary properties /// An event log item. public void TrackEvent(EventTelemetry telemetry) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackEvent); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackEvent); if (telemetry == null) { CoreEventSource.Log.TrackEventTelemetryIsNull(); @@ -208,7 +208,7 @@ public void TrackEvent(EventTelemetry telemetry) /// public void TrackAvailability(string name, DateTimeOffset timeStamp, TimeSpan duration, string runLocation, bool success, string message = null, IDictionary properties = null) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackAvailability); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackAvailability); var availabilityTelemetry = new AvailabilityTelemetry(name, timeStamp, duration, runLocation, success, message); if (properties != null && properties.Count > 0) @@ -229,7 +229,7 @@ public void TrackAvailability(string name, DateTimeOffset timeStamp, TimeSpan du /// An availability telemetry item. public void TrackAvailability(AvailabilityTelemetry telemetry) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackAvailability); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackAvailability); if (telemetry == null) { CoreEventSource.Log.TrackAvailabilityTelemetryIsNull(); @@ -281,7 +281,7 @@ public void TrackAvailability(AvailabilityTelemetry telemetry) /// Message to display. public void TrackTrace(string message) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); var state = new DictionaryLogState(null, message); this.Logger.Log(LogLevel.Information, 0, state, null, (s, ex) => s.Message); } @@ -296,7 +296,7 @@ public void TrackTrace(string message) /// Trace severity level. public void TrackTrace(string message, SeverityLevel severityLevel) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); LogLevel logLevel = GetLogLevel(severityLevel); var state = new DictionaryLogState(null, message); this.Logger.Log(logLevel, 0, state, null, (s, ex) => s.Message); @@ -312,7 +312,7 @@ public void TrackTrace(string message, SeverityLevel severityLevel) /// Named string values you can use to search and classify events. public void TrackTrace(string message, IDictionary properties) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); var state = new DictionaryLogState(properties, message); this.Logger.Log(LogLevel.Information, 0, state, null, (s, ex) => s.Message); } @@ -328,7 +328,7 @@ public void TrackTrace(string message, IDictionary properties) /// Named string values you can use to search and classify events. public void TrackTrace(string message, SeverityLevel severityLevel, IDictionary properties) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); LogLevel logLevel = GetLogLevel(severityLevel); var state = new DictionaryLogState(properties, message); this.Logger.Log(logLevel, 0, state, null, (s, ex) => s.Message); @@ -344,7 +344,7 @@ public void TrackTrace(string message, SeverityLevel severityLevel, IDictionary< /// Message with optional properties. public void TrackTrace(TraceTelemetry telemetry) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackTrace); if (telemetry == null) { telemetry = new TraceTelemetry(); @@ -379,10 +379,10 @@ public void TrackTrace(TraceTelemetry telemetry) /// /// Metric name. /// Metric value. - /// Named string values you can use to classify and filter metrics. + /// Named string values you can use to classify and filter metrics. public void TrackMetric(string name, double value, IDictionary properties = null) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackMetric); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackMetric); // Get or create histogram for this metric var histogram = this.Configuration.MetricsManager.GetOrCreateHistogram(name, null); @@ -410,10 +410,10 @@ public void TrackMetric(string name, double value, IDictionary p /// If your application requires sending a separate telemetry item at every occasion without aggregation across time, /// you likely have a use case for event telemetry; see . /// - /// The metric telemetry item. + /// The metric telemetry item. public void TrackMetric(MetricTelemetry telemetry) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackMetric); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackMetric); if (telemetry == null) { CoreEventSource.Log.TrackMetricTelemetryIsNull(); @@ -451,7 +451,7 @@ public void TrackMetric(MetricTelemetry telemetry) /// public void TrackException(Exception exception, IDictionary properties = null) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackException); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackException); if (exception == null) { exception = new InvalidOperationException(Utils.PopulateRequiredStringValue(null, "message", typeof(ExceptionTelemetry).FullName)); @@ -470,7 +470,7 @@ public void TrackException(Exception exception, IDictionary prop /// public void TrackException(ExceptionTelemetry telemetry) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackException); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackException); // TODO investigate how problem id, custom message, etc should appear in portal if (telemetry == null) { @@ -531,7 +531,7 @@ public void TrackDependency(string dependencyTypeName, string target, string dep /// /// /// - /// This method implements a shim layer that converts Application Insights DependencyTelemetry objects + /// This method implements a shim layer that converts Application Insights DependencyTelemetry objects /// into OpenTelemetry Activities. The Azure Monitor Exporter then processes these Activities to emit telemetry. /// /// @@ -560,14 +560,14 @@ public void TrackDependency(string dependencyTypeName, string target, string dep /// /// /// These override attributes ensure backward compatibility and prevent data loss during the OpenTelemetry migration. - /// For Activities created by OpenTelemetry instrumentation (without override attributes), the exporter will map + /// For Activities created by OpenTelemetry instrumentation (without override attributes), the exporter will map /// semantic convention attributes (url.full, db.system, messaging.system, etc.) to Application Insights fields. /// /// Learn more /// public void TrackDependency(DependencyTelemetry telemetry) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackDependency); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackDependency); if (telemetry == null) { return; @@ -707,7 +707,7 @@ public void TrackRequest(string name, DateTimeOffset startTime, TimeSpan duratio /// /// /// - /// This method implements a shim layer that converts Application Insights RequestTelemetry objects + /// This method implements a shim layer that converts Application Insights RequestTelemetry objects /// into OpenTelemetry Activities. The Azure Monitor Exporter then processes these Activities to emit telemetry. /// /// @@ -735,14 +735,14 @@ public void TrackRequest(string name, DateTimeOffset startTime, TimeSpan duratio /// /// /// These override attributes ensure backward compatibility and prevent data loss during the OpenTelemetry migration. - /// For Activities created by OpenTelemetry instrumentation (without override attributes), the exporter will map + /// For Activities created by OpenTelemetry instrumentation (without override attributes), the exporter will map /// semantic convention attributes (url.full, http.response.status_code, messaging.system, etc.) to Application Insights fields. /// /// Learn more /// public void TrackRequest(RequestTelemetry request) { - this.Configuration.FeatureReporter.MarkFeatureInUse(StatsbeatFeatures.TrackRequest); + this.Configuration.FeatureReporter?.MarkFeatureInUse(StatsbeatFeatures.TrackRequest); if (request == null) { return; diff --git a/BASE/src/Microsoft.ApplicationInsights/TelemetryClientExtensions.cs b/BASE/src/Microsoft.ApplicationInsights/TelemetryClientExtensions.cs index 50d7a4cf5..6c8e3416b 100644 --- a/BASE/src/Microsoft.ApplicationInsights/TelemetryClientExtensions.cs +++ b/BASE/src/Microsoft.ApplicationInsights/TelemetryClientExtensions.cs @@ -62,7 +62,7 @@ public static IOperationHolder StartOperation( } #endif - telemetryClient.Configuration.FeatureReporter.MarkFeatureInUse(Internal.StatsbeatFeatures.StartOperation); + telemetryClient.Configuration.FeatureReporter?.MarkFeatureInUse(Internal.StatsbeatFeatures.StartOperation); var effectiveName = string.IsNullOrEmpty(operationName) ? typeof(T).Name : operationName; var kind = ResolveActivityKind(); @@ -161,7 +161,7 @@ public static IOperationHolder StartOperation( operationTelemetry.Name = typeof(T).Name; } - telemetryClient.Configuration.FeatureReporter.MarkFeatureInUse(Internal.StatsbeatFeatures.StartOperation); + telemetryClient.Configuration.FeatureReporter?.MarkFeatureInUse(Internal.StatsbeatFeatures.StartOperation); var kind = ResolveActivityKind(); var source = telemetryClient.TelemetryConfiguration.ApplicationInsightsActivitySource; @@ -244,7 +244,7 @@ public static IOperationHolder StartOperation( return null; } - telemetryClient.Configuration.FeatureReporter.MarkFeatureInUse(Internal.StatsbeatFeatures.StartOperation); + telemetryClient.Configuration.FeatureReporter?.MarkFeatureInUse(Internal.StatsbeatFeatures.StartOperation); // if already started activity, we just link it — not create a new one if (activity.Id == null) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6cf29f0f..fff56c5e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- [Fix #3197: `NullReferenceException` when using TelemetryClient APIs when no connection string is provided.](https://github.com/microsoft/ApplicationInsights-dotnet/pull/3199) ## Version 3.1.2 - [Fix `HttpException: Request is not available in this context` in the WEB package when calling `TrackDependency` from `Application_Start` in classic ASP.NET. The WEB activity processors now safely handle the case where `HttpContext.Request` is not yet available.](https://github.com/microsoft/ApplicationInsights-dotnet/pull/3184)