diff --git a/AzureIntegration.sln b/AzureIntegration.sln index 3f02a31..a218307 100644 --- a/AzureIntegration.sln +++ b/AzureIntegration.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26228.9 +VisualStudioVersion = 15.0.26412.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.AzureAppServicesIntegration", "src\Microsoft.AspNetCore.AzureAppServicesIntegration\Microsoft.AspNetCore.AzureAppServicesIntegration.csproj", "{5916BEB5-0969-469B-976C-A392E015DFAC}" EndProject @@ -33,7 +33,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Web.Xdt.Extension EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.AzureAppServices.SiteExtension", "src\Microsoft.AspNetCore.AzureAppServices.SiteExtension\Microsoft.AspNetCore.AzureAppServices.SiteExtension.csproj", "{1CE2D76B-39E6-46C0-8F6F-C63E370955A9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationInsightsJavaScriptSnippetTest", "test\ApplicationInsightsJavaScriptSnippetTest\ApplicationInsightsJavaScriptSnippetTest.csproj", "{0899A101-E451-40A4-81B0-7AA18202C25D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests", "test\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests\Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests.csproj", "{0899A101-E451-40A4-81B0-7AA18202C25D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/build/dependencies.props b/build/dependencies.props index 3cf718e..ef28bfb 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -2,7 +2,7 @@ 2.0.0-preview1-* 0.4.0-* - 2.0.0 + 2.1.0-beta2 4.3.0 2.0.0-* 4.7.1 diff --git a/sample/ApplicationInsightsHostingStartupSample/ApplicationInsightsHostingStartupSample.csproj b/sample/ApplicationInsightsHostingStartupSample/ApplicationInsightsHostingStartupSample.csproj index f2469be..b382f9b 100644 --- a/sample/ApplicationInsightsHostingStartupSample/ApplicationInsightsHostingStartupSample.csproj +++ b/sample/ApplicationInsightsHostingStartupSample/ApplicationInsightsHostingStartupSample.csproj @@ -11,6 +11,7 @@ + diff --git a/sample/ApplicationInsightsHostingStartupSample/CurrentResponseTelemetryChannel.cs b/sample/ApplicationInsightsHostingStartupSample/CurrentResponseTelemetryChannel.cs new file mode 100644 index 0000000..2f4a303 --- /dev/null +++ b/sample/ApplicationInsightsHostingStartupSample/CurrentResponseTelemetryChannel.cs @@ -0,0 +1,37 @@ +using System; +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.DataContracts; +using Microsoft.AspNetCore.Http; + +namespace IISSample +{ + public class CurrentResponseTelemetryChannel : ITelemetryChannel + { + private readonly HttpResponse _response; + + public CurrentResponseTelemetryChannel(HttpResponse response) + { + _response = response; + } + + public void Dispose() + { + } + + public void Send(ITelemetry item) + { + if (item is TraceTelemetry traceTelemetry) + { + _response.WriteAsync(traceTelemetry.Message + Environment.NewLine).GetAwaiter().GetResult(); + } + } + + public void Flush() + { + + } + + public bool? DeveloperMode { get; set; } + public string EndpointAddress { get; set; } + } +} \ No newline at end of file diff --git a/sample/ApplicationInsightsHostingStartupSample/Startup.cs b/sample/ApplicationInsightsHostingStartupSample/Startup.cs index 9ef8e2d..302772b 100644 --- a/sample/ApplicationInsightsHostingStartupSample/Startup.cs +++ b/sample/ApplicationInsightsHostingStartupSample/Startup.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Linq; +using Microsoft.ApplicationInsights.Extensibility; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; @@ -20,13 +21,39 @@ public void ConfigureServices(IServiceCollection services) services.AddMvc(); } - public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) + public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) { - loggerfactory.AddConsole(LogLevel.Debug); + loggerFactory.AddConsole(LogLevel.Debug); - var logger = loggerfactory.CreateLogger("Requests"); + var logger = loggerFactory.CreateLogger("Requests"); app.UseMvcWithDefaultRoute(); + app.Map("/log", logApp => logApp.Run(async (context) => + { + TelemetryConfiguration.Active.TelemetryChannel = new CurrentResponseTelemetryChannel(context.Response); + + var systemLogger = loggerFactory.CreateLogger("System.Namespace"); + systemLogger.LogTrace("System trace log"); + systemLogger.LogInformation("System information log"); + systemLogger.LogWarning("System warning log"); + + var microsoftLogger = loggerFactory.CreateLogger("Microsoft.Namespace"); + microsoftLogger.LogTrace("Microsoft trace log"); + microsoftLogger.LogInformation("Microsoft information log"); + microsoftLogger.LogWarning("Microsoft warning log"); + + var customLogger = loggerFactory.CreateLogger("Custom.Namespace"); + customLogger.LogTrace("Custom trace log"); + customLogger.LogInformation("Custom information log"); + customLogger.LogWarning("Custom warning log"); + + var specificLogger = loggerFactory.CreateLogger("Specific.Namespace"); + specificLogger.LogTrace("Specific trace log"); + specificLogger.LogInformation("Specific information log"); + specificLogger.LogWarning("Specific warning log"); + + TelemetryConfiguration.Active.TelemetryChannel = null; + })); app.Run(async (context) => { logger.LogDebug("Received request: " + context.Request.Method + " " + context.Request.Path); diff --git a/sample/ApplicationInsightsHostingStartupSample/appsettings.json b/sample/ApplicationInsightsHostingStartupSample/appsettings.json index cc2304f..a7581a6 100644 --- a/sample/ApplicationInsightsHostingStartupSample/appsettings.json +++ b/sample/ApplicationInsightsHostingStartupSample/appsettings.json @@ -4,8 +4,15 @@ }, "Logging": { "IncludeScopes": false, - "LogLevel": { - "Default": "Warning" + "Debug": { + "LogLevel": { + "Default": "Warning" + } + }, + "Console": { + "LogLevel": { + "Default": "Warning" + } } } } diff --git a/sample/ApplicationInsightsHostingStartupSample/home/site/diagnostics/ApplicationInsights.settings.json b/sample/ApplicationInsightsHostingStartupSample/home/site/diagnostics/ApplicationInsights.settings.json new file mode 100644 index 0000000..e4f3435 --- /dev/null +++ b/sample/ApplicationInsightsHostingStartupSample/home/site/diagnostics/ApplicationInsights.settings.json @@ -0,0 +1,11 @@ +{ + "Logging": { + "Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerProvider": { + "LogLevel": { + "Microsoft": "Information", + "Specific": "Trace", + "Application": "Trace" + } + } + } +} \ No newline at end of file diff --git a/sample/AzureAppServicesHostingStartupSample/AzureAppServicesHostingStartupSample.csproj b/sample/AzureAppServicesHostingStartupSample/AzureAppServicesHostingStartupSample.csproj index a9e5db0..2653d7b 100644 --- a/sample/AzureAppServicesHostingStartupSample/AzureAppServicesHostingStartupSample.csproj +++ b/sample/AzureAppServicesHostingStartupSample/AzureAppServicesHostingStartupSample.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsLoggerStartupFilter.cs b/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsLoggerStartupFilter.cs new file mode 100644 index 0000000..abde0fd --- /dev/null +++ b/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsLoggerStartupFilter.cs @@ -0,0 +1,27 @@ +// 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.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup +{ + internal class ApplicationInsightsLoggerStartupFilter : IStartupFilter + { + private readonly Func _noFilter = (s, level) => true; + + public Action Configure(Action next) + { + return builder => + { + var loggerFactory = builder.ApplicationServices.GetService(); + // We need to disable filtering on logger, filtering would be done by LoggerFactory + loggerFactory.AddApplicationInsights(builder.ApplicationServices, _noFilter); + next(builder); + }; + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsStartupLoader.cs b/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsStartupLoader.cs index 59906ee..2141279 100644 --- a/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsStartupLoader.cs +++ b/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/ApplicationInsightsStartupLoader.cs @@ -1,8 +1,14 @@ // 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 System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; [assembly: HostingStartup(typeof(Microsoft.AspNetCore.ApplicationInsights.HostingStartup.ApplicationInsightsHostingStartup))] @@ -17,22 +23,60 @@ namespace Microsoft.AspNetCore.ApplicationInsights.HostingStartup /// public class ApplicationInsightsHostingStartup : IHostingStartup { + private const string ApplicationInsightsLoggerFactory = "Microsoft.ApplicationInsights.AspNetCore.Logging.ApplicationInsightsLoggerProvider"; + private const string ApplicationInsightsSettingsFile = "ApplicationInsights.settings.json"; + + private static readonly KeyValuePair[] _defaultLoggingLevels = { + new KeyValuePair("Microsoft", "Warning"), + new KeyValuePair("System", "Warning"), + new KeyValuePair("Default", "Information") + }; + /// /// Calls UseApplicationInsights /// /// public void Configure(IWebHostBuilder builder) { + builder.ConfigureAppConfiguration((context, configurationBuilder) => ConfigureLogging(configurationBuilder)); builder.UseApplicationInsights(); + builder.ConfigureServices(InitializeServices); } + private static void ConfigureLogging(IConfigurationBuilder configurationBuilder) + { + // Skip adding default rules when debugger is attached + // we want to send all events to VS + if (!Debugger.IsAttached) + { + configurationBuilder.AddInMemoryCollection(GetDefaultLoggingSettings()); + } + + var home = Environment.GetEnvironmentVariable("HOME"); + if (!string.IsNullOrEmpty(home)) + { + var settingsFile = Path.Combine(home, "site", "diagnostics", ApplicationInsightsSettingsFile); + configurationBuilder.AddJsonFile(settingsFile, optional: true); + } + } + + private static KeyValuePair[] GetDefaultLoggingSettings() + { + return _defaultLoggingLevels.Select(pair => + { + var key = $"Logging:{ApplicationInsightsLoggerFactory}:LogLevel:{pair.Key}"; + return new KeyValuePair(key, pair.Value); + }).ToArray(); + } + /// /// Adds the Javascript to the . /// /// The associated with the application. private void InitializeServices(IServiceCollection services) { + services.AddSingleton(); services.AddSingleton(); } } diff --git a/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.csproj b/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.csproj index c664103..f0c6a6c 100644 --- a/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.csproj +++ b/src/Microsoft.AspNetCore.ApplicationInsights.HostingStartup/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.csproj @@ -15,6 +15,7 @@ + \ No newline at end of file diff --git a/test/ApplicationInsightsJavaScriptSnippetTest/AfterScript.html b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/AfterScript.html similarity index 100% rename from test/ApplicationInsightsJavaScriptSnippetTest/AfterScript.html rename to test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/AfterScript.html diff --git a/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsFunctionalTest.cs b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsFunctionalTest.cs new file mode 100644 index 0000000..b3e5f17 --- /dev/null +++ b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsFunctionalTest.cs @@ -0,0 +1,66 @@ +// 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 System.IO; +using Microsoft.Extensions.Logging.Testing; +using Xunit.Abstractions; + +namespace ApplicationInsightsJavaScriptSnippetTest +{ + public class ApplicationInsightsFunctionalTest : LoggedTest + { + public ApplicationInsightsFunctionalTest(ITestOutputHelper output) : base(output) + { + } + + protected static string GetApplicationPath() + { + var current = new DirectoryInfo(AppContext.BaseDirectory); + while (current != null) + { + if (File.Exists(Path.Combine(current.FullName, "AzureIntegration.sln"))) + { + break; + } + current = current.Parent; + } + + if (current == null) + { + throw new InvalidOperationException("Could not find the solution directory"); + } + + return Path.GetFullPath(Path.Combine(current.FullName, "sample", "ApplicationInsightsHostingStartupSample")); + } + + protected static bool PreservePublishedApplicationForDebugging + { + get + { + var deletePublishedFolder = Environment.GetEnvironmentVariable("ASPNETCORE_DELETEPUBLISHEDFOLDER"); + + if (string.Equals("false", deletePublishedFolder, StringComparison.OrdinalIgnoreCase) + || string.Equals("0", deletePublishedFolder, StringComparison.OrdinalIgnoreCase)) + { + // preserve the published folder and do not delete it + return true; + } + + // do not preserve the published folder and delete it + return false; + } + } + + protected static string GetCurrentBuildConfiguration() + { + var configuration = "Debug"; + if (string.Equals(Environment.GetEnvironmentVariable("Configuration"), "Release", StringComparison.OrdinalIgnoreCase)) + { + configuration = "Release"; + } + + return configuration; + } + } +} \ No newline at end of file diff --git a/test/ApplicationInsightsJavaScriptSnippetTest/ApplicationInsightsJavaScriptSnippetTest.cs b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsJavaScriptSnippetTest.cs similarity index 65% rename from test/ApplicationInsightsJavaScriptSnippetTest/ApplicationInsightsJavaScriptSnippetTest.cs rename to test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsJavaScriptSnippetTest.cs index d627677..cc7244d 100644 --- a/test/ApplicationInsightsJavaScriptSnippetTest/ApplicationInsightsJavaScriptSnippetTest.cs +++ b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsJavaScriptSnippetTest.cs @@ -14,7 +14,7 @@ namespace ApplicationInsightsJavaScriptSnippetTest { - public class ApplicationInsightsJavaScriptSnippetTest : LoggedTest + public class ApplicationInsightsJavaScriptSnippetTest : ApplicationInsightsFunctionalTest { public ApplicationInsightsJavaScriptSnippetTest(ITestOutputHelper output) : base(output) { @@ -34,7 +34,7 @@ private async Task JavaScriptSnippetInjectionTestSuite(ApplicationType applicati using (StartLog(out var loggerFactory, testName)) { var logger = loggerFactory.CreateLogger(nameof(ApplicationInsightsJavaScriptSnippetTest)); - var deploymentParameters = new DeploymentParameters(GetApplicationPath(applicationType), ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) + var deploymentParameters = new DeploymentParameters(GetApplicationPath(), ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) { PublishApplicationBeforeDeployment = true, PreservePublishedApplicationForDebugging = PreservePublishedApplicationForDebugging, @@ -79,54 +79,5 @@ private async Task JavaScriptSnippetInjectionTestSuite(ApplicationType applicati } } } - - private static string GetApplicationPath(ApplicationType applicationType) - { - var current = new DirectoryInfo(AppContext.BaseDirectory); - while (current != null) - { - if (File.Exists(Path.Combine(current.FullName, "AzureIntegration.sln"))) - { - break; - } - current = current.Parent; - } - - if (current == null) - { - throw new InvalidOperationException("Could not find the solution directory"); - } - - return Path.GetFullPath(Path.Combine(current.FullName, "sample", "ApplicationInsightsHostingStartupSample")); - } - - private static bool PreservePublishedApplicationForDebugging - { - get - { - var deletePublishedFolder = Environment.GetEnvironmentVariable("ASPNETCORE_DELETEPUBLISHEDFOLDER"); - - if (string.Equals("false", deletePublishedFolder, StringComparison.OrdinalIgnoreCase) - || string.Equals("0", deletePublishedFolder, StringComparison.OrdinalIgnoreCase)) - { - // preserve the published folder and do not delete it - return true; - } - - // do not preserve the published folder and delete it - return false; - } - } - - private static string GetCurrentBuildConfiguration() - { - var configuration = "Debug"; - if (string.Equals(Environment.GetEnvironmentVariable("Configuration"), "Release", StringComparison.OrdinalIgnoreCase)) - { - configuration = "Release"; - } - - return configuration; - } } } diff --git a/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsLoggingTest.cs b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsLoggingTest.cs new file mode 100644 index 0000000..1c0bfc6 --- /dev/null +++ b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/ApplicationInsightsLoggingTest.cs @@ -0,0 +1,95 @@ +// 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.Collections.Generic; +using System.IO; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.Extensions.Logging; +using Xunit; +using Xunit.Abstractions; + +namespace ApplicationInsightsJavaScriptSnippetTest +{ + public class ApplicationInsightsLoggingTest : ApplicationInsightsFunctionalTest + { + public ApplicationInsightsLoggingTest(ITestOutputHelper output) : base(output) + { + } + + [Theory] + [InlineData(ApplicationType.Portable)] + [InlineData(ApplicationType.Standalone)] + public async Task ScriptInjected(ApplicationType applicationType) + { + var testName = $"ApplicationInsightsLoggingTest_{applicationType}"; + using (StartLog(out var loggerFactory, testName)) + { + var logger = loggerFactory.CreateLogger(nameof(ApplicationInsightsJavaScriptSnippetTest)); + var deploymentParameters = new DeploymentParameters(GetApplicationPath(), ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) + { + PublishApplicationBeforeDeployment = true, + PreservePublishedApplicationForDebugging = PreservePublishedApplicationForDebugging, + TargetFramework = "netcoreapp2.0", + Configuration = GetCurrentBuildConfiguration(), + ApplicationType = applicationType, + EnvironmentVariables = + { + new KeyValuePair( + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", + "Microsoft.AspNetCore.ApplicationInsights.HostingStartup"), + new KeyValuePair( + "HOME", + Path.Combine(GetApplicationPath(), "home")), + }, + }; + + using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) + { + var deploymentResult = await deployer.DeployAsync(); + var httpClientHandler = new HttpClientHandler(); + var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); + + // Request to base address and check if various parts of the body are rendered & measure the cold startup time. + var response = await RetryHelper.RetryRequest( + async () => await httpClient.GetAsync("/log"), + logger: logger, cancellationToken: deploymentResult.HostShutdownToken); + + Assert.False(response == null, "Response object is null because the client could not " + + "connect to the server after multiple retries"); + + var responseText = await response.Content.ReadAsStringAsync(); + + // Enabled by default + Assert.Contains("System warning log", responseText); + // Disabled by default + Assert.DoesNotContain("System information log", responseText); + // Disabled by default + Assert.DoesNotContain("System trace log", responseText); + + // Enabled by default + Assert.Contains("Microsoft warning log", responseText); + // Disabled by default but overridden by ApplicationInsights.settings.json + Assert.Contains("Microsoft information log", responseText); + // Disabled by default + Assert.DoesNotContain("Microsoft trace log", responseText); + + // Enabled by default + Assert.Contains("Custom warning log", responseText); + // Enabled by default + Assert.Contains("Custom information log", responseText); + // Disabled by default + Assert.DoesNotContain("Custom trace log", responseText); + + // Enabled by default + Assert.Contains("Specific warning log", responseText); + // Enabled by default + Assert.Contains("Specific information log", responseText); + // Disabled by default but overridden by ApplicationInsights.settings.json + Assert.Contains("Specific trace log", responseText); + } + } + } + } +} diff --git a/test/ApplicationInsightsJavaScriptSnippetTest/BeforeScript.html b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/BeforeScript.html similarity index 100% rename from test/ApplicationInsightsJavaScriptSnippetTest/BeforeScript.html rename to test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/BeforeScript.html diff --git a/test/ApplicationInsightsJavaScriptSnippetTest/ApplicationInsightsJavaScriptSnippetTest.csproj b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests.csproj similarity index 100% rename from test/ApplicationInsightsJavaScriptSnippetTest/ApplicationInsightsJavaScriptSnippetTest.csproj rename to test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests.csproj diff --git a/test/ApplicationInsightsJavaScriptSnippetTest/Rendered.html b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/Rendered.html similarity index 100% rename from test/ApplicationInsightsJavaScriptSnippetTest/Rendered.html rename to test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/Rendered.html diff --git a/test/ApplicationInsightsJavaScriptSnippetTest/Validator.cs b/test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/Validator.cs similarity index 100% rename from test/ApplicationInsightsJavaScriptSnippetTest/Validator.cs rename to test/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.Tests/Validator.cs