diff --git a/Datadog.Trace.sln b/Datadog.Trace.sln index 9f45fd749a25..680b1224dc5a 100644 --- a/Datadog.Trace.sln +++ b/Datadog.Trace.sln @@ -546,6 +546,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Datadog.Trace.Tools.dd_dotn EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.AWS.DynamoDBv2", "tracer\test\test-applications\integrations\Samples.AWS.DynamoDBv2\Samples.AWS.DynamoDBv2.csproj", "{D59C5649-BE0E-4A33-B868-B652D8614534}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.Tools.Shared", "tracer\src\Datadog.Trace.Tools.Shared\Datadog.Trace.Tools.Shared.csproj", "{7A1B9BFE-052D-435E-B27F-72AF3DDCC0A0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.Tools.dd_dotnet.Tests", "tracer\test\Datadog.Trace.Tools.dd_dotnet.Tests\Datadog.Trace.Tools.dd_dotnet.Tests.csproj", "{4E9535E2-C918-4C39-9F1B-F182C185DE64}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Amazon.Lambda.RuntimeSupport", "tracer\test\test-applications\integrations\Samples.Amazon.Lambda.RuntimeSupport\Samples.Amazon.Lambda.RuntimeSupport.csproj", "{18A6904A-5AFD-4816-AC3F-9F5E433720B5}" EndProject Global @@ -1304,6 +1308,14 @@ Global {D59C5649-BE0E-4A33-B868-B652D8614534}.Debug|Any CPU.Build.0 = Debug|Any CPU {D59C5649-BE0E-4A33-B868-B652D8614534}.Release|Any CPU.ActiveCfg = Release|Any CPU {D59C5649-BE0E-4A33-B868-B652D8614534}.Release|Any CPU.Build.0 = Release|Any CPU + {7A1B9BFE-052D-435E-B27F-72AF3DDCC0A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A1B9BFE-052D-435E-B27F-72AF3DDCC0A0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A1B9BFE-052D-435E-B27F-72AF3DDCC0A0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A1B9BFE-052D-435E-B27F-72AF3DDCC0A0}.Release|Any CPU.Build.0 = Release|Any CPU + {4E9535E2-C918-4C39-9F1B-F182C185DE64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E9535E2-C918-4C39-9F1B-F182C185DE64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E9535E2-C918-4C39-9F1B-F182C185DE64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E9535E2-C918-4C39-9F1B-F182C185DE64}.Release|Any CPU.Build.0 = Release|Any CPU {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -1520,6 +1532,8 @@ Global {A9632530-0FB8-4156-BD3C-DD432527768E} = {8CEC2042-F11C-49F5-A674-2355793B600A} {F594BFBE-1F71-4B3A-BBDA-C4372A6501E9} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} {D59C5649-BE0E-4A33-B868-B652D8614534} = {BAF8F246-3645-42AD-B1D0-0F7EAFBAB34A} + {7A1B9BFE-052D-435E-B27F-72AF3DDCC0A0} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {4E9535E2-C918-4C39-9F1B-F182C185DE64} = {8CEC2042-F11C-49F5-A674-2355793B600A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/AnalyzeInstrumentationErrorsCommand.cs b/tracer/src/Datadog.Trace.Tools.Runner/AnalyzeInstrumentationErrorsCommand.cs index d1041e7be808..ebde4c2ef7a7 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/AnalyzeInstrumentationErrorsCommand.cs +++ b/tracer/src/Datadog.Trace.Tools.Runner/AnalyzeInstrumentationErrorsCommand.cs @@ -12,7 +12,6 @@ using Datadog.InstrumentedAssemblyGenerator; using Datadog.InstrumentedAssemblyVerification; using Datadog.Trace.Configuration.Telemetry; -using Datadog.Trace.Tools.Runner.Checks; using Spectre.Console; namespace Datadog.Trace.Tools.Runner; @@ -174,8 +173,7 @@ private string GetLogDirectory(int? pid) string logDirectory = null; if (pid != null) { - var process = ProcessInfo.GetProcessInfo(pid.Value); - logDirectory = process?.GetProcessLogDirectory(); + logDirectory = ProcessConfiguration.GetProcessLogDirectory(pid.Value); } return logDirectory ?? Logging.DatadogLoggingFactory.GetLogDirectory(NullConfigurationTelemetry.Instance); diff --git a/tracer/src/Datadog.Trace.Tools.Runner/CheckAgentCommand.cs b/tracer/src/Datadog.Trace.Tools.Runner/CheckAgentCommand.cs deleted file mode 100644 index 0d4e48914b50..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/CheckAgentCommand.cs +++ /dev/null @@ -1,79 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System; -using System.CommandLine; -using System.CommandLine.Invocation; -using System.CommandLine.Parsing; -using System.Threading.Tasks; -using Datadog.Trace.Configuration; -using Datadog.Trace.Configuration.Telemetry; -using Datadog.Trace.Tools.Runner.Checks; -using Spectre.Console; - -namespace Datadog.Trace.Tools.Runner -{ - internal class CheckAgentCommand : Command - { - private readonly Argument _urlArgument = new("url") { Arity = ArgumentArity.ZeroOrOne }; - - public CheckAgentCommand() - : base("agent") - { - AddArgument(_urlArgument); - - AddValidator(Validate); - - this.SetHandler(ExecuteAsync); - } - - private async Task ExecuteAsync(InvocationContext context) - { - ExporterSettings configuration; - - var url = _urlArgument.GetValue(context); - - if (url == null) - { - // Try to autodetect the agent settings - configuration = new ExporterSettings(new EnvironmentConfigurationSourceInternal(), NullConfigurationTelemetry.Instance); - - AnsiConsole.WriteLine("No Agent URL provided, using environment variables"); - } - else - { - configuration = new ExporterSettings(source: null, NullConfigurationTelemetry.Instance) { AgentUriInternal = new Uri(url) }; - } - - var result = await AgentConnectivityCheck.RunAsync(new ImmutableExporterSettings(configuration, true)).ConfigureAwait(false); - - if (!result) - { - context.ExitCode = 1; - return; - } - - Utils.WriteSuccess("Connected successfully to the Agent."); - } - - private void Validate(CommandResult commandResult) - { - var url = commandResult.GetValueForArgument(_urlArgument); - - if (url != null) - { - try - { - _ = new Uri(url); - } - catch (UriFormatException ex) - { - commandResult.ErrorMessage = ex.Message; - } - } - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/CheckCommand.cs b/tracer/src/Datadog.Trace.Tools.Runner/CheckCommand.cs new file mode 100644 index 000000000000..f1e38924ff55 --- /dev/null +++ b/tracer/src/Datadog.Trace.Tools.Runner/CheckCommand.cs @@ -0,0 +1,75 @@ +// +// 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 2017 Datadog, Inc. +// + +using System; +using System.CommandLine; +using System.CommandLine.Invocation; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Spectre.Console; + +namespace Datadog.Trace.Tools.Runner +{ + internal class CheckCommand : Command + { + private readonly ApplicationContext _applicationContext; + + public CheckCommand(ApplicationContext applicationContext) + : base("check") + { + _applicationContext = applicationContext; + + AddArgument(Command); + + this.SetHandler(Execute); + } + + public Argument Command { get; } = new("command", CommandLineHelpers.ParseArrayArgument, isDefault: true); + + private void Execute(InvocationContext context) + { + var tracerHome = Utils.GetHomePath(_applicationContext.RunnerFolder); + + // pick the right one depending on the platform + var ddDotnet = (platform: _applicationContext.Platform, arch: RuntimeInformation.OSArchitecture, musl: Utils.IsAlpine()) switch + { + (Platform.Windows, Architecture.X64, _) => Path.Combine(tracerHome, "win-x64", "dd-dotnet.exe"), + (Platform.Windows, Architecture.X86, _) => Path.Combine(tracerHome, "win-x64", "dd-dotnet.exe"), + (Platform.Linux, Architecture.X64, false) => Path.Combine(tracerHome, "linux-x64", "dd-dotnet"), + (Platform.Linux, Architecture.X64, true) => Path.Combine(tracerHome, "linux-musl-x64", "dd-dotnet"), + (Platform.Linux, Architecture.Arm64, false) => Path.Combine(tracerHome, "linux-arm64", "dd-dotnet"), + (Platform.Linux, Architecture.Arm64, true) => Path.Combine(tracerHome, "linux-musl-arm64", "dd-dotnet"), + var other => throw new NotSupportedException( + $"Unsupported platform/architecture combination: ({other.platform}{(other.musl ? " musl" : string.Empty)}/{other.arch})") + }; + + var commandLine = string.Join(' ', Environment.GetCommandLineArgs().Skip(1)); + + if (!File.Exists(ddDotnet)) + { + Utils.WriteError($"dd-dotnet not found at {ddDotnet}"); + context.ExitCode = 1; + return; + } + + if (_applicationContext.Platform == Platform.Linux) + { + // Make sure the dd-dotnet binary is executable + Process.Start("chmod", $"+x {ddDotnet}")!.WaitForExit(); + } + + var startInfo = new ProcessStartInfo(ddDotnet, commandLine) { UseShellExecute = false }; + + startInfo.EnvironmentVariables["DD_INTERNAL_OVERRIDE_COMMAND"] = "dd-trace"; + + var process = Process.Start(startInfo); + process.WaitForExit(); + + context.ExitCode = process.ExitCode; + } + } +} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/CheckIisCommand.cs b/tracer/src/Datadog.Trace.Tools.Runner/CheckIisCommand.cs deleted file mode 100644 index 52c054a39634..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/CheckIisCommand.cs +++ /dev/null @@ -1,280 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -using System; -using System.Collections.Generic; -using System.CommandLine; -using System.CommandLine.Invocation; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Datadog.Trace.Configuration; -using Datadog.Trace.Tools.Runner.Checks; -using Microsoft.Web.Administration; -using Spectre.Console; - -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner -{ - internal class CheckIisCommand : Command - { - private readonly Argument _siteNameArgument = new("siteName") { Arity = ArgumentArity.ZeroOrOne }; - - public CheckIisCommand() - : base("iis") - { - AddArgument(_siteNameArgument); - - this.SetHandler(ExecuteAsync); - } - - public async Task ExecuteAsync(InvocationContext context) - { - var siteName = _siteNameArgument.GetValue(context); - - var result = await ExecuteAsync(siteName, null, null).ConfigureAwait(false); - - context.ExitCode = result; - } - - internal static async Task ExecuteAsync(string siteAndApplicationName, string applicationHostConfigurationPath, int? pid, IRegistryService registryService = null) - { - static IEnumerable GetAllApplicationNames(ServerManager sm) - { - return from s in sm.Sites - from a in s.Applications - select $"{s.Name}{a.Path}"; - } - - var serverManager = new ServerManager(readOnly: true, applicationHostConfigurationPath); - - if (siteAndApplicationName == null) - { - AnsiConsole.WriteLine(IisApplicationNotProvided()); - - var allApplicationNames = GetAllApplicationNames(serverManager); - AnsiConsole.WriteLine(ListAllIisApplications(allApplicationNames)); - - return 1; - } - - var values = siteAndApplicationName.Split('/', 2); - - var siteName = values[0]; - var applicationName = values.Length > 1 ? $"/{values[1]}" : "/"; - - AnsiConsole.WriteLine(FetchingApplication(siteName, applicationName)); - - var site = serverManager.Sites[siteName]; - var application = site?.Applications[applicationName]; - - if (site == null || application == null) - { - Utils.WriteError(CouldNotFindIisApplication(siteName, applicationName)); - - var allApplicationNames = GetAllApplicationNames(serverManager); - Utils.WriteError(ListAllIisApplications(allApplicationNames)); - - return 1; - } - - var pool = serverManager.ApplicationPools[application.ApplicationPoolName]; - - // The WorkerProcess part of ServerManager doesn't seem to be compatible with IISExpress - // so we skip this bit when launched from the tests - if (pid == null) - { - var workerProcesses = pool.WorkerProcesses; - - if (workerProcesses.Count > 0) - { - // If there are multiple worker processes, we just take the first one - // In theory, all worker processes have the same configuration - pid = workerProcesses[0].ProcessId; - } - } - - if (pid == null) - { - Utils.WriteWarning(NoWorkerProcess); - } - else - { - AnsiConsole.WriteLine(InspectingWorkerProcess(pid.Value)); - - var rootDirectory = application.VirtualDirectories.FirstOrDefault(d => d.Path == "/")?.PhysicalPath; - - IConfigurationSource appSettingsConfigurationSource = null; - - try - { - var config = application.GetWebConfiguration(); - var appSettings = config.GetSection("appSettings"); - var collection = appSettings.GetCollection(); - - appSettingsConfigurationSource = new DictionaryConfigurationSource( - collection.ToDictionary(c => (string)c.Attributes["key"].Value, c => (string)c.Attributes["value"].Value)); - } - catch (Exception ex) - { - Utils.WriteWarning(ErrorExtractingConfiguration(ex.Message)); - } - - var process = ProcessInfo.GetProcessInfo(pid.Value, rootDirectory, appSettingsConfigurationSource); - - if (process == null) - { - Utils.WriteError(GetProcessError); - return 1; - } - - if (process.DotnetRuntime.HasFlag(ProcessInfo.Runtime.NetCore) && !string.IsNullOrEmpty(pool.ManagedRuntimeVersion)) - { - Utils.WriteWarning(IisMixedRuntimes); - } - - if (process.Modules.Any(m => Path.GetFileName(m).Equals("aspnetcorev2_outofprocess.dll", StringComparison.OrdinalIgnoreCase))) - { - // IIS site is hosting aspnetcore in out-of-process mode - // Trying to locate the actual application process - AnsiConsole.WriteLine(OutOfProcess); - - var childProcesses = process.GetChildProcesses(); - - // Get either the first process that is dotnet, or the first that is not conhost - int? dotnetPid = null; - int? fallbackPid = null; - - foreach (var childPid in childProcesses) - { - using var childProcess = Process.GetProcessById(childPid); - - if (childProcess.ProcessName.Equals("dotnet", StringComparison.OrdinalIgnoreCase)) - { - dotnetPid = childPid; - break; - } - - if (!childProcess.ProcessName.Equals("conhost", StringComparison.OrdinalIgnoreCase)) - { - fallbackPid = childPid; - } - } - - var aspnetCorePid = dotnetPid ?? fallbackPid; - - if (aspnetCorePid == null) - { - Utils.WriteError(AspNetCoreProcessNotFound); - return 1; - } - - AnsiConsole.WriteLine(AspNetCoreProcessFound(aspnetCorePid.Value)); - - process = ProcessInfo.GetProcessInfo(aspnetCorePid.Value); - - if (process == null) - { - Utils.WriteError(GetProcessError); - return 1; - } - } - - if (!ProcessBasicCheck.Run(process, registryService)) - { - CheckAppPoolsEnvVars(pool, serverManager); - return 1; - } - - if (!await AgentConnectivityCheck.RunAsync(process).ConfigureAwait(false)) - { - return 1; - } - } - - if (!GacCheck.Run()) - { - return 1; - } - - Utils.WriteSuccess(IisNoIssue); - - return 0; - } - - internal static void CheckAppPoolsEnvVars(ApplicationPool pool, ServerManager serverManager) - { - var relevantProfilerConfiguration = new Dictionary - { - { "COR_ENABLE_PROFILING", "1" }, - { "CORECLR_ENABLE_PROFILING", "1" }, - { "COR_PROFILER", Utils.Profilerid }, - { "CORECLR_PROFILER", Utils.Profilerid } - }; - - var relevantProfilerPathConfiguration = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "COR_PROFILER_PATH", - "COR_PROFILER_PATH_32", - "COR_PROFILER_PATH_64", - "CORECLR_PROFILER_PATH", - "CORECLR_PROFILER_PATH_32", - "CORECLR_PROFILER_PATH_64" - }; - - if (pool != null) - { - CheckEnvironmentVariables(pool.GetCollection("environmentVariables"), relevantProfilerConfiguration, relevantProfilerPathConfiguration, pool.Name); - } - - if (serverManager != null) - { - var defaultEnvironmentVariables = serverManager.ApplicationPools?.GetChildElement("applicationPoolDefaults").GetCollection("environmentVariables"); - if (defaultEnvironmentVariables != null) - { - CheckEnvironmentVariables(defaultEnvironmentVariables, relevantProfilerConfiguration, relevantProfilerPathConfiguration, "applicationPoolDefaults"); - } - } - } - - private static void CheckEnvironmentVariables(ConfigurationElementCollection environmentVariablesCollection, Dictionary relevantProfilerConfiguration, HashSet relevantProfilerPathConfiguration, string poolName) - { - var foundVariables = new Dictionary(); - var foundPathVariables = new Dictionary(); - - foreach (var variable in environmentVariablesCollection) - { - var name = (string)variable.Attributes["name"].Value; - var value = (string)variable.Attributes["value"].Value; - - if (relevantProfilerConfiguration.ContainsKey(name) && value != relevantProfilerConfiguration[name]) - { - foundVariables[name] = value; - } - else if (relevantProfilerPathConfiguration.Contains(name) && !ProcessBasicCheck.IsExpectedProfilerFile(value)) - { - foundPathVariables[name] = value; - } - } - - if (foundVariables.Count != 0 || foundPathVariables.Count != 0) - { - Utils.WriteWarning(AppPoolCheckFindings(poolName)); - - foreach (var variable in foundVariables) - { - Utils.WriteError(WrongEnvironmentVariableFormat(variable.Key, relevantProfilerConfiguration[variable.Key], variable.Value.ToString())); - } - - foreach (var profilerPath in foundPathVariables) - { - Utils.WriteError(WrongProfilerEnvironment(profilerPath.Key, profilerPath.Value)); - } - } - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/CheckProcessCommand.cs b/tracer/src/Datadog.Trace.Tools.Runner/CheckProcessCommand.cs deleted file mode 100644 index 89947919a31e..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/CheckProcessCommand.cs +++ /dev/null @@ -1,74 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -using System.CommandLine; -using System.CommandLine.Invocation; -using System.IO; -using System.Threading.Tasks; -using Datadog.Trace.Tools.Runner.Checks; -using Spectre.Console; -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner -{ - internal class CheckProcessCommand : Command - { - private readonly Argument _pidArgument = new("pid"); - - public CheckProcessCommand() - : base("process") - { - AddArgument(_pidArgument); - - this.SetHandler(ExecuteAsync); - } - - private async Task ExecuteAsync(InvocationContext context) - { - var pid = _pidArgument.GetValue(context); - - AnsiConsole.WriteLine("Running checks on process " + pid); - - var process = ProcessInfo.GetProcessInfo(pid); - - if (process == null) - { - Utils.WriteError("Could not fetch information about target process. Make sure to run the command from an elevated prompt, and check that the pid is correct."); - context.ExitCode = 1; - return; - } - - AnsiConsole.WriteLine("Process name: " + process.Name); - - var mainModule = process.MainModule != null ? Path.GetFileName(process.MainModule) : null; - - if (mainModule == "w3wp.exe" || mainModule == "iisexpress.exe") - { - if (process.EnvironmentVariables.ContainsKey("APP_POOL_ID")) - { - Utils.WriteWarning(IisProcess); - } - } - - var foundIssue = !ProcessBasicCheck.Run(process); - - if (foundIssue) - { - context.ExitCode = 1; - return; - } - - foundIssue = !await AgentConnectivityCheck.RunAsync(process).ConfigureAwait(false); - - if (foundIssue) - { - context.ExitCode = 1; - return; - } - - Utils.WriteSuccess("No issue found with the target process."); - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/AgentConnectivityCheck.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/AgentConnectivityCheck.cs deleted file mode 100644 index 4258ba67dd94..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/AgentConnectivityCheck.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Datadog.Trace.Agent; -using Datadog.Trace.Configuration; -using Datadog.Trace.Configuration.Telemetry; -using Spectre.Console; - -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner.Checks -{ - internal class AgentConnectivityCheck - { - public static Task RunAsync(ProcessInfo process) - { - var settings = new ExporterSettings(process.Configuration, NullConfigurationTelemetry.Instance); - - var url = settings.AgentUriInternal.ToString(); - - AnsiConsole.WriteLine(DetectedAgentUrlFormat(url)); - - return RunAsync(new ImmutableExporterSettings(settings, true)); - } - - public static async Task RunAsync(ImmutableExporterSettings settings) - { - var payload = Vendors.MessagePack.MessagePackSerializer.Serialize(Array.Empty()); - - var requestFactory = TracesTransportStrategy.Get(settings); - - DisplayInfoMessage(settings); - - var endpoint = requestFactory.GetEndpoint("/v0.4/traces"); - var request = requestFactory.Create(endpoint); - - var content = new ByteArrayContent(payload); - content.Headers.ContentType = new MediaTypeHeaderValue("application/msgpack"); - - try - { - var response = await request.PostAsync(new ArraySegment(payload), "application/msgpack").ConfigureAwait(false); - - if (response.StatusCode != 200) - { - Utils.WriteError(WrongStatusCodeFormat((HttpStatusCode)response.StatusCode)); - return false; - } - - var versionHeader = response.GetHeader("Datadog-Agent-Version"); - - if (versionHeader != null) - { - AnsiConsole.WriteLine(DetectedAgentVersionFormat(versionHeader)); - } - else - { - Utils.WriteWarning(AgentDetectionFailed); - } - } - catch (Exception ex) - { - Utils.WriteError(ErrorDetectingAgent(settings.AgentUriInternal.ToString(), ex.Message)); - return false; - } - - return true; - } - - private static void DisplayInfoMessage(ImmutableExporterSettings settings) - { - string transport; - string endpoint; - - if (settings.TracesTransport == TracesTransportType.UnixDomainSocket) - { - transport = "domain sockets"; - endpoint = settings.TracesUnixDomainSocketPathInternal ?? ""; - } - else - { - transport = "HTTP"; - endpoint = settings.AgentUriInternal.ToString(); - } - - AnsiConsole.WriteLine(ConnectToEndpointFormat(endpoint, transport)); - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/GacCheck.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/GacCheck.cs deleted file mode 100644 index 247fc053b588..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/GacCheck.cs +++ /dev/null @@ -1,61 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using Spectre.Console; -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner.Checks -{ - internal class GacCheck - { - public static bool Run() - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return true; - } - - var gacFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Microsoft.NET", "assembly", "GAC_MSIL", "Datadog.Trace"); - - if (!Directory.Exists(gacFolder)) - { - Utils.WriteError(MissingGac); - return false; - } - - bool foundVersions = false; - - foreach (var folder in Directory.GetDirectories(gacFolder)) - { - if (!File.Exists(Path.Combine(folder, "Datadog.Trace.dll"))) - { - continue; - } - - var name = new DirectoryInfo(folder).Name; - - // Format: v4.0_2.3.0.0__def86d061d0d2eeb - var match = Regex.Match(name, @"v4.0_(?\d+\.\d+\.\d+\.\d+)__def86d061d0d2eeb"); - - var version = match.Success ? match.Groups["version"].Value : name; - - AnsiConsole.WriteLine(GacVersionFormat(version)); - foundVersions = true; - } - - if (!foundVersions) - { - Utils.WriteError(MissingGac); - return false; - } - - return true; - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/IRegistryService.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/IRegistryService.cs deleted file mode 100644 index f7602e7eea09..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/IRegistryService.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -#nullable enable - -namespace Datadog.Trace.Tools.Runner.Checks -{ - internal interface IRegistryService - { - string[] GetLocalMachineValueNames(string key); - - string? GetLocalMachineValue(string key); - - public string[] GetLocalMachineKeyNames(string key); - - public string? GetLocalMachineKeyNameValue(string key, string subKeyName, string name); - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessBasicCheck.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessBasicCheck.cs deleted file mode 100644 index 34e7c10e8fd2..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessBasicCheck.cs +++ /dev/null @@ -1,632 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using Datadog.Trace.Tools.Runner.Checks.Windows; -using Spectre.Console; - -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner.Checks -{ - internal class ProcessBasicCheck - { - internal const string ClsidKey = @"SOFTWARE\Classes\CLSID\" + Utils.Profilerid + @"\InprocServer32"; - internal const string Clsid32Key = @"SOFTWARE\Classes\Wow6432Node\CLSID\" + Utils.Profilerid + @"\InprocServer32"; - - public static bool Run(ProcessInfo process, IRegistryService? registryService = null) - { - bool ok = true; - var runtime = process.DotnetRuntime; - Version? nativeTracerVersion = null; - - if (runtime == ProcessInfo.Runtime.NetFx) - { - AnsiConsole.WriteLine(NetFrameworkRuntime); - } - else if (runtime == ProcessInfo.Runtime.NetCore) - { - AnsiConsole.WriteLine(NetCoreRuntime); - } - else - { - Utils.WriteWarning(runtime == ProcessInfo.Runtime.Mixed ? BothRuntimesDetected : RuntimeDetectionFailed); - runtime = ProcessInfo.Runtime.NetFx; - } - - var loaderModule = FindLoader(process); - var nativeTracerModule = FindNativeTracerModule(process, loaderModule != null); - - if (loaderModule == null) - { - AnsiConsole.WriteLine(LoaderNotLoaded); - } - - if (nativeTracerModule == null) - { - Utils.WriteWarning(NativeTracerNotLoaded); - ok = false; - } - else - { - // Only check the version of the native binary on Windows - // .so modules don't have version metadata - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - if (!Version.TryParse(FileVersionInfo.GetVersionInfo(nativeTracerModule).FileVersion, out nativeTracerVersion)) - { - nativeTracerVersion = null; - } - - AnsiConsole.WriteLine(ProfilerVersion(nativeTracerVersion != null ? $"{nativeTracerVersion}" : "{empty}")); - } - } - - var tracerModules = FindTracerModules(process).ToArray(); - - if (tracerModules.Length == 0) - { - Utils.WriteWarning(TracerNotLoaded); - ok = false; - } - else if (tracerModules.Length == 1) - { - var version = FileVersionInfo.GetVersionInfo(tracerModules[0]); - AnsiConsole.WriteLine(TracerVersion(version.FileVersion ?? "{empty}")); - } - else if (tracerModules.Length > 1) - { - // There are too many tracers in there. Find out if it's bad or very bad - bool areAllVersion2 = true; - var versions = new HashSet(); - - foreach (var tracer in tracerModules) - { - var version = FileVersionInfo.GetVersionInfo(tracer); - - versions.Add(version.FileVersion ?? "{empty}"); - - if (version.FileMajorPart < 2) - { - areAllVersion2 = false; - } - } - - Utils.WriteWarning(MultipleTracers(versions)); - - if (!areAllVersion2) - { - Utils.WriteError(VersionConflict); - ok = false; - } - } - - if (process.EnvironmentVariables.TryGetValue("DD_DOTNET_TRACER_HOME", out var tracerHome)) - { - if (!Directory.Exists(tracerHome)) - { - Utils.WriteWarning(TracerHomeNotFoundFormat(tracerHome)); - ok = false; - } - } - else - { - Utils.WriteWarning(EnvironmentVariableNotSet("DD_DOTNET_TRACER_HOME")); - ok = false; - } - - string corProfilerPathKey = runtime == ProcessInfo.Runtime.NetCore ? "CORECLR_PROFILER_PATH" : "COR_PROFILER_PATH"; - string corProfilerPathKey32 = runtime == ProcessInfo.Runtime.NetCore ? "CORECLR_PROFILER_PATH_32" : "COR_PROFILER_PATH_32"; - string corProfilerPathKey64 = runtime == ProcessInfo.Runtime.NetCore ? "CORECLR_PROFILER_PATH_64" : "COR_PROFILER_PATH_64"; - - ok &= CheckProfilerPath(process, corProfilerPathKey, requiredOnLinux: true); - ok &= CheckProfilerPath(process, corProfilerPathKey32, requiredOnLinux: false); - ok &= CheckProfilerPath(process, corProfilerPathKey64, requiredOnLinux: false); - - string corProfilerKey = runtime == ProcessInfo.Runtime.NetCore ? "CORECLR_PROFILER" : "COR_PROFILER"; - - process.EnvironmentVariables.TryGetValue(corProfilerKey, out var corProfiler); - - if (corProfiler != Utils.Profilerid) - { - Utils.WriteWarning(WrongEnvironmentVariableFormat(corProfilerKey, Utils.Profilerid, corProfiler)); - ok = false; - } - - string corEnableKey = runtime == ProcessInfo.Runtime.NetCore ? "CORECLR_ENABLE_PROFILING" : "COR_ENABLE_PROFILING"; - - process.EnvironmentVariables.TryGetValue(corEnableKey, out var corEnable); - - if (corEnable != "1") - { - Utils.WriteError(WrongEnvironmentVariableFormat(corEnableKey, "1", corEnable)); - ok = false; - } - - process.EnvironmentVariables.TryGetValue(corProfilerPathKey, out var corProfilerPathValue); - process.EnvironmentVariables.TryGetValue(corProfilerPathKey32, out var corProfilerPathValue32); - process.EnvironmentVariables.TryGetValue(corProfilerPathKey64, out var corProfilerPathValue64); - - string?[] valuesToCheck = { corProfilerPathValue, corProfilerPathValue32, corProfilerPathValue64 }; - var isTracingUsingBundle = TracingWithBundle(valuesToCheck, process.Id); - - if (!ok && isTracingUsingBundle) - { - AnsiConsole.WriteLine(TracingWithBundleProfilerPath); - } - else if (!ok) - { - AnsiConsole.WriteLine(TracingWithInstaller); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - if (!CheckRegistry(CheckWindowsInstallation(process.Id, registryService), registryService)) - { - ok = false; - } - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - CheckLinuxInstallation("/opt/datadog/"); - } - } - - // Running non-blocker checks after confirming setup was done correctly - if (ok) - { - if (process.EnvironmentVariables.TryGetValue("DD_TRACE_ENABLED", out var traceEnabledValue)) - { - if (!ParseBooleanConfigurationValue(traceEnabledValue)) - { - Utils.WriteError(TracerNotEnabled(traceEnabledValue)); - } - } - - bool isContinuousProfilerEnabled; - - if (process.EnvironmentVariables.TryGetValue("DD_PROFILING_ENABLED", out var profilingEnabled)) - { - if (ParseBooleanConfigurationValue(profilingEnabled)) - { - AnsiConsole.WriteLine(ContinuousProfilerEnabled); - isContinuousProfilerEnabled = true; - } - else - { - AnsiConsole.WriteLine(ContinuousProfilerDisabled); - isContinuousProfilerEnabled = false; - } - } - else - { - AnsiConsole.WriteLine(ContinuousProfilerNotSet); - isContinuousProfilerEnabled = false; - } - - if (isContinuousProfilerEnabled) - { - ok &= CheckContinuousProfiler(process, loaderModule); - } - } - - return ok; - } - - internal static bool CheckContinuousProfiler(ProcessInfo process, string? loaderModule) - { - bool ok = true; - - var continuousProfilerModule = FindContinuousProfilerModule(process); - - if (continuousProfilerModule == null) - { - Utils.WriteWarning(ContinuousProfilerNotLoaded); - ok = false; - } - - if (loaderModule == null) - { - Utils.WriteError(ContinuousProfilerWithoutLoader); - ok = false; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - process.EnvironmentVariables.TryGetValue("LD_PRELOAD", out var ldPreload); - - if (ldPreload == null) - { - Utils.WriteError(LdPreloadNotSet); - ok = false; - } - else - { - if (Path.GetFileName(ldPreload) != "Datadog.Linux.ApiWrapper.x64.so") - { - Utils.WriteError(WrongLdPreload(ldPreload)); - ok = false; - } - else if (!File.Exists(ldPreload)) - { - Utils.WriteError(ApiWrapperNotFound(ldPreload)); - ok = false; - } - } - } - - return ok; - } - - internal static bool CheckRegistry(string? tracerProgramVersion, IRegistryService? registry = null) - { - registry ??= new Windows.RegistryService(); - - try - { - bool ok = true; - - // Check that the profiler is properly registered - if (tracerProgramVersion is null) - { - ok &= CheckClsid(registry, ClsidKey); - ok &= CheckClsid(registry, Clsid32Key); - } - else if (RuntimeInformation.OSArchitecture is Architecture.X64) - { - ok &= CheckClsid(registry, ClsidKey); - - if (new Version(tracerProgramVersion) < new Version("2.14.0.0")) - { - ok &= CheckClsid(registry, Clsid32Key); - } - } - else if (RuntimeInformation.OSArchitecture is Architecture.X86) - { - ok &= CheckClsid(registry, Clsid32Key); - } - - // Look for registry keys that could have been set by other profilers - var suspiciousNames = new HashSet(StringComparer.OrdinalIgnoreCase) - { - "COR_ENABLE_PROFILING", - "CORECLR_ENABLE_PROFILING", - "COR_PROFILER", - "CORECLR_PROFILER", - "COR_PROFILER_PATH", - "CORECLR_PROFILER_PATH", - "COR_PROFILER_PATH_64", - "CORECLR_PROFILER_PATH_64" - }; - - bool foundKey = false; - - var parentKeys = new[] { @"SOFTWARE\Microsoft\.NETFramework", @"SOFTWARE\WOW6432Node\Microsoft\.NETFramework" }; - - foreach (var parentKey in parentKeys) - { - foreach (var name in registry.GetLocalMachineValueNames(parentKey)) - { - if (suspiciousNames.Contains(name)) - { - Utils.WriteWarning(SuspiciousRegistryKey(parentKey, name)); - foundKey = true; - } - } - } - - ok &= !foundKey; - - return ok; - } - catch (Exception ex) - { - Utils.WriteError(ErrorCheckingRegistry(ex.Message)); - return true; - } - } - - internal static bool CheckProfilerPath(ProcessInfo process, string key, bool requiredOnLinux) - { - bool ok = true; - - if (process.EnvironmentVariables.TryGetValue(key, out var profilerPath)) - { - if (!IsExpectedProfilerFile(profilerPath)) - { - Utils.WriteError(WrongProfilerEnvironment(key, profilerPath)); - ok = false; - } - - if (!File.Exists(profilerPath)) - { - Utils.WriteError(MissingProfilerEnvironment(key, profilerPath)); - ok = false; - } - } - else if (requiredOnLinux) - { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Utils.WriteError(EnvironmentVariableNotSet(key)); - ok = false; - } - } - - return ok; - } - - private static bool CheckClsid(IRegistryService registry, string registryKey) - { - var profilerPath = registry.GetLocalMachineValue(registryKey); - - if (profilerPath == null) - { - Utils.WriteWarning(MissingRegistryKey(registryKey)); - return false; - } - - if (!IsExpectedProfilerFile(profilerPath)) - { - Utils.WriteError(WrongProfilerRegistry(registryKey, profilerPath)); - return false; - } - - if (!File.Exists(profilerPath)) - { - Utils.WriteError(MissingProfilerRegistry(registryKey, profilerPath)); - return false; - } - - return true; - } - - internal static bool IsExpectedProfilerFile(string fullPath) - { - var fileName = Path.GetFileName(fullPath); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return "Datadog.Trace.ClrProfiler.Native.dll".Equals(fileName, StringComparison.OrdinalIgnoreCase) || - "Datadog.Tracer.Native.dll".Equals(fileName, StringComparison.OrdinalIgnoreCase) || - // Check for legacy names - "Datadog.AutoInstrumentation.NativeLoader.x64.dll".Equals(fileName, StringComparison.OrdinalIgnoreCase) || - "Datadog.AutoInstrumentation.NativeLoader.x86.dll".Equals(fileName, StringComparison.OrdinalIgnoreCase); - } - - // Paths are case-sensitive on Linux - return "Datadog.Trace.ClrProfiler.Native.so".Equals(fileName, StringComparison.Ordinal) || - "Datadog.Tracer.Native.so".Equals(fileName, StringComparison.Ordinal) || - // Check for legacy names - "Datadog.AutoInstrumentation.NativeLoader.so".Equals(fileName, StringComparison.Ordinal); - } - - private static string? FindLoader(ProcessInfo process) - { - foreach (var module in process.Modules) - { - var fileName = Path.GetFileName(module); - - if (fileName.Equals("Datadog.Trace.ClrProfiler.Native.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("Datadog.Trace.ClrProfiler.Native.so", StringComparison.Ordinal)) - { - // This could be either the native tracer or the loader. - // If it's the loader then there should be a loader.conf file next to it. - var folder = Path.GetDirectoryName(module)!; - - if (File.Exists(Path.Combine(folder, "loader.conf"))) - { - return module; - } - } - else if (fileName.Equals("Datadog.AutoInstrumentation.NativeLoader.x64.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("Datadog.AutoInstrumentation.NativeLoader.x86.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("Datadog.AutoInstrumentation.NativeLoader.so", StringComparison.Ordinal)) - { - return module; - } - } - - return null; - } - - private static string? FindContinuousProfilerModule(ProcessInfo process) - { - foreach (var module in process.Modules) - { - var fileName = Path.GetFileName(module); - - if (fileName.Equals("Datadog.Profiler.Native.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("Datadog.Profiler.Native.so", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("Datadog.AutoInstrumentation.Profiler.Native.x64.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("Datadog.AutoInstrumentation.Profiler.Native.x86.dll", StringComparison.OrdinalIgnoreCase)) - { - return module; - } - } - - return null; - } - - private static string? FindNativeTracerModule(ProcessInfo process, bool foundLoader) - { - var expectedFileName = foundLoader ? "Datadog.Tracer.Native" : "Datadog.Trace.ClrProfiler.Native"; - - foreach (var module in process.Modules) - { - var fileName = Path.GetFileName(module); - - if (fileName.Equals($"{expectedFileName}.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals($"{expectedFileName}.so", StringComparison.OrdinalIgnoreCase)) - { - return module; - } - } - - return null; - } - - private static IEnumerable FindTracerModules(ProcessInfo process) - { - foreach (var module in process.Modules) - { - var fileName = Path.GetFileName(module); - - if (fileName.Equals("Datadog.Trace.dll", StringComparison.OrdinalIgnoreCase)) - { - yield return module; - } - } - } - - private static bool ParseBooleanConfigurationValue(string value) - { - var trimmedValue = value.Trim(); - - return trimmedValue is "true" - or "True" - or "TRUE" - or "yes" - or "Yes" - or "YES" - or "t" - or "T" - or "Y" - or "y" - or "1"; - } - - private static bool TracingWithBundle(string?[] profilerPathValues, int processId) - { - Process process = Process.GetProcessById(processId); - - // Get the file path of the main module (the .exe file) - string? filePath = process.MainModule?.FileName; - string? directoryPath = Path.GetDirectoryName(filePath); - - string[] expectedEndingsForBundleSetup = - { - "/datadog/linux-musl-x64/Datadog.Trace.ClrProfiler.Native.so", - "/datadog/linux-x64/Datadog.Trace.ClrProfiler.Native.so", - "/datadog/linux-arm64/Datadog.Trace.ClrProfiler.Native.so", - "\\datadog\\win-x64\\Datadog.Trace.ClrProfiler.Native.dll", - "\\datadog\\win-x86\\Datadog.Trace.ClrProfiler.Native.dll" - }; - - foreach (var bundleSetupEnding in expectedEndingsForBundleSetup) - { - foreach (var profilerPath in profilerPathValues) - { - if (profilerPath is not null && profilerPath.Equals(directoryPath + bundleSetupEnding, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - } - - return false; - } - - private static string? CheckWindowsInstallation(int processId, IRegistryService? registryService = null) - { - const string datadog64BitProgram = "Datadog .NET Tracer 64-bit"; - const string datadog32BitProgram = "Datadog .NET Tracer 32-bit"; - const string uninstallKey64Bit = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"; - const string uninstallKey32Bit = @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"; - - if (GetLocalMachineSubKeyVersion(uninstallKey64Bit, datadog64BitProgram, out var tracerVersion)) - { - Utils.WriteSuccess(TracerProgramFound(datadog64BitProgram)); - return tracerVersion; - } - - if (GetLocalMachineSubKeyVersion(uninstallKey32Bit, datadog32BitProgram, out tracerVersion)) - { - Utils.WriteSuccess(TracerProgramFound(datadog32BitProgram)); - var processBitness = ProcessEnvironmentWindows.GetProcessBitness(Process.GetProcessById(processId)); - - if (processBitness is 64) - { - Utils.WriteError(WrongTracerArchitecture(datadog32BitProgram)); - } - - return tracerVersion; - } - - Utils.WriteError(TraceProgramNotFound); - - return tracerVersion; - } - - private static bool GetLocalMachineSubKeyVersion(string uninstallKey, string datadogProgramName, out string? tracerVersion, IRegistryService? registryService = null) - { - registryService ??= new Windows.RegistryService(); - - tracerVersion = null; - var versionFound = false; - - foreach (var subKeyName in registryService.GetLocalMachineKeyNames(uninstallKey)) - { - var subKeyDisplayName = registryService.GetLocalMachineKeyNameValue(uninstallKey, subKeyName, "DisplayName"); - - if (subKeyDisplayName == datadogProgramName) - { - tracerVersion = registryService.GetLocalMachineKeyNameValue(uninstallKey, subKeyName, "VersionMajor") + "." + registryService.GetLocalMachineKeyNameValue(uninstallKey, subKeyName, "VersionMinor"); - versionFound = true; - } - } - - return versionFound; - } - - internal static void CheckLinuxInstallation(string installDirectory) - { - string archFolder; - var osArchitecture = RuntimeInformation.OSArchitecture; - - if (osArchitecture == Architecture.X64) - { - archFolder = Utils.IsAlpine() ? "linux-musl-x64" : "linux-x64"; - } - else if (osArchitecture == Architecture.Arm64) - { - archFolder = "linux-arm64"; - } - else - { - Utils.WriteError(UnsupportedLinuxArchitecture(osArchitecture.ToString())); - return; - } - - try - { - if (!Directory.Exists(Path.Join(installDirectory, archFolder))) - { - string[] directories = Directory.GetDirectories(installDirectory); - - // Iterate through directories and filter based on the starting string - foreach (string directory in directories) - { - DirectoryInfo dirInfo = new DirectoryInfo(directory); - if (dirInfo.Name.StartsWith("linux-", StringComparison.OrdinalIgnoreCase)) - { - Utils.WriteError(WrongLinuxFolder(archFolder, dirInfo.Name)); - return; - } - } - } - } - catch (Exception ex) - { - Utils.WriteError(ErrorCheckingLinuxDirectory(ex.Message)); - } - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessInfo.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessInfo.cs deleted file mode 100644 index 9f35ca1f6801..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessInfo.cs +++ /dev/null @@ -1,235 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Management; -using System.Runtime.InteropServices; -using System.Xml.Linq; -using Datadog.Trace.Configuration; -using Datadog.Trace.Configuration.Telemetry; - -namespace Datadog.Trace.Tools.Runner.Checks -{ - internal class ProcessInfo - { - public ProcessInfo(Process process, string? baseDirectory = null, IConfigurationSource? appSettings = null) - { - Name = process.ProcessName; - Id = process.Id; - EnvironmentVariables = ProcessEnvironment.ReadVariables(process); - MainModule = process.MainModule?.FileName; - - Modules = ProcessEnvironment.ReadModules(process); - - DotnetRuntime = DetectRuntime(Modules); - Configuration = ExtractConfigurationSource(baseDirectory, appSettings); - } - - /// - /// Initializes a new instance of the class to be used for unit tests. - /// - internal ProcessInfo(string name, int id, IReadOnlyDictionary environmentVariables, string mainModule, string[] modules) - { - Name = name; - Id = id; - EnvironmentVariables = environmentVariables; - MainModule = mainModule; - Modules = modules; - - DotnetRuntime = DetectRuntime(Modules); - Configuration = ExtractConfigurationSource(null, null); - } - - [Flags] - public enum Runtime - { - Unknown = 0, - NetFx = 1, - NetCore = 2, - Mixed = NetFx | NetCore - } - - public string Name { get; } - - public int Id { get; } - - public string[] Modules { get; } - - public IReadOnlyDictionary EnvironmentVariables { get; } - - public string? MainModule { get; } - - public Runtime DotnetRuntime { get; } - - public IConfigurationSource? Configuration { get; } - - public static ProcessInfo? GetProcessInfo(int pid, string? baseDirectory = null, IConfigurationSource? appSettings = null) - { - try - { - using var process = Process.GetProcessById(pid); - return new ProcessInfo(process, baseDirectory, appSettings); - } - catch (Exception ex) - { - Utils.WriteError("Error while trying to fetch process information: " + ex.Message); - return null; - } - } - - public IReadOnlyList GetChildProcesses() - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return Array.Empty(); - } - - var query = $"Select * From Win32_Process Where ParentProcessId = {Id}"; - using var searcher = new ManagementObjectSearcher(query); - using var processList = searcher.Get(); - - var result = new List(); - - foreach (var obj in processList) - { - result.Add(Convert.ToInt32(obj.GetPropertyValue("ProcessId"))); - obj.Dispose(); - } - - return result; - } - - internal string? GetProcessLogDirectory() - { - var config = new ConfigurationBuilder(Configuration ?? NullConfigurationSource.Instance, NullConfigurationTelemetry.Instance); - - var logDirectory = config.WithKeys(ConfigurationKeys.LogDirectory).AsString(); - if (logDirectory == null) - { -#pragma warning disable 618 // ProfilerLogPath is deprecated but still supported - var nativeLogFile = config.WithKeys(ConfigurationKeys.ProfilerLogPath).AsString(); -#pragma warning restore 618 - if (!string.IsNullOrEmpty(nativeLogFile)) - { - logDirectory = Path.GetDirectoryName(nativeLogFile); - } - } - - return logDirectory; - } - - private static Runtime DetectRuntime(string[] modules) - { - var result = Runtime.Unknown; - - foreach (var module in modules) - { - var fileName = Path.GetFileName(module); - - if (fileName.Equals("clr.dll", StringComparison.OrdinalIgnoreCase)) - { - result |= Runtime.NetFx; - } - else if (fileName.Equals("coreclr.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("libcoreclr.so", StringComparison.OrdinalIgnoreCase)) - { - result |= Runtime.NetCore; - } - } - - return result; - } - - private static IConfigurationSource? LoadApplicationConfig(string? mainModule) - { - if (mainModule == null) - { - return null; - } - - var folder = Path.GetDirectoryName(mainModule); - - if (folder == null) - { - return null; - } - - var configFileName = Path.GetFileName(mainModule) + ".config"; - var configPath = Path.Combine(folder, configFileName); - - if (!File.Exists(configPath)) - { - return null; - } - - try - { - var document = XDocument.Load(configPath); - - var appSettings = document.Element("configuration")?.Element("appSettings"); - - if (appSettings == null) - { - return null; - } - - var settings = new Dictionary(); - - foreach (var setting in appSettings.Elements()) - { - var key = setting.Attribute("key")?.Value; - var value = setting.Attribute("value")?.Value; - - if (key != null) - { - settings[key] = value ?? string.Empty; - } - } - - return new DictionaryConfigurationSource(settings); - } - catch (Exception ex) - { - Utils.WriteWarning($"An error occured while parsing the configuration file {configPath}: {ex.Message}"); - return null; - } - } - - private IConfigurationSource ExtractConfigurationSource(string? baseDirectory, IConfigurationSource? appSettings) - { - baseDirectory ??= Path.GetDirectoryName(MainModule); - - var configurationSource = new CompositeConfigurationSourceInternal(); - - configurationSource.AddInternal(new DictionaryConfigurationSource(EnvironmentVariables)); - - if (appSettings != null) - { - configurationSource.AddInternal(appSettings); - } - else if (DotnetRuntime.HasFlag(Runtime.NetFx)) - { - var appConfigSource = LoadApplicationConfig(MainModule); - - if (appConfigSource != null) - { - configurationSource.AddInternal(appConfigSource); - } - } - - if (GlobalConfigurationSource.TryLoadJsonConfigurationFile(configurationSource, baseDirectory, out var jsonConfigurationSource)) - { - configurationSource.AddInternal(jsonConfigurationSource); - } - - return configurationSource; - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Resources.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/Resources.cs deleted file mode 100644 index d71d4d2398c2..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Resources.cs +++ /dev/null @@ -1,156 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Runtime.InteropServices; -using System.Text; - -namespace Datadog.Trace.Tools.Runner.Checks -{ - internal static class Resources - { - public const string NetFrameworkRuntime = "Target process is running with .NET Framework"; - public const string NetCoreRuntime = "Target process is running with .NET Core"; - public const string RuntimeDetectionFailed = "Failed to detect target process runtime, assuming .NET Framework"; - public const string BothRuntimesDetected = "The target process is running .NET Framework and .NET Core simultaneously. Checks will be performed assuming a .NET Framework runtime."; - public const string LoaderNotLoaded = "The native loader library is not loaded into the process"; - public const string NativeTracerNotLoaded = "The native tracer library is not loaded into the process"; - public const string TracerNotLoaded = "Tracer is not loaded into the process"; - public const string AgentDetectionFailed = "Could not detect the agent version. It may be running with a version older than 7.27.0."; - public const string IisProcess = "The target process is an IIS process. The detection of the configuration might be incomplete, it's recommended to use dd-trace check iis instead."; - public const string MissingGac = "The Datadog.Trace assembly could not be found in the GAC. Make sure the tracer has been properly installed with the MSI."; - public const string NoWorkerProcess = "No worker process found, to perform additional checks make sure the application is active"; - public const string GetProcessError = "Could not fetch information about target process. Make sure to run the command from an elevated prompt, and check that the pid is correct."; - public const string IisNoIssue = "No issue found with the IIS site."; - public const string IisMixedRuntimes = "The application pool is configured to host both .NET Framework and .NET Core runtimes. When hosting .NET Core, it's recommended to set '.NET CLR Version' to 'No managed code' to prevent conflict: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1#create-the-iis-site:~:text=CLR%20version%20to-,No%20Managed%20Code,-%3A"; - public const string OutOfProcess = "Detected ASP.NET Core hosted out of proces. Trying to find the application process."; - public const string AspNetCoreProcessNotFound = "Could not find the ASP.NET Core applicative process."; - public const string VersionConflict = "Tracer version 1.x can't be loaded simultaneously with other versions and will produce orphaned traces. Make sure to synchronize the Datadog.Trace NuGet version with the installed automatic instrumentation package version."; - - public const string TracingWithBundleProfilerPath = "Datadog.Trace.Bundle Nuget related documentation: https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/dotnet-core/?tab=nuget#install-the-tracer"; - public const string TracingWithInstaller = "Installer/MSI related documentation: https://docs.datadoghq.com/tracing/trace_collection/dd_libraries/dotnet-framework?tab=windows#install-the-tracer"; - public const string TraceProgramNotFound = "Unable to find Datadog .NET Tracer program, make sure the tracer has been properly installed with the MSI."; - - public const string ContinuousProfilerEnabled = "DD_PROFILING_ENABLED is set."; - public const string ContinuousProfilerDisabled = "The continuous profiler is explicitly disabled through DD_PROFILING_ENABLED."; - public const string ContinuousProfilerNotSet = "DD_PROFILING_ENABLED is not set, the continuous profiler is disabled."; - public const string ContinuousProfilerNotLoaded = "The continuous profiler library is not loaded into the process."; - public const string ContinuousProfilerWithoutLoader = "The continuous profiler needs the Datadog.Trace.ClrProfiler.Native module and the loader.conf file to work. Try reinstalling the tracer in version 2.14+."; - - public const string LdPreloadNotSet = "The environment variable LD_PRELOAD is not set. Check the Datadog .NET Profiler documentation to set it properly."; - - public static string TracerNotEnabled(string value) => $"The value for DD_TRACE_ENABLED is set to {value}, to enable automatic tracing set it to true."; - - public static string ApiWrapperNotFound(string path) => $"The environment variable LD_PRELOAD is set to '{path}' but the file could not be found. Check the Datadog .NET Profiler documentation to set it properly."; - - public static string WrongLdPreload(string path) => $"The environment variable LD_PRELOAD is set to '{path}' but it should point to Datadog.Linux.ApiWrapper.x64.so instead. Check the Datadog .NET Profiler documentation to set it properly."; - - public static string ProfilerVersion(string version) => $"The native library version {version} is loaded into the process."; - - public static string TracerVersion(string version) => $"The tracer version {version} is loaded into the process."; - - public static string EnvironmentVariableNotSet(string environmentVariable) => $"The environment variable {environmentVariable} is not set"; - - public static string TracerHomeNotFoundFormat(string tracerHome) => $"DD_DOTNET_TRACER_HOME is set to '{tracerHome}' but the directory does not exist"; - - public static string WrongEnvironmentVariableFormat(string key, string expectedValue, string? actualValue) => $"The environment variable {key} should be set to '{expectedValue}' (current value: {EscapeOrNotSet(actualValue)})"; - - public static string DetectedAgentUrlFormat(string url) => $"Detected agent url: {url}. Note: this url may be incorrect if you configured the application through a configuration file."; - - public static string WrongStatusCodeFormat(HttpStatusCode statusCode) => $"Agent replied with wrong status code: {statusCode}"; - - public static string DetectedAgentVersionFormat(string version) => $"Detected agent version {version}"; - - public static string ErrorDetectingAgent(string url, string error) => $"Error connecting to Agent at {url}: {error}"; - - public static string ConnectToEndpointFormat(string endpoint, string transport) => $"Connecting to Agent at endpoint {endpoint} using {transport}"; - - public static string ErrorCheckingRegistry(string error) => $"Error trying to read the registry: {error}"; - - public static string SuspiciousRegistryKey(string parentKey, string key) => $@"The registry key HKEY_LOCAL_MACHINE\{parentKey}\{key} is defined and could prevent the tracer from working properly. Please check that all external profilers have been uninstalled properly."; - - public static string MissingRegistryKey(string key) => $@"The registry key {key} is missing. If using the MSI, make sure the installation was completed correctly try to repair/reinstall it."; - - public static string MissingProfilerRegistry(string key, string path) => $@"The registry key {key} was set to path '{path}' but the file is missing or you don't have sufficient permission. Try reinstalling the tracer with the MSI and check the permissions."; - - public static string MissingProfilerEnvironment(string key, string path) => $@"The environment variable {key} is set to {path} but the file is missing or you don't have sufficient permission."; - - public static string GacVersionFormat(string version) => $"Found Datadog.Trace version {version} in the GAC"; - - public static string FetchingApplication(string site, string application) => $"Fetching IIS application \"{site}{application}\"."; - - public static string InspectingWorkerProcess(int pid) => $"Inspecting worker process {pid}"; - - public static string ErrorExtractingConfiguration(string error) => $"Could not extract configuration from site: {error}"; - - public static string AspNetCoreProcessFound(int pid) => $"Found ASP.NET Core applicative process: {pid}"; - - public static string WrongProfilerRegistry(string registryKey, string actualProfiler) => $"The registry key {registryKey} was set to '{actualProfiler}' but it should point to 'Datadog.Trace.ClrProfiler.Native.dll'. Please check that all external profilers have been uninstalled properly and try reinstalling the tracer."; - - public static string IisApplicationNotProvided() => "IIS application name not provided. "; - - public static string CouldNotFindIisApplication(string site, string application) => $"Could not find IIS application \"{site}{application}\". "; - - public static string ListAllIisApplications(IEnumerable availableApplications) - { - var sb = new StringBuilder(); - - sb.AppendLine("Available IIS applications:"); - - foreach (var app in availableApplications) - { - sb.AppendLine($" - {app}"); - } - - sb.AppendLine(); - sb.AppendLine("USAGE:"); - sb.AppendLine(" dd-trace check iis [siteName]"); - - return sb.ToString(); - } - - public static string MultipleTracers(IEnumerable versions) - { - var sb = new StringBuilder(); - - sb.AppendLine("Found multiple instances of Datadog.Trace.dll in the target process."); - sb.AppendLine("Detected versions:"); - - // The ordering is not required but makes the output consistent for tests - foreach (var version in versions.OrderBy(v => v)) - { - sb.AppendLine($"- {version}"); - } - - return sb.ToString(); - } - - public static string WrongProfilerEnvironment(string environmentVariable, string actualProfiler) - { - var expectedProfiler = RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows) - ? "Datadog.Trace.ClrProfiler.Native.dll" : "Datadog.Trace.ClrProfiler.Native.so"; - - return $"- The environment variable {environmentVariable} was set to '{actualProfiler}' but it should point to '{expectedProfiler}'"; - } - - private static string EscapeOrNotSet(string? str) => str == null ? "not set" : $"'{str}'"; - - public static string TracerProgramFound(string tracerProgramName) => $"{tracerProgramName} found in the installed programs."; - - public static string WrongTracerArchitecture(string tracerArchitecture) => $"Found {tracerArchitecture} installed but the current process is 64 Bit, make sure to install the 64-bit tracer instead."; - - public static string AppPoolCheckFindings(string appPool) => $"Check did not pass, fix the configuration on the {appPool} AppPool:"; - - public static string WrongLinuxFolder(string expected, string found) => $"Unable to find expected {expected} folder, found {found} instead, make sure to use the correct installer."; - - public static string UnsupportedLinuxArchitecture(string osArchitecture) => $"The Linux architecture: {osArchitecture} is not supported by the tracer, check: https://docs.datadoghq.com/tracing/trace_collection/compatibility/dotnet-core/#supported-processor-architectures "; - - public static string ErrorCheckingLinuxDirectory(string error) => $"Error trying to check the Linux installer directory: {error}"; - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/NativeMethods.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/NativeMethods.cs deleted file mode 100644 index d6fd33c3d70c..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/NativeMethods.cs +++ /dev/null @@ -1,233 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -#pragma warning disable SA1201 // Elements should appear in the correct order - -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace Datadog.Trace.Tools.Runner.Checks.Windows -{ - internal static class NativeMethods - { - [StructLayout(LayoutKind.Sequential)] - public struct SYSTEM_INFO - { - public ushort wProcessorArchitecture; - public ushort wReserved; - public uint dwPageSize; - public IntPtr lpMinimumApplicationAddress; - public IntPtr lpMaximumApplicationAddress; - public IntPtr dwActiveProcessorMask; - public uint dwNumberOfProcessors; - public uint dwProcessorType; - public uint dwAllocationGranularity; - public ushort wProcessorLevel; - public ushort wProcessorRevision; - } - - [DllImport("kernel32.dll", ExactSpelling = true)] - public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); - - [DllImport("kernel32.dll", ExactSpelling = true)] - public static extern void GetNativeSystemInfo(out SYSTEM_INFO lpSystemInfo); - - // ------------------------------------------------------------------------------------------------------- - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct PROCESS_BASIC_INFORMATION - { - public IntPtr Reserved1; - public IntPtr PebBaseAddress; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public IntPtr[] Reserved2; - public IntPtr UniqueProcessId; - public IntPtr InheritedFromUniqueProcessId; - } - - public const int ProcessBasicInformation = 0; - public const int ProcessWow64Information = 26; - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtQueryInformationProcess( - IntPtr hProcess, - int pic, - ref PROCESS_BASIC_INFORMATION pbi, - int cb, - ref int pSize); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtQueryInformationProcess( - IntPtr hProcess, - int pic, - ref IntPtr pi, - int cb, - ref int pSize); - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct PROCESS_BASIC_INFORMATION_WOW64 - { - public long Reserved1; - public long PebBaseAddress; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public long[] Reserved2; - public long UniqueProcessId; - public long Reserved3; - } - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtWow64QueryInformationProcess64( - IntPtr hProcess, - int pic, - ref PROCESS_BASIC_INFORMATION_WOW64 pbi, - int cb, - ref int pSize); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory( - IntPtr hProcess, - IntPtr lpBaseAddress, - [Out] byte[] lpBuffer, - IntPtr dwSize, - ref IntPtr lpNumberOfBytesRead); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory( - IntPtr hProcess, - IntPtr lpBaseAddress, - IntPtr lpBuffer, - IntPtr dwSize, - ref IntPtr lpNumberOfBytesRead); - - [DllImport("kernel32.dll", SetLastError = true)] - public static unsafe extern bool ReadProcessMemory( - IntPtr hProcess, - IntPtr lpBaseAddress, - void* lpBuffer, - IntPtr dwSize, - ref IntPtr lpNumberOfBytesRead); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtWow64ReadVirtualMemory64( - IntPtr hProcess, - long lpBaseAddress, - IntPtr lpBuffer, - long dwSize, - ref long lpNumberOfBytesRead); - - [DllImport("ntdll.dll", SetLastError = true)] - public static extern int NtWow64ReadVirtualMemory64( - IntPtr hProcess, - long lpBaseAddress, - [Out] byte[] lpBuffer, - long dwSize, - ref long lpNumberOfBytesRead); - - [DllImport("ntdll.dll", SetLastError = true)] - public static unsafe extern int NtWow64ReadVirtualMemory64( - IntPtr hProcess, - long lpBaseAddress, - void* lpBuffer, - long dwSize, - ref long lpNumberOfBytesRead); - - public const int STATUS_SUCCESS = 0; - - public const int PAGE_NOACCESS = 0x01; - public const int PAGE_EXECUTE = 0x10; - - [StructLayout(LayoutKind.Sequential)] - public struct MEMORY_BASIC_INFORMATION - { - public IntPtr BaseAddress; - public IntPtr AllocationBase; - public int AllocationProtect; - public IntPtr RegionSize; - public int State; - public int Protect; - public int Type; - } - - [DllImport("kernel32")] - public static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, int dwLength); - - [StructLayout(LayoutKind.Sequential)] - public struct MEMORY_BASIC_INFORMATION_WOW64 - { - public long BaseAddress; - public long AllocationBase; - public int AllocationProtect; - public long RegionSize; - public int State; - public int Protect; - public int Type; - } - - public enum MEMORY_INFORMATION_CLASS - { - MemoryBasicInformation - } - - [DllImport("ntdll.dll")] - public static extern int NtWow64QueryVirtualMemory64( - IntPtr hProcess, - long lpAddress, - MEMORY_INFORMATION_CLASS memoryInformationClass, - IntPtr lpBuffer, // MEMORY_BASIC_INFORMATION_WOW64, pointer must be 64-bit aligned - long memoryInformationLength, - ref long returnLength); - - [DllImport("kernel32.dll")] - public static extern bool IsWow64Process(IntPtr hProcess, out bool wow64Process); - - // ------------------------------------------------------------------------------------------------------- - - public const int ERROR_ACCESS_DENIED = 5; - public const int ERROR_INVALID_HANDLE = 6; - public const int ERROR_INVALID_PARAMETER = 87; - - public const int CTRL_C_EVENT = 0; - public const int CTRL_BREAK_EVENT = 1; - - [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] - public static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId); - - [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] - public static extern bool AttachConsole(int dwProcessId); - - [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] - public static extern bool FreeConsole(); - - public delegate bool HANDLER_ROUTINE(int dwCtrlType); - - [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true)] - public static extern bool SetConsoleCtrlHandler(HANDLER_ROUTINE HandlerRoutine, bool Add); - - // ------------------------------------------------------------------------------------------------------- - - public const int MAX_PATH = 260; - - public const int ERROR_INSUFFICIENT_BUFFER = 0x0000007A; - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize); - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/OpenFiles.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/OpenFiles.cs deleted file mode 100644 index 572012b55b7b..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/OpenFiles.cs +++ /dev/null @@ -1,491 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code taken from https://github.com/urosjovanovic/MceController/blob/master/VmcServices/DetectOpenFiles.cs - -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; -using Microsoft.Win32.SafeHandles; -// ReSharper disable InconsistentNaming - -namespace Datadog.Trace.Tools.Runner.Checks.Windows -{ - internal class OpenFiles - { - private const string NetworkDevicePrefix = "\\Device\\LanmanRedirector\\"; - private const int MaxPath = 260; - private const int HandleTypeTokenCount = 27; - - private static readonly string[] HandleTypeTokens = - { - string.Empty, string.Empty, "Directory", "SymbolicLink", "Token", - "Process", "Thread", "Unknown7", "Event", "EventPair", "Mutant", - "Unknown11", "Semaphore", "Timer", "Profile", "WindowStation", - "Desktop", "Section", "Key", "Port", "WaitablePort", - "Unknown21", "Unknown22", "Unknown23", "Unknown24", - "IoCompletion", "File" - }; - - private static Dictionary _deviceMap; - - internal enum NT_STATUS - { - STATUS_SUCCESS = 0x00000000, - STATUS_BUFFER_OVERFLOW = unchecked((int)0x80000005L), - STATUS_INFO_LENGTH_MISMATCH = unchecked((int)0xC0000004L) - } - - internal enum SYSTEM_INFORMATION_CLASS - { - SystemBasicInformation = 0, - SystemPerformanceInformation = 2, - SystemTimeOfDayInformation = 3, - SystemProcessInformation = 5, - SystemProcessorPerformanceInformation = 8, - SystemHandleInformation = 16, - SystemInterruptInformation = 23, - SystemExceptionInformation = 33, - SystemRegistryQuotaInformation = 37, - SystemLookasideInformation = 45 - } - - internal enum OBJECT_INFORMATION_CLASS - { - ObjectBasicInformation = 0, - ObjectNameInformation = 1, - ObjectTypeInformation = 2, - ObjectAllTypesInformation = 3, - ObjectHandleInformation = 4 - } - - [Flags] - internal enum ProcessAccessRights - { - PROCESS_DUP_HANDLE = 0x00000040 - } - - [Flags] - internal enum DuplicateHandleOptions - { - DUPLICATE_CLOSE_SOURCE = 0x1, - DUPLICATE_SAME_ACCESS = 0x2 - } - - private enum SystemHandleType - { - OB_TYPE_UNKNOWN = 0, - OB_TYPE_TYPE = 1, - OB_TYPE_DIRECTORY, - OB_TYPE_SYMBOLIC_LINK, - OB_TYPE_TOKEN, - OB_TYPE_PROCESS, - OB_TYPE_THREAD, - OB_TYPE_UNKNOWN_7, - OB_TYPE_EVENT, - OB_TYPE_EVENT_PAIR, - OB_TYPE_MUTANT, - OB_TYPE_UNKNOWN_11, - OB_TYPE_SEMAPHORE, - OB_TYPE_TIMER, - OB_TYPE_PROFILE, - OB_TYPE_WINDOW_STATION, - OB_TYPE_DESKTOP, - OB_TYPE_SECTION, - OB_TYPE_KEY, - OB_TYPE_PORT, - OB_TYPE_WAITABLE_PORT, - OB_TYPE_UNKNOWN_21, - OB_TYPE_UNKNOWN_22, - OB_TYPE_UNKNOWN_23, - OB_TYPE_UNKNOWN_24, - // OB_TYPE_CONTROLLER, - // OB_TYPE_DEVICE, - // OB_TYPE_DRIVER, - OB_TYPE_IO_COMPLETION, - OB_TYPE_FILE - } - - public static IEnumerable GetOpenFiles(int processId) - { - NT_STATUS ret; - int length = 0x10000; - - do - { - var ptr = IntPtr.Zero; - - try - { - ptr = Marshal.AllocHGlobal(length); - - ret = NativeMethods.NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS.SystemHandleInformation, ptr, length, out var returnLength); - - if (ret == NT_STATUS.STATUS_INFO_LENGTH_MISMATCH) - { - // Round required memory up to the nearest 64KB boundary. - length = ((returnLength + 0xffff) & ~0xffff); - } - else if (ret == NT_STATUS.STATUS_SUCCESS) - { - int handleCount = Marshal.ReadInt32(ptr); - int offset = sizeof(int); - int size = Marshal.SizeOf(); - - using var processHandle = NativeMethods.OpenProcess(ProcessAccessRights.PROCESS_DUP_HANDLE, true, processId); - - for (int i = 0; i < handleCount; i++) - { - var handleEntry = Marshal.PtrToStructure(ptr + offset); - int ownerProcessId = GetProcessId(handleEntry.OwnerPid); - - if (ownerProcessId == processId) - { - if (ExtractFileNameFromHandle(handleEntry, processHandle, out var fileName)) - { - yield return fileName; - } - } - - offset += size; - } - } - } - finally - { - Marshal.FreeHGlobal(ptr); - } - } - while (ret == NT_STATUS.STATUS_INFO_LENGTH_MISMATCH); - } - - private static bool ExtractFileNameFromHandle(SYSTEM_HANDLE_ENTRY handleEntry, SafeHandle processHandle, out string fileName) - { - var handle = (IntPtr)handleEntry.HandleValue; - - SafeObjectHandle duplicatedHandle = null; - - try - { - if (!DuplicateHandle(handle, processHandle, out duplicatedHandle)) - { - fileName = null; - return false; - } - - handle = duplicatedHandle.DangerousGetHandle(); - - if (GetHandleType(handle, out var handleType) && handleType == SystemHandleType.OB_TYPE_FILE) - { - if (GetFileNameFromHandle(handle, out var devicePath)) - { - return ConvertDevicePathToDosPath(devicePath, out fileName); - } - } - } - finally - { - duplicatedHandle?.Close(); - } - - fileName = null; - return false; - } - - private static int GetProcessId(IntPtr processId) - { - if (IntPtr.Size == 4) - { - return (int)processId; - } - - return (int)((long)processId >> 32); - } - - private static bool DuplicateHandle(IntPtr handle, SafeHandle processHandle, out SafeObjectHandle duplicatedHandle) - { - var currentProcess = NativeMethods.GetCurrentProcess(); - - return NativeMethods.DuplicateHandle(processHandle.DangerousGetHandle(), handle, currentProcess, out duplicatedHandle, 0, false, DuplicateHandleOptions.DUPLICATE_SAME_ACCESS); - } - - private static bool GetFileNameFromHandle(IntPtr handle, out string fileName) - { - var fileType = NativeMethods.GetFileType(handle); - - // FILE_TYPE_DISK - if (fileType != 0x1) - { - fileName = null; - return false; - } - - var ptr = IntPtr.Zero; - - try - { - int length = 0x200; // 512 bytes - - ptr = Marshal.AllocHGlobal(length); - - var ret = NativeMethods.NtQueryObject(handle, OBJECT_INFORMATION_CLASS.ObjectNameInformation, ptr, length, out length); - - if (ret == NT_STATUS.STATUS_BUFFER_OVERFLOW) - { - Marshal.FreeHGlobal(ptr); - ptr = Marshal.AllocHGlobal(length); - - ret = NativeMethods.NtQueryObject(handle, OBJECT_INFORMATION_CLASS.ObjectNameInformation, ptr, length, out length); - } - - if (ret == NT_STATUS.STATUS_SUCCESS) - { - var objNameInfo = Marshal.PtrToStructure(ptr); - fileName = objNameInfo.Name.Buffer; - return fileName.Length != 0; - } - } - finally - { - Marshal.FreeHGlobal(ptr); - } - - fileName = string.Empty; - return false; - } - - private static bool GetHandleType(IntPtr handle, out SystemHandleType handleType) - { - var token = GetHandleTypeToken(handle); - return GetHandleTypeFromToken(token, out handleType); - } - - private static bool GetHandleTypeFromToken(string token, out SystemHandleType handleType) - { - for (int i = 1; i < HandleTypeTokenCount; i++) - { - if (HandleTypeTokens[i] == token) - { - handleType = (SystemHandleType)i; - return true; - } - } - - handleType = SystemHandleType.OB_TYPE_UNKNOWN; - return false; - } - - private static string GetHandleTypeToken(IntPtr handle) - { - NativeMethods.NtQueryObject(handle, OBJECT_INFORMATION_CLASS.ObjectTypeInformation, IntPtr.Zero, 0, out var length); - var ptr = IntPtr.Zero; - - try - { - ptr = Marshal.AllocHGlobal(length); - - if (NativeMethods.NtQueryObject(handle, OBJECT_INFORMATION_CLASS.ObjectTypeInformation, ptr, length, out length) == NT_STATUS.STATUS_SUCCESS) - { - var objTypeInfo = Marshal.PtrToStructure(ptr); - return objTypeInfo.TypeName.Buffer; - } - } - finally - { - Marshal.FreeHGlobal(ptr); - } - - return string.Empty; - } - - private static bool ConvertDevicePathToDosPath(string devicePath, out string dosPath) - { - EnsureDeviceMap(); - int i = devicePath.Length; - - while (i > 0 && (i = devicePath.LastIndexOf('\\', i - 1)) != -1) - { - if (_deviceMap.TryGetValue(devicePath.Substring(0, i), out var drive)) - { - dosPath = string.Concat(drive, devicePath.Substring(i)); - return dosPath.Length != 0; - } - } - - dosPath = string.Empty; - return false; - } - - private static void EnsureDeviceMap() - { - if (_deviceMap == null) - { - var localDeviceMap = BuildDeviceMap(); - Interlocked.CompareExchange(ref _deviceMap, localDeviceMap, null); - } - } - - private static Dictionary BuildDeviceMap() - { - var logicalDrives = Environment.GetLogicalDrives(); - var localDeviceMap = new Dictionary(logicalDrives.Length); - var lpTargetPath = new StringBuilder(MaxPath); - - foreach (var drive in logicalDrives) - { - var lpDeviceName = drive.Substring(0, 2); - NativeMethods.QueryDosDevice(lpDeviceName, lpTargetPath, MaxPath); - localDeviceMap.Add(NormalizeDeviceName(lpTargetPath.ToString()), lpDeviceName); - } - - localDeviceMap.Add(NetworkDevicePrefix.Substring(0, NetworkDevicePrefix.Length - 1), "\\"); - return localDeviceMap; - } - - private static string NormalizeDeviceName(string deviceName) - { - if (string.Compare(deviceName, 0, NetworkDevicePrefix, 0, NetworkDevicePrefix.Length, StringComparison.InvariantCulture) == 0) - { - var shareName = deviceName.Substring(deviceName.IndexOf('\\', NetworkDevicePrefix.Length) + 1); - return NetworkDevicePrefix + shareName; - } - - return deviceName; - } - - // Modified from original solution based on https://stackoverflow.com/a/9995536 - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private struct SYSTEM_HANDLE_ENTRY - { - public IntPtr OwnerPid; - public byte ObjectType; - public byte HandleFlags; - public short HandleValue; - public IntPtr ObjectPointer; - public int AccessMask; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - private struct UNICODE_STRING - { - public ushort Length; - public ushort MaximumLength; - [MarshalAs(UnmanagedType.LPWStr)] - public string Buffer; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private struct OBJECT_TYPE_INFORMATION - { - public UNICODE_STRING TypeName; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 22)] - public ulong[] Reserved; - } - - [StructLayout(LayoutKind.Sequential, Pack = 1)] - private struct OBJECT_NAME_INFORMATION - { - public UNICODE_STRING Name; - public IntPtr NameBuffer; - } - - internal static class NativeMethods - { - [DllImport("ntdll.dll")] - internal static extern NT_STATUS NtQuerySystemInformation( - [In] SYSTEM_INFORMATION_CLASS SystemInformationClass, - [In] IntPtr SystemInformation, - [In] int SystemInformationLength, - [Out] out int ReturnLength); - - [DllImport("ntdll.dll")] - internal static extern NT_STATUS NtQueryObject( - [In] IntPtr Handle, - [In] OBJECT_INFORMATION_CLASS ObjectInformationClass, - [In] IntPtr ObjectInformation, - [In] int ObjectInformationLength, - [Out] out int ReturnLength); - - [DllImport("kernel32.dll", SetLastError = true)] - internal static extern SafeProcessHandle OpenProcess( - [In] ProcessAccessRights dwDesiredAccess, - [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, - [In] int dwProcessId); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DuplicateHandle( - [In] IntPtr hSourceProcessHandle, - [In] IntPtr hSourceHandle, - [In] IntPtr hTargetProcessHandle, - [Out] out SafeObjectHandle lpTargetHandle, - [In] int dwDesiredAccess, - [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, - [In] DuplicateHandleOptions dwOptions); - - [DllImport("kernel32.dll")] - internal static extern IntPtr GetCurrentProcess(); - - [DllImport("kernel32.dll", SetLastError = true)] - internal static extern int GetProcessId( - [In] IntPtr Process); - - [DllImport("kernel32.dll")] - internal static extern int GetFileType( - [In] IntPtr hFile); - - [DllImport("kernel32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool CloseHandle( - [In] IntPtr hObject); - - [DllImport("kernel32.dll", SetLastError = true)] - internal static extern int QueryDosDevice( - [In] string lpDeviceName, - [Out] StringBuilder lpTargetPath, - [In] int ucchMax); - } - - internal sealed class SafeObjectHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private SafeObjectHandle() - : base(true) - { - } - - internal SafeObjectHandle(IntPtr preexistingHandle, bool ownsHandle) - : base(ownsHandle) - { - SetHandle(preexistingHandle); - } - - protected override bool ReleaseHandle() - { - return NativeMethods.CloseHandle(handle); - } - } - - internal sealed class SafeProcessHandle : SafeHandleZeroOrMinusOneIsInvalid - { - private SafeProcessHandle() - : base(true) - { - } - - internal SafeProcessHandle(IntPtr preexistingHandle, bool ownsHandle) - : base(ownsHandle) - { - SetHandle(preexistingHandle); - } - - protected override bool ReleaseHandle() - { - return NativeMethods.CloseHandle(handle); - } - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessEnvironmentWindows.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessEnvironmentWindows.cs deleted file mode 100644 index cb951182925f..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessEnvironmentWindows.cs +++ /dev/null @@ -1,551 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -#pragma warning disable SA1300 // Element should begin with upper-case letter - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading; - -namespace Datadog.Trace.Tools.Runner.Checks.Windows -{ - internal static class ProcessEnvironmentWindows - { - public static IReadOnlyDictionary ReadVariables(Process process) - { - return _ReadVariablesCore(process); - } - - public static int GetProcessBitness(Process process) - { - return _GetProcessBitness(process.Handle); - } - - private static Dictionary _ReadVariablesCore(Process process) - { - int retryCount = 5; - bool RetryPolicy() => --retryCount > 0; - - Again: - try - { - var stream = _GetEnvStream(process.Handle); - var reader = new ProcessBinaryReader(new BufferedStream(stream), Encoding.Unicode); - var env = _ReadEnv(reader); - - if (env.Count == 0) - { - // Empty environment may indicate that a process environment block has not been initialized yet. - if (RetryPolicy()) - { - goto Again; - } - } - - return env; - } - catch (EndOfStreamException ex) - { - if (process.HasExited) - { - throw new InvalidOperationException("The target process has exited", ex); - } - - // There may be a race condition in environment block initialization of a recently started process. - if (RetryPolicy()) - { - Thread.Sleep(1000); - goto Again; - } - else - { - throw; - } - } - } - - private static Stream _GetEnvStream(IntPtr hProcess) - { - var penv = _GetPenv(hProcess); - if (penv.CanBeRepresentedByNativePointer) - { - int dataSize; - if (!_HasReadAccess(hProcess, penv, out dataSize)) - { - throw new Exception("Unable to read environment block."); - } - - dataSize = _ClampEnvSize(dataSize); - - var adapter = new ProcessMemoryAdapter(hProcess); - return new ProcessMemoryStream(adapter, penv, dataSize); - } - else if (penv.Size == 8 && IntPtr.Size == 4) - { - // Accessing a 64-bit process from 32-bit host. - - int dataSize; - try - { - if (!_HasReadAccessWow64(hProcess, penv.ToInt64(), out dataSize)) - { - throw new Exception("Unable to read environment block with WOW64 API."); - } - } - catch (EntryPointNotFoundException) - { - // Windows 10 does not provide NtWow64QueryVirtualMemory64 API call. - dataSize = -1; - } - - dataSize = _ClampEnvSize(dataSize); - - var adapter = new ProcessMemoryAdapterWow64(hProcess); - return new ProcessMemoryStream(adapter, penv, dataSize); - } - else - { - throw new Exception("Unable to access process memory due to unsupported bitness cardinality."); - } - } - - private static int _ClampEnvSize(int size) - { - int maxSize = EnvironmentInfo.MaxSize; - - if (maxSize != -1) - { - if (size == -1 || size > maxSize) - { - size = maxSize; - } - } - - return size; - } - - private static Dictionary _ReadEnv(ProcessBinaryReader br) - { - // Environment variables are case insensitive on Windows - var env = new Dictionary(StringComparer.OrdinalIgnoreCase); - - while (true) - { - var s = br.ReadCString(); - if (s.Length == 0) - { - // End of environment block. - break; - } - - int j = s.IndexOf('='); - if (j <= 0) - { - continue; - } - - string name = s.Substring(0, j); - string value = s.Substring(j + 1); - - env[name] = value; - } - - return env; - } - - private static bool _TryReadIntPtr32(IntPtr hProcess, IntPtr ptr, out IntPtr readPtr) - { - bool result; -#pragma warning disable CS0618, SYSLIB0004 // Type or member is obsolete - RuntimeHelpers.PrepareConstrainedRegions(); -#pragma warning restore CS0618, SYSLIB0004 // Type or member is obsolete - try - { - } - finally - { - int dataSize = sizeof(int); - var data = Marshal.AllocHGlobal(dataSize); - var res_len = IntPtr.Zero; - bool b = NativeMethods.ReadProcessMemory( - hProcess, - ptr, - data, - new IntPtr(dataSize), - ref res_len); - readPtr = new IntPtr(Marshal.ReadInt32(data)); - Marshal.FreeHGlobal(data); - if (!b || (int)res_len != dataSize) - { - result = false; - } - else - { - result = true; - } - } - - return result; - } - - private static bool _TryReadIntPtr(IntPtr hProcess, IntPtr ptr, out IntPtr readPtr) - { - bool result; -#pragma warning disable CS0618, SYSLIB0004 // Type or member is obsolete - RuntimeHelpers.PrepareConstrainedRegions(); -#pragma warning restore CS0618, SYSLIB0004 // Type or member is obsolete - try - { - } - finally - { - int dataSize = IntPtr.Size; - var data = Marshal.AllocHGlobal(dataSize); - var res_len = IntPtr.Zero; - bool b = NativeMethods.ReadProcessMemory( - hProcess, - ptr, - data, - new IntPtr(dataSize), - ref res_len); - readPtr = Marshal.ReadIntPtr(data); - Marshal.FreeHGlobal(data); - if (!b || (int)res_len != dataSize) - { - result = false; - } - else - { - result = true; - } - } - - return result; - } - - private static bool _TryReadIntPtrWow64(IntPtr hProcess, long ptr, out long readPtr) - { - bool result; -#pragma warning disable CS0618, SYSLIB0004 // Type or member is obsolete - RuntimeHelpers.PrepareConstrainedRegions(); -#pragma warning restore CS0618, SYSLIB0004 // Type or member is obsolete - try - { - } - finally - { - int dataSize = sizeof(long); - var data = Marshal.AllocHGlobal(dataSize); - long res_len = 0; - int status = NativeMethods.NtWow64ReadVirtualMemory64( - hProcess, - ptr, - data, - dataSize, - ref res_len); - readPtr = Marshal.ReadInt64(data); - Marshal.FreeHGlobal(data); - if (status != NativeMethods.STATUS_SUCCESS || res_len != dataSize) - { - result = false; - } - else - { - result = true; - } - } - - return result; - } - - private static UniPtr _GetPenv(IntPtr hProcess) - { - int processBitness = _GetProcessBitness(hProcess); - - if (processBitness == 64) - { - if (Environment.Is64BitProcess) - { - // Accessing a 64-bit process from 64-bit host. - - IntPtr pPeb = _GetPeb64(hProcess); - - if (!_TryReadIntPtr(hProcess, pPeb + 0x20, out var ptr)) - { - throw new Exception("Unable to read PEB."); - } - - if (!_TryReadIntPtr(hProcess, ptr + 0x80, out var penv)) - { - throw new Exception("Unable to read RTL_USER_PROCESS_PARAMETERS."); - } - - return penv; - } - else - { - // Accessing a 64-bit process from 32-bit host. - - var pPeb = _GetPeb64(hProcess); - - if (!_TryReadIntPtrWow64(hProcess, pPeb.ToInt64() + 0x20, out var ptr)) - { - throw new Exception("Unable to read PEB."); - } - - if (!_TryReadIntPtrWow64(hProcess, ptr + 0x80, out var penv)) - { - throw new Exception("Unable to read RTL_USER_PROCESS_PARAMETERS."); - } - - return new UniPtr(penv); - } - } - else - { - // Accessing a 32-bit process from 32-bit host. - - IntPtr pPeb = _GetPeb32(hProcess); - - if (!_TryReadIntPtr32(hProcess, pPeb + 0x10, out var ptr)) - { - throw new Exception("Unable to read PEB."); - } - - if (!_TryReadIntPtr32(hProcess, ptr + 0x48, out var penv)) - { - throw new Exception("Unable to read RTL_USER_PROCESS_PARAMETERS."); - } - - return penv; - } - } - - private static int _GetProcessBitness(IntPtr hProcess) - { - if (Environment.Is64BitOperatingSystem) - { - if (!NativeMethods.IsWow64Process(hProcess, out var wow64)) - { - return 32; - } - - if (wow64) - { - return 32; - } - - return 64; - } - else - { - return 32; - } - } - - private static IntPtr _GetPeb32(IntPtr hProcess) - { - if (Environment.Is64BitProcess) - { - var ptr = IntPtr.Zero; - int res_len = 0; - int pbiSize = IntPtr.Size; - int status = NativeMethods.NtQueryInformationProcess( - hProcess, - NativeMethods.ProcessWow64Information, - ref ptr, - pbiSize, - ref res_len); - - if (res_len != pbiSize) - { - throw new Exception("Unable to query process information."); - } - - return ptr; - } - else - { - return _GetPebNative(hProcess); - } - } - - private static IntPtr _GetPebNative(IntPtr hProcess) - { - var pbi = new NativeMethods.PROCESS_BASIC_INFORMATION(); - int res_len = 0; - int pbiSize = Marshal.SizeOf(pbi); - int status = NativeMethods.NtQueryInformationProcess( - hProcess, - NativeMethods.ProcessBasicInformation, - ref pbi, - pbiSize, - ref res_len); - - if (res_len != pbiSize) - { - throw new Exception("Unable to query process information."); - } - - return pbi.PebBaseAddress; - } - - private static UniPtr _GetPeb64(IntPtr hProcess) - { - if (Environment.Is64BitProcess) - { - return _GetPebNative(hProcess); - } - else - { - // Get PEB via WOW64 API. - var pbi = new NativeMethods.PROCESS_BASIC_INFORMATION_WOW64(); - int res_len = 0; - int pbiSize = Marshal.SizeOf(pbi); - int status = NativeMethods.NtWow64QueryInformationProcess64( - hProcess, - NativeMethods.ProcessBasicInformation, - ref pbi, - pbiSize, - ref res_len); - - if (res_len != pbiSize) - { - throw new Exception("Unable to query process information."); - } - - return new UniPtr(pbi.PebBaseAddress); - } - } - - private static bool _HasReadAccess(IntPtr hProcess, IntPtr address, out int size) - { - size = 0; - - var memInfo = new NativeMethods.MEMORY_BASIC_INFORMATION(); - int result = NativeMethods.VirtualQueryEx( - hProcess, - address, - ref memInfo, - Marshal.SizeOf(memInfo)); - - if (result == 0) - { - return false; - } - - if (memInfo.Protect == NativeMethods.PAGE_NOACCESS || memInfo.Protect == NativeMethods.PAGE_EXECUTE) - { - return false; - } - - try - { - size = Convert.ToInt32(memInfo.RegionSize.ToInt64() - (address.ToInt64() - memInfo.BaseAddress.ToInt64())); - } - catch (OverflowException) - { - return false; - } - - if (size <= 0) - { - return false; - } - - return true; - } - - private static bool _HasReadAccessWow64(IntPtr hProcess, long address, out int size) - { - size = 0; - - NativeMethods.MEMORY_BASIC_INFORMATION_WOW64 memInfo; - -#if NET45 - var memInfoType = typeof(NativeMethods.MEMORY_BASIC_INFORMATION_WOW64); - int memInfoLength = Marshal.SizeOf(memInfoType); -#else - int memInfoLength = memInfoLength = Marshal.SizeOf(); -#endif - - const int memInfoAlign = 8; - - long resultLength = 0; - int result; - - IntPtr hMemInfo = Marshal.AllocHGlobal(memInfoLength + (memInfoAlign * 2)); - try - { - // Align to 64 bits. - var hMemInfoAligned = new IntPtr(hMemInfo.ToInt64() & ~(memInfoAlign - 1L)); - - result = NativeMethods.NtWow64QueryVirtualMemory64( - hProcess, - address, - NativeMethods.MEMORY_INFORMATION_CLASS.MemoryBasicInformation, - hMemInfoAligned, - memInfoLength, - ref resultLength); - -#if NET45 - memInfo = (NativeMethods.MEMORY_BASIC_INFORMATION_WOW64)Marshal.PtrToStructure(hMemInfoAligned, memInfoType); -#else - memInfo = Marshal.PtrToStructure(hMemInfoAligned); -#endif - } - finally - { - Marshal.FreeHGlobal(hMemInfo); - } - - if (result != NativeMethods.STATUS_SUCCESS) - { - return false; - } - - if (memInfo.Protect == NativeMethods.PAGE_NOACCESS || memInfo.Protect == NativeMethods.PAGE_EXECUTE) - { - return false; - } - - try - { - size = Convert.ToInt32(memInfo.RegionSize - (address - memInfo.BaseAddress)); - } - catch (OverflowException) - { - return false; - } - - if (size <= 0) - { - return false; - } - - return true; - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/RegistryService.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/RegistryService.cs deleted file mode 100644 index 3e8e5daaf447..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/RegistryService.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -using System; -using System.Runtime.InteropServices; -using Microsoft.Win32; - -#nullable enable - -namespace Datadog.Trace.Tools.Runner.Checks.Windows -{ - internal class RegistryService : IRegistryService - { - public string[] GetLocalMachineValueNames(string key) - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return Array.Empty(); - } - - var registryKey = Registry.LocalMachine.OpenSubKey(key); - - if (registryKey == null) - { - return Array.Empty(); - } - - return registryKey.GetValueNames(); - } - - public string? GetLocalMachineValue(string key) - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return null; - } - - var registryKey = Registry.LocalMachine.OpenSubKey(key); - - return registryKey?.GetValue(null) as string; - } - - public string[] GetLocalMachineKeyNames(string key) - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return Array.Empty(); - } - - var registryKey = Registry.LocalMachine.OpenSubKey(key); - - if (registryKey == null) - { - return Array.Empty(); - } - - return registryKey.GetSubKeyNames(); - } - - public string? GetLocalMachineKeyNameValue(string key, string subKeyName, string name) - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return string.Empty; - } - - var registryKey = Registry.LocalMachine.OpenSubKey(key); - - if (registryKey == null) - { - return string.Empty; - } - - var subKey = registryKey.OpenSubKey(subKeyName); - - return subKey?.GetValue(name) as string; - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/UniPtr.cs b/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/UniPtr.cs deleted file mode 100644 index 95bf8f6ea93a..000000000000 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/UniPtr.cs +++ /dev/null @@ -1,97 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -#pragma warning disable SA1201 // Elements should appear in the correct order -#pragma warning disable SA1308 // Variable names should not be prefixed - -using System; - -namespace Datadog.Trace.Tools.Runner.Checks.Windows -{ - /// - /// Universal pointer that can hold both 32 and 64 bit values. - /// - internal readonly struct UniPtr : IEquatable - { - public UniPtr(IntPtr value) - { - m_Value = value.ToInt64(); - m_Size = (byte)IntPtr.Size; - } - - public UniPtr(long value) - { - m_Value = value; - m_Size = sizeof(long); - } - - public UniPtr(ulong value) - : this((long)value) - { - } - - private readonly long m_Value; - private readonly byte m_Size; - - public int Size => m_Size; - - public readonly long ToInt64() => m_Value; - - public readonly ulong ToUInt64() => (ulong)m_Value; - - public readonly bool FitsInNativePointer => m_Size <= IntPtr.Size; - - public readonly bool CanBeRepresentedByNativePointer - { - get - { - int actualSize = m_Size; - - if (actualSize == 8) - { - if (m_Value >> 32 == 0) - { - actualSize = 4; - } - } - - return actualSize <= IntPtr.Size; - } - } - - public static implicit operator IntPtr(UniPtr p) => new IntPtr(p.ToInt64()); - - public static implicit operator UniPtr(IntPtr p) => new UniPtr(p); - - public static UniPtr operator +(UniPtr a, long b) => new UniPtr(a.ToInt64() + b); - - public static bool operator ==(UniPtr a, UniPtr b) => a.ToUInt64() == b.ToUInt64(); - - public static bool operator !=(UniPtr a, UniPtr b) => a.ToUInt64() != b.ToUInt64(); - - public override int GetHashCode() => m_Value.GetHashCode(); - - public override bool Equals(object obj) => obj is UniPtr other && Equals(other); - - public bool Equals(UniPtr other) => m_Value == other.m_Value; - - public override readonly string ToString() => ((ulong)m_Value).ToString(); - } -} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Datadog.Trace.Tools.Runner.csproj b/tracer/src/Datadog.Trace.Tools.Runner/Datadog.Trace.Tools.Runner.csproj index c1d5839966ec..120e7a35a9ba 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Datadog.Trace.Tools.Runner.csproj +++ b/tracer/src/Datadog.Trace.Tools.Runner/Datadog.Trace.Tools.Runner.csproj @@ -133,6 +133,7 @@ + diff --git a/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs b/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs new file mode 100644 index 000000000000..05dd3bfa7bbc --- /dev/null +++ b/tracer/src/Datadog.Trace.Tools.Runner/ProcessConfiguration.cs @@ -0,0 +1,69 @@ +// +// 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 2017 Datadog, Inc. +// +#nullable enable + +using System; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Configuration; +using Datadog.Trace.Configuration.Telemetry; +using Datadog.Trace.Tools.Shared; + +namespace Datadog.Trace.Tools.Runner +{ + internal static class ProcessConfiguration + { + internal static string? GetProcessLogDirectory(int pid) + { + ProcessInfo processInfo; + + try + { + processInfo = ProcessInfo.GetProcessInfo(pid); + } + catch (Exception ex) + { + Utils.WriteError("Error while trying to fetch process information: " + ex.Message); + return null; + } + + IReadOnlyDictionary? applicationConfig; + + try + { + applicationConfig = processInfo.LoadApplicationConfig(); + } + catch (Exception ex) + { + Utils.WriteError("Error while trying to load application configuration: " + ex.Message); + return null; + } + + IConfigurationSource applicationConfigurationSource = NullConfigurationSource.Instance; + + if (applicationConfig != null) + { + applicationConfigurationSource = new DictionaryConfigurationSource(applicationConfig); + } + + var config = new ConfigurationBuilder(applicationConfigurationSource, NullConfigurationTelemetry.Instance); + + var logDirectory = config.WithKeys(ConfigurationKeys.LogDirectory).AsString(); + + if (logDirectory == null) + { +#pragma warning disable 618 // ProfilerLogPath is deprecated but still supported + var nativeLogFile = config.WithKeys(ConfigurationKeys.ProfilerLogPath).AsString(); +#pragma warning restore 618 + if (!string.IsNullOrEmpty(nativeLogFile)) + { + logDirectory = Path.GetDirectoryName(nativeLogFile); + } + } + + return logDirectory; + } + } +} diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Program.cs b/tracer/src/Datadog.Trace.Tools.Runner/Program.cs index 68d27d30985b..55888c04c594 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Program.cs +++ b/tracer/src/Datadog.Trace.Tools.Runner/Program.cs @@ -102,16 +102,7 @@ IEnumerable GetLayout(HelpContext context) ciCommand.AddCommand(new RunCiCommand(applicationContext)); ciCommand.AddCommand(new CrankCommand()); - var checkCommand = new Command("check"); - builder.Command.AddCommand(checkCommand); - - checkCommand.AddCommand(new CheckProcessCommand()); - checkCommand.AddCommand(new CheckAgentCommand()); - - if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - checkCommand.AddCommand(new CheckIisCommand()); - } + builder.Command.AddCommand(new CheckCommand(applicationContext)); builder.Command.AddCommand(new RunCommand(applicationContext)); builder.Command.AddCommand(new AotCommand { IsHidden = true }); diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Utils.cs b/tracer/src/Datadog.Trace.Tools.Runner/Utils.cs index 1626060a5cb6..8aa6ab76e4d7 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Utils.cs +++ b/tracer/src/Datadog.Trace.Tools.Runner/Utils.cs @@ -26,6 +26,18 @@ internal class Utils { public const string Profilerid = "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}"; + public static string GetHomePath(string runnerFolder) + { + // In the current nuspec structure RunnerFolder has the following format: + // C:\Users\[user]\.dotnet\tools\.store\datadog.trace.tools.runner\[version]\datadog.trace.tools.runner\[version]\tools\netcoreapp3.1\any + // C:\Users\[user]\.dotnet\tools\.store\datadog.trace.tools.runner\[version]\datadog.trace.tools.runner\[version]\tools\netcoreapp2.1\any + // And the Home folder is: + // C:\Users\[user]\.dotnet\tools\.store\datadog.trace.tools.runner\[version]\datadog.trace.tools.runner\[version]\home + // So we have to go up 3 folders. + + return DirectoryExists("Home", Path.Combine(runnerFolder, "..", "..", "..", "home"), Path.Combine(runnerFolder, "home")); + } + public static Dictionary GetProfilerEnvironmentVariables(InvocationContext context, string runnerFolder, Platform platform, CommonTracerSettings options, bool reducePathLength) { var tracerHomeFolder = options.TracerHome.GetValue(context); @@ -392,12 +404,6 @@ internal static bool IsAlpine() private static Dictionary GetBaseProfilerEnvironmentVariables(string runnerFolder, Platform platform, string tracerHomeFolder, bool reducePathLength) { - // In the current nuspec structure RunnerFolder has the following format: - // C:\Users\[user]\.dotnet\tools\.store\datadog.trace.tools.runner\[version]\datadog.trace.tools.runner\[version]\tools\netcoreapp3.1\any - // C:\Users\[user]\.dotnet\tools\.store\datadog.trace.tools.runner\[version]\datadog.trace.tools.runner\[version]\tools\netcoreapp2.1\any - // And the Home folder is: - // C:\Users\[user]\.dotnet\tools\.store\datadog.trace.tools.runner\[version]\datadog.trace.tools.runner\[version]\home - // So we have to go up 3 folders. string tracerHome = null; if (!string.IsNullOrEmpty(tracerHomeFolder)) { @@ -408,7 +414,7 @@ private static Dictionary GetBaseProfilerEnvironmentVariables(st } } - tracerHome ??= DirectoryExists("Home", Path.Combine(runnerFolder, "..", "..", "..", "home"), Path.Combine(runnerFolder, "home")); + tracerHome ??= GetHomePath(runnerFolder); if (tracerHome == null) { diff --git a/tracer/src/Datadog.Trace.Tools.Shared/AssemblyInfo.cs b/tracer/src/Datadog.Trace.Tools.Shared/AssemblyInfo.cs new file mode 100644 index 000000000000..867909681a01 --- /dev/null +++ b/tracer/src/Datadog.Trace.Tools.Shared/AssemblyInfo.cs @@ -0,0 +1,10 @@ +// +// 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 2017 Datadog, Inc. +// + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Datadog.Trace.Tools.Runner.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.Tools.dd_dotnet.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/tracer/src/Datadog.Trace.Tools.Shared/Datadog.Trace.Tools.Shared.csproj b/tracer/src/Datadog.Trace.Tools.Shared/Datadog.Trace.Tools.Shared.csproj new file mode 100644 index 000000000000..6e75ce98bc6b --- /dev/null +++ b/tracer/src/Datadog.Trace.Tools.Shared/Datadog.Trace.Tools.Shared.csproj @@ -0,0 +1,23 @@ + + + + net7.0;net6.0;net5.0;netcoreapp3.1;netcoreapp3.0;netcoreapp2.2;netcoreapp2.1; + Datadog.Trace.Tools.Shared + true + enable + + + CS1591;SA1600;SA1602 + + false + + + + + + + + + + + diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Linux/ProcessEnvironmentLinux.cs b/tracer/src/Datadog.Trace.Tools.Shared/Linux/ProcessEnvironmentLinux.cs similarity index 98% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Linux/ProcessEnvironmentLinux.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Linux/ProcessEnvironmentLinux.cs index 63f27920a855..35a89d547132 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Linux/ProcessEnvironmentLinux.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Linux/ProcessEnvironmentLinux.cs @@ -9,7 +9,7 @@ using System.IO; using System.Linq; -namespace Datadog.Trace.Tools.Runner.Checks.Linux +namespace Datadog.Trace.Tools.Shared.Linux { internal class ProcessEnvironmentLinux { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessEnvironment.cs b/tracer/src/Datadog.Trace.Tools.Shared/ProcessEnvironment.cs similarity index 74% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessEnvironment.cs rename to tracer/src/Datadog.Trace.Tools.Shared/ProcessEnvironment.cs index 7272bb2d439c..de6be83f473e 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/ProcessEnvironment.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/ProcessEnvironment.cs @@ -2,7 +2,6 @@ // 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 2017 Datadog, Inc. // -#nullable enable using System; using System.Collections.Generic; @@ -10,10 +9,19 @@ using System.Linq; using System.Runtime.InteropServices; -namespace Datadog.Trace.Tools.Runner.Checks +namespace Datadog.Trace.Tools.Shared { - internal class ProcessEnvironment + /// + /// Helpers functions to read information about a target process + /// + public static class ProcessEnvironment { + /// + /// Reads the environment variables of a process + /// + /// Target process + /// List of environment variablzq + /// Throws if running on an unsupported OS public static IReadOnlyDictionary ReadVariables(Process process) { if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) @@ -29,6 +37,11 @@ public static IReadOnlyDictionary ReadVariables(Process process) throw new NotSupportedException("Reading environment variables is currently only supported on Windows and Linux."); } + /// + /// Reads the modules of a process + /// + /// Target process + /// List of modules public static string[] ReadModules(Process process) { if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessInfo.cs b/tracer/src/Datadog.Trace.Tools.Shared/ProcessInfo.cs similarity index 63% rename from tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessInfo.cs rename to tracer/src/Datadog.Trace.Tools.Shared/ProcessInfo.cs index ecd766496c73..8e271edee609 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessInfo.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/ProcessInfo.cs @@ -10,11 +10,11 @@ using System.Runtime.InteropServices; using System.Xml.Linq; -namespace Datadog.Trace.Tools.dd_dotnet.Checks; +namespace Datadog.Trace.Tools.Shared; -internal class ProcessInfo +public class ProcessInfo { - public ProcessInfo(Process process, string? baseDirectory = null, IReadOnlyDictionary? appSettings = null) + public ProcessInfo(Process process) { Name = process.ProcessName; Id = process.Id; @@ -24,7 +24,6 @@ public ProcessInfo(Process process, string? baseDirectory = null, IReadOnlyDicti Modules = ProcessEnvironment.ReadModules(process); DotnetRuntime = DetectRuntime(Modules); - Configuration = ExtractConfigurationSource(baseDirectory, appSettings); } /// @@ -39,7 +38,6 @@ internal ProcessInfo(string name, int id, IReadOnlyDictionary en Modules = modules; DotnetRuntime = DetectRuntime(Modules); - Configuration = ExtractConfigurationSource(null, null); } [Flags] @@ -63,93 +61,27 @@ public enum Runtime public Runtime DotnetRuntime { get; } - public IConfigurationSource? Configuration { get; } - - public static ProcessInfo? GetProcessInfo(int pid, string? baseDirectory = null, IReadOnlyDictionary? appSettings = null) - { - try - { - using var process = Process.GetProcessById(pid); - return new ProcessInfo(process, baseDirectory, appSettings); - } - catch (Exception ex) - { - Utils.WriteError("Error while trying to fetch process information: " + ex); - return null; - } - } - - public IReadOnlyList GetChildProcesses() + public static ProcessInfo GetProcessInfo(int pid) { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return Array.Empty(); - } - - var pids = new List(); - - foreach (var process in Process.GetProcesses()) - { - try - { - var handle = process.Handle; - - int queryStatus = Windows.NativeMethods.NtQueryInformationProcess(handle, 0, out var pbi, Marshal.SizeOf(), out _); - - if (queryStatus == 0 && pbi.InheritedFromUniqueProcessId == Id) - { - pids.Add(process.Id); - } - } - catch - { - } - finally - { - process.Dispose(); - } - } - - return pids; + using var process = Process.GetProcessById(pid); + return new ProcessInfo(process); } - private static Runtime DetectRuntime(string[] modules) + public IReadOnlyDictionary? LoadApplicationConfig() { - var result = Runtime.Unknown; - - foreach (var module in modules) - { - var fileName = Path.GetFileName(module); - - if (fileName.Equals("clr.dll", StringComparison.OrdinalIgnoreCase)) - { - result |= Runtime.NetFx; - } - else if (fileName.Equals("coreclr.dll", StringComparison.OrdinalIgnoreCase) - || fileName.Equals("libcoreclr.so", StringComparison.OrdinalIgnoreCase)) - { - result |= Runtime.NetCore; - } - } - - return result; - } - - private static IReadOnlyDictionary? LoadApplicationConfig(string? mainModule) - { - if (mainModule == null) + if (MainModule == null) { return null; } - var folder = Path.GetDirectoryName(mainModule); + var folder = Path.GetDirectoryName(MainModule); if (folder == null) { return null; } - var configFileName = Path.GetFileName(mainModule) + ".config"; + var configFileName = Path.GetFileName(MainModule) + ".config"; var configPath = Path.Combine(folder, configFileName); if (!File.Exists(configPath)) @@ -185,40 +117,63 @@ private static Runtime DetectRuntime(string[] modules) } catch (Exception ex) { - Utils.WriteWarning($"An error occured while parsing the configuration file {configPath}: {ex.Message}"); - return null; + throw new InvalidOperationException($"An error occured while parsing the configuration file {configPath}: {ex.Message}", ex); } } - private IConfigurationSource ExtractConfigurationSource(string? baseDirectory, IReadOnlyDictionary? appSettings) + public IReadOnlyList GetChildProcesses() { - baseDirectory ??= Path.GetDirectoryName(MainModule); - - var configurationSource = new CompositeConfigurationSource(); - - configurationSource.Add(new DictionaryConfigurationSource(EnvironmentVariables)); - - if (appSettings != null) + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - configurationSource.Add(new DictionaryConfigurationSource(appSettings)); + return Array.Empty(); } - else if (DotnetRuntime.HasFlag(Runtime.NetFx)) + + var pids = new List(); + + foreach (var process in Process.GetProcesses()) { - var appConfigSource = LoadApplicationConfig(MainModule); + try + { + var handle = process.Handle; + + int queryStatus = Windows.NativeMethods.NtQueryInformationProcess(handle, 0, out var pbi, Marshal.SizeOf(), out _); - if (appConfigSource != null) + if (queryStatus == 0 && pbi.InheritedFromUniqueProcessId.ToInt32() == Id) + { + pids.Add(process.Id); + } + } + catch { - configurationSource.Add(new DictionaryConfigurationSource(appConfigSource)); + } + finally + { + process.Dispose(); } } - var jsonConfigurationSource = JsonConfigurationSource.TryLoadJsonConfigurationFile(configurationSource, baseDirectory); + return pids; + } + + private static Runtime DetectRuntime(string[] modules) + { + var result = Runtime.Unknown; - if (jsonConfigurationSource != null) + foreach (var module in modules) { - configurationSource.Add(jsonConfigurationSource); + var fileName = Path.GetFileName(module); + + if (fileName.Equals("clr.dll", StringComparison.OrdinalIgnoreCase)) + { + result |= Runtime.NetFx; + } + else if (fileName.Equals("coreclr.dll", StringComparison.OrdinalIgnoreCase) + || fileName.Equals("libcoreclr.so", StringComparison.OrdinalIgnoreCase)) + { + result |= Runtime.NetCore; + } } - return configurationSource; + return result; } } diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/EnvironmentInfo.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/EnvironmentInfo.cs similarity index 97% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/EnvironmentInfo.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/EnvironmentInfo.cs index 609174f2c023..1343ae4b3580 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/EnvironmentInfo.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/EnvironmentInfo.cs @@ -20,7 +20,7 @@ using System; -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal static class EnvironmentInfo { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/IProcessMemoryAdapter.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/IProcessMemoryAdapter.cs similarity index 97% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/IProcessMemoryAdapter.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/IProcessMemoryAdapter.cs index cd8e9d3fa635..6620fb5687f3 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/IProcessMemoryAdapter.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/IProcessMemoryAdapter.cs @@ -18,7 +18,7 @@ // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { /// /// Provides low-level access to the process memory. diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/NativeMethods.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/NativeMethods.cs similarity index 98% rename from tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/NativeMethods.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/NativeMethods.cs index 09adfeda8d89..9546d385c49e 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/NativeMethods.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/NativeMethods.cs @@ -24,9 +24,9 @@ using System.Runtime.InteropServices; using System.Text; -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { - internal static class NativeMethods + public static class NativeMethods { [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/OpenFiles.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/OpenFiles.cs similarity index 99% rename from tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/OpenFiles.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/OpenFiles.cs index d953f4a25971..5ba85b660f67 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/OpenFiles.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/OpenFiles.cs @@ -16,7 +16,7 @@ // ReSharper disable InconsistentNaming -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal class OpenFiles { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessBinaryReader.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessBinaryReader.cs similarity index 97% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessBinaryReader.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessBinaryReader.cs index c1f760683aad..3f304dec4f30 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessBinaryReader.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessBinaryReader.cs @@ -21,7 +21,7 @@ using System.IO; using System.Text; -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal sealed class ProcessBinaryReader : BinaryReader { diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessEnvironmentWindows.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessEnvironmentWindows.cs similarity index 99% rename from tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessEnvironmentWindows.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessEnvironmentWindows.cs index b160d45901a9..c7edb71dac1b 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessEnvironmentWindows.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessEnvironmentWindows.cs @@ -29,9 +29,9 @@ using System.Text; using System.Threading; -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { - internal static class ProcessEnvironmentWindows + public static class ProcessEnvironmentWindows { public static IReadOnlyDictionary ReadVariables(Process process) { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryAdapter.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryAdapter.cs similarity index 98% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryAdapter.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryAdapter.cs index b76242137a8f..587115e972c4 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryAdapter.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryAdapter.cs @@ -22,7 +22,7 @@ using System.ComponentModel; using System.Runtime.InteropServices; -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal sealed class ProcessMemoryAdapter : IProcessMemoryAdapter { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryAdapterWow64.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryAdapterWow64.cs similarity index 97% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryAdapterWow64.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryAdapterWow64.cs index 0cb4629c65cc..feb0cde3a642 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryAdapterWow64.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryAdapterWow64.cs @@ -20,7 +20,7 @@ using System; -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal sealed class ProcessMemoryAdapterWow64 : IProcessMemoryAdapter { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryStream.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryStream.cs similarity index 98% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryStream.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryStream.cs index afe1d2cc653c..2ed769bd4969 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/ProcessMemoryStream.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/ProcessMemoryStream.cs @@ -21,7 +21,7 @@ using System; using System.IO; -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal sealed class ProcessMemoryStream : Stream { diff --git a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/SystemInfo.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/SystemInfo.cs similarity index 96% rename from tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/SystemInfo.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/SystemInfo.cs index c2ec87fcead8..d68270e92f5c 100644 --- a/tracer/src/Datadog.Trace.Tools.Runner/Checks/Windows/SystemInfo.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/SystemInfo.cs @@ -18,7 +18,7 @@ // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. -namespace Datadog.Trace.Tools.Runner.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { internal static class SystemInfo { diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/UniPtr.cs b/tracer/src/Datadog.Trace.Tools.Shared/Windows/UniPtr.cs similarity index 98% rename from tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/UniPtr.cs rename to tracer/src/Datadog.Trace.Tools.Shared/Windows/UniPtr.cs index eefa27dffe8b..7a84f9126ef6 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/UniPtr.cs +++ b/tracer/src/Datadog.Trace.Tools.Shared/Windows/UniPtr.cs @@ -23,7 +23,7 @@ using System; -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows +namespace Datadog.Trace.Tools.Shared.Windows { /// /// Universal pointer that can hold both 32 and 64 bit values. diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/AssemblyInfo.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/AssemblyInfo.cs index 9a3a51f22119..e974281592ca 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/AssemblyInfo.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/AssemblyInfo.cs @@ -5,5 +5,6 @@ using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Datadog.Trace.Tools.dd_dotnet.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] [assembly: InternalsVisibleTo("Datadog.Trace.Tools.dd_dotnet.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckIisCommand.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckIisCommand.cs index 4d03c97b6b05..ac5aae1ff6f2 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckIisCommand.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckIisCommand.cs @@ -15,6 +15,7 @@ using System.Threading.Tasks; using Datadog.Trace.Tools.dd_dotnet.Checks; using Datadog.Trace.Tools.dd_dotnet.Checks.Windows.IIS; +using Datadog.Trace.Tools.Shared; using Spectre.Console; using static Datadog.Trace.Tools.dd_dotnet.Checks.Resources; @@ -129,11 +130,15 @@ internal static async Task ExecuteAsync(string? siteAndApplicationName, str Utils.WriteWarning(ErrorExtractingConfiguration(ex.Message)); } - var process = ProcessInfo.GetProcessInfo(pid, rootDirectory, appSettings); + ProcessInfo process; - if (process == null) + try + { + process = ProcessInfo.GetProcessInfo(pid); + } + catch (Exception ex) { - Utils.WriteError(GetProcessError); + Utils.WriteError(GetProcessError(ex.Message)); return 1; } @@ -180,11 +185,13 @@ internal static async Task ExecuteAsync(string? siteAndApplicationName, str AnsiConsole.WriteLine(AspNetCoreProcessFound(aspnetCorePid.Value)); - process = ProcessInfo.GetProcessInfo(aspnetCorePid.Value); - - if (process == null) + try + { + process = ProcessInfo.GetProcessInfo(aspnetCorePid.Value); + } + catch (Exception ex) { - Utils.WriteError(GetProcessError); + Utils.WriteError(GetProcessError(ex.Message)); return 1; } } @@ -195,7 +202,9 @@ internal static async Task ExecuteAsync(string? siteAndApplicationName, str return 1; } - if (!await AgentConnectivityCheck.RunAsync(process).ConfigureAwait(false)) + var configurationSource = process.ExtractConfigurationSource(rootDirectory, appSettings); + + if (!await AgentConnectivityCheck.RunAsync(configurationSource).ConfigureAwait(false)) { return 1; } diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckProcessCommand.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckProcessCommand.cs index 139be56f8ddc..ed85a8023160 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckProcessCommand.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CheckProcessCommand.cs @@ -3,11 +3,13 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // +using System; using System.CommandLine; using System.CommandLine.Invocation; using System.IO; using System.Threading.Tasks; using Datadog.Trace.Tools.dd_dotnet.Checks; +using Datadog.Trace.Tools.Shared; using Spectre.Console; using static Datadog.Trace.Tools.dd_dotnet.Checks.Resources; @@ -31,10 +33,15 @@ private async Task ExecuteAsync(InvocationContext context) AnsiConsole.WriteLine("Running checks on process " + pid); - var process = ProcessInfo.GetProcessInfo(pid); + ProcessInfo process; - if (process == null) + try { + process = ProcessInfo.GetProcessInfo(pid); + } + catch (Exception ex) + { + Utils.WriteError("Error while trying to fetch process information: " + ex.Message); Utils.WriteError("Could not fetch information about target process. Make sure to run the command from an elevated prompt, and check that the pid is correct."); context.ExitCode = 1; return; @@ -60,7 +67,8 @@ private async Task ExecuteAsync(InvocationContext context) return; } - foundIssue = !await AgentConnectivityCheck.RunAsync(process).ConfigureAwait(false); + var configurationSource = process.ExtractConfigurationSource(null, null); + foundIssue = !await AgentConnectivityCheck.RunAsync(configurationSource).ConfigureAwait(false); if (foundIssue) { diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/AgentConnectivityCheck.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/AgentConnectivityCheck.cs index e6189d440a27..0297ecfcdd6f 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/AgentConnectivityCheck.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/AgentConnectivityCheck.cs @@ -20,9 +20,9 @@ namespace Datadog.Trace.Tools.dd_dotnet.Checks { internal class AgentConnectivityCheck { - public static Task RunAsync(ProcessInfo process) + public static Task RunAsync(IConfigurationSource? configurationSource) { - var settings = new ExporterSettings(process.Configuration); + var settings = new ExporterSettings(configurationSource); var url = settings.AgentUri.ToString(); diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/IRegistryService.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/IRegistryService.cs index 5bd3f2d2fa32..e0b92a730aa0 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/IRegistryService.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/IRegistryService.cs @@ -3,8 +3,6 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // -#nullable enable - namespace Datadog.Trace.Tools.dd_dotnet.Checks { internal interface IRegistryService diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Linux/ProcessEnvironmentLinux.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Linux/ProcessEnvironmentLinux.cs deleted file mode 100644 index bf1e45166624..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Linux/ProcessEnvironmentLinux.cs +++ /dev/null @@ -1,82 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Linux; - -internal class ProcessEnvironmentLinux -{ - public static IReadOnlyDictionary ReadVariables(Process process) - { - /* - /proc/[pid]/environ - This file contains the environment for the process. The entries are separated by - null bytes ('\0'), and there may be a null byte at the end. - */ - - var path = $"/proc/{process.Id}/environ"; - - var result = new Dictionary(); - - foreach (var line in File.ReadAllText(path).Split('\0', System.StringSplitOptions.RemoveEmptyEntries)) - { - var values = line.Split('=', 2); - result[values[0]] = values.Length > 1 ? values[1] : string.Empty; - } - - return result; - } - - public static string[] ReadModules(Process process) => ReadModulesFromFile($"/proc/{process.Id}/maps"); - - internal static string[] ReadModulesFromFile(string path) - { - /* - /proc/[pid]/maps - A file containing the currently mapped memory regions and their access permissions. - The format is: - - address perms offset dev inode pathname - 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm - 08056000-08058000 rw-p 0000d000 03:0c 64593 /usr/sbin/gpm - 08058000-0805b000 rwxp 00000000 00:00 0 - 40000000-40013000 r-xp 00000000 03:0c 4165 /lib/ld-2.2.4.so - 40013000-40015000 rw-p 00012000 03:0c 4165 /lib/ld-2.2.4.so - 4001f000-40135000 r-xp 00000000 03:0c 45494 /lib/libc-2.2.4.so - 40135000-4013e000 rw-p 00115000 03:0c 45494 /lib/libc-2.2.4.so - 4013e000-40142000 rw-p 00000000 00:00 0 - bffff000-c0000000 rwxp 00000000 00:00 0 - where "address" is the address space in the process that it occupies, "perms" is a set of permissions: - r = read - w = write - x = execute - s = shared - p = private (copy on write) - "offset" is the offset into the file/whatever, "dev" is the device (major:minor), and "inode" is the inode on that device. 0 indicates that no inode is associated with the memory region, as the case would be with BSS (uninitialized data). - Under Linux 2.0 there is no field giving pathname. - */ - - var modules = new HashSet(); - - foreach (var line in File.ReadAllLines(path)) - { - var values = line.Split(' ', 6, System.StringSplitOptions.RemoveEmptyEntries); - - if (values.Length != 6) - { - continue; - } - - modules.Add(values[5]); - } - - return modules.ToArray(); - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessBasicCheck.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessBasicCheck.cs index 15c12a794282..5a8545ad6b8d 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessBasicCheck.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessBasicCheck.cs @@ -2,7 +2,6 @@ // 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 2017 Datadog, Inc. // -#nullable enable using System; using System.Collections.Generic; @@ -11,6 +10,8 @@ using System.Linq; using System.Runtime.InteropServices; using Datadog.Trace.Tools.dd_dotnet.Checks.Windows; +using Datadog.Trace.Tools.Shared; +using Datadog.Trace.Tools.Shared.Windows; using Spectre.Console; using static Datadog.Trace.Tools.dd_dotnet.Checks.Resources; @@ -25,7 +26,6 @@ public static bool Run(ProcessInfo process, IRegistryService? registryService = { bool ok = true; var runtime = process.DotnetRuntime; - Version? nativeTracerVersion = null; if (runtime == ProcessInfo.Runtime.NetFx) { @@ -60,7 +60,7 @@ public static bool Run(ProcessInfo process, IRegistryService? registryService = // .so modules don't have version metadata if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - if (!Version.TryParse(FileVersionInfo.GetVersionInfo(nativeTracerModule).FileVersion, out nativeTracerVersion)) + if (!Version.TryParse(FileVersionInfo.GetVersionInfo(nativeTracerModule).FileVersion, out var nativeTracerVersion)) { nativeTracerVersion = null; } @@ -266,7 +266,7 @@ internal static bool CheckContinuousProfiler(ProcessInfo process, string? loader internal static bool CheckRegistry(string? tracerProgramVersion, IRegistryService? registry = null) { - registry ??= new Windows.RegistryService(); + registry ??= new RegistryService(); try { diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessConfiguration.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessConfiguration.cs new file mode 100644 index 000000000000..b91f15417d3d --- /dev/null +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessConfiguration.cs @@ -0,0 +1,55 @@ +// +// 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 2017 Datadog, Inc. +// + +using System; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Tools.Shared; + +namespace Datadog.Trace.Tools.dd_dotnet.Checks; + +internal static class ProcessConfiguration +{ + internal static IConfigurationSource ExtractConfigurationSource(this ProcessInfo process, string? baseDirectory, IReadOnlyDictionary? appSettings) + { + baseDirectory ??= Path.GetDirectoryName(process.MainModule); + + var configurationSource = new CompositeConfigurationSource(); + + configurationSource.Add(new DictionaryConfigurationSource(process.EnvironmentVariables)); + + if (appSettings != null) + { + configurationSource.Add(new DictionaryConfigurationSource(appSettings)); + } + else if (process.DotnetRuntime.HasFlag(ProcessInfo.Runtime.NetFx)) + { + IReadOnlyDictionary? appConfigSource = null; + + try + { + appConfigSource = process.LoadApplicationConfig(); + } + catch (Exception ex) + { + Utils.WriteError("Error while trying to load application configuration: " + ex.Message); + } + + if (appConfigSource != null) + { + configurationSource.Add(new DictionaryConfigurationSource(appConfigSource)); + } + } + + var jsonConfigurationSource = JsonConfigurationSource.TryLoadJsonConfigurationFile(configurationSource, baseDirectory); + + if (jsonConfigurationSource != null) + { + configurationSource.Add(jsonConfigurationSource); + } + + return configurationSource; + } +} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessEnvironment.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessEnvironment.cs deleted file mode 100644 index ef84347f5b7d..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/ProcessEnvironment.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Runtime.InteropServices; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks; - -internal class ProcessEnvironment -{ - public static IReadOnlyDictionary ReadVariables(Process process) - { - if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - return Windows.ProcessEnvironmentWindows.ReadVariables(process); - } - - if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) - { - return Linux.ProcessEnvironmentLinux.ReadVariables(process); - } - - throw new NotSupportedException("Reading environment variables is currently only supported on Windows and Linux."); - } - - public static string[] ReadModules(Process process) - { - if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) - { - // On Linux, Process.Modules does not list dynamically loaded assemblies: https://github.com/dotnet/runtime/issues/64042 - return Linux.ProcessEnvironmentLinux.ReadModules(process); - } - - var modules = process.Modules - .OfType() - .Select(p => p.FileName) - .Where(p => p != null) - .ToArray()!; - - if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - // On Windows, Process.Modules misses some dynamically loaded assemblies - return modules.Union(Windows.OpenFiles.GetOpenFiles(process.Id)).Distinct(StringComparer.OrdinalIgnoreCase).ToArray()!; - } - - return modules!; - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Resources.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Resources.cs index 2a47fe837f17..66032215aee2 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Resources.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Resources.cs @@ -24,7 +24,6 @@ internal static class Resources public const string IisProcess = "The target process is an IIS process. The detection of the configuration might be incomplete, it's recommended to use dd-trace check iis instead."; public const string MissingGac = "The Datadog.Trace assembly could not be found in the GAC. Make sure the tracer has been properly installed with the MSI."; public const string NoWorkerProcess = "No worker process found, to perform additional checks make sure the application is active"; - public const string GetProcessError = "Could not fetch information about target process. Make sure to run the command from an elevated prompt, and check that the pid is correct."; public const string IisNoIssue = "No issue found with the IIS site."; public const string IisMixedRuntimes = "The application pool is configured to host both .NET Framework and .NET Core runtimes. When hosting .NET Core, it's recommended to set '.NET CLR Version' to 'No managed code' to prevent conflict: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1#create-the-iis-site:~:text=CLR%20version%20to-,No%20Managed%20Code,-%3A"; public const string OutOfProcess = "Detected ASP.NET Core hosted out of proces. Trying to find the application process."; @@ -44,6 +43,8 @@ internal static class Resources public const string LdPreloadNotSet = "The environment variable LD_PRELOAD is not set. Check the Datadog .NET Profiler documentation to set it properly."; + public static string GetProcessError(string error) => $"Could not fetch information about target process: {error}. Make sure to run the command from an elevated prompt, and check that the pid is correct."; + public static string TracerNotEnabled(string value) => $"The value for DD_TRACE_ENABLED is set to {value}, to enable automatic tracing set it to true."; public static string ApiWrapperNotFound(string path) => $"The environment variable LD_PRELOAD is set to '{path}' but the file could not be found. Check the Datadog .NET Profiler documentation to set it properly."; diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/EnvironmentInfo.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/EnvironmentInfo.cs deleted file mode 100644 index 41e21a2c900b..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/EnvironmentInfo.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -using System; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - internal static class EnvironmentInfo - { - static EnvironmentInfo() - { - var os = Environment.OSVersion; - if (os.Platform == PlatformID.Win32NT && os.Version < new Version(6, 0)) - { - // Windows Server 2003 and Windows XP: The maximum size of the environment block for the process is 32,767 characters. - MaxSize = 32767; - } - else - { - // Starting with Windows Vista and Windows Server 2008, there is no technical limitation on the size of the environment block. - MaxSize = -1; - } - } - - /// - /// Gets the maximum environment block size or -1 if there is no limit. - /// - public static int MaxSize { get; } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IIS/IisManager.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IIS/IisManager.cs index 7589ab05d5f8..e30d0f034cfe 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IIS/IisManager.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IIS/IisManager.cs @@ -8,6 +8,7 @@ using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Threading; +using Datadog.Trace.Tools.Shared.Windows; namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows.IIS { diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IProcessMemoryAdapter.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IProcessMemoryAdapter.cs deleted file mode 100644 index 57d91ef3d8f8..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/IProcessMemoryAdapter.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - /// - /// Provides low-level access to the process memory. - /// - internal interface IProcessMemoryAdapter - { - /// - /// Gets the page size measured in bytes according to the granularity of memory access control. - /// - int PageSize { get; } - - /// - /// Reads the process memory. - /// - /// The address to start reading at. - /// The buffer to read to. - /// The buffer offset to start reading to. - /// The count of bytes to read. - /// - /// - /// Indicates whether to throw an exception on error. - /// - /// - /// The support of this flag is optional; an adapter may just prefer to return -1 even when the flag is true. - /// - /// - /// The count of read bytes or -1 on error. - int ReadMemory(UniPtr address, byte[] buffer, int offset, int count, bool throwOnError); - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessBinaryReader.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessBinaryReader.cs deleted file mode 100644 index 9a45c10d8f4b..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessBinaryReader.cs +++ /dev/null @@ -1,57 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -using System.IO; -using System.Text; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - internal sealed class ProcessBinaryReader : BinaryReader - { - public ProcessBinaryReader(Stream input, Encoding encoding) - : base(input, encoding) - { - } - - public string ReadCString() - { - var sb = new StringBuilder(); - - while (true) - { - int c = Read(); - if (c == -1) - { - throw new EndOfStreamException(); - } - - if (c == 0) - { - // End of string. - break; - } - - sb.Append((char)c); - } - - return sb.ToString(); - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryAdapter.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryAdapter.cs deleted file mode 100644 index a869e1dcb9b6..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryAdapter.cs +++ /dev/null @@ -1,80 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -using System; -using System.ComponentModel; -using System.Runtime.InteropServices; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - internal sealed class ProcessMemoryAdapter : IProcessMemoryAdapter - { - private readonly IntPtr _hProcess; - - public ProcessMemoryAdapter(IntPtr hProcess) - { - _hProcess = hProcess; - } - - public int PageSize => SystemInfo.PageSize; - - public unsafe int ReadMemory(UniPtr address, byte[] buffer, int offset, int count, bool throwOnError) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (offset + count > buffer.Length) - { - throw new ArgumentException(); - } - - var actualCount = IntPtr.Zero; - bool result; - - fixed (byte* p = buffer) - { - result = NativeMethods.ReadProcessMemory( - _hProcess, - address, - p + offset, - new IntPtr(count), - ref actualCount); - } - - if (!result) - { - if (throwOnError) - { - int error = Marshal.GetLastWin32Error(); - if (error != 0) - { - throw new Win32Exception(error); - } - } - - return -1; - } - - return actualCount.ToInt32(); - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryAdapterWow64.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryAdapterWow64.cs deleted file mode 100644 index 481004a86c23..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryAdapterWow64.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -using System; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - internal sealed class ProcessMemoryAdapterWow64 : IProcessMemoryAdapter - { - private readonly IntPtr _hProcess; - - public ProcessMemoryAdapterWow64(IntPtr hProcess) - { - _hProcess = hProcess; - } - - public int PageSize => SystemInfo.Native.PageSize; - - public unsafe int ReadMemory(UniPtr address, byte[] buffer, int offset, int count, bool throwOnError) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (offset + count > buffer.Length) - { - throw new ArgumentException(); - } - - long actualCount = 0; - int result; - - fixed (byte* p = buffer) - { - result = NativeMethods.NtWow64ReadVirtualMemory64( - _hProcess, - address.ToInt64(), - p + offset, - count, - ref actualCount); - } - - if (result != NativeMethods.STATUS_SUCCESS) - { - return -1; - } - - return (int)actualCount; - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryStream.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryStream.cs deleted file mode 100644 index 70c01625d55f..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/ProcessMemoryStream.cs +++ /dev/null @@ -1,161 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -using System; -using System.IO; - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - internal sealed class ProcessMemoryStream : Stream - { - private readonly IProcessMemoryAdapter _adapter; - private readonly UniPtr _baseAddress; - private readonly long _regionLength; - - private readonly uint _pageSize; - private readonly UniPtr _firstPageAddress; - - private long _position; - - public ProcessMemoryStream(IProcessMemoryAdapter adapter, UniPtr baseAddress, long regionLength) - { - _adapter = adapter; - _baseAddress = baseAddress; - _regionLength = regionLength; - - _pageSize = (uint)adapter.PageSize; - _firstPageAddress = GetPageLowerBound(baseAddress); - } - - public override bool CanRead => true; - - public override bool CanSeek => false; - - public override bool CanWrite => false; - - public override long Length - { - get - { - if (_regionLength == -1) - { - throw new NotSupportedException(); - } - - return _regionLength; - } - } - - public override long Position - { - get => _position; - set - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value)); - } - - _position = value; - } - } - - public override void Flush() - { - } - - public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); - - public override void SetLength(long value) => throw new NotSupportedException(); - - private UniPtr GetPageLowerBound(UniPtr address) - { - var pageSize = _pageSize; - return new UniPtr(address.ToUInt64() / pageSize * pageSize); - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (offset + count > buffer.Length) - { - throw new ArgumentException(); - } - - int totalCount = 0; - do - { - var addr = _baseAddress + _position; - - var pageStart = GetPageLowerBound(addr); - var pageEnd = pageStart + _pageSize; - - int currentCount = count; - - var remainingPageSize = pageEnd.ToUInt64() - addr.ToUInt64(); - if ((ulong)currentCount > remainingPageSize) - { - currentCount = (int)remainingPageSize; - } - - var regionLength = _regionLength; - if (regionLength != -1) - { - long remainingRegionLength = regionLength - _position; - if (currentCount > remainingRegionLength) - { - currentCount = (int)remainingRegionLength; - } - } - - if (currentCount == 0) - { - // EOF - return totalCount; - } - - bool throwOnError = pageStart == _firstPageAddress; - - int r = _adapter.ReadMemory(addr, buffer, offset, currentCount, throwOnError); - if (r <= 0) - { - if (throwOnError) - { - // In case if process memory adapter disregards a throw on error flag. - throw new IOException(); - } - - // Assume EOF. - break; - } - - count -= r; - offset += r; - totalCount += r; - - _position += r; - } - while (count > 0); - - return totalCount; - } - - public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/SystemInfo.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/SystemInfo.cs deleted file mode 100644 index f50b5313186b..000000000000 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Checks/Windows/SystemInfo.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -// Original code from https://github.com/gapotchenko/Gapotchenko.FX/tree/master/Source/Gapotchenko.FX.Diagnostics.Process -// MIT License -// -// Copyright © 2019 Gapotchenko and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -namespace Datadog.Trace.Tools.dd_dotnet.Checks.Windows -{ - internal static class SystemInfo - { - static SystemInfo() - { - NativeMethods.GetSystemInfo(out var systemInfo); - PageSize = checked((int)systemInfo.dwPageSize); - } - - public static int PageSize { get; } - - public static class Native - { - static Native() - { - NativeMethods.GetNativeSystemInfo(out var systemInfo); - PageSize = checked((int)systemInfo.dwPageSize); - } - - public static int PageSize { get; } - } - } -} diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CommandWithExamples.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CommandWithExamples.cs index a258017c153a..85c4a8680da2 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/CommandWithExamples.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/CommandWithExamples.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.CommandLine; using System.CommandLine.Help; +using System.IO; namespace Datadog.Trace.Tools.dd_dotnet; @@ -19,6 +20,10 @@ public CommandWithExamples(string name, string? description = null) { } + public static string Command => + Environment.GetEnvironmentVariable("DD_INTERNAL_OVERRIDE_COMMAND") + ?? Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]); + public IReadOnlyList Examples => _examples; public static HelpSectionDelegate ExamplesSection() @@ -41,6 +46,6 @@ static void GenerateExamplesSection(HelpContext context) public void AddExample(string example) { - _examples.Add(example); + _examples.Add($"{Command} {example}"); } } diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj index 1b737464eef7..ac30e4e22f54 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Datadog.Trace.Tools.dd_dotnet.csproj @@ -76,6 +76,7 @@ + diff --git a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Program.cs b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Program.cs index 8953f9def5a6..2412f8be3c66 100644 --- a/tracer/src/Datadog.Trace.Tools.dd_dotnet/Program.cs +++ b/tracer/src/Datadog.Trace.Tools.dd_dotnet/Program.cs @@ -40,7 +40,7 @@ IEnumerable GetLayout(HelpContext context) var localizationResources = new CustomLocalizationResources(); - var rootCommand = new CommandWithExamples("dd-trace"); + var rootCommand = new CommandWithExamples(CommandWithExamples.Command); var builder = new CommandLineBuilder(rootCommand) .UseLocalizationResources(localizationResources) @@ -55,9 +55,9 @@ IEnumerable GetLayout(HelpContext context) return helpBuilder; }); - rootCommand.AddExample("dd-dotnet run --dd-env prod -- myApp --argument-for-my-app"); - rootCommand.AddExample("dd-dotnet check process "); - rootCommand.AddExample("dd-dotnet check iis "); + rootCommand.AddExample("run --dd-env prod -- myApp --argument-for-my-app"); + rootCommand.AddExample("check process "); + rootCommand.AddExample("check iis "); var checkCommand = new Command("check"); builder.Command.AddCommand(checkCommand); diff --git a/tracer/src/Datadog.Trace/DuckTyping/DuckType.cs b/tracer/src/Datadog.Trace/DuckTyping/DuckType.cs index 3672368a00e8..20f0e3932e2f 100644 --- a/tracer/src/Datadog.Trace/DuckTyping/DuckType.cs +++ b/tracer/src/Datadog.Trace/DuckTyping/DuckType.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using System.Reflection; using System.Reflection.Emit; @@ -374,10 +375,18 @@ private static ModuleBuilder CreateTypeAndModuleBuilder(Type typeToDeriveFrom, T assembly = assembly.Replace(".", "_").Replace("+", "__"); } - // Create a valid type name that can be used as a member of a class. (BenchmarkDotNet fails if is an invalid name) - string proxyTypeName = $"{assembly}.{typeToDelegateTo.FullName?.Replace(".", "_").Replace("+", "__")}.{typeToDeriveFrom.FullName?.Replace(".", "_").Replace("+", "__")}_{++_typeCount}"; + // Create a "valid" type name (doesn't always hold) that can be used as a member of a class. (BenchmarkDotNet fails if is an invalid name) + // The name we generate here is primarily for debugging purposes (stack traces etc), so we don't try too hard + var proxyTypeNameSuffix = $"_{(++_typeCount).ToString(CultureInfo.InvariantCulture)}"; + var proxyTypeNamePrefix = $"{assembly}.{typeToDelegateTo.FullName?.Replace(".", "_").Replace("+", "__")}.{typeToDeriveFrom.FullName?.Replace(".", "_").Replace("+", "__")}"; + + // the maximum length for an assembly-qualified type name is 1024, so we need to account for that + var maxPrefixSize = 1023 - proxyTypeNameSuffix.Length; + var proxyTypeName = (proxyTypeNamePrefix.Length > maxPrefixSize + ? proxyTypeNamePrefix.Substring(0, maxPrefixSize) + : proxyTypeNamePrefix) + + proxyTypeNameSuffix; - // Create Type proxyTypeBuilder = moduleBuilder.DefineType( proxyTypeName, typeAttributes, diff --git a/tracer/test/Datadog.Trace.DuckTyping.Tests/LongTypeNameTests.cs b/tracer/test/Datadog.Trace.DuckTyping.Tests/LongTypeNameTests.cs new file mode 100644 index 000000000000..96b66c9bb68c --- /dev/null +++ b/tracer/test/Datadog.Trace.DuckTyping.Tests/LongTypeNameTests.cs @@ -0,0 +1,150 @@ +// +// 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 2017 Datadog, Inc. +// + +using FluentAssertions; +using Xunit; + +#pragma warning disable SA1201 // Elements must appear in the correct order +#pragma warning disable SA1402 // File may only contain a single class +#pragma warning disable SA1403 // file may only contain one namespace + +namespace Datadog.Trace.DuckTyping.Tests +{ + public class LongTypeNameTests + { + public const string ExpectedValue = "It works!"; + + [Fact] + public void CanDuckTypeLongNamedTypes() + { + // We saw this in an escalation + // Type name was too long. The fully qualified type name must be less than 1,024 characters + // Note that this limitation doesn't include the length of any parent classes for nested types + // or the length of the assembly name + const int maxTypeNameSize = 1024; + + var originalTestCase = new Grpc.AspNetCore.Server.Internal.CallHandlers.UnaryServerCallHandler< + SomeNamespace.ThatIsPrettyLong.Ish.Services.ProductSecretValuesServiceImpl< + SomeNamespace.ThatIsPrettyLong.Ish.Data.Infrastructure.Database.Connection.DatabaseConnectionHandle, + SomeNamespace.ThatIsPrettyLong.Ish.Data.Infrastructure.Database.Transaction.DatabaseTransactionHandle>, + SomeNamespace.ThatIsPrettyLong.Ish.Services.SomeBigProductThing.GetSuperSecretWossnameToHandleThisNewRequest, + SomeNamespace.ThatIsPrettyLong.Ish.Services.SomeBigProductThing.ThisTestWossnameResponse>(); + + var longGeneric = new MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse< + MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse>>>>>>>>>>>>>>(); + + // We can't create a type which has a "raw" name longer than 1024 (doesn't compile) + // But this will mean will still need to do some truncation when creating the type + var javaStyle = new CreatingSomeNestingToMakeThingsEvenWorse.MyTargetTypeThatHasAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongName(); + + longGeneric.GetType().FullName!.Length.Should().BeGreaterThan(maxTypeNameSize); + originalTestCase.GetType().FullName!.Length.Should().BeGreaterThan(maxTypeNameSize); + + // original test case + var interfaceProxy = originalTestCase.DuckCast(); + interfaceProxy.Value.Should().Be(ExpectedValue); + + var structProxy = longGeneric.DuckCast(); + structProxy.Value.Should().Be(ExpectedValue); + + // long generic + interfaceProxy = longGeneric.DuckCast(); + interfaceProxy.Value.Should().Be(ExpectedValue); + + structProxy = longGeneric.DuckCast(); + structProxy.Value.Should().Be(ExpectedValue); + + // javaStyle + interfaceProxy = javaStyle.DuckCast(); + interfaceProxy.Value.Should().Be(ExpectedValue); + + structProxy = javaStyle.DuckCast(); + structProxy.Value.Should().Be(ExpectedValue); + } + + public class MyTargetTypeThatHasAReallyReallyReallyLongNameAndIsGenericToMakeItWorse + { + public string Value => ExpectedValue; + } + + public class CreatingSomeNestingToMakeThingsEvenWorse + { + public class MyTargetTypeThatHasAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongName + { + public string Value => ExpectedValue; + } + } + + public interface ILongNamedTypeProxy + { + public string Value { get; } + } + + [DuckCopy] + public struct LongNamedTypeProxy + { + public string Value; + } + } +} + +namespace Grpc.AspNetCore.Server.Internal.CallHandlers +{ + public class UnaryServerCallHandler + { + public string Value => Datadog.Trace.DuckTyping.Tests.LongTypeNameTests.ExpectedValue; + } +} + +namespace SomeNamespace.ThatIsPrettyLong.Ish +{ + namespace Services + { + public class ProductSecretValuesServiceImpl + { + } + + namespace SomeBigProductThing + { + public class GetSuperSecretWossnameToHandleThisNewRequest + { + } + + public class ThisTestWossnameResponse + { + } + } + } + + namespace Data.Infrastructure.Database + { + public class Connection + { + public class DatabaseConnectionHandle + { + } + } + + public class Transaction + { + public class DatabaseTransactionHandle + { + } + } + } +} diff --git a/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/CheckCommandTests.cs b/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/CheckCommandTests.cs new file mode 100644 index 000000000000..ff278ad85d32 --- /dev/null +++ b/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/CheckCommandTests.cs @@ -0,0 +1,25 @@ +// +// 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 2017 Datadog, Inc. +// + +using FluentAssertions; +using Xunit; + +namespace Datadog.Trace.Tools.Runner.ArtifactTests; + +public class CheckCommandTests : RunnerTests +{ + [Fact] + public void Help() + { + using var helper = StartProcess("check"); + + helper.Process.WaitForExit(); + helper.Drain(); + + helper.Process.ExitCode.Should().Be(1); + helper.StandardOutput.Should().Contain("dd-trace check [command] [options]"); + helper.ErrorOutput.Should().Contain("Required command was not provided."); + } +} diff --git a/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/LegacyCommandLineArgumentsTests.cs b/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/LegacyCommandLineArgumentsTests.cs index f57c49988623..7455ae999686 100644 --- a/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/LegacyCommandLineArgumentsTests.cs +++ b/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/LegacyCommandLineArgumentsTests.cs @@ -5,9 +5,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Runtime.InteropServices; using System.Text.RegularExpressions; using Datadog.Trace.TestHelpers; using FluentAssertions; @@ -18,7 +16,7 @@ namespace Datadog.Trace.Tools.Runner.ArtifactTests { [CollectionDefinition(nameof(LegacyCommandLineArgumentsTests), DisableParallelization = true)] [Collection(nameof(LegacyCommandLineArgumentsTests))] - public class LegacyCommandLineArgumentsTests + public class LegacyCommandLineArgumentsTests : RunnerTests { [Fact] public void InvalidArgument() @@ -86,23 +84,6 @@ public void LocateTracerHome() helper.ErrorOutput.Should().BeEmpty(); } - private static string GetRunnerToolTargetFolder() - { - var folder = Environment.GetEnvironmentVariable("ToolInstallDirectory"); - - if (string.IsNullOrEmpty(folder)) - { - folder = Path.Combine( - EnvironmentTools.GetSolutionDirectory(), - "tracer", - "bin", - "runnerTool", - "installed"); - } - - return folder; - } - private static AssertionScope StartAssertionScope(ProcessHelper processHelper) { var scope = new AssertionScope(); @@ -113,24 +94,5 @@ private static AssertionScope StartAssertionScope(ProcessHelper processHelper) return scope; } - - private ProcessHelper StartProcess(string arguments, params (string Key, string Value)[] environmentVariables) - { - var targetFolder = GetRunnerToolTargetFolder(); - var executable = Path.Combine(targetFolder, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dd-trace.exe" : "dd-trace"); - - var processStart = new ProcessStartInfo(executable, arguments) - { - RedirectStandardError = true, - RedirectStandardOutput = true - }; - - foreach (var (key, value) in environmentVariables) - { - processStart.EnvironmentVariables[key] = value; - } - - return new ProcessHelper(Process.Start(processStart)); - } } } diff --git a/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/RunnerTests.cs b/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/RunnerTests.cs new file mode 100644 index 000000000000..0862062d3278 --- /dev/null +++ b/tracer/test/Datadog.Trace.Tools.Runner.ArtifactTests/RunnerTests.cs @@ -0,0 +1,51 @@ +// +// 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 2017 Datadog, Inc. +// + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using Datadog.Trace.TestHelpers; + +namespace Datadog.Trace.Tools.Runner.ArtifactTests; + +public abstract class RunnerTests +{ + protected ProcessHelper StartProcess(string arguments, params (string Key, string Value)[] environmentVariables) + { + var targetFolder = GetRunnerToolTargetFolder(); + var executable = Path.Combine(targetFolder, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "dd-trace.exe" : "dd-trace"); + + var processStart = new ProcessStartInfo(executable, arguments) + { + RedirectStandardError = true, + RedirectStandardOutput = true + }; + + foreach (var (key, value) in environmentVariables) + { + processStart.EnvironmentVariables[key] = value; + } + + return new ProcessHelper(Process.Start(processStart)); + } + + private static string GetRunnerToolTargetFolder() + { + var folder = Environment.GetEnvironmentVariable("ToolInstallDirectory"); + + if (string.IsNullOrEmpty(folder)) + { + folder = Path.Combine( + EnvironmentTools.GetSolutionDirectory(), + "tracer", + "bin", + "runnerTool", + "installed"); + } + + return folder; + } +} diff --git a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/AgentConnectivityCheckTests.cs b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/AgentConnectivityCheckTests.cs deleted file mode 100644 index 3e13503b3059..000000000000 --- a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/AgentConnectivityCheckTests.cs +++ /dev/null @@ -1,198 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// -#nullable enable - -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Threading.Tasks; -using Datadog.Trace.Configuration; -using Datadog.Trace.TestHelpers; -using Datadog.Trace.Tools.Runner.Checks; -using FluentAssertions; -using FluentAssertions.Execution; -using Xunit; -using Xunit.Abstractions; - -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner.IntegrationTests.Checks -{ - [Collection(nameof(ConsoleTestsCollection))] - public class AgentConnectivityCheckTests : ConsoleTestHelper - { - public AgentConnectivityCheckTests(ITestOutputHelper output) - : base(output) - { - } - - public static IEnumerable TestData => new List - { - new object[] { new[] { ("DD_TRACE_AGENT_URL", "http://fakeurl:7777/") } }, - new object[] { new[] { ("DD_AGENT_HOST", "fakeurl"), ("DD_TRACE_AGENT_PORT", "7777") } }, - new object[] { new[] { ("DD_AGENT_HOST", "wrong"), ("DD_TRACE_AGENT_PORT", "1111"), ("DD_TRACE_AGENT_URL", "http://fakeurl:7777/") } }, - }; - - [SkippableTheory] - [Trait("RunOnWindows", "True")] - [MemberData(nameof(TestData))] - public async Task DetectAgentUrl((string, string)[] environmentVariables) - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole(enableProfiler: false, environmentVariables); - - using var console = ConsoleHelper.Redirect(); - - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - _ = await AgentConnectivityCheck.RunAsync(processInfo!); - - console.Output.Should().Contain(DetectedAgentUrlFormat("http://fakeurl:7777/")); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task DetectTransportHttp() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var agent = MockTracerAgent.Create(Output, TcpPortProvider.GetOpenPort()); - - var url = $"http://127.0.0.1:{agent.Port}/"; - - using var helper = await StartConsole(enableProfiler: false, ("DD_TRACE_AGENT_URL", url)); - - using var console = ConsoleHelper.Redirect(); - - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - _ = await AgentConnectivityCheck.RunAsync(processInfo!); - - console.Output.Should().Contain(ConnectToEndpointFormat(url, "HTTP")); - } - -#if NETCOREAPP3_1_OR_GREATER - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task DetectTransportUds() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - var tracesUdsPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var url = $"unix://{tracesUdsPath}"; - var uri = new System.Uri(url); - - using var agent = MockTracerAgent.Create(Output, new UnixDomainSocketConfig(tracesUdsPath, null)); - using var helper = await StartConsole(enableProfiler: false, ("DD_TRACE_AGENT_URL", url)); - using var console = ConsoleHelper.Redirect(); - - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - _ = await AgentConnectivityCheck.RunAsync(processInfo!); - - console.Output.Should().Contain(ConnectToEndpointFormat(uri.PathAndQuery, "domain sockets")); - } -#endif - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task NoAgent() - { - using var console = ConsoleHelper.Redirect(); - - var result = await AgentConnectivityCheck.RunAsync(CreateSettings("http://fakeurl/")); - - result.Should().BeFalse(); - - // Note for future maintainers: this assertion needs to be changed to something smarter - // if the error message stops being at the end of the string - console.Output.Should().Contain(ErrorDetectingAgent("http://fakeurl/", string.Empty)); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task FaultyAgent() - { - using var console = ConsoleHelper.Redirect(); - - using var agent = MockTracerAgent.Create(Output, TcpPortProvider.GetOpenPort()); - - agent.RequestReceived += (_, e) => e.Value.Response.StatusCode = (int)HttpStatusCode.InternalServerError; - - var result = await AgentConnectivityCheck.RunAsync(CreateSettings($"http://localhost:{agent.Port}/")); - - result.Should().BeFalse(); - - console.Output.Should().Contain(WrongStatusCodeFormat(HttpStatusCode.InternalServerError)); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task DetectVersion() - { - const string expectedVersion = "7.66.55"; - - using var console = ConsoleHelper.Redirect(); - - using var agent = MockTracerAgent.Create(Output, TcpPortProvider.GetOpenPort()); - agent.Version = expectedVersion; - - var result = await AgentConnectivityCheck.RunAsync(CreateSettings($"http://localhost:{agent.Port}/")); - - result.Should().BeTrue(); - - console.Output.Should().Contain(DetectedAgentVersionFormat(expectedVersion)); - } - -#if NETCOREAPP3_1_OR_GREATER - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task DetectVersionUds() - { - const string expectedVersion = "7.66.55"; - - using var console = ConsoleHelper.Redirect(); - - var tracesUdsPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - - using var agent = MockTracerAgent.Create(Output, new UnixDomainSocketConfig(tracesUdsPath, null)); - agent.Version = expectedVersion; - - var settings = new ExporterSettings - { - AgentUri = new System.Uri($"unix://{tracesUdsPath}"), - }; - - var result = await AgentConnectivityCheck.RunAsync(new ImmutableExporterSettings(settings)); - - result.Should().BeTrue(); - - console.Output.Should().Contain(DetectedAgentVersionFormat(expectedVersion)); - } -#endif - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task NoVersion() - { - using var console = ConsoleHelper.Redirect(); - - using var agent = MockTracerAgent.Create(Output, TcpPortProvider.GetOpenPort()); - agent.Version = null; - - var result = await AgentConnectivityCheck.RunAsync(CreateSettings($"http://localhost:{agent.Port}/")); - - result.Should().BeTrue(); - - console.Output.Should().Contain(AgentDetectionFailed); - } - - private static ImmutableExporterSettings CreateSettings(string url) => new(new ExporterSettings { AgentUri = new(url) }); - } -} diff --git a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/ConsoleTestHelper.cs b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/ConsoleTestHelper.cs deleted file mode 100644 index 3fac9bfcf414..000000000000 --- a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/ConsoleTestHelper.cs +++ /dev/null @@ -1,107 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -#nullable enable - -using System; -using System.Diagnostics; -using System.Threading.Tasks; -using Datadog.Trace.TestHelpers; -using Xunit.Abstractions; - -namespace Datadog.Trace.Tools.Runner.IntegrationTests.Checks -{ - public abstract class ConsoleTestHelper : TestHelper - { - protected ConsoleTestHelper(ITestOutputHelper output) - : base("Console", output) - { - } - - protected Task StartConsole(bool enableProfiler, params (string Key, string Value)[] environmentVariables) - { - return StartConsole(EnvironmentHelper, enableProfiler, environmentVariables); - } - - protected async Task StartConsole(EnvironmentHelper environmentHelper, bool enableProfiler, params (string Key, string Value)[] environmentVariables) - { - string sampleAppPath = environmentHelper.GetSampleApplicationPath(); - var executable = EnvironmentHelper.IsCoreClr() ? environmentHelper.GetSampleExecutionSource() : sampleAppPath; - var args = EnvironmentHelper.IsCoreClr() ? $"{sampleAppPath} wait" : "wait"; - - var processStart = new ProcessStartInfo(executable, args) - { - UseShellExecute = false, - RedirectStandardError = true, - RedirectStandardOutput = true - }; - - MockTracerAgent? agent = null; - - if (enableProfiler) - { - agent = MockTracerAgent.Create(Output); - - environmentHelper.SetEnvironmentVariables( - agent, - aspNetCorePort: 1000, - processStart.Environment); - } - - foreach (var (key, value) in environmentVariables) - { - processStart.EnvironmentVariables[key] = value; - } - - var startedTask = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - Action callback = s => - { - if (s.StartsWith("Waiting")) - { - startedTask.TrySetResult(true); - } - }; - - var helper = new CustomProcessHelper(agent, Process.Start(processStart)!, callback); - - var completed = await Task.WhenAny( - helper.Task, - startedTask.Task, - Task.Delay(TimeSpan.FromSeconds(10))); - - if (completed == startedTask.Task) - { - return helper; - } - - helper.Dispose(); - - if (completed == helper.Task) - { - throw new Exception("The target process unexpectedly exited"); - } - - throw new TimeoutException("Timeout when waiting for the target process to start"); - } - - private class CustomProcessHelper : ProcessHelper - { - private readonly MockTracerAgent? _agent; - - public CustomProcessHelper(MockTracerAgent? agent, Process process, Action? onDataReceived = null) - : base(process, onDataReceived) - { - _agent = agent; - } - - public override void Dispose() - { - base.Dispose(); - _agent?.Dispose(); - } - } - } -} diff --git a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/IisCheckTests.cs b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/IisCheckTests.cs deleted file mode 100644 index fbb63f8ecfb0..000000000000 --- a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/IisCheckTests.cs +++ /dev/null @@ -1,271 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -#if NETCOREAPP3_1 - -using System; -using System.Diagnostics; -using System.IO; -using System.Net.Http; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using Datadog.Trace.TestHelpers; -using Datadog.Trace.Tools.Runner.Checks; -using FluentAssertions; -using Moq; -using Xunit; -using Xunit.Abstractions; - -namespace Datadog.Trace.Tools.Runner.IntegrationTests.Checks -{ - [Collection(nameof(ConsoleTestsCollection))] - public class IisCheckTests : TestHelper - { - public IisCheckTests(ITestOutputHelper output) - : base("AspNetCoreMvc31", output) - { - } - - [SkippableTheory] - [Trait("RunOnWindows", "True")] - [InlineData(true)] - [InlineData(false)] - public async Task WorkingApp(bool mixedRuntimes) - { - EnsureWindowsAndX64(); - - var siteName = mixedRuntimes ? "sample/mixed" : "sample"; - - var buildPs1 = Path.Combine(EnvironmentTools.GetSolutionDirectory(), "tracer", "build.ps1"); - - try - { - // GacFixture is not compatible with .NET Core, use the Nuke target instead - Process.Start("powershell", $"{buildPs1} GacAdd --framework net461").WaitForExit(); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreInProcess); - - using var console = ConsoleHelper.Redirect(); - - var result = await CheckIisCommand.ExecuteAsync( - siteName, - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(0); - - if (mixedRuntimes) - { - console.Output.Should().Contain(Resources.IisMixedRuntimes); - } - - console.Output.Should().Contain(Resources.IisNoIssue); - } - finally - { - Process.Start("powershell", $"{buildPs1} GacRemove --framework net461").WaitForExit(); - } - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task NestedApp() - { - EnsureWindowsAndX64(); - - var siteName = "sample/nested/app"; - - var buildPs1 = Path.Combine(EnvironmentTools.GetSolutionDirectory(), "tracer", "build.ps1"); - - try - { - // GacFixture is not compatible with .NET Core, use the Nuke target instead - Process.Start("powershell", $"{buildPs1} GacAdd --framework net461").WaitForExit(); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreInProcess); - - using var console = ConsoleHelper.Redirect(); - - var result = await CheckIisCommand.ExecuteAsync( - siteName, - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(0); - - console.Output.Should().Contain(Resources.IisNoIssue); - } - finally - { - Process.Start("powershell", $"{buildPs1} GacRemove --framework net461").WaitForExit(); - } - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task OutOfProcess() - { - EnsureWindowsAndX64(); - - var buildPs1 = Path.Combine(EnvironmentTools.GetSolutionDirectory(), "tracer", "build.ps1"); - - try - { - // GacFixture is not compatible with .NET Core, use the Nuke target instead - Process.Start("powershell", $"{buildPs1} GacAdd --framework net461").WaitForExit(); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreOutOfProcess); - - using var console = ConsoleHelper.Redirect(); - - var result = await CheckIisCommand.ExecuteAsync( - "sample", - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(0); - - console.Output.Should().Contain(Resources.OutOfProcess); - console.Output.Should().NotContain(Resources.AspNetCoreProcessNotFound); - console.Output.Should().Contain(Resources.IisNoIssue); - } - finally - { - Process.Start("powershell", $"{buildPs1} GacRemove --framework net461").WaitForExit(); - } - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task NoGac() - { - EnsureWindowsAndX64(); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreInProcess); - - using var console = ConsoleHelper.Redirect(); - - var result = await CheckIisCommand.ExecuteAsync( - "sample", - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(1); - - console.Output.Should().Contain(Resources.MissingGac); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task ListSites() - { - EnsureWindowsAndX64(); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreInProcess); - - using var console = ConsoleHelper.Redirect(); - - var result = await CheckIisCommand.ExecuteAsync( - "dummySite", - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(1); - - console.Output.Should().Contain(Resources.CouldNotFindIisApplication("dummySite", "/")); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task ListApplications() - { - EnsureWindowsAndX64(); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreInProcess); - - using var console = ConsoleHelper.Redirect(); - - var result = await CheckIisCommand.ExecuteAsync( - "sample/dummy", - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(1); - - console.Output.Should().Contain(Resources.CouldNotFindIisApplication("sample", "/dummy")); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task IncorrectlyConfiguredAppPool() - { - EnsureWindowsAndX64(); - - EnvironmentHelper.SetAutomaticInstrumentation(false); - - using var iisFixture = await StartIis(IisAppType.AspNetCoreInProcess); - using var console = ConsoleHelper.Redirect(); - var result = await CheckIisCommand.ExecuteAsync( - "sample", - iisFixture.IisExpress.ConfigFile, - iisFixture.IisExpress.Process.Id, - MockRegistryService()); - - result.Should().Be(1); - console.Output.Should().Contain(Resources.AppPoolCheckFindings("applicationPoolDefaults")); - console.Output.Should().Contain(Resources.WrongEnvironmentVariableFormat("COR_ENABLE_PROFILING", "1", "0")); - console.Output.Should().Contain(Resources.WrongEnvironmentVariableFormat("CORECLR_ENABLE_PROFILING", "1", "0")); - } - - private static void EnsureWindowsAndX64() - { - if (!RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows) - || IntPtr.Size != 8) - { - throw new SkipException(); - } - } - - private static IRegistryService MockRegistryService() - { - var registryService = new Mock(); - registryService.Setup(r => r.GetLocalMachineValueNames(It.Is(@"SOFTWARE\Microsoft\.NETFramework", StringComparer.Ordinal))) - .Returns(Array.Empty()); - registryService.Setup(r => r.GetLocalMachineValue(It.Is(s => s == ProcessBasicChecksTests.ClsidKey || s == ProcessBasicChecksTests.Clsid32Key))) - .Returns(EnvironmentHelper.GetNativeLoaderPath()); - - return registryService.Object; - } - - private async Task StartIis(IisAppType appType) - { - var fixture = new IisFixture { ShutdownPath = "/shutdown" }; - - try - { - fixture.TryStartIis(this, appType); - } - catch (Exception) - { - fixture.Dispose(); - throw; - } - - // Send a request to initialize the app - using var httpClient = new HttpClient(); - await httpClient.GetAsync($"http://localhost:{fixture.HttpPort}/"); - - return fixture; - } - } -} - -#endif diff --git a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/ProcessBasicChecksTests.cs b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/ProcessBasicChecksTests.cs deleted file mode 100644 index 10149ce6f810..000000000000 --- a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Checks/ProcessBasicChecksTests.cs +++ /dev/null @@ -1,490 +0,0 @@ -// -// 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 2017 Datadog, Inc. -// - -using System; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using Datadog.Trace.TestHelpers; -using Datadog.Trace.Tools.Runner.Checks; -using FluentAssertions; -using FluentAssertions.Execution; -using Moq; -using Xunit; -using Xunit.Abstractions; -using static System.IO.DirectoryInfo; -using static Datadog.Trace.Tools.Runner.Checks.Resources; - -namespace Datadog.Trace.Tools.Runner.IntegrationTests.Checks -{ - [Collection(nameof(ConsoleTestsCollection))] - public class ProcessBasicChecksTests : ConsoleTestHelper - { - internal const string ClsidKey = @"SOFTWARE\Classes\CLSID\{846F5F1C-F9AE-4B07-969E-05C26BC060D8}\InprocServer32"; - internal const string Clsid32Key = @"SOFTWARE\Classes\Wow6432Node\CLSID\{846F5F1C-F9AE-4B07-969E-05C26BC060D8}\InprocServer32"; -#if NET_FRAMEWORK - private const string CorProfilerKey = "COR_PROFILER"; - private const string CorProfilerPathKey = "COR_PROFILER_PATH"; - private const string CorProfilerPath32Key = "COR_PROFILER_PATH_32"; - private const string CorProfilerPath64Key = "COR_PROFILER_PATH_64"; - private const string CorEnableKey = "COR_ENABLE_PROFILING"; -#else - private const string CorProfilerKey = "CORECLR_PROFILER"; - private const string CorProfilerPathKey = "CORECLR_PROFILER_PATH"; - private const string CorProfilerPath32Key = "CORECLR_PROFILER_PATH_32"; - private const string CorProfilerPath64Key = "CORECLR_PROFILER_PATH_64"; - private const string CorEnableKey = "CORECLR_ENABLE_PROFILING"; -#endif - - private static readonly string ProfilerPath = EnvironmentHelper.GetNativeLoaderPath(); - - public ProcessBasicChecksTests(ITestOutputHelper output) - : base(output) - { - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task DetectRuntime() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole(enableProfiler: false); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - -#if NET_FRAMEWORK - const string expectedOutput = NetFrameworkRuntime; -#else - const string expectedOutput = NetCoreRuntime; -#endif - - console.Output.Should().Contain(expectedOutput); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task VersionConflict1X() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - var environmentHelper = new EnvironmentHelper("VersionConflict.1x", typeof(TestHelper), Output); - using var helper = await StartConsole(environmentHelper, enableProfiler: true); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - result.Should().BeFalse(); - - console.Output.Should().Contain(VersionConflict); - - console.Output.Should().Contain(MultipleTracers(new[] { "1.29.0.0", TracerConstants.AssemblyVersion })); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task NoEnvironmentVariables() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole(enableProfiler: false); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - result.Should().BeFalse(); - - console.Output.Should().ContainAll( - LoaderNotLoaded, - NativeTracerNotLoaded, - TracerNotLoaded, - EnvironmentVariableNotSet("DD_DOTNET_TRACER_HOME"), - WrongEnvironmentVariableFormat(CorProfilerKey, Utils.Profilerid, null), - WrongEnvironmentVariableFormat(CorEnableKey, "1", null)); - - if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) - { - // The variable is not required on Windows because the path is set through the registry - console.Output.Should().NotContain(EnvironmentVariableNotSet(CorProfilerPathKey)); - } - else - { - console.Output.Should().Contain(EnvironmentVariableNotSet(CorProfilerPathKey)); - } - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task WrongEnvironmentVariables() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole( - enableProfiler: false, - ("DD_PROFILING_ENABLED", "1"), - ("DD_DOTNET_TRACER_HOME", "TheDirectoryDoesNotExist"), - (CorProfilerKey, Guid.Empty.ToString("B")), - (CorEnableKey, "0"), - (CorProfilerPathKey, "dummyPath"), - (CorProfilerPath32Key, "dummyPath"), - (CorProfilerPath64Key, "dummyPath")); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - result.Should().BeFalse(); - - console.Output.Should().ContainAll( - LoaderNotLoaded, - NativeTracerNotLoaded, - TracerNotLoaded, - TracerHomeNotFoundFormat("TheDirectoryDoesNotExist"), - WrongEnvironmentVariableFormat(CorProfilerKey, Utils.Profilerid, Guid.Empty.ToString("B")), - WrongEnvironmentVariableFormat(CorEnableKey, "1", "0"), - MissingProfilerEnvironment(CorProfilerPathKey, "dummyPath"), - WrongProfilerEnvironment(CorProfilerPathKey, "dummyPath"), - MissingProfilerEnvironment(CorProfilerPath32Key, "dummyPath"), - WrongProfilerEnvironment(CorProfilerPath32Key, "dummyPath"), - MissingProfilerEnvironment(CorProfilerPath64Key, "dummyPath"), - WrongProfilerEnvironment(CorProfilerPath64Key, "dummyPath"), - TracingWithInstaller); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public async Task Working() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole(enableProfiler: true); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - using var scope = new AssertionScope(); - scope.AddReportable("Output", console.Output); - - result.Should().BeTrue(); - - console.Output.Should().Contain( - TracerVersion(TracerConstants.AssemblyVersion), - ContinuousProfilerNotSet); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - console.Output.Should().Contain(ProfilerVersion(TracerConstants.AssemblyVersion)); - } - - console.Output.Should().NotContainAny( - NativeTracerNotLoaded, - TracerNotLoaded, - "DD_DOTNET_TRACER_HOME", - CorProfilerKey, - CorEnableKey, - CorProfilerPathKey, - CorProfilerPath32Key, - CorProfilerPath64Key); - } - - [SkippableFact] - public async Task WorkingWithContinuousProfiler() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - string archFolder; - - if (FrameworkDescription.Instance.ProcessArchitecture == ProcessArchitecture.Arm64) - { - archFolder = "linux-arm64"; - } - else - { - archFolder = Utils.IsAlpine() ? "linux-musl-x64" : "linux-x64"; - } - - var apiWrapperPath = Path.Combine(EnvironmentHelper.MonitoringHome, archFolder, "Datadog.Linux.ApiWrapper.x64.so"); - - using var helper = await StartConsole( - enableProfiler: true, - ("DD_PROFILING_ENABLED", "1"), - ("LD_PRELOAD", apiWrapperPath)); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - using var scope = new AssertionScope(); - scope.AddReportable("Output", console.Output); - - result.Should().BeTrue(); - - console.Output.Should().ContainAll( - TracerVersion(TracerConstants.AssemblyVersion), - ContinuousProfilerEnabled); - - console.Output.Should().NotContainAny( - NativeTracerNotLoaded, - TracerNotLoaded, - ContinuousProfilerNotSet, - ContinuousProfilerNotLoaded, - "LD_PRELOAD", - "DD_DOTNET_TRACER_HOME", - CorProfilerKey, - CorEnableKey, - CorProfilerPathKey, - CorProfilerPath32Key, - CorProfilerPath64Key); - } - - [SkippableFact] - public async Task WrongLdPreload() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole( - enableProfiler: true, - ("DD_PROFILING_ENABLED", "1"), - ("LD_PRELOAD", "/dummyPath")); - - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - using var scope = new AssertionScope(); - scope.AddReportable("Output", console.Output); - - result.Should().BeFalse(); - - console.Output.Should().NotContain(ApiWrapperNotFound("/dummyPath")); - console.Output.Should().Contain(Resources.WrongLdPreload("/dummyPath")); - } - - [SkippableFact] - public async Task LdPreloadNotFound() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - using var helper = await StartConsole( - enableProfiler: true, - ("DD_PROFILING_ENABLED", "1"), - ("LD_PRELOAD", "/dummyPath/Datadog.Linux.ApiWrapper.x64.so")); - - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - using var scope = new AssertionScope(); - scope.AddReportable("Output", console.Output); - - result.Should().BeFalse(); - - console.Output.Should().Contain(ApiWrapperNotFound("/dummyPath/Datadog.Linux.ApiWrapper.x64.so")); - console.Output.Should().NotContain(Resources.WrongLdPreload("/dummyPath/Datadog.Linux.ApiWrapper.x64.so")); - } - - [SkippableTheory] - [InlineData(true)] - [InlineData(false)] - [InlineData(null)] - public async Task DetectContinousProfilerState(bool? enabled) - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - var environmentVariables = enabled == null ? Array.Empty<(string, string)>() - : new[] { ("DD_PROFILING_ENABLED", enabled == true ? "1" : "0") }; - - using var helper = await StartConsole(enableProfiler: true, environmentVariables); - var processInfo = ProcessInfo.GetProcessInfo(helper.Process.Id); - - processInfo.Should().NotBeNull(); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.Run(processInfo, MockRegistryService(Array.Empty(), ProfilerPath)); - - using var scope = new AssertionScope(); - scope.AddReportable("Output", console.Output); - - if (enabled == null) - { - console.Output.Should().Contain(ContinuousProfilerNotSet); - } - else if (enabled == true) - { - console.Output.Should().Contain(ContinuousProfilerEnabled); - } - else - { - console.Output.Should().Contain(ContinuousProfilerDisabled); - } - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public void GoodRegistry() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - var registryService = MockRegistryService(Array.Empty(), ProfilerPath); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.CheckRegistry("2.14", registryService); - - result.Should().BeTrue(); - - console.Output.Should().NotContainAny(ErrorCheckingRegistry(string.Empty), "is defined and could prevent the tracer from working properly"); - console.Output.Should().NotContain(MissingRegistryKey(ClsidKey)); - console.Output.Should().NotContain(MissingProfilerRegistry(ClsidKey, ProfilerPath)); - } - - [SkippableTheory] - [Trait("RunOnWindows", "True")] - [InlineData(true)] - [InlineData(false)] - public void BadRegistryKey(bool wow64) - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - var registryService = MockRegistryService(new[] { "cor_profiler" }, ProfilerPath, wow64); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.CheckRegistry("2.14", registryService); - - result.Should().BeFalse(); - - var netFrameworkKey = wow64 ? @"SOFTWARE\WOW6432Node\Microsoft\.NETFramework" : @"SOFTWARE\Microsoft\.NETFramework"; - - console.Output.Should().Contain(SuspiciousRegistryKey(netFrameworkKey, "cor_profiler")); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public void ProfilerNotRegistered() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - SkipOn.PlatformAndArchitecture(SkipOn.PlatformValue.Linux, SkipOn.ArchitectureValue.ARM64); - var registryService = MockRegistryService(Array.Empty(), null); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.CheckRegistry("2.14", registryService); - - result.Should().BeFalse(); - - console.Output.Should().Contain(MissingRegistryKey(ClsidKey)); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public void ProfilerNotFoundRegistry() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - SkipOn.PlatformAndArchitecture(SkipOn.PlatformValue.Linux, SkipOn.ArchitectureValue.ARM64); - var registryService = MockRegistryService(Array.Empty(), "dummyPath/" + Path.GetFileName(ProfilerPath)); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.CheckRegistry("2.14", registryService); - - result.Should().BeFalse(); - - console.Output.Should().NotContain(MissingRegistryKey(ClsidKey)); - console.Output.Should().Contain(MissingProfilerRegistry(ClsidKey, "dummyPath/" + Path.GetFileName(ProfilerPath))); - } - - [SkippableFact] - [Trait("RunOnWindows", "True")] - public void WrongProfilerRegistry() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - SkipOn.PlatformAndArchitecture(SkipOn.PlatformValue.Linux, SkipOn.ArchitectureValue.ARM64); - var registryService = MockRegistryService(Array.Empty(), "wrongProfiler.dll"); - - using var console = ConsoleHelper.Redirect(); - - var result = ProcessBasicCheck.CheckRegistry("2.14", registryService); - - result.Should().BeFalse(); - - console.Output.Should().NotContain(MissingRegistryKey(ClsidKey)); - console.Output.Should().Contain(Resources.WrongProfilerRegistry(ClsidKey, "wrongProfiler.dll")); - } - - [SkippableFact] - public void LinuxInstallationDirectory() - { - SkipOn.Platform(SkipOn.PlatformValue.MacOs); - - string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - Directory.CreateDirectory(tempDirectory); - - try - { - var (extension, archPath) = (EnvironmentTools.GetOS(), EnvironmentTools.GetPlatform(), EnvironmentTools.GetTestTargetPlatform(), Utils.IsAlpine()) switch - { - ("win", _, "X64", _) => ("dll", "win-x64"), - ("win", _, "X86", _) => ("dll", "win-x86"), - ("linux", "Arm64", _, _) => ("so", "linux-arm64"), - ("linux", "X64", _, false) => ("so", "linux-x64"), - ("linux", "X64", _, true) => ("so", "linux-musl-x64"), - ("osx", _, _, _) => ("dylib", "osx"), - var unsupportedTarget => throw new PlatformNotSupportedException(unsupportedTarget.ToString()) - }; - - var dir = Path.Join(tempDirectory, archPath); - var path = Path.Join(dir, $"Datadog.Trace.ClrProfiler.Native.{extension}"); - Directory.CreateDirectory(dir); - File.WriteAllText(path, string.Empty); - - using var console = ConsoleHelper.Redirect(); - - ProcessBasicCheck.CheckLinuxInstallation(tempDirectory); - console.Output.Should().BeEmpty(); - } - finally - { - // cleanup - Directory.Delete(tempDirectory, recursive: true); - } - } - - private static IRegistryService MockRegistryService(string[] frameworkKeyValues, string profilerKeyValue, bool wow64 = false) - { - var registryService = new Mock(); - - var netFrameworkKey = wow64 ? @"SOFTWARE\WOW6432Node\Microsoft\.NETFramework" : @"SOFTWARE\Microsoft\.NETFramework"; - - registryService.Setup(r => r.GetLocalMachineValueNames(It.Is(netFrameworkKey, StringComparer.Ordinal))) - .Returns(frameworkKeyValues); - registryService.Setup(r => r.GetLocalMachineValue(It.Is(s => s == ClsidKey || s == Clsid32Key))) - .Returns(profilerKeyValue); - - return registryService.Object; - } - } -} diff --git a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Datadog.Trace.Tools.Runner.IntegrationTests.csproj b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Datadog.Trace.Tools.Runner.IntegrationTests.csproj index 0c404e4fb3e2..29bc806a0fbc 100644 --- a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Datadog.Trace.Tools.Runner.IntegrationTests.csproj +++ b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/Datadog.Trace.Tools.Runner.IntegrationTests.csproj @@ -4,16 +4,6 @@ netcoreapp2.1;netcoreapp3.0;netcoreapp3.1;net5.0;net6.0;net7.0 - - - - - - - Always - - - diff --git a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/applicationHost.config b/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/applicationHost.config deleted file mode 100644 index 44b2df504498..000000000000 --- a/tracer/test/Datadog.Trace.Tools.Runner.IntegrationTests/applicationHost.config +++ /dev/null @@ -1,1038 +0,0 @@ - - - - - - - - -
-
-
-
-
-
-
-
- - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
- -
-
- -
-
-
- - -
-
-
-
-
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/Datadog.Trace.Tools.Runner.Tests.csproj b/tracer/test/Datadog.Trace.Tools.Runner.Tests/Datadog.Trace.Tools.Runner.Tests.csproj index 5ae42c7d767c..129ae93e35fc 100644 --- a/tracer/test/Datadog.Trace.Tools.Runner.Tests/Datadog.Trace.Tools.Runner.Tests.csproj +++ b/tracer/test/Datadog.Trace.Tools.Runner.Tests/Datadog.Trace.Tools.Runner.Tests.csproj @@ -34,20 +34,8 @@ - - Always - - - Always - Always - - Always - - - Always - diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/AgentConnectivityCheckTests.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/AgentConnectivityCheckTests.cs index b74e52dd8009..48c843698bd5 100644 --- a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/AgentConnectivityCheckTests.cs +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/AgentConnectivityCheckTests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Datadog.Trace.TestHelpers; using Datadog.Trace.Tools.dd_dotnet.Checks; +using Datadog.Trace.Tools.Shared; using FluentAssertions; using Xunit; using Xunit.Abstractions; @@ -46,7 +47,7 @@ public async Task DetectAgentUrl((string, string)[] environmentVariables) processInfo.Should().NotBeNull(); - _ = await AgentConnectivityCheck.RunAsync(processInfo!); + _ = await AgentConnectivityCheck.RunAsync(processInfo.ExtractConfigurationSource(null, null)); console.Output.Should().Contain(DetectedAgentUrlFormat("http://fakeurl:7777/")); } @@ -68,7 +69,7 @@ public async Task DetectTransportHttp() processInfo.Should().NotBeNull(); - _ = await AgentConnectivityCheck.RunAsync(processInfo!); + _ = await AgentConnectivityCheck.RunAsync(processInfo.ExtractConfigurationSource(null, null)); console.Output.Should().Contain(ConnectToEndpointFormat(url, "HTTP")); } @@ -91,7 +92,7 @@ public async Task DetectTransportUds() processInfo.Should().NotBeNull(); - _ = await AgentConnectivityCheck.RunAsync(processInfo!); + _ = await AgentConnectivityCheck.RunAsync(processInfo.ExtractConfigurationSource(null, null)); console.Output.Should().Contain(ConnectToEndpointFormat(uri.PathAndQuery, "domain sockets")); } diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs index df1e5d26b4fd..70028db3c47c 100644 --- a/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.IntegrationTests/Checks/ProcessBasicChecksTests.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Datadog.Trace.TestHelpers; using Datadog.Trace.Tools.dd_dotnet.Checks; +using Datadog.Trace.Tools.Shared; using FluentAssertions; using FluentAssertions.Execution; using Moq; diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/CallDatadogConfigJson.exe.config b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/CallDatadogConfigJson.exe.config similarity index 100% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/CallDatadogConfigJson.exe.config rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/CallDatadogConfigJson.exe.config diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/CustomTestFramework.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/CustomTestFramework.cs new file mode 100644 index 000000000000..f11477b77ebf --- /dev/null +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/CustomTestFramework.cs @@ -0,0 +1,20 @@ +// +// 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 2017 Datadog, Inc. +// + +using Xunit; +using Xunit.Abstractions; + +[assembly: TestFramework("Datadog.Trace.Tools.dd_dotnet.Tests.CustomTestFramework", "Datadog.Trace.Tools.dd_dotnet.Tests")] + +namespace Datadog.Trace.Tools.dd_dotnet.Tests +{ + public class CustomTestFramework : Datadog.Trace.TestHelpers.CustomTestFramework + { + public CustomTestFramework(IMessageSink messageSink) + : base(messageSink) + { + } + } +} diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/Datadog.Trace.Tools.dd_dotnet.Tests.csproj b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/Datadog.Trace.Tools.dd_dotnet.Tests.csproj new file mode 100644 index 000000000000..3f9d4e7830b3 --- /dev/null +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/Datadog.Trace.Tools.dd_dotnet.Tests.csproj @@ -0,0 +1,50 @@ + + + net7.0 + + true + true + SA1300 + + + + + + Always + + + + + + + + + tracer + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/DoNotCallDatadogConfigJson.exe.config b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/DoNotCallDatadogConfigJson.exe.config similarity index 100% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/DoNotCallDatadogConfigJson.exe.config rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/DoNotCallDatadogConfigJson.exe.config diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/ProcessEnvironmentLinuxTests.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/ProcessEnvironmentLinuxTests.cs similarity index 88% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/ProcessEnvironmentLinuxTests.cs rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/ProcessEnvironmentLinuxTests.cs index ef55a838dba6..cca1cb845271 100644 --- a/tracer/test/Datadog.Trace.Tools.Runner.Tests/ProcessEnvironmentLinuxTests.cs +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/ProcessEnvironmentLinuxTests.cs @@ -3,11 +3,11 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // -using Datadog.Trace.Tools.Runner.Checks.Linux; +using Datadog.Trace.Tools.Shared.Linux; using FluentAssertions; using Xunit; -namespace Datadog.Trace.Tools.Runner.Tests +namespace Datadog.Trace.Tools.dd_dotnet.Tests { public class ProcessEnvironmentLinuxTests { diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/ProcessInfoTests.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/ProcessInfoTests.cs similarity index 88% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/ProcessInfoTests.cs rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/ProcessInfoTests.cs index 1e2ab4603a8c..ece6e8a06658 100644 --- a/tracer/test/Datadog.Trace.Tools.Runner.Tests/ProcessInfoTests.cs +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/ProcessInfoTests.cs @@ -8,11 +8,12 @@ using System.IO; using System.Linq; using Datadog.Trace.Configuration; -using Datadog.Trace.Tools.Runner.Checks; +using Datadog.Trace.Tools.dd_dotnet.Checks; +using Datadog.Trace.Tools.Shared; using FluentAssertions; using Xunit; -namespace Datadog.Trace.Tools.Runner.Tests +namespace Datadog.Trace.Tools.dd_dotnet.Tests { public class ProcessInfoTests { @@ -78,7 +79,7 @@ public void UseEnvironment() mainModule: Path.Combine(Environment.CurrentDirectory, "noAppConfig.exe"), GetModulesForNetFramework()); - var settings = new ExporterSettings(process.Configuration); + var settings = new ExporterSettings(process.ExtractConfigurationSource(null, null)); settings.AgentUri.Should().Be("http://environment/"); } @@ -93,7 +94,7 @@ public void UseJsonConfigFromAppConfig() mainModule: Path.Combine(Environment.CurrentDirectory, "CallDatadogConfigJson.exe"), GetModulesForNetFramework()); - var settings = new ExporterSettings(process.Configuration); + var settings = new ExporterSettings(process.ExtractConfigurationSource(null, null)); settings.AgentUri.Should().Be("http://datadogConfig.json/"); } @@ -108,7 +109,7 @@ public void DontUseAppConfigWithNetCore() mainModule: Path.Combine(Environment.CurrentDirectory, "CallDatadogConfigJson.exe"), GetModulesForNetCore()); - var settings = new ExporterSettings(process.Configuration); + var settings = new ExporterSettings(process.ExtractConfigurationSource(null, null)); settings.AgentUri.Should().Be("http://datadog.json/"); } @@ -123,7 +124,7 @@ public void UseJsonConfigFromEnvironment() mainModule: Path.Combine(Environment.CurrentDirectory, "noAppConfig.exe"), GetModulesForNetFramework()); - var settings = new ExporterSettings(process.Configuration); + var settings = new ExporterSettings(process.ExtractConfigurationSource(null, null)); settings.AgentUri.Should().Be("http://datadogConfig.json/"); } @@ -138,7 +139,7 @@ public void UseAppConfig() mainModule: Path.Combine(Environment.CurrentDirectory, "DoNotCallDatadogConfigJson.exe"), GetModulesForNetFramework()); - var settings = new ExporterSettings(process.Configuration); + var settings = new ExporterSettings(process.ExtractConfigurationSource(null, null)); settings.AgentUri.Should().Be("http://app.config/"); } diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/RegistryServiceTests.cs b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/RegistryServiceTests.cs similarity index 95% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/RegistryServiceTests.cs rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/RegistryServiceTests.cs index 971dbc75539a..589e39806ae7 100644 --- a/tracer/test/Datadog.Trace.Tools.Runner.Tests/RegistryServiceTests.cs +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/RegistryServiceTests.cs @@ -5,13 +5,13 @@ using System; using Datadog.Trace.TestHelpers; -using Datadog.Trace.Tools.Runner.Checks; -using Datadog.Trace.Tools.Runner.Checks.Windows; +using Datadog.Trace.Tools.dd_dotnet.Checks; +using Datadog.Trace.Tools.dd_dotnet.Checks.Windows; using FluentAssertions; using Moq; using Xunit; -namespace Datadog.Trace.Tools.Runner.Tests +namespace Datadog.Trace.Tools.Shared.Tests { public class RegistryServiceTests { diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/datadog.json b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/datadog.json similarity index 100% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/datadog.json rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/datadog.json diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/datadogConfig.json b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/datadogConfig.json similarity index 100% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/datadogConfig.json rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/datadogConfig.json diff --git a/tracer/test/Datadog.Trace.Tools.Runner.Tests/maps.txt b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/maps.txt similarity index 100% rename from tracer/test/Datadog.Trace.Tools.Runner.Tests/maps.txt rename to tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/maps.txt diff --git a/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/xunit.runner.json b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/xunit.runner.json new file mode 100644 index 000000000000..eae9335ded8e --- /dev/null +++ b/tracer/test/Datadog.Trace.Tools.dd_dotnet.Tests/xunit.runner.json @@ -0,0 +1,4 @@ +{ + "diagnosticMessages": true, + "internalDiagnosticMessages": true +} \ No newline at end of file