diff --git a/CHANGELOG.md b/CHANGELOG.md index b7aa525354..6b50bda60f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,13 @@ # Changelog ## VNext +- [QuickPulseTelemetryModule and MonitoringDataPoint have a new Cloud Role Name field for sending with ping and post requests to QuickPulse Service.](https://github.com/microsoft/ApplicationInsights-dotnet/pull/2100) ## Version 2.16.0-beta1 - [ILogger LogError and LogWarning variants write exception `ExceptionStackTrace` when `TrackExceptionsAsExceptionTelemetry` flag is set to `false`](https://github.com/microsoft/ApplicationInsights-dotnet/pull/2065) - [Upgrade to System.Diagnostics.DiagnosticSource v5.0.0-rc.2.20475.5](https://github.com/microsoft/ApplicationInsights-dotnet/pull/2091) - [The `{OriginalFormat}` field in ILogger will be emitted as `OriginalFormat` with the braces removed](https://github.com/microsoft/ApplicationInsights-dotnet/pull/2071) - ApplicationInsightsLoggerProvider populates structured logging key/values irrespective of whether Scopes are enabled or not. - ## Version 2.15.0 - EventCounterCollector module does not add AggregationInterval as a dimension to the metric. diff --git a/WEB/Src/PerformanceCollector/Perf.Shared.NetFull/Implementation/QuickPulse/QuickPulseServiceClient.cs b/WEB/Src/PerformanceCollector/Perf.Shared.NetFull/Implementation/QuickPulse/QuickPulseServiceClient.cs index de2952a9a6..1f63e26b01 100644 --- a/WEB/Src/PerformanceCollector/Perf.Shared.NetFull/Implementation/QuickPulse/QuickPulseServiceClient.cs +++ b/WEB/Src/PerformanceCollector/Perf.Shared.NetFull/Implementation/QuickPulse/QuickPulseServiceClient.cs @@ -20,6 +20,8 @@ internal sealed class QuickPulseServiceClient : IQuickPulseServiceClient { private readonly string instanceName; + private readonly string roleName; + private readonly string streamId; private readonly string machineName; @@ -45,6 +47,7 @@ internal sealed class QuickPulseServiceClient : IQuickPulseServiceClient public QuickPulseServiceClient( Uri serviceUri, string instanceName, + string roleName, string streamId, string machineName, string version, @@ -55,6 +58,7 @@ public QuickPulseServiceClient( { this.ServiceUri = serviceUri; this.instanceName = instanceName; + this.roleName = roleName; this.streamId = streamId; this.machineName = machineName; this.version = version; @@ -230,6 +234,7 @@ private void WritePingData(DateTimeOffset timestamp, Stream stream) InvariantVersion = MonitoringDataPoint.CurrentInvariantVersion, // InstrumentationKey = instrumentationKey, // ikey is currently set in query string parameter Instance = this.instanceName, + RoleName = this.roleName, StreamId = this.streamId, MachineName = this.machineName, Timestamp = timestamp.UtcDateTime, @@ -268,6 +273,7 @@ private void WriteSamples(IEnumerable samples, string inst InvariantVersion = MonitoringDataPoint.CurrentInvariantVersion, InstrumentationKey = instrumentationKey, Instance = this.instanceName, + RoleName = this.roleName, StreamId = this.streamId, MachineName = this.machineName, Timestamp = sample.EndTimestamp.UtcDateTime, diff --git a/WEB/Src/PerformanceCollector/Perf.Shared.NetStandard/Implementation/QuickPulse/QuickPulseServiceClient.cs b/WEB/Src/PerformanceCollector/Perf.Shared.NetStandard/Implementation/QuickPulse/QuickPulseServiceClient.cs index ba0d7ac2b6..d64c7dfd0c 100644 --- a/WEB/Src/PerformanceCollector/Perf.Shared.NetStandard/Implementation/QuickPulse/QuickPulseServiceClient.cs +++ b/WEB/Src/PerformanceCollector/Perf.Shared.NetStandard/Implementation/QuickPulse/QuickPulseServiceClient.cs @@ -24,6 +24,8 @@ internal sealed class QuickPulseServiceClient : IQuickPulseServiceClient { private readonly string instanceName; + private readonly string roleName; + private readonly string streamId; private readonly string machineName; @@ -51,6 +53,7 @@ internal sealed class QuickPulseServiceClient : IQuickPulseServiceClient public QuickPulseServiceClient( Uri serviceUri, string instanceName, + string roleName, string streamId, string machineName, string version, @@ -61,6 +64,7 @@ public QuickPulseServiceClient( { this.ServiceUri = serviceUri; this.instanceName = instanceName; + this.roleName = roleName; this.streamId = streamId; this.machineName = machineName; this.version = version; @@ -234,6 +238,7 @@ private void WritePingData(DateTimeOffset timestamp, Stream stream) InvariantVersion = MonitoringDataPoint.CurrentInvariantVersion, // InstrumentationKey = instrumentationKey, // ikey is currently set in query string parameter Instance = this.instanceName, + RoleName = this.roleName, StreamId = this.streamId, MachineName = this.machineName, Timestamp = timestamp.UtcDateTime, @@ -272,6 +277,7 @@ private void WriteSamples(IEnumerable samples, string inst InvariantVersion = MonitoringDataPoint.CurrentInvariantVersion, InstrumentationKey = instrumentationKey, Instance = this.instanceName, + RoleName = this.roleName, StreamId = this.streamId, MachineName = this.machineName, Timestamp = sample.EndTimestamp.UtcDateTime, diff --git a/WEB/Src/PerformanceCollector/Perf.Tests/QuickPulse/QuickPulseServiceClientTests.cs b/WEB/Src/PerformanceCollector/Perf.Tests/QuickPulse/QuickPulseServiceClientTests.cs index 510d6c9753..1b95f133a4 100644 --- a/WEB/Src/PerformanceCollector/Perf.Tests/QuickPulse/QuickPulseServiceClientTests.cs +++ b/WEB/Src/PerformanceCollector/Perf.Tests/QuickPulse/QuickPulseServiceClientTests.cs @@ -53,6 +53,8 @@ public sealed class QuickPulseServiceClientTests : IDisposable private string lastPingInstance; + private string lastPingRoleName; + private string lastVersion; private string lastAuthApiKey; @@ -90,6 +92,7 @@ public void TestInitialize() this.submitCount = 0; this.lastPingTimestamp = null; this.lastPingInstance = string.Empty; + this.lastPingRoleName = string.Empty; this.lastVersion = string.Empty; this.lastAuthApiKey = string.Empty; ArrayHelpers.ForEach(QuickPulseConstants.XMsQpsAuthOpaqueHeaderNames, headerName => this.lastOpaqueAuthHeaderValues.Add(headerName, null)); @@ -162,9 +165,10 @@ public void QuickPulseServiceClientPingsTheService() { // ARRANGE string instance = Guid.NewGuid().ToString(); + string roleName = Guid.NewGuid().ToString(); var timestamp = DateTimeOffset.UtcNow; - var serviceClient = new QuickPulseServiceClient(this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, instance, instance, instance, string.Empty, new Clock(), false, 0); + var serviceClient = new QuickPulseServiceClient(this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, instance, roleName, instance, instance, string.Empty, new Clock(), false, 0); // ACT CollectionConfigurationInfo configurationInfo; @@ -179,6 +183,7 @@ public void QuickPulseServiceClientPingsTheService() Assert.AreEqual(3, this.pingCount); Assert.AreEqual(timestamp.DateTime.ToFileTimeUtc() / 10000, this.lastPingTimestamp.Value.DateTime.ToFileTimeUtc() / 10000); Assert.AreEqual(instance, this.lastPingInstance); + Assert.AreEqual(roleName, this.lastPingRoleName); } [TestMethod] @@ -192,6 +197,7 @@ public void QuickPulseServiceClientSubmitsSamplesToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -266,6 +272,7 @@ public void QuickPulseServiceClientSetsTransmissionTimeCorrectly() string.Empty, string.Empty, string.Empty, + string.Empty, timeProvider, false, 0); @@ -337,6 +344,7 @@ public void QuickPulseServiceClientRoundsSampleValuesWhenSubmittingToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -374,6 +382,7 @@ public void QuickPulseServiceClientFillsInSampleWeightWhenSubmittingToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -424,6 +433,7 @@ public void QuickPulseServiceClientFillsInTelemetryDocumentsWhenSubmittingToServ string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -514,6 +524,7 @@ public void QuickPulseServiceClientFillsInGlobalDocumentQuotaReachedWhenSubmitti string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -562,6 +573,7 @@ public void QuickPulseServiceClientInterpretsPingResponseCorrectlyWhenHeaderTrue string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -588,6 +600,7 @@ public void QuickPulseServiceClientInterpretsPingResponseCorrectlyWhenHeaderFals string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -614,6 +627,7 @@ public void QuickPulseServiceClientInterpretsPingResponseCorrectlyWhenHeaderInva string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -640,6 +654,7 @@ public void QuickPulseServiceClientInterpretsPingResponseCorrectlyWhenHeaderMiss string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -666,6 +681,7 @@ public void QuickPulseServiceClientInterpretsSubmitSamplesResponseCorrectlyWhenH string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -698,6 +714,7 @@ public void QuickPulseServiceClientInterpretsSubmitSamplesResponseCorrectlyWhenH string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -730,6 +747,7 @@ public void QuickPulseServiceClientInterpretsSubmitSamplesResponseCorrectlyWhenH string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -762,6 +780,7 @@ public void QuickPulseServiceClientInterpretsSubmitSamplesResponseCorrectlyWhenH string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -794,6 +813,7 @@ public void QuickPulseServiceClientDoesNotRetryPing() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0, @@ -822,6 +842,7 @@ public void QuickPulseServiceClientDoesNotRetrySubmitSamples() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0, @@ -857,6 +878,7 @@ public void QuickPulseServiceClientDoesNotReadCollectionConfigurationFromPingWhe string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -898,6 +920,7 @@ public void QuickPulseServiceClientDoesNotReadCollectionConfigurationFromPostWhe string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -946,6 +969,7 @@ public void QuickPulseServiceClientReadsCollectionConfigurationFromPingWhenETagI string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -989,6 +1013,7 @@ public void QuickPulseServiceClientReadsCollectionConfigurationFromPostWhenETagI string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1039,6 +1064,7 @@ public void QuickPulseServiceClientDoesNotReadCollectionConfigurationFromPingWhe string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1076,6 +1102,7 @@ public void QuickPulseServiceClientDoesNotReadCollectionConfigurationFromPostWhe string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1120,6 +1147,7 @@ public void QuickPulseServiceClientProducesCalculatedMetricsCorrectly() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1183,14 +1211,16 @@ public void QuickPulseServiceClientProducesCalculatedMetricsCorrectly() } [TestMethod] - public void QuickPulseServiceClientSubmitsInstanceNameToServiceWithPing() + public void QuickPulseServiceClientSubmitsRoleAndInstanceNameToServiceWithPing() { // ARRANGE var instanceName = "this instance"; + var roleName = "this role name"; var serviceClient = new QuickPulseServiceClient( this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, instanceName, - instanceName, + roleName, + string.Empty, instanceName, string.Empty, new Clock(), @@ -1208,17 +1238,46 @@ public void QuickPulseServiceClientSubmitsInstanceNameToServiceWithPing() Assert.AreEqual(1, this.pings.Count); Assert.AreEqual(instanceName, this.pings[0].Item1.InstanceName); Assert.AreEqual(instanceName, this.pings[0].Item3.Instance); + Assert.AreEqual(roleName, this.pings[0].Item3.RoleName); + } + + [TestMethod] + public void QuickPulseServiceClientSubmitsRoleNameWithNullValueValidation() + { + // ARRANGE + var serviceClient = new QuickPulseServiceClient( + this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, + string.Empty, + null, + string.Empty, + string.Empty, + string.Empty, + new Clock(), + false, + 0); + + // ACT + CollectionConfigurationInfo configurationInfo; + serviceClient.Ping(Guid.NewGuid().ToString(), DateTimeOffset.UtcNow, string.Empty, string.Empty, out configurationInfo); + + + // ASSERT + this.WaitForProcessing(requestCount: 1); + Assert.AreEqual(1, this.pings.Count); + Assert.IsNull(this.pings[0].Item3.RoleName); } [TestMethod] - public void QuickPulseServiceClientSubmitsInstanceNameToServiceWithSubmitSamples() + public void QuickPulseServiceClientSubmitsRoleAndInstanceNameToServiceWithSubmitSamples() { // ARRANGE var now = DateTimeOffset.UtcNow; var instanceName = "this instance"; + var roleName = "this role name"; var serviceClient = new QuickPulseServiceClient( this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, instanceName, + roleName, instanceName, instanceName, string.Empty, @@ -1242,6 +1301,7 @@ public void QuickPulseServiceClientSubmitsInstanceNameToServiceWithSubmitSamples // ASSERT Assert.AreEqual(1, this.samples.Count); Assert.AreEqual(instanceName, this.samples[0].Item3.Instance); + Assert.AreEqual(roleName, this.samples[0].Item3.RoleName); } [TestMethod] @@ -1252,6 +1312,7 @@ public void QuickPulseServiceClientSubmitsStreamIdToServiceWithPing() var serviceClient = new QuickPulseServiceClient( this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, string.Empty, + string.Empty, streamId, string.Empty, string.Empty, @@ -1281,6 +1342,7 @@ public void QuickPulseServiceClientSubmitsStreamIdToServiceWithSubmitSamples() var serviceClient = new QuickPulseServiceClient( this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, string.Empty, + string.Empty, streamId, string.Empty, string.Empty, @@ -1315,6 +1377,7 @@ public void QuickPulseServiceClientSubmitsMachineNameToServiceWithPing() this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, string.Empty, string.Empty, + string.Empty, machineName, string.Empty, new Clock(), @@ -1344,6 +1407,7 @@ public void QuickPulseServiceClientSubmitsMachineNameToServiceWithSubmitSamples( this.TestContext.Properties[ServiceEndpointPropertyName] as Uri, string.Empty, string.Empty, + string.Empty, machineName, string.Empty, new Clock(), @@ -1378,6 +1442,7 @@ public void QuickPulseServiceClientSubmitsInvariantVersionToServiceWithPing() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1406,6 +1471,7 @@ public void QuickPulseServiceClientSubmitsInvariantVersionToServiceWithSubmitSam string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1439,6 +1505,7 @@ public void QuickPulseServiceClientSubmitsTransmissionTimeToServiceWithPing() string.Empty, string.Empty, string.Empty, + string.Empty, timeProvider, false, 0); @@ -1466,6 +1533,7 @@ public void QuickPulseServiceClientSubmitsTransmissionTimeToServiceWithSubmitSam string.Empty, string.Empty, string.Empty, + string.Empty, timeProvider, false, 0); @@ -1503,6 +1571,7 @@ public void QuickPulseServiceClientSubmitsVersionToServiceWithPing() string.Empty, string.Empty, string.Empty, + string.Empty, version, new Clock(), false, @@ -1531,6 +1600,7 @@ public void QuickPulseServiceClientSubmitsVersionToServiceWithSubmitSamples() string.Empty, string.Empty, string.Empty, + string.Empty, version, new Clock(), false, @@ -1567,6 +1637,7 @@ public void QuickPulseServiceClientSubmitsAuthApiKeyToServiceWithPing() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1595,6 +1666,7 @@ public void QuickPulseServiceClientSubmitsAuthApiKeyToServiceWithSubmitSamples() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1628,6 +1700,7 @@ public void QuickPulseServiceClientResubmitsAuthOpaqueHeadersToServiceWithPing() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1667,6 +1740,7 @@ public void QuickPulseServiceClientResubmitsAuthOpaqueHeadersToServiceWithSubmit string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1713,6 +1787,7 @@ public void QuickPulseServiceClientSubmitsCollectionConfigurationETagToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1747,6 +1822,7 @@ public void QuickPulseServiceClientSubmitsCollectionConfigurationErrorsToService string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1811,6 +1887,7 @@ public void QuickPulseServiceClientSubmitsInstrumentationKeyToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), false, 0); @@ -1845,6 +1922,7 @@ public void QuickPulseServiceClientSubmitsIsWebAppToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), true, 0); @@ -1879,6 +1957,7 @@ public void QuickPulseServiceClientSubmitsProcessorCountToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), true, 7); @@ -1913,6 +1992,7 @@ public void QuickPulseServiceClientSubmitsTopCpuProcessesToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), true, 0); @@ -1953,6 +2033,7 @@ public void QuickPulseServiceClientSubmitsTopCpuProcessesAccessDeniedToService() string.Empty, string.Empty, string.Empty, + string.Empty, new Clock(), true, 0); @@ -2052,6 +2133,7 @@ private void ProcessRequest(HttpListener listener, AutoResetEvent ev) this.lastPingTimestamp = dataPoint.Timestamp; this.lastPingInstance = dataPoint.Instance; + this.lastPingRoleName = dataPoint.RoleName; this.lastVersion = dataPoint.Version; } diff --git a/WEB/Src/PerformanceCollector/PerformanceCollector/Implementation/QuickPulse/Service contract/MonitoringDataPoint.cs b/WEB/Src/PerformanceCollector/PerformanceCollector/Implementation/QuickPulse/Service contract/MonitoringDataPoint.cs index c5d444c175..f3f33bc1d0 100644 --- a/WEB/Src/PerformanceCollector/PerformanceCollector/Implementation/QuickPulse/Service contract/MonitoringDataPoint.cs +++ b/WEB/Src/PerformanceCollector/PerformanceCollector/Implementation/QuickPulse/Service contract/MonitoringDataPoint.cs @@ -32,6 +32,9 @@ internal struct MonitoringDataPoint [DataMember] public string Instance { get; set; } + [DataMember] + public string RoleName { get; set; } + [DataMember] public string StreamId { get; set; } diff --git a/WEB/Src/PerformanceCollector/PerformanceCollector/QuickPulseTelemetryModule.cs b/WEB/Src/PerformanceCollector/PerformanceCollector/QuickPulseTelemetryModule.cs index 82d2244ac6..56d21b5107 100644 --- a/WEB/Src/PerformanceCollector/PerformanceCollector/QuickPulseTelemetryModule.cs +++ b/WEB/Src/PerformanceCollector/PerformanceCollector/QuickPulseTelemetryModule.cs @@ -12,6 +12,7 @@ using Microsoft.ApplicationInsights.DataContracts; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility.Filtering; + using Microsoft.ApplicationInsights.Extensibility.Implementation; using Microsoft.ApplicationInsights.Extensibility.Implementation.Tracing; using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation; using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.Implementation.QuickPulse; @@ -260,7 +261,7 @@ private static void ValidateConfiguration(TelemetryConfiguration configuration) } } - private static string GetInstanceName(TelemetryConfiguration configuration) + private static CloudContext GetCloudContext(TelemetryConfiguration configuration) { // we need to initialize an item to get instance information var fakeItem = new EventTelemetry(); @@ -274,7 +275,7 @@ private static string GetInstanceName(TelemetryConfiguration configuration) // we don't care what happened there } - return string.IsNullOrWhiteSpace(fakeItem.Context?.Cloud?.RoleInstance) ? Environment.MachineName : fakeItem.Context.Cloud.RoleInstance; + return fakeItem.Context?.Cloud; } private static string GetStreamId() @@ -403,7 +404,9 @@ private void InitializeServiceClient(TelemetryConfiguration configuration) } // create the default production implementation of the service client with the best service endpoint we could get - string instanceName = GetInstanceName(configuration); + CloudContext cloudContext = GetCloudContext(configuration); + string instanceName = string.IsNullOrWhiteSpace(cloudContext?.RoleInstance) ? Environment.MachineName : cloudContext.RoleInstance; + string roleName = cloudContext?.RoleName ?? string.Empty; string streamId = GetStreamId(); var assemblyVersion = SdkVersionUtils.GetSdkVersion(null); bool isWebApp = PerformanceCounterUtility.IsWebAppRunningInAzure(); @@ -411,6 +414,7 @@ private void InitializeServiceClient(TelemetryConfiguration configuration) this.ServiceClient = new QuickPulseServiceClient( serviceEndpointUri, instanceName, + roleName, streamId, this.ServerId, assemblyVersion,