diff --git a/CHANGELOG.md b/CHANGELOG.md index 127d7e92d1..760000f1e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ This component adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.h ### Fixed +- Fixed log emission issue for ASP.NET Core 6.0 apps and enhanced diagnostics. + ### Security ## [1.0.1](https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation/releases/tag/v1.0.1) diff --git a/OpenTelemetry.AutoInstrumentation.sln b/OpenTelemetry.AutoInstrumentation.sln index 49466e5b23..6ddbf17bf0 100644 --- a/OpenTelemetry.AutoInstrumentation.sln +++ b/OpenTelemetry.AutoInstrumentation.sln @@ -203,6 +203,8 @@ 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}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -963,6 +965,18 @@ 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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1036,6 +1050,7 @@ 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} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} diff --git a/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs b/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs index a90fc43c5e..d5a971c1ba 100644 --- a/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs +++ b/src/OpenTelemetry.AutoInstrumentation/Logger/LogBuilderExtensions.cs @@ -31,15 +31,16 @@ public static ILoggingBuilder AddOpenTelemetryLogs(this ILoggingBuilder builder) { try { - if (!(builder.Services is ServiceCollection services)) + 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; } // Integrate AddOpenTelemetry only once for ServiceCollection. _loggingProviderSdkType ??= Type.GetType("OpenTelemetry.Logs.LoggerProviderBuilderSdk, OpenTelemetry"); - var openTelemetryLoggerProviderDescriptor = services.FirstOrDefault(descriptor => descriptor.ImplementationType == _loggingProviderSdkType); + var openTelemetryLoggerProviderDescriptor = builder.Services.FirstOrDefault(descriptor => descriptor.ImplementationType == _loggingProviderSdkType); if (openTelemetryLoggerProviderDescriptor != null) { AutoInstrumentationEventSource.Log.Verbose("Logs: AddOpenTelemetry already called on logging builder instance."); diff --git a/test/IntegrationTests/LogRazorTests.cs b/test/IntegrationTests/LogRazorTests.cs new file mode 100644 index 0000000000..1fcc501173 --- /dev/null +++ b/test/IntegrationTests/LogRazorTests.cs @@ -0,0 +1,59 @@ +// +// 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 Xunit.Abstractions; + +namespace IntegrationTests; + +public class LogRazorTests : TestHelper +{ + public LogRazorTests(ITestOutputHelper output) + : base("Razor", output) + { + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + [Trait("Category", "EndToEnd")] + public void SubmitLogs(bool enableClrProfiler) + { + 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"); + } + + SetEnvironmentVariable("OTEL_DOTNET_AUTO_LOGS_INCLUDE_FORMATTED_MESSAGE", "true"); + RunTestApplication(); + + collector.AssertExpectations(); + } +} +#endif diff --git a/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml b/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml new file mode 100644 index 0000000000..1df1cb19ff --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml @@ -0,0 +1,5 @@ +@page +

Hello World!

+@model TestApplication.Razor.Pages.IndexModel +@{ +} diff --git a/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml.cs b/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml.cs new file mode 100644 index 0000000000..c12e36c81d --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Razor/Pages/Index.cshtml.cs @@ -0,0 +1,36 @@ +// +// 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. +// + +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace TestApplication.Razor.Pages; + +#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."); + } +} diff --git a/test/test-applications/integrations/TestApplication.Razor/Program.cs b/test/test-applications/integrations/TestApplication.Razor/Program.cs new file mode 100644 index 0000000000..35aa847781 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Razor/Program.cs @@ -0,0 +1,44 @@ +// +// 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. +// + +using System.Net.Http; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; + +namespace TestApplication.Razor; + +public class Program +{ + public static void Main(string[] args) + { + using var host = CreateHostBuilder(args).Build(); + host.Start(); + + 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(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + webBuilder.UseUrls($"http://127.0.0.1:0"); + }); +} diff --git a/test/test-applications/integrations/TestApplication.Razor/Startup.cs b/test/test-applications/integrations/TestApplication.Razor/Startup.cs new file mode 100644 index 0000000000..abe5de228b --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Razor/Startup.cs @@ -0,0 +1,50 @@ +// +// 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/TestApplication.Razor.csproj b/test/test-applications/integrations/TestApplication.Razor/TestApplication.Razor.csproj new file mode 100644 index 0000000000..51663a15b7 --- /dev/null +++ b/test/test-applications/integrations/TestApplication.Razor/TestApplication.Razor.csproj @@ -0,0 +1,7 @@ + + + + net7.0;net6.0 + + +