diff --git a/CHANGELOG.md b/CHANGELOG.md index 0445425997..5b75d2db96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,10 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h ### Fixed +- Fixed log emission issue which resulted in same logs being exported multiple + times for ASP.NET Core 6.0 apps when bytecode instrumentation was enabled + and `WebApplicationBuilder` was used. + ### Security ## [1.0.2](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/tag/v1.0.2) diff --git a/OpenTelemetry.AutoInstrumentation.sln b/OpenTelemetry.AutoInstrumentation.sln index 6ddbf17bf0..eb28835973 100644 --- a/OpenTelemetry.AutoInstrumentation.sln +++ b/OpenTelemetry.AutoInstrumentation.sln @@ -203,7 +203,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Azure", "te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.Wcf.Client.DotNet", "test\test-applications\integrations\TestApplication.Wcf.Client.DotNet\TestApplication.Wcf.Client.DotNet.csproj", "{EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.Razor", "test\test-applications\integrations\TestApplication.Razor\TestApplication.Razor.csproj", "{1C76773E-2582-40DB-A720-3798E3928876}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestApplication.MinimalApi", "test\test-applications\integrations\TestApplication.MinimalApi\TestApplication.MinimalApi.csproj", "{803A3DD1-016E-4713-8066-A1C81A6ADBA3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestApplication.Worker", "test\test-applications\integrations\TestApplication.Worker\TestApplication.Worker.csproj", "{E04065C2-0512-41C6-A428-AC85342B3D03}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -965,18 +967,30 @@ Global {EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x64.Build.0 = Release|x64 {EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x86.ActiveCfg = Release|x86 {EDE168E0-DBCD-4DE3-B55A-4B633ED6565E}.Release|x86.Build.0 = Release|x86 - {1C76773E-2582-40DB-A720-3798E3928876}.Debug|Any CPU.ActiveCfg = Debug|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Debug|Any CPU.Build.0 = Debug|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Debug|x64.ActiveCfg = Debug|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Debug|x64.Build.0 = Debug|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Debug|x86.ActiveCfg = Debug|x86 - {1C76773E-2582-40DB-A720-3798E3928876}.Debug|x86.Build.0 = Debug|x86 - {1C76773E-2582-40DB-A720-3798E3928876}.Release|Any CPU.ActiveCfg = Release|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Release|Any CPU.Build.0 = Release|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Release|x64.ActiveCfg = Release|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Release|x64.Build.0 = Release|x64 - {1C76773E-2582-40DB-A720-3798E3928876}.Release|x86.ActiveCfg = Release|x86 - {1C76773E-2582-40DB-A720-3798E3928876}.Release|x86.Build.0 = Release|x86 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Debug|Any CPU.ActiveCfg = Debug|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Debug|Any CPU.Build.0 = Debug|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Debug|x64.ActiveCfg = Debug|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Debug|x64.Build.0 = Debug|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Debug|x86.ActiveCfg = Debug|x86 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Debug|x86.Build.0 = Debug|x86 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Release|Any CPU.ActiveCfg = Release|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Release|Any CPU.Build.0 = Release|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Release|x64.ActiveCfg = Release|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Release|x64.Build.0 = Release|x64 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Release|x86.ActiveCfg = Release|x86 + {803A3DD1-016E-4713-8066-A1C81A6ADBA3}.Release|x86.Build.0 = Release|x86 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Debug|Any CPU.ActiveCfg = Debug|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Debug|Any CPU.Build.0 = Debug|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Debug|x64.ActiveCfg = Debug|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Debug|x64.Build.0 = Debug|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Debug|x86.ActiveCfg = Debug|x86 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Debug|x86.Build.0 = Debug|x86 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Release|Any CPU.ActiveCfg = Release|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Release|Any CPU.Build.0 = Release|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Release|x64.ActiveCfg = Release|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Release|x64.Build.0 = Release|x64 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Release|x86.ActiveCfg = Release|x86 + {E04065C2-0512-41C6-A428-AC85342B3D03}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1050,7 +1064,8 @@ Global {C66927FD-ED1F-4079-8733-51AB7463060D} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {3A125210-A784-4982-ACDB-C3442E414E44} = {E409ADD3-9574-465C-AB09-4324D205CC7C} {EDE168E0-DBCD-4DE3-B55A-4B633ED6565E} = {E409ADD3-9574-465C-AB09-4324D205CC7C} - {1C76773E-2582-40DB-A720-3798E3928876} = {E409ADD3-9574-465C-AB09-4324D205CC7C} + {803A3DD1-016E-4713-8066-A1C81A6ADBA3} = {E409ADD3-9574-465C-AB09-4324D205CC7C} + {E04065C2-0512-41C6-A428-AC85342B3D03} = {E409ADD3-9574-465C-AB09-4324D205CC7C} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} diff --git a/src/OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper/BootstrapperHostingStartup.cs b/src/OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper/BootstrapperHostingStartup.cs index 8c9c57afeb..ac94357082 100644 --- a/src/OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper/BootstrapperHostingStartup.cs +++ b/src/OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper/BootstrapperHostingStartup.cs @@ -60,7 +60,7 @@ public void Configure(IWebHostBuilder builder) try { - builder.ConfigureLogging(logging => logging.AddOpenTelemetryLogs()); + builder.ConfigureLogging(logging => logging.AddOpenTelemetryLogsFromStartup()); var applicationName = GetApplicationName(); Logger.Information($"BootstrapperHostingStartup loaded for application with name {applicationName}."); diff --git a/src/OpenTelemetry.AutoInstrumentation/Instrumentations/Logger/LoggingBuilderIntegration.cs b/src/OpenTelemetry.AutoInstrumentation/Instrumentations/Logger/LoggingBuilderIntegration.cs index 7ac018df3c..f20ac1ae41 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Instrumentations/Logger/LoggingBuilderIntegration.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Instrumentations/Logger/LoggingBuilderIntegration.cs @@ -47,7 +47,7 @@ internal static CallTargetReturn OnMethodEnd(TTarget instance, Exceptio if (instance is not null) { var logBuilderExtensionsType = Type.GetType("OpenTelemetry.AutoInstrumentation.Logger.LogBuilderExtensions, OpenTelemetry.AutoInstrumentation"); - var methodInfo = logBuilderExtensionsType?.GetMethod("AddOpenTelemetryLogs"); + var methodInfo = logBuilderExtensionsType?.GetMethod("AddOpenTelemetryLogsFromIntegration"); methodInfo?.Invoke(null, new[] { (object)instance }); } diff --git a/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs b/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs index d5a971c1ba..3557385e75 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs @@ -26,15 +26,42 @@ namespace OpenTelemetry.AutoInstrumentation.Logger; internal static class LogBuilderExtensions { private static Type? _loggingProviderSdkType; + private static volatile bool _hostingStartupRan; - public static ILoggingBuilder AddOpenTelemetryLogs(this ILoggingBuilder builder) + // this method is only called from LoggingBuilderIntegration + public static void AddOpenTelemetryLogsFromIntegration(ILoggingBuilder builder) + { + // For Net6, if HostingStartupAssembly is configured, we don't want to call integration again for host's ServiceCollection. + // OpenTelemetryLogger-related services were already added to WebApplicationServiceCollection and will + // be copied to host's ServiceCollection later. We can't depend on integration's + // capability to detect if integration was called before (by checking if ServiceDescriptor with + // given type is already added to ServiceCollection) as copying services from WebApplicationServiceCollection + // to host's ServiceCollection happens AFTER integration is called. + + // All of this additional checking is NOT needed for net7. There we can rely on integration's capability + // to detect if integration was called before, because WebApplicationServiceCollection is not used when building host. + + if (builder.Services is ServiceCollection && !(IsNet6() && _hostingStartupRan && IsHostServiceCollection(builder.Services))) + { + AddOpenTelemetryLogs(builder); + } + } + + // this method is only called from BootstrapperHostingStartup + public static void AddOpenTelemetryLogsFromStartup(this ILoggingBuilder builder) + { + AddOpenTelemetryLogs(builder); + _hostingStartupRan = true; + } + + private static void AddOpenTelemetryLogs(ILoggingBuilder builder) { try { if (builder.Services == null) { AutoInstrumentationEventSource.Log.Verbose("Logs: The builder.Services property is not of the IServiceCollection type, so we're skipping the integration of logs with ServiceCollection."); - return builder; + return; } // Integrate AddOpenTelemetry only once for ServiceCollection. @@ -44,7 +71,7 @@ public static ILoggingBuilder AddOpenTelemetryLogs(this ILoggingBuilder builder) if (openTelemetryLoggerProviderDescriptor != null) { AutoInstrumentationEventSource.Log.Verbose("Logs: AddOpenTelemetry already called on logging builder instance."); - return builder; + return; } var settings = Instrumentation.LogSettings.Value; @@ -93,8 +120,24 @@ public static ILoggingBuilder AddOpenTelemetryLogs(this ILoggingBuilder builder) AutoInstrumentationEventSource.Log.Error($"Error in AddOpenTelemetryLogs: {ex}"); throw; } + } + + private static bool IsNet6() + { + var frameworkDescription = FrameworkDescription.Instance; + return frameworkDescription.Name == ".NET" && frameworkDescription.ProductVersion.StartsWith("6"); + } + + private static bool IsHostServiceCollection(IServiceCollection builderServices) + { + var applicationLifetimeType = Type.GetType("Microsoft.Extensions.Hosting.Internal.ApplicationLifetime, Microsoft.Extensions.Hosting"); + if (applicationLifetimeType == null) + { + return false; + } - return builder; + var applicationLifetimeDescriptor = builderServices.FirstOrDefault(sd => sd.ImplementationType == applicationLifetimeType); + return applicationLifetimeDescriptor != null; } } #endif diff --git a/test/IntegrationTests/IntegrationTests.csproj b/test/IntegrationTests/IntegrationTests.csproj index 1ad67d10ec..451759069c 100644 --- a/test/IntegrationTests/IntegrationTests.csproj +++ b/test/IntegrationTests/IntegrationTests.csproj @@ -26,6 +26,7 @@ + diff --git a/test/IntegrationTests/MinimalApiTests.cs b/test/IntegrationTests/MinimalApiTests.cs new file mode 100644 index 0000000000..8c8e464645 --- /dev/null +++ b/test/IntegrationTests/MinimalApiTests.cs @@ -0,0 +1,91 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#if NET6_0_OR_GREATER + +using IntegrationTests.Helpers; +using OpenTelemetry.AutoInstrumentation; +using OpenTelemetry.Proto.Logs.V1; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace IntegrationTests; + +public class MinimalApiTests : TestHelper +{ + public MinimalApiTests(ITestOutputHelper output) + : base("MinimalApi", output) + { + } + + [SkippableTheory] + [InlineData(true, true)] + [InlineData(true, false)] + [InlineData(false, true)] + [Trait("Category", "EndToEnd")] + public async Task SubmitsLogsWithoutDuplicates(bool enableByteCodeInstrumentation, bool enableHostingStartupAssembly) + { +#if NET6_0 + Skip.If(EnvironmentTools.IsMacOS(), "Known issue on MacOS."); +#endif + + using var collector = new MockLogsCollector(Output); + SetExporter(collector); + + SetEnvironmentVariable("OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE", "true"); + + if (enableByteCodeInstrumentation) + { + EnableBytecodeInstrumentation(); + collector.ExpectCollected(ValidateCombinedLogsExport, "All log records should be exported once."); + } + + if (enableHostingStartupAssembly) + { + SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper"); + if (!enableByteCodeInstrumentation) + { + // otherwise expectation was already set + collector.ExpectCollected(ValidateSingleAppLogExport, "Application log records should be exported once."); + } + } + + RunTestApplication(); + + // wait for fixed amount of time for logs to be collected before asserting + await Task.Delay(TimeSpan.FromSeconds(10)); + + collector.AssertCollected(); + } + + private static bool ValidateCombinedLogsExport(IEnumerable records) + { + return ValidateSingleAppLogExport(records) && ValidateSingleBeforeHostLogRecord(records); + } + + private static bool ValidateSingleBeforeHostLogRecord(IEnumerable records) + { + var beforeHostLogCount = records.Count(lr => Convert.ToString(lr.Body) == "{ \"stringValue\": \"Logged before host is built.\" }"); + return beforeHostLogCount == 1; + } + + private static bool ValidateSingleAppLogExport(IEnumerable records) + { + var appLogCount = records.Count(lr => Convert.ToString(lr.Body) == "{ \"stringValue\": \"Request received.\" }"); + return appLogCount == 1; + } +} +#endif diff --git a/test/IntegrationTests/LogRazorTests.cs b/test/IntegrationTests/WorkerTests.cs similarity index 53% rename from test/IntegrationTests/LogRazorTests.cs rename to test/IntegrationTests/WorkerTests.cs index 1fcc501173..d6fe57fd88 100644 --- a/test/IntegrationTests/LogRazorTests.cs +++ b/test/IntegrationTests/WorkerTests.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,46 +14,45 @@ // limitations under the License. // -#if NET6_0_OR_GREATER using IntegrationTests.Helpers; +using OpenTelemetry.Proto.Logs.V1; using Xunit.Abstractions; +#if NET6_0_OR_GREATER + namespace IntegrationTests; -public class LogRazorTests : TestHelper +public class WorkerTests : TestHelper { - public LogRazorTests(ITestOutputHelper output) - : base("Razor", output) + public WorkerTests(ITestOutputHelper output) + : base("Worker", output) { } - [Theory] - [InlineData(true)] - [InlineData(false)] - [Trait("Category", "EndToEnd")] - public void SubmitLogs(bool enableClrProfiler) + [Fact] + public async Task SubmitsLogsWithoutDuplicates() { using var collector = new MockLogsCollector(Output); SetExporter(collector); - collector.Expect(logRecord => - { - var logsAsString = Convert.ToString(logRecord); - return logsAsString != null && logsAsString.Contains("Warning from Razor App."); - }); - - if (enableClrProfiler) - { - EnableBytecodeInstrumentation(); - } - else - { - SetEnvironmentVariable("ASPNETCORE_HOSTINGSTARTUPASSEMBLIES", "OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper"); - } + + collector.ExpectCollected(ValidateSingleAppLogRecord, "App log record should be exported once."); SetEnvironmentVariable("OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE", "true"); + + EnableBytecodeInstrumentation(); + RunTestApplication(); - collector.AssertExpectations(); + // wait for fixed amount of time for logs to be collected before asserting + await Task.Delay(TimeSpan.FromSeconds(10)); + + collector.AssertCollected(); + } + + private static bool ValidateSingleAppLogRecord(IEnumerable records) + { + return records.Count(lr => Convert.ToString(lr.Body) == "{ \"stringValue\": \"Worker running.\" }") == 1; } } + #endif diff --git a/test/test-applications/integrations/TestApplication.Razor/Program.cs b/test/test-applications/integrations/TestApplication.MinimalApi/Program.cs similarity index 50% rename from test/test-applications/integrations/TestApplication.Razor/Program.cs rename to test/test-applications/integrations/TestApplication.MinimalApi/Program.cs index 35aa847781..b4fc0cde04 100644 --- a/test/test-applications/integrations/TestApplication.Razor/Program.cs +++ b/test/test-applications/integrations/TestApplication.MinimalApi/Program.cs @@ -18,27 +18,27 @@ using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; -namespace TestApplication.Razor; +using var loggerFactory = LoggerFactory.Create(builder => + { + builder + .AddFilter("Microsoft", LogLevel.Warning); + }); +var logger = loggerFactory.CreateLogger(); +logger.LogInformation("Logged before host is built."); +var builder = WebApplication.CreateBuilder(args); -public class Program +using var app = builder.Build(); +app.MapGet("/test", (ILogger logger) => { - public static void Main(string[] args) - { - using var host = CreateHostBuilder(args).Build(); - host.Start(); + logger.LogInformation("Request received."); + return "Hello World!"; +}); - var server = (IServer?)host.Services.GetService(typeof(IServer)); - var addressFeature = server?.Features.Get(); - var address = addressFeature?.Addresses.First(); - using var httpClient = new HttpClient(); - httpClient.GetAsync($"{address}/").Wait(); - } +app.Start(); - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - webBuilder.UseUrls($"http://127.0.0.1:0"); - }); -} +var server = (IServer?)app.Services.GetService(typeof(IServer)); +var addressFeature = server?.Features.Get(); +var address = addressFeature?.Addresses.First(); + +using var httpClient = new HttpClient(); +httpClient.GetAsync($"{address}/test").Wait(); diff --git a/test/test-applications/integrations/TestApplication.MinimalApi/Properties/launchSettings.json b/test/test-applications/integrations/TestApplication.MinimalApi/Properties/launchSettings.json new file mode 100644 index 0000000000..ce0f4f75d8 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.MinimalApi/Properties/launchSettings.json @@ -0,0 +1,49 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:19686", + "sslPort": 44323 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5102", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7273;http://localhost:5102", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "instrumented": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "OpenTelemetry.AutoInstrumentation.AspNetCoreBootstrapper", + "CORECLR_ENABLE_PROFILING": "1", + "CORECLR_PROFILER": "{918728DD-259F-4A6A-AC2B-B85E1B658318}", + "CORECLR_PROFILER_PATH": "$(SolutionDir)bin\\tracer-home\\win-x64\\OpenTelemetry.AutoInstrumentation.Native.dll", + "DOTNET_ADDITIONAL_DEPS": "$(SolutionDir)bin\\tracer-home\\AdditionalDeps", + "DOTNET_SHARED_STORE": "$(SolutionDir)bin\\tracer-home\\store", + "DOTNET_STARTUP_HOOKS": "$(SolutionDir)bin\\tracer-home\\net\\OpenTelemetry.AutoInstrumentation.StartupHook.dll", + "OTEL_DOTNET_AUTO_HOME": "$(SolutionDir)bin\\tracer-home", + "OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED": "true" + }, + "use64Bit": true, + "nativeDebugging": true, + "applicationUrl": "http://localhost:54568" + } + } +} diff --git a/test/test-applications/integrations/TestApplication.Razor/TestApplication.Razor.csproj b/test/test-applications/integrations/TestApplication.MinimalApi/TestApplication.MinimalApi.csproj similarity index 100% rename from test/test-applications/integrations/TestApplication.Razor/TestApplication.Razor.csproj rename to test/test-applications/integrations/TestApplication.MinimalApi/TestApplication.MinimalApi.csproj diff --git a/test/test-applications/integrations/TestApplication.MinimalApi/appsettings.Development.json b/test/test-applications/integrations/TestApplication.MinimalApi/appsettings.Development.json new file mode 100644 index 0000000000..0c208ae918 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.MinimalApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/test/test-applications/integrations/TestApplication.MinimalApi/appsettings.json b/test/test-applications/integrations/TestApplication.MinimalApi/appsettings.json new file mode 100644 index 0000000000..10f68b8c8b --- /dev/null +++ b/test/test-applications/integrations/TestApplication.MinimalApi/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml b/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml deleted file mode 100644 index 1df1cb19ff..0000000000 --- a/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml +++ /dev/null @@ -1,5 +0,0 @@ -@page -

Hello World!

-@model TestApplication.Razor.Pages.IndexModel -@{ -} diff --git a/test/test-applications/integrations/TestApplication.Razor/Startup.cs b/test/test-applications/integrations/TestApplication.Razor/Startup.cs deleted file mode 100644 index abe5de228b..0000000000 --- a/test/test-applications/integrations/TestApplication.Razor/Startup.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -namespace TestApplication.Razor; - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) - { - services.AddRazorPages(); - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger logger) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/Error"); - app.UseHsts(); - } - - app.UseHttpsRedirection(); - app.UseStaticFiles(); - - app.UseRouting(); - - app.UseEndpoints(endpoints => - { - endpoints.MapRazorPages(); - }); - - logger.LogWarning("Startup Configuration is completed."); - } -} diff --git a/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml.cs b/test/test-applications/integrations/TestApplication.Worker/Program.cs similarity index 52% rename from test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml.cs rename to test/test-applications/integrations/TestApplication.Worker/Program.cs index c12e36c81d..3639c47427 100644 --- a/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml.cs +++ b/test/test-applications/integrations/TestApplication.Worker/Program.cs @@ -1,4 +1,4 @@ -// +// // Copyright The OpenTelemetry Authors // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,23 +14,10 @@ // limitations under the License. // -using Microsoft.AspNetCore.Mvc.RazorPages; +using TestApplication.Worker; -namespace TestApplication.Razor.Pages; +IHost host = Host.CreateDefaultBuilder(args) + .ConfigureServices(services => { services.AddHostedService(); }) + .Build(); -#pragma warning disable SA1649 // File name should match first type name -public class IndexModel : PageModel -#pragma warning restore SA1649 // File name should match first type name -{ - private readonly ILogger _logger; - - public IndexModel(ILogger logger) - { - _logger = logger; - } - - public void OnGet() - { - _logger.LogWarning("Warning from Razor App."); - } -} +await host.RunAsync(); diff --git a/test/test-applications/integrations/TestApplication.Worker/Properties/launchSettings.json b/test/test-applications/integrations/TestApplication.Worker/Properties/launchSettings.json new file mode 100644 index 0000000000..a514ee3d18 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Worker/Properties/launchSettings.json @@ -0,0 +1,19 @@ +{ + "profiles": { + "instrumented": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development", + "CORECLR_ENABLE_PROFILING": "1", + "CORECLR_PROFILER": "{918728DD-259F-4A6A-AC2B-B85E1B658318}", + "CORECLR_PROFILER_PATH": "$(SolutionDir)bin\\tracer-home\\win-x64\\OpenTelemetry.AutoInstrumentation.Native.dll", + "DOTNET_ADDITIONAL_DEPS": "$(SolutionDir)bin\\tracer-home\\AdditionalDeps", + "DOTNET_SHARED_STORE": "$(SolutionDir)bin\\tracer-home\\store", + "DOTNET_STARTUP_HOOKS": "$(SolutionDir)bin\\tracer-home\\net\\OpenTelemetry.AutoInstrumentation.StartupHook.dll", + "OTEL_DOTNET_AUTO_HOME": "$(SolutionDir)bin\\tracer-home", + "OTEL_DOTNET_AUTO_LOGS_CONSOLE_EXPORTER_ENABLED": "true" + } + } + } +} diff --git a/test/test-applications/integrations/TestApplication.Worker/TestApplication.Worker.csproj b/test/test-applications/integrations/TestApplication.Worker/TestApplication.Worker.csproj new file mode 100644 index 0000000000..18a4f66b71 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Worker/TestApplication.Worker.csproj @@ -0,0 +1,10 @@ + + + + net7.0;net6.0 + + + + + + diff --git a/test/test-applications/integrations/TestApplication.Worker/Worker.cs b/test/test-applications/integrations/TestApplication.Worker/Worker.cs new file mode 100644 index 0000000000..5023a074a7 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Worker/Worker.cs @@ -0,0 +1,37 @@ +// +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +namespace TestApplication.Worker; + +public class Worker : BackgroundService +{ + private readonly ILogger _logger; + private readonly IHostApplicationLifetime _hostApplicationLifetime; + + public Worker(ILogger logger, IHostApplicationLifetime hostApplicationLifetime) + { + _logger = logger; + _hostApplicationLifetime = hostApplicationLifetime; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + _logger.LogInformation("Worker running."); + await Task.Delay(1000, stoppingToken); + // When completed, the entire app host will stop. + _hostApplicationLifetime.StopApplication(); + } +} diff --git a/test/test-applications/integrations/TestApplication.Worker/appsettings.Development.json b/test/test-applications/integrations/TestApplication.Worker/appsettings.Development.json new file mode 100644 index 0000000000..b2dcdb6742 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Worker/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/test/test-applications/integrations/TestApplication.Worker/appsettings.json b/test/test-applications/integrations/TestApplication.Worker/appsettings.json new file mode 100644 index 0000000000..b2dcdb6742 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Worker/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +}