diff --git a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ProfileExporter.cpp b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ProfileExporter.cpp index 16f19839f4fc..774f19fd8398 100644 --- a/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ProfileExporter.cpp +++ b/profiler/src/ProfilerEngine/Datadog.Profiler.Native/ProfileExporter.cpp @@ -279,6 +279,17 @@ std::string ProfileExporter::BuildAgentEndpoint(IConfiguration const* configurat // handle "with agent" case auto url = configuration->GetAgentUrl(); // copy expected here + if (url.rfind("unix://", 0) == 0) + { + auto path = fs::path(url.substr(7)); + std::error_code ec; + if (!fs::exists(path, ec)) + { + Log::Debug("Env var '", EnvironmentVariables::AgentUrl, "' contains a path to a non-existent UDS '", url, "'. Fallback to default (HTTP)."); + url = ""; + } + } + if (url.empty()) { // Agent mode @@ -298,14 +309,14 @@ std::string ProfileExporter::BuildAgentEndpoint(IConfiguration const* configurat } #endif + } - if (url.empty()) - { - // Use default HTTP endpoint - std::stringstream oss; - oss << "http://" << configuration->GetAgentHost() << ":" << configuration->GetAgentPort(); - url = oss.str(); - } + if (url.empty()) + { + // Use default HTTP endpoint + std::stringstream oss; + oss << "http://" << configuration->GetAgentHost() << ":" << configuration->GetAgentPort(); + url = oss.str(); } Log::Info("Using agent endpoint ", url); diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Allocations/AllocationsProfilerTest.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Allocations/AllocationsProfilerTest.cs index 6f8bf0196298..668dea3d91e3 100644 --- a/profiler/test/Datadog.Profiler.IntegrationTests/Allocations/AllocationsProfilerTest.cs +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Allocations/AllocationsProfilerTest.cs @@ -353,7 +353,7 @@ private static int GotoEoL(string text, int pos) // no size available for .NET Framework if (sample.Value.Count > 1) { - size = sample.Value[1]; + size = sample.Value[1]; } var labels = sample.Labels(profile).ToArray(); diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Bugs/UnixDomainSocketBug.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Bugs/UnixDomainSocketBug.cs new file mode 100644 index 000000000000..b81da61ad6a1 --- /dev/null +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Bugs/UnixDomainSocketBug.cs @@ -0,0 +1,40 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2022 Datadog, Inc. +// + +using System.IO; +using System.Linq; +using Datadog.Profiler.IntegrationTests.Helpers; +using Datadog.Profiler.SmokeTests; +using Xunit; +using Xunit.Abstractions; + +namespace Datadog.Profiler.IntegrationTests.Bugs +{ + public class UnixDomainSocketBug + { + private readonly ITestOutputHelper _output; + + public UnixDomainSocketBug(ITestOutputHelper output) + { + _output = output; + } + + [TestAppFact("Samples.Computer01")] + public void MustUseHttpIfUDS_DoesNotExist(string appName, string framework, string appAssembly) + { + var runner = new SmokeTestRunner(appName, framework, appAssembly, commandLine: "--scenario 1", output: _output); + EnvironmentHelper.DisableDefaultProfilers(runner); + runner.EnvironmentHelper.SetVariable(EnvironmentVariables.WallTimeProfilerEnabled, "1"); + runner.EnvironmentHelper.SetVariable(EnvironmentVariables.AgentUrl, "unix:///non_existent/socket"); + runner.RunAndCheck(); + + var logFile = Directory.GetFiles(runner.EnvironmentHelper.LogDir) + .Single(f => Path.GetFileName(f).StartsWith("DD-DotNet-Profiler-Native-")); + + var nbSignalHandlerInstallation = File.ReadLines(logFile) + .Count(l => l.Contains("Env var 'DD_TRACE_AGENT_URL' contains a path to a non-existent UDS 'unix:///non_existent/socket'. Fallback to default (HTTP).")); + } + } +} diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Exceptions/ExceptionsTest.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Exceptions/ExceptionsTest.cs index bb8fffe46b3f..8f08cf8d3ed0 100644 --- a/profiler/test/Datadog.Profiler.IntegrationTests/Exceptions/ExceptionsTest.cs +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Exceptions/ExceptionsTest.cs @@ -120,7 +120,7 @@ public void ThrowExceptionsInParallel(string appName, string framework, string a } [Trait("Category", "LinuxOnly")] - [TestAppFact("Samples.ExceptionGenerator", new [] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now + [TestAppFact("Samples.ExceptionGenerator", new[] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now public void ThrowExceptionsInParallelWithNewCpuProfiler(string appName, string framework, string appAssembly) { StackTrace expectedStack; @@ -222,7 +222,7 @@ public void Sampling(string appName, string framework, string appAssembly) exceptionCounts.Should().ContainKey("System.InvalidOperationException").WhoseValue.Should().Be(1); } - [TestAppFact("Samples.ExceptionGenerator", new [] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now + [TestAppFact("Samples.ExceptionGenerator", new[] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now public void GetExceptionSamplesWithTimestamp(string appName, string framework, string appAssembly) { var runner = new TestApplicationRunner(appName, framework, appAssembly, _output, commandLine: Scenario1); @@ -233,7 +233,7 @@ public void GetExceptionSamplesWithTimestamp(string appName, string framework, s CheckExceptionProfiles(runner, true); } - [TestAppFact("Samples.ExceptionGenerator", new [] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now + [TestAppFact("Samples.ExceptionGenerator", new[] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now public void GetExceptionSamplesWithoutTimestamp(string appName, string framework, string appAssembly) { var runner = new TestApplicationRunner(appName, framework, appAssembly, _output, commandLine: Scenario1); diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentHelper.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentHelper.cs index d80899d4621e..4cf1ab49eae4 100644 --- a/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentHelper.cs +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentHelper.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Runtime.InteropServices; using Datadog.Profiler.IntegrationTests.Xunit; +using Datadog.Profiler.SmokeTests; namespace Datadog.Profiler.IntegrationTests.Helpers { @@ -91,11 +92,12 @@ internal static string GetConfiguration() internal static void DisableDefaultProfilers(TestApplicationRunner runner) { - runner.Environment.SetVariable(EnvironmentVariables.WallTimeProfilerEnabled, "0"); - runner.Environment.SetVariable(EnvironmentVariables.CpuProfilerEnabled, "0"); - runner.Environment.SetVariable(EnvironmentVariables.GarbageCollectionProfilerEnabled, "0"); - runner.Environment.SetVariable(EnvironmentVariables.ExceptionProfilerEnabled, "0"); - runner.Environment.SetVariable(EnvironmentVariables.ContentionProfilerEnabled, "0"); + DisableDefaultProfilers(runner.Environment); + } + + internal static void DisableDefaultProfilers(SmokeTestRunner runner) + { + DisableDefaultProfilers(runner.EnvironmentHelper); } internal void EnableTracer() @@ -213,6 +215,15 @@ internal string GetTestOutputPath() return _testOutputPath; } + private static void DisableDefaultProfilers(EnvironmentHelper env) + { + env.SetVariable(EnvironmentVariables.WallTimeProfilerEnabled, "0"); + env.SetVariable(EnvironmentVariables.CpuProfilerEnabled, "0"); + env.SetVariable(EnvironmentVariables.GarbageCollectionProfilerEnabled, "0"); + env.SetVariable(EnvironmentVariables.ExceptionProfilerEnabled, "0"); + env.SetVariable(EnvironmentVariables.ContentionProfilerEnabled, "0"); + } + private static string BuildTestOutputPath(string framework) { // DD_TESTING_OUPUT_DIR is set by the CI diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentVariables.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentVariables.cs index 5dd89adbe62b..ef68bdde251a 100644 --- a/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentVariables.cs +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Helpers/EnvironmentVariables.cs @@ -34,5 +34,6 @@ internal class EnvironmentVariables public const string TelemetryToDiskEnabled = "DD_INTERNAL_PROFILING_TELEMETRY_TO_DISK_ENABLED"; public const string EtwReplayEndpoint = "DD_INTERNAL_ETW_REPLAY_ENDPOINT"; public const string SsiTelemetryEnabled = "DD_INTERNAL_PROFILING_SSI_TELEMETRY_ENABLED"; + public const string AgentUrl = "DD_TRACE_AGENT_URL"; } } diff --git a/profiler/test/Datadog.Profiler.IntegrationTests/Signature/SignatureTest.cs b/profiler/test/Datadog.Profiler.IntegrationTests/Signature/SignatureTest.cs index 3cb031fbeef5..4721ad795717 100644 --- a/profiler/test/Datadog.Profiler.IntegrationTests/Signature/SignatureTest.cs +++ b/profiler/test/Datadog.Profiler.IntegrationTests/Signature/SignatureTest.cs @@ -21,7 +21,7 @@ public SignatureTest(ITestOutputHelper output) _output = output; } - [TestAppFact("Samples.Computer01", new [] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now + [TestAppFact("Samples.Computer01", new[] { "net462", "netcoreapp3.1", "net6.0", "net8.0", })] // FIXME: .NET 9 skipping .NET 9 for now public void ValidateSignatures(string appName, string framework, string appAssembly) { var runner = new TestApplicationRunner(appName, framework, appAssembly, _output, commandLine: "--scenario 20"); diff --git a/tracer/test/Datadog.Trace.TestHelpers/MockSpanLink.cs b/tracer/test/Datadog.Trace.TestHelpers/MockSpanLink.cs index a960cd63f86f..b0a3073a85b4 100644 --- a/tracer/test/Datadog.Trace.TestHelpers/MockSpanLink.cs +++ b/tracer/test/Datadog.Trace.TestHelpers/MockSpanLink.cs @@ -28,6 +28,6 @@ public class MockSpanLink public string TraceState { get; set; } [Key("attributes")] - public Dictionary Attributes { get; set; } + public Dictionary Attributes { get; set; } } }