Update package layouts & ship continuous profiler in dd-trace/NuGet#3060
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| Logger.Info($"Copying file '{source}' to 'file {dest}'"); | ||
| CopyFileToDirectory(source, dest, FileExistsPolicy.Overwrite); | ||
| var (arch, ext) = GetUnixArchitectureAndExtension(); | ||
| var sourceDir = ProfilerOutputDirectory / "DDProf-Deploy"; |
There was a problem hiding this comment.
This division / overload that Nuke has is really cool
| <Component Id="EnvironmentVariablesShared" Guid="{C314A305-9C24-4E46-9ECF-E5EEA703BDEA}" Win64="$(var.Win64)"> | ||
| <CreateFolder/> | ||
| <Environment Id="DD_NATIVELOADER_CONFIGFILE" Name="DD_NATIVELOADER_CONFIGFILE" Action="set" Permanent="no" System="yes" Value="[INSTALLFOLDER]loader.conf" Part="all" /> | ||
| <?if $(var.Win64) = yes ?> |
There was a problem hiding this comment.
I suspected that this would not work when 1) the 64-bit installer is installed and 2) a 32-bit process is being instrumented, and I was able to verify this issue locally. When this happens the loader emits the following log lines:
[2022-08-08 14:01:16.683 | debug | PId: 62804 | TId: 56360] Load: C:\Program Files\Datadog\.NET Tracer\win-x64\Datadog.Tracer.Native.dll
[2022-08-08 14:01:16.683 | warning | PId: 62804 | TId: 56360] Load: Error loading dynamic library 'C:\Program Files\Datadog\.NET Tracer\win-x64\Datadog.Tracer.Native.dll': 02F66CA0
This is only an issue with the MSI and specifically the 64-bit installer because we have to globally set DD_NATIVELOADER_CONFIGFILE for all applications, but the config loader must be able to select the native bits that match the process bitness. To handle this correctly, I think we'll need to do the following:
- Install the
loader.confat the[INSTALLFOLDER]location - This
loader.confwill need to include thewin-x64andwin-x86subdirectories in its lookup paths - Always set
DD_NATIVELOADER_CONFIGFILEto point to the[INSTALLFOLDER]loader.conflocation
Compared to the BEFORE state, the only change should be the loader.conf file. The new loader.conf should look like the following:
#Profiler
PROFILER;{BD1A650D-AC5D-4896-B64F-D6FA25D6B26A};win-x64;.\win-x64\Datadog.Profiler.Native.dll
PROFILER;{BD1A650D-AC5D-4896-B64F-D6FA25D6B26A};win-x86;.\win-x86\Datadog.Profiler.Native.dll
#Tracer
TRACER;{50DA5EED-F1ED-B00B-1055-5AFE55A1ADE5};win-x64;.\win-x64\Datadog.Tracer.Native.dll
TRACER;{50DA5EED-F1ED-B00B-1055-5AFE55A1ADE5};win-x86;.\win-x86\Datadog.Tracer.Native.dll
There was a problem hiding this comment.
I started a thread here where I suggested we could move all of the 32-bit assets into the Program Files (x86) folder just like Datadog.Trace.ClrProfiler.Native.dll, since that's required to be placed there. If we did that AND we did not set DD_NATIVELOADER_CONFIGFILE globally, then what would happen is the loader DLL would look in its directory for a loader.conf file. Since all of the 64-bit files (and the loader) would be in the same directory as the 64-bit Datadog.Trace.ClrProfiler.Native.dll loader and all of the 32-bit files (and the loader) would be in the same directory as the 32-bit Datadog.Trace.ClrProfiler.Native.dll loader, this should fix the issue I surfaced. This seems to me like the cleanest solution that addresses both issues. What do you think?
There was a problem hiding this comment.
I think having everything 32-bit in the 32-bit program folder makes a lot of sense. My only question is whether having all the managed dlls in a separate folder away from the native loaders becomes an issue then.. It breaks the "clean, unified layout" we currently have (but the MSI breaks that anyway by having two install locations).
Essentially it's a question of whether it's better to have
- x86 assets all in the same location
- simple loader conf
- tracer home cannot be inferred from native dll locations, and is in a separate location
or
- native loader separate from x86 native dlls + loader conf
- tweaked loader conf
- tracer home can be inferred from native tracer etc
I was initially thinking the first approach, but now I'm leaning to the second approach...
Also... I didn't realise we don't have any 32-bit on x64 tests in CI 😬 We should have one at least! I'll try adding a smoke test separately...
There was a problem hiding this comment.
Have we considered installing all the files into a single base location, either Program Files or Program Files (x86) or other, instead of splitting them up? I think we can do that now that we have the win-x64 and win-x86 folders, and it could make things simpler by keeping everything contained in a single path (like all the other packages). On the other hand, this may require some MSI trickery, since MSI can be finicky about what is x64 vs x86.
Related: there is a long-standing bug where we allow users to change the tracer installation path, but that only applies to the files in Program Files. Users cannot change where the Program Files (x86) files are installed. We've had support cases of users not wanting to install anything into C:\, for example, but that is currently not possible.
There was a problem hiding this comment.
Have we considered installing all the files into a single base location, either Program Files or Program Files (x86) or other, instead of splitting them up?
MSIs aren't my strong point, so I don't know why we split them up at all (I thought we always had the win-x64 and winx-86 folders). I assumed it was because we register via the ID with the MSI, not using the profiler path, so I assumed the profiler had to be in the expected folder (i.e. Program Files (X86) for 32-bit processes)
If we can avoid it, I'm strongly in favour of not splitting them up! Especially if it solves additional issues.
There was a problem hiding this comment.
Those changes look good to me! We should also update our docs to remove the unnecessary COR_PROFILER/CORECLR_PROFILER GUID.
Question: As we now set the COR_PROFILER/CORECLR_PROFILER GUID as a machine-wide env var, should we remove it from the IIS registry keys to avoid the duplication?
I say go for it 👍🏼
There was a problem hiding this comment.
I think it's always clearer for the user (or troubleshooter) to have all the config variables in the same place. If we are setting the IIS variables in the registry I find it always usefull to have them all together, althaough some of them could be declared globally.
There was a problem hiding this comment.
I think it's always clearer for the user (or troubleshooter) to have all the config variables in the same place.
The trouble is we need to support IIS, windows services and ad-hoc apps. With the approach we've taken here, users only need to set COR_ENABLE_PROFILING for the windows services or for the standalone apps, nothing else needs setting.
If we don't take this approach then either:
- We require customers to set the env var paths to the profiler correctly when running windows services etc. That's potentially 4/8 env vars... I think it's better to only require the
COR_ENABLE_PROFILING/CORECLR_ENABLE_PROFILINGvariables, as they're harder to screw up - Duplicate config variables in multiple places, i.e. globally and in IIS. There's more chances for things to go out sync then
|
By the way, some of the installer smoke tests haven't run because they require some extra variables to be set. Can you make sure they all get run before merging? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
Just a note comparing the size of assets before and after this PR:
|
zacharycmontoya
left a comment
There was a problem hiding this comment.
LGTM. I wasn't 100% sure if the Datadog.Linux.ApiWrapper.x64.so path was correct in all of the files, but if the tests are all passing and the profiling team signs off, then I assume it's good. Nice work and thanks for the phenomenal PR description!
pierotibou
left a comment
There was a problem hiding this comment.
LGTM (but not the most knowledgeable on that part clearly).
Thanks a LOT for this huge work and the premilinary work that allow us to make that change with more confidence.
The location (and naming) of As it's a required config for customers, unfortunately, we can't change its location. Hence why the linux installers all keep this file (or a symlink to it) in the This only applies to the linux installers though:
|
|
I checked out the branch, if I run |
|
|
||
| <NativeLinuxX86DeployFilesSrcDir>$(BaseOutputPath)\$(Configuration)-x86\profiler\src\ProfilerEngine\Datadog.Profiler.Native.Linux</NativeLinuxX86DeployFilesSrcDir> | ||
| <NativeLinuxX64DeployFilesSrcDir>$(BaseOutputPath)\$(Configuration)-x64\profiler\src\ProfilerEngine\Datadog.Profiler.Native.Linux</NativeLinuxX64DeployFilesSrcDir> | ||
| <NativeWindowsDeployFilesSrcDir>$(BaseOutputPath)\$(ConfigBasedRelativeOutputPath)\profiler\src\ProfilerEngine\Datadog.Profiler.Native.Windows</NativeWindowsDeployFilesSrcDir> |
There was a problem hiding this comment.
Removing the bitness info in the path might break here. Since x86 and x64 binaries have now the same name, they can be copied into the same folder: I don't know which one will erase the other.
I mean, yes, they can be overwritten, but if they are, then we have a build problem 😄 They are currently (before and after this change), built to separate folders, e.g. Release-x86 and Release-x64.
When they're copied to DDProf-Deploy they're deployed to the win-x64 and win-x86 folders, so there's again no issue with overwritting AFAICT?
There's a bigger question here for me - why do we need the DDProf-Deploy directory at all? For me, it adds confusion and complexity? It's not where things are built to, so we could just "deploy" them to the Monitoring Home directory, where they end up eventually anyway?
I was a bit torn on the "dropping the bitness from the file names" question, but we ultimately opted for it for consistency, and to reduce the duplication in the arch-specific folders. That, coupled with the fact we have to drop it in some cases for back compat reasons led us to this state... I think we can safely add it back in later though if it's an issue, it's only the Datadog.Trace.ClrProfiler.Native file we can't ever rename 🙂
There was a problem hiding this comment.
When they're copied to DDProf-Deploy they're deployed to the win-x64 and win-x86 folders, so there's again no issue with overwritting AFAICT?
Where is this done?
The$(BaseOutputPath)$ (ConfigBasedRelativeOutputPath) does not seem to contain the bitness
There was a problem hiding this comment.
Where is this done?
The (ConfigBasedRelativeOutputPath) does not seem to contain the bitness
ConfigBasedRelativeOutputPath contains the bitness 🙂 It's (e.g.) Release-x86 or Release-x64
| <NativeX64DeployFiles Include="$(NativeWindowsX64DeployFilesSrcDir)\*.dll" /> | ||
| <NativeX64DeployFiles Include="$(NativeWindowsX64DeployFilesSrcDir)\*.pdb" /> | ||
| <NativeX64DeployFiles Include="$(NativeLinuxX64DeployFilesSrcDir)\*.so" /> | ||
| <NativeDeployFiles Include="$(NativeWindowsDeployFilesSrcDir)\*.dll" /> |
There was a problem hiding this comment.
Also, the simple answer is that NativeWindowsDeployFilesSrcDir is different for different architectures 🙂
There was a problem hiding this comment.
I have to admit that I don't see NativeWindowsDeployFilesSrcDir set.
However, is it the "source" from which the files will be copied (could be different because generated during the build)?
Here, I'm talking about the destination in DDProf-Deploy
There was a problem hiding this comment.
I have to admit that I don't see NativeWindowsDeployFilesSrcDir set.
It's set on line 46, on your previous comment, and includesRelease-x64etc in the path.
Here, I'm talking about the destination in DDProf-Deploy
The destination is given by DeployDirectoryBase, which is DDProf-Deploy/win-x64 and DDProf-Deploy/win-x86 respectively.
On linux we currently still build to the root, as we only build one architecture. We would need to update the CMakefile etc to account for that if we start building for multiple arches at once on Linux. But that's a current issue too, so there's no change in that
|
|
||
| <AllDeployFiles Include="@(NativeX86DeployFiles)" /> | ||
| <AllDeployFiles Include="@(NativeX64DeployFiles)" /> | ||
| <AllDeployFiles Include="@(NativeDeployFiles)" /> |
| <Message Text="[PrepareDeployDirectory] NativeWindowsX64DeployFilesSrcDir: '$(NativeWindowsX64DeployFilesSrcDir)'" Importance="high" /> | ||
| <Message Text="[PrepareDeployDirectory] NativeLinuxX86DeployFilesSrcDir: '$(NativeLinuxX86DeployFilesSrcDir)'" Importance="high" /> | ||
| <Message Text="[PrepareDeployDirectory] NativeLinuxX64DeployFilesSrcDir: '$(NativeLinuxX64DeployFilesSrcDir)'" Importance="high" /> | ||
| <Message Text="[PrepareDeployDirectory] NativeWindowsDeployFilesSrcDir: '$(NativeWindowsDeployFilesSrcDir)'" Importance="high" /> |
| <?include $(sys.CURRENTDIR)\Config.wxi?> | ||
| <Fragment> | ||
| <ComponentGroup Id="ContinuousProfiler.Files" Directory="ContinuousProfiler"> | ||
| <ComponentGroup Id="ContinuousProfiler.Files" Directory="INSTALLFOLDER"> |
There was a problem hiding this comment.
What are the files that will be copied in this root folder for the profiler?
I'm not sure we have any since we got rid of Datadog.AutoInstrumentation.Profiler.Managed.dll
There was a problem hiding this comment.
You're right, there aren't any! The Tracer has this too, I'm not sure exactly why it's there, not sure if it's required or not. I'll try cleaning it up in a subsequent PR
| .EnableNoRestore() | ||
| .EnableNoBuild() | ||
| .SetProcessEnvironmentVariable("TracerHomeDirectory", TracerHomeDirectory) | ||
| .SetProcessEnvironmentVariable("TracerHomeDirectory", MonitoringHomeDirectory) |
There was a problem hiding this comment.
Won't this cause some confusion? In other places in this PR, it seemed like we are deprecating the concept of a "TracerHome", but maybe I misinterpreted?
There was a problem hiding this comment.
Won't this cause some confusion? In other places in this PR, it seemed like we are deprecating the concept of a "TracerHome", but maybe I misinterpreted?
Yep, we're deprecating the use of TracerHome, there's still some cleanup to do to remove all traces of it though 🙂 I'll push that to a later PR for simplicity
OmerRaviv
left a comment
There was a problem hiding this comment.
I only did a quick superficial pass to verify that I don't see any thing that stands out for the debugger, but LGTM!
Yep, you will always need to run I think I can definitely improve this in a later PR by making it a direct dependency and re-working some things! |
Benchmarks Report 🐌Benchmarks for #3060 compared to master:
The following thresholds were used for comparing the benchmark speeds:
Allocation changes below 0.5% are ignored. Benchmark detailsBenchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.AppSecBodyBenchmark - Faster 🎉 Fewer allocations 🎉
|
| Benchmark | base/diff | Base Median (ns) | Diff Median (ns) | Modality |
|---|---|---|---|---|
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net472 | 91.755 | 16,927.50 | 184.49 | |
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleMoreComplexBody‑netcoreapp3.1 | 61.439 | 14,413.83 | 234.60 | |
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleSimpleBody‑net472 | 9.359 | 1,704.44 | 182.12 | |
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleSimpleBody‑netcoreapp3.1 | 7.750 | 1,822.71 | 235.19 |
| Benchmark | Base Allocated | Diff Allocated | Change | Change % |
|---|---|---|---|---|
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleSimpleBody‑netcoreapp3.1 | 1.37 KB | 424 B | -944 B | -69.01% |
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleSimpleBody‑net472 | 1.49 KB | 425 B | -1.07 KB | -71.51% |
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleMoreComplexBody‑netcoreapp3.1 | 7.85 KB | 400 B | -7.45 KB | -94.90% |
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net472 | 8.75 KB | 401 B | -8.35 KB | -95.42% |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | AllCycleSimpleBody |
net472 | 1.7μs | 1.42ns | 5.32ns | 0.237 | 0 | 0 | 1.49 KB |
| master | AllCycleSimpleBody |
netcoreapp3.1 | 1.82μs | 1.64ns | 6.14ns | 0.0183 | 0 | 0 | 1.37 KB |
| master | AllCycleMoreComplexBody |
net472 | 16.9μs | 17.5ns | 67.9ns | 1.39 | 0.0246 | 0 | 8.75 KB |
| master | AllCycleMoreComplexBody |
netcoreapp3.1 | 14.4μs | 18.1ns | 65.1ns | 0.108 | 0 | 0 | 7.85 KB |
| master | BodyExtractorSimpleBody |
net472 | 248ns | 0.213ns | 0.826ns | 0.0573 | 0 | 0 | 361 B |
| master | BodyExtractorSimpleBody |
netcoreapp3.1 | 224ns | 0.234ns | 0.876ns | 0.00382 | 0 | 0 | 272 B |
| master | BodyExtractorMoreComplexBody |
net472 | 14.5μs | 10.3ns | 38.5ns | 1.21 | 0.0216 | 0 | 7.62 KB |
| master | BodyExtractorMoreComplexBody |
netcoreapp3.1 | 12μs | 15.4ns | 57.6ns | 0.0897 | 0 | 0 | 6.75 KB |
| #3060 | AllCycleSimpleBody |
net472 | 182ns | 0.143ns | 0.535ns | 0.0675 | 9.19E-05 | 0 | 425 B |
| #3060 | AllCycleSimpleBody |
netcoreapp3.1 | 235ns | 0.314ns | 1.22ns | 0.00586 | 0 | 0 | 424 B |
| #3060 | AllCycleMoreComplexBody |
net472 | 185ns | 0.146ns | 0.546ns | 0.0637 | 0 | 0 | 401 B |
| #3060 | AllCycleMoreComplexBody |
netcoreapp3.1 | 234ns | 0.239ns | 0.926ns | 0.00539 | 0 | 0 | 400 B |
| #3060 | BodyExtractorSimpleBody |
net472 | 266ns | 0.118ns | 0.425ns | 0.0573 | 0 | 0 | 361 B |
| #3060 | BodyExtractorSimpleBody |
netcoreapp3.1 | 231ns | 0.264ns | 1.02ns | 0.00376 | 0 | 0 | 272 B |
| #3060 | BodyExtractorMoreComplexBody |
net472 | 14.3μs | 31.1ns | 120ns | 1.2 | 0.0214 | 0 | 7.62 KB |
| #3060 | BodyExtractorMoreComplexBody |
netcoreapp3.1 | 12.2μs | 12.1ns | 45.4ns | 0.0907 | 0 | 0 | 6.75 KB |
Benchmarks.Trace.AspNetCoreBenchmark - Unknown 🤷 Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendRequest |
net472 | 0ns | 0ns | 0ns | 0 | 0 | 0 | 0 b |
| master | SendRequest |
netcoreapp3.1 | 179μs | 154ns | 597ns | 0.178 | 0 | 0 | 20.33 KB |
| #3060 | SendRequest |
net472 | 0ns | 0ns | 0ns | 0 | 0 | 0 | 0 b |
| #3060 | SendRequest |
netcoreapp3.1 | 178μs | 122ns | 473ns | 0.178 | 0 | 0 | 20.33 KB |
Benchmarks.Trace.DbCommandBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteNonQuery |
net472 | 1.54μs | 0.822ns | 3.08ns | 0.126 | 0.000771 | 0 | 794 B |
| master | ExecuteNonQuery |
netcoreapp3.1 | 1.26μs | 0.338ns | 1.26ns | 0.0107 | 0 | 0 | 824 B |
| #3060 | ExecuteNonQuery |
net472 | 1.55μs | 0.359ns | 1.39ns | 0.126 | 0.000773 | 0 | 794 B |
| #3060 | ExecuteNonQuery |
netcoreapp3.1 | 1.33μs | 0.553ns | 2.07ns | 0.0108 | 0 | 0 | 824 B |
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | CallElasticsearch |
net472 | 2.25μs | 0.417ns | 1.56ns | 0.159 | 0 | 0 | 1 KB |
| master | CallElasticsearch |
netcoreapp3.1 | 1.44μs | 1.05ns | 4.08ns | 0.0136 | 0 | 0 | 984 B |
| master | CallElasticsearchAsync |
net472 | 2.34μs | 0.764ns | 2.86ns | 0.18 | 0 | 0 | 1.14 KB |
| master | CallElasticsearchAsync |
netcoreapp3.1 | 1.52μs | 0.378ns | 1.46ns | 0.0144 | 0 | 0 | 1.1 KB |
| #3060 | CallElasticsearch |
net472 | 2.19μs | 0.725ns | 2.81ns | 0.159 | 0 | 0 | 1 KB |
| #3060 | CallElasticsearch |
netcoreapp3.1 | 1.34μs | 0.667ns | 2.58ns | 0.0129 | 0 | 0 | 984 B |
| #3060 | CallElasticsearchAsync |
net472 | 2.25μs | 0.841ns | 3.03ns | 0.181 | 0 | 0 | 1.14 KB |
| #3060 | CallElasticsearchAsync |
netcoreapp3.1 | 1.44μs | 0.603ns | 2.26ns | 0.0151 | 0 | 0 | 1.1 KB |
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteAsync |
net472 | 2.39μs | 5.41ns | 21ns | 0.199 | 0 | 0 | 1.26 KB |
| master | ExecuteAsync |
netcoreapp3.1 | 1.56μs | 1.75ns | 6.78ns | 0.0166 | 0 | 0 | 1.22 KB |
| #3060 | ExecuteAsync |
net472 | 2.5μs | 5.41ns | 20.2ns | 0.2 | 0 | 0 | 1.26 KB |
| #3060 | ExecuteAsync |
netcoreapp3.1 | 1.61μs | 2.16ns | 8.38ns | 0.0161 | 0 | 0 | 1.22 KB |
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendAsync |
net472 | 5μs | 6.38ns | 24.7ns | 0.394 | 0 | 0 | 2.48 KB |
| master | SendAsync |
netcoreapp3.1 | 3.15μs | 4.14ns | 15.5ns | 0.0316 | 0 | 0 | 2.36 KB |
| #3060 | SendAsync |
net472 | 4.95μs | 7.13ns | 27.6ns | 0.392 | 0 | 0 | 2.48 KB |
| #3060 | SendAsync |
netcoreapp3.1 | 3.19μs | 6.14ns | 23.8ns | 0.0317 | 0 | 0 | 2.36 KB |
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 2.87μs | 1.75ns | 6.76ns | 0.263 | 0 | 0 | 1.66 KB |
| master | EnrichedLog |
netcoreapp3.1 | 2.35μs | 0.736ns | 2.75ns | 0.0236 | 0 | 0 | 1.73 KB |
| #3060 | EnrichedLog |
net472 | 2.74μs | 1.28ns | 4.97ns | 0.263 | 0 | 0 | 1.66 KB |
| #3060 | EnrichedLog |
netcoreapp3.1 | 2.3μs | 0.743ns | 2.78ns | 0.0233 | 0 | 0 | 1.73 KB |
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 147μs | 72.3ns | 280ns | 0.666 | 0.222 | 0 | 4.5 KB |
| master | EnrichedLog |
netcoreapp3.1 | 114μs | 218ns | 845ns | 0.056 | 0 | 0 | 4.38 KB |
| #3060 | EnrichedLog |
net472 | 148μs | 78.2ns | 303ns | 0.672 | 0.224 | 0 | 4.5 KB |
| #3060 | EnrichedLog |
netcoreapp3.1 | 112μs | 138ns | 534ns | 0.056 | 0 | 0 | 4.38 KB |
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 5.43μs | 10.2ns | 39.5ns | 0.543 | 0.0027 | 0 | 3.43 KB |
| master | EnrichedLog |
netcoreapp3.1 | 4.22μs | 6.96ns | 26.9ns | 0.0524 | 0 | 0 | 3.8 KB |
| #3060 | EnrichedLog |
net472 | 5.38μs | 9.15ns | 35.4ns | 0.544 | 0.00268 | 0 | 3.43 KB |
| #3060 | EnrichedLog |
netcoreapp3.1 | 4.28μs | 8.37ns | 32.4ns | 0.0514 | 0 | 0 | 3.8 KB |
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendReceive |
net472 | 2.08μs | 0.941ns | 3.65ns | 0.193 | 0 | 0 | 1.22 KB |
| master | SendReceive |
netcoreapp3.1 | 1.63μs | 0.7ns | 2.71ns | 0.0164 | 0 | 0 | 1.21 KB |
| #3060 | SendReceive |
net472 | 2μs | 0.594ns | 2.22ns | 0.193 | 0 | 0 | 1.22 KB |
| #3060 | SendReceive |
netcoreapp3.1 | 1.7μs | 0.332ns | 1.2ns | 0.0162 | 0 | 0 | 1.21 KB |
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 4.71μs | 0.78ns | 3.02ns | 0.328 | 0 | 0 | 2.08 KB |
| master | EnrichedLog |
netcoreapp3.1 | 4.23μs | 1.1ns | 3.82ns | 0.0211 | 0 | 0 | 1.69 KB |
| #3060 | EnrichedLog |
net472 | 4.78μs | 1.41ns | 5.48ns | 0.33 | 0 | 0 | 2.08 KB |
| #3060 | EnrichedLog |
netcoreapp3.1 | 4.2μs | 1.21ns | 4.36ns | 0.021 | 0 | 0 | 1.69 KB |
Benchmarks.Trace.SpanBenchmark - Faster 🎉 Same allocations ✔️
Faster 🎉 in #3060
Benchmark
base/diff
Base Median (ns)
Diff Median (ns)
Modality
Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net472
1.131
1,172.19
1,036.45
| Benchmark | base/diff | Base Median (ns) | Diff Median (ns) | Modality |
|---|---|---|---|---|
| Benchmarks.Trace.SpanBenchmark.StartFinishScope‑net472 | 1.131 | 1,172.19 | 1,036.45 |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | StartFinishSpan |
net472 | 824ns | 0.151ns | 0.545ns | 0.104 | 0 | 0 | 658 B |
| master | StartFinishSpan |
netcoreapp3.1 | 758ns | 0.279ns | 1.08ns | 0.00872 | 0 | 0 | 648 B |
| master | StartFinishScope |
net472 | 1.17μs | 0.237ns | 0.916ns | 0.117 | 0 | 0 | 738 B |
| master | StartFinishScope |
netcoreapp3.1 | 883ns | 0.303ns | 1.09ns | 0.0102 | 0 | 0 | 768 B |
| #3060 | StartFinishSpan |
net472 | 859ns | 0.438ns | 1.58ns | 0.104 | 0 | 0 | 658 B |
| #3060 | StartFinishSpan |
netcoreapp3.1 | 738ns | 0.339ns | 1.31ns | 0.00851 | 0 | 0 | 648 B |
| #3060 | StartFinishScope |
net472 | 1.04μs | 0.389ns | 1.51ns | 0.117 | 0 | 0 | 738 B |
| #3060 | StartFinishScope |
netcoreapp3.1 | 851ns | 0.232ns | 0.835ns | 0.0103 | 0 | 0 | 768 B |
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | RunOnMethodBegin |
net472 | 1.28μs | 0.359ns | 1.39ns | 0.117 | 0 | 0 | 738 B |
| master | RunOnMethodBegin |
netcoreapp3.1 | 1.01μs | 0.471ns | 1.82ns | 0.0106 | 0 | 0 | 768 B |
| #3060 | RunOnMethodBegin |
net472 | 1.25μs | 0.185ns | 0.665ns | 0.117 | 0 | 0 | 738 B |
| #3060 | RunOnMethodBegin |
netcoreapp3.1 | 1.03μs | 0.507ns | 1.9ns | 0.0103 | 0 | 0 | 768 B |
|
LGTM for appsec, thank you for fixing the paths!! |
|
I think it is always a good improvement to simplify things, and this cleans up file path hell. Great job. |
Code Coverage Report 📊✔️ Merging #3060 into master will not change line coverage
View the full report for further details: Datadog.Trace Breakdown ✔️
The following classes have significant coverage changes.
View the full reports for further details: |
## Summary of changes Updates the fallback path when loading the native loader (runtime ID store) to use an absolute path ## Reason for change By default, we load the native loader using an env var set by the loader itself. This is the default approach, but there's also a fallback in case this is not set for some reason. On Windows only, we were using just the filename to load the library, which can be ambiguous depending on dll search paths. This changes the Windows lookup to use an absolute path like we do on Linux ## Implementation details Remove the `#ifdef` for Windows, and construct the full path in both cases. ## Test coverage Should be covered by existing tests ## Other details Note that the old comment of "the native loader is in the parent directory" has been incorrect since #3060 (v2.14.0, back in 2022 😅)

Summary of changes
windows-tracer-home.zip(for AAS)Reason for change
We need to ship the continuous profiler with all the existing installation mechanisms. That was not going to be possible with the existing package layouts and assumptions, consequently we have adopted a package layout which:
dd-tracelayout, where the arch-specific versions are in subfolderslinux-x64,win-x86etcThis also will hopefully simplify some of the build/test code, though much of that will later come in subsequent refactoring.
Implementation details
Prior to these changes, each platform had a slightly different package layout, which also meant the build process was rather convoluted, required copying files around and renaming, and generally wasn't idempotent (e.g. you couldn't run
ZipMonitoringHometwice without a clean in between). As well as fixing the package layouts this PR goes someway to cleaning up the build. For example:MonitoringHomeDirectory. TheTracerHomeDirectoryandProfilerHomeDirectorybuild variables have gone; everything goes into monitoring home.Datadog.Profiler.Native,Datadog.Tracer.Native, andDatadog.Trace.ClrProfiler.Native(native loader). The profiler's api wrapper dll remains asDatadog.Linux.ApiWrapper.x64for back compat reasons. There is no renaming of dlls as part of the build anymoredd-traceand the NuGet) is done in Nuke, instead of using Azure DevOps tasks. That gives us extra portability and makes it easier to test locally. The yaml pipline should only upload and download files to the same logical directory, it shouldn't be "moving stuff around".DD_TRACE_DEBUG=.The main changes are obviously to the package layout for each of the install mechanisms.
windows-tracer-home.zipThe tracer home zip is used by AAS, and has been updated to include the continuous profiler. The layout has not changed significantly here, but the continuous profiler and native loader have been added.
MSI
The MSI layout has changed significantly. Prior to this PR, after install, the MSI had the following folder layout.
BEFORE
For the x64 installer, the
C:\Program Files\Datadog\.NET TracerandC:\Program Files (x86)\Datadog\.NET Tracerrespectively look like this:For the x86 installer,
C:\Program Files (x86)\Datadog\.NET Tracerlooks like this:AFTER
After this PR, the file names have been normalized to match other platforms, and the layout has been changed to remove the

/tracerand/continuousprofilersubfolders. The x64 installer also now deploys entirely toProgram Files, which also resolves a long-standing issue around controlling the install folder:and the x86 installer folder looks like this:
This is obviously a big change, but luckily the MSI is where we have the most flexibility to rearrange things,
as we register the dll via the com ID, so we shouldn't have to worry about paths.We now don't register the dll via COM, and instead provide the paths, which actually gives us more flexibility to fix the package layoutLinux installers
.deb/tar/rpmBEFORE
Prior to this PR, the package layouts for Linux looked like this.
Note that they all look the same, but they're not; the native files in each one are different!
AFTER
After this PR, each package layout is unique.
For backwards compatibility reasons:
NuGet / dd-trace tool
The NuGet layout is essentially unchanged, but now includes the native loader + profiler for each platform. The NuGet and the dd-tool use the same layout, so I'm only showing the one example here:
BEFORE
AFTER
Regarding backwards compatibility:
Datadog.Linux.ApiWrapper.x64.soin the arch-specific folder seemed like the easiest/best option. Customers will need to set theLD_PRELOADvariable accordingly.dd-trace?Should we set it when setting env vars to start the process? Or does the customer have to set it before callingdd-trace? If the former, that should be done in this (or another) PR. If the latter, we could have a problem 😬Test coverage
Test coverage is primarily provided by the installer smoke tests and existing integration tests.
Additionally:
For the latter point I will do this, but I would appreciate if someone from each team would cast an eye over and makes sure there's nothing untoward, particularly where it comes to native dll interaction (debugger team optional as it's not yet GA) 🙂 . I'll attach some log files here to make it easier, then each team can indicate that they're happy? There are more permutations than below, but I stripped down to the bear minimum IMO😬 Alternatively, just tick away and YOLO it 😉
Other details
There's lots of build cleanup I'd like to do after this, but I'd like to leave that to later PRs as this is complex enough as it is.
It's maybe also worth noting that in all cases other than the linux packages, the native dlls are all in the same folder, and the loader.conf paths all point to files in the same directory. It may be worth considering making loader.conf optional if that gives any start performance benefits (i.e. assume everything in the same directory unless we say otherwise).