diff --git a/src/NuGet.Services.Logging/NuGet.Services.Logging.csproj b/src/NuGet.Services.Logging/NuGet.Services.Logging.csproj index 1002f297..0e94c426 100644 --- a/src/NuGet.Services.Logging/NuGet.Services.Logging.csproj +++ b/src/NuGet.Services.Logging/NuGet.Services.Logging.csproj @@ -50,6 +50,7 @@ + diff --git a/src/NuGet.Services.Logging/TelemetryInitializers/AzureWebAppTelemetryInitializer.cs b/src/NuGet.Services.Logging/TelemetryInitializers/AzureWebAppTelemetryInitializer.cs new file mode 100644 index 00000000..4ac2997c --- /dev/null +++ b/src/NuGet.Services.Logging/TelemetryInitializers/AzureWebAppTelemetryInitializer.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.Extensibility; + +namespace NuGet.Services.Logging +{ + /// + /// Overrides the initialized telemetry context. This should be added last in + /// the Application Insights telemetry list. + /// See: https://github.com/microsoft/ApplicationInsights-dotnet-server/blob/e5a0edbe570e0938d3cb7a36a57b25d0db4d3c01/Src/WindowsServer/WindowsServer.Shared/AzureWebAppRoleEnvironmentTelemetryInitializer.cs#L12 + /// + public class AzureWebAppTelemetryInitializer + : ITelemetryInitializer + { + private const string StagingSlotSuffix = "-staging"; + + public void Initialize(ITelemetry telemetry) + { + // Application Insight's Azure Web App Role Environment telemetry initializer uses + // the hostname for the "cloud_roleName" property, which unintentionally creates separate + // role names for our production/staging slots. + var roleName = telemetry.Context.Cloud.RoleName; + if (!string.IsNullOrEmpty(roleName) && roleName.EndsWith(StagingSlotSuffix, StringComparison.OrdinalIgnoreCase)) + { + telemetry.Context.Cloud.RoleName = roleName.Substring(0, roleName.Length - StagingSlotSuffix.Length); + } + } + } +} diff --git a/tests/NuGet.Services.Logging.Tests/NuGet.Services.Logging.Tests.csproj b/tests/NuGet.Services.Logging.Tests/NuGet.Services.Logging.Tests.csproj index 425dffbd..dd952133 100644 --- a/tests/NuGet.Services.Logging.Tests/NuGet.Services.Logging.Tests.csproj +++ b/tests/NuGet.Services.Logging.Tests/NuGet.Services.Logging.Tests.csproj @@ -54,6 +54,7 @@ + diff --git a/tests/NuGet.Services.Logging.Tests/TelemetryInitializers/AzureWebAppTelemetryInitializerFacts.cs b/tests/NuGet.Services.Logging.Tests/TelemetryInitializers/AzureWebAppTelemetryInitializerFacts.cs new file mode 100644 index 00000000..d9326dea --- /dev/null +++ b/tests/NuGet.Services.Logging.Tests/TelemetryInitializers/AzureWebAppTelemetryInitializerFacts.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.DataContracts; +using Moq; +using Xunit; + +namespace NuGet.Services.Logging.Tests +{ + public class AzureWebAppTelemetryInitializerFacts + { + [Theory] + [InlineData(null, null)] + [InlineData("hello", "hello")] + [InlineData("-staging-test", "-staging-test")] + [InlineData("hello-staging", "hello")] + [InlineData("hello-sTAGing", "hello")] + public void UpdatesRoleName(string input, string expected) + { + var telemetry = new Mock(); + var context = new TelemetryContext(); + + context.Cloud.RoleName = input; + + telemetry.Setup(t => t.Context).Returns(context); + + var target = new AzureWebAppTelemetryInitializer(); + target.Initialize(telemetry.Object); + + Assert.Equal(expected, context.Cloud.RoleName); + } + } +}