From edf2bc131da692e0d64c280e95059d70de09c3f6 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Wed, 15 Nov 2023 10:47:30 +0000 Subject: [PATCH] Return total memory when limit is max value. (#2214) * Update metrics providers - Implement changes to unlimited memory metric. - Remove inactive_file.bytes per https://github.com/elastic/apm/pull/339 - Refactor code - Optimise code to avoid allocations. * Update and add tests * Update benchmarks and add profiling project * Update editorconfig to avoid range errors * Cleanup white space in build.fs * Linux bug fixes * Fix formatting * Remove commented code * Add code comment * Fixes after rebase --- .editorconfig | 2 + ElasticApmAgent.sln | 216 ++++++------- .../CgroupMetricsProviderBenchmarks.cs | 130 ++++++++ .../Elastic.Apm.Benchmarks.csproj | 14 +- .../FreeAndTotalMemoryProviderBenchmarks.cs | 55 ++++ .../MetricsBenchmarks.cs | 2 +- benchmarks/Elastic.Apm.Benchmarks/Program.cs | 15 +- .../Elastic.Apm.Profiling.csproj | 21 ++ benchmarks/Elastic.Apm.Profiling/Program.cs | 63 ++++ build/scripts/Build.fs | 4 +- src/Elastic.Apm/Elastic.Apm.csproj | 1 + .../Metrics/Linux/GlobalMemoryStatus.cs | 190 ++++++++++++ src/Elastic.Apm/Metrics/MetricsCollector.cs | 9 +- .../MetricsProvider/CgroupMetricsProvider.cs | 198 +++++++----- .../FreeAndTotalMemoryProvider.cs | 119 +++---- ...emoryStatusEx.cs => GlobalMemoryStatus.cs} | 0 .../Elastic.Apm.Tests.csproj | 1 + .../Metrics/CgroupMetricsProviderTests.cs | 211 +++++++------ .../FreeAndTotalMemoryProviderTests.cs | 34 ++ .../Metrics/Linux/GlobalMemoryStatusTests.cs | 128 ++++++++ .../TestHelpers/CgroupFileHelper.cs | 292 ++++++++++++++++++ .../TestResources/proc/cgroup | 2 - .../TestResources/proc/cgroup2 | 2 - .../TestResources/proc/cgroup2_only_0 | 1 - .../TestResources/proc/cgroup2_only_memory | 1 - .../proc/limited/memory/memory.limit_in_bytes | 1 - .../proc/limited/memory/memory.stat | 40 --- .../proc/limited/memory/memory.usage_in_bytes | 1 - .../TestResources/proc/meminfo | 6 - .../TestResources/proc/meminfo-3.14 | 7 - .../proc/sys_cgroup2/slice/memory.current | 1 - .../proc/sys_cgroup2/slice/memory.max | 1 - .../proc/sys_cgroup2/slice/memory.stat | 40 --- .../slice/memory.current | 1 - .../sys_cgroup2_unlimited/slice/memory.max | 1 - .../sys_cgroup2_unlimited/slice/memory.stat | 40 --- .../slice/memory.current | 1 - .../slice/memory.max | 1 - .../slice/memory.stat | 40 --- .../unlimited/memory/memory.limit_in_bytes | 1 - .../proc/unlimited/memory/memory.stat | 40 --- .../unlimited/memory/memory.usage_in_bytes | 1 - 42 files changed, 1326 insertions(+), 608 deletions(-) create mode 100644 benchmarks/Elastic.Apm.Benchmarks/CgroupMetricsProviderBenchmarks.cs create mode 100644 benchmarks/Elastic.Apm.Benchmarks/FreeAndTotalMemoryProviderBenchmarks.cs create mode 100644 benchmarks/Elastic.Apm.Profiling/Elastic.Apm.Profiling.csproj create mode 100644 benchmarks/Elastic.Apm.Profiling/Program.cs create mode 100644 src/Elastic.Apm/Metrics/Linux/GlobalMemoryStatus.cs rename src/Elastic.Apm/Metrics/Windows/{GlobalMemoryStatusEx.cs => GlobalMemoryStatus.cs} (100%) create mode 100644 test/Elastic.Apm.Tests/Metrics/FreeAndTotalMemoryProviderTests.cs create mode 100644 test/Elastic.Apm.Tests/Metrics/Linux/GlobalMemoryStatusTests.cs create mode 100644 test/Elastic.Apm.Tests/TestHelpers/CgroupFileHelper.cs delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/cgroup delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/cgroup2 delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_0 delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_memory delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.limit_in_bytes delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.stat delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.usage_in_bytes delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/meminfo delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/meminfo-3.14 delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.current delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.max delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.stat delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.current delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.max delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.stat delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.current delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.max delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.stat delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.limit_in_bytes delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.stat delete mode 100644 test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.usage_in_bytes diff --git a/.editorconfig b/.editorconfig index 03d07b427..c5c598041 100644 --- a/.editorconfig +++ b/.editorconfig @@ -202,6 +202,8 @@ resharper_csharp_accessor_owner_body=expression_body resharper_redundant_case_label_highlighting=do_not_show resharper_redundant_argument_default_value_highlighting=do_not_show +dotnet_diagnostic.IDE0057.severity = none + [*.{sh,bat,ps1}] trim_trailing_whitespace=true insert_final_newline=true diff --git a/ElasticApmAgent.sln b/ElasticApmAgent.sln index 53989af2a..c82db139d 100644 --- a/ElasticApmAgent.sln +++ b/ElasticApmAgent.sln @@ -1,6 +1,7 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30309.148 + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34221.43 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{3734A52F-2222-454B-BF58-1BA5C1F29D77}" ProjectSection(SolutionItems) = preProject @@ -33,7 +34,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HttpListenerSample", "sampl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Benchmarks", "benchmarks\Elastic.Apm.Benchmarks\Elastic.Apm.Benchmarks.csproj", "{F069CE99-F418-4BC2-9E44-8F03497D8DA8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetFullFrameworkSampleApp", "test\iis\AspNetFullFrameworkSampleApp\AspNetFullFrameworkSampleApp.csproj", "{C45DCD78-7E8A-437C-ABBB-01D154ABCFC4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetFullFrameworkSampleApp", "test\iis\AspNetFullFrameworkSampleApp\AspNetFullFrameworkSampleApp.csproj", "{C45DCD78-7E8A-437C-ABBB-01D154ABCFC4}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiSample", "test\integrations\applications\WebApiSample\WebApiSample.csproj", "{319E2094-D2E1-46C5-8985-9693CD8DDCBD}" EndProject @@ -87,111 +88,111 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Extensions.Logg EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.MongoDb.Tests", "test\instrumentations\Elastic.Apm.MongoDb.Tests\Elastic.Apm.MongoDb.Tests.csproj", "{FB07C133-C353-4061-A308-B9A6EF48AB7E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.ServiceBus.Tests", "test\azure\Elastic.Apm.Azure.ServiceBus.Tests\Elastic.Apm.Azure.ServiceBus.Tests.csproj", "{D9CC53B2-5F6B-434B-8689-2350F3A9FB2D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.ServiceBus.Tests", "test\azure\Elastic.Apm.Azure.ServiceBus.Tests\Elastic.Apm.Azure.ServiceBus.Tests.csproj", "{D9CC53B2-5F6B-434B-8689-2350F3A9FB2D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.ServiceBus.Sample", "sample\Elastic.Apm.Azure.ServiceBus.Sample\Elastic.Apm.Azure.ServiceBus.Sample.csproj", "{27563B4E-ECB1-4F1B-B9F1-22C2C165B270}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.ServiceBus.Sample", "sample\Elastic.Apm.Azure.ServiceBus.Sample\Elastic.Apm.Azure.ServiceBus.Sample.csproj", "{27563B4E-ECB1-4F1B-B9F1-22C2C165B270}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.Storage.Tests", "test\azure\Elastic.Apm.Azure.Storage.Tests\Elastic.Apm.Azure.Storage.Tests.csproj", "{37BD6194-A47B-4D17-BB9A-642E8909DED9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.Storage.Tests", "test\azure\Elastic.Apm.Azure.Storage.Tests\Elastic.Apm.Azure.Storage.Tests.csproj", "{37BD6194-A47B-4D17-BB9A-642E8909DED9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.CosmosDb.Tests", "test\azure\Elastic.Apm.Azure.CosmosDb.Tests\Elastic.Apm.Azure.CosmosDb.Tests.csproj", "{0EEA16C4-C7DF-4D90-94C2-009417D765AC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.CosmosDb.Tests", "test\azure\Elastic.Apm.Azure.CosmosDb.Tests\Elastic.Apm.Azure.CosmosDb.Tests.csproj", "{0EEA16C4-C7DF-4D90-94C2-009417D765AC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NpgsqlSample", "test\profiler\applications\NpgsqlSample\NpgsqlSample.csproj", "{BA2D3FCD-C25E-4E34-9A30-BE1FB16E1841}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NpgsqlSample", "test\profiler\applications\NpgsqlSample\NpgsqlSample.csproj", "{BA2D3FCD-C25E-4E34-9A30-BE1FB16E1841}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Profiler.Managed.Tests", "test\profiler\Elastic.Apm.Profiler.Managed.Tests\Elastic.Apm.Profiler.Managed.Tests.csproj", "{4983083A-87AD-496E-B0BC-84C8097D0590}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Profiler.Managed.Tests", "test\profiler\Elastic.Apm.Profiler.Managed.Tests\Elastic.Apm.Profiler.Managed.Tests.csproj", "{4983083A-87AD-496E-B0BC-84C8097D0590}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.AdoNet", "test\profiler\applications\Elastic.Apm.AdoNet\Elastic.Apm.AdoNet.csproj", "{14BEE605-6180-4B9E-87F5-A24BA79461B5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.AdoNet", "test\profiler\applications\Elastic.Apm.AdoNet\Elastic.Apm.AdoNet.csproj", "{14BEE605-6180-4B9E-87F5-A24BA79461B5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.AdoNet.NetStandard", "test\profiler\applications\Elastic.Apm.AdoNet.NetStandard\Elastic.Apm.AdoNet.NetStandard.csproj", "{AAB983A1-6080-449D-95D8-7E7BA05DDFAA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.AdoNet.NetStandard", "test\profiler\applications\Elastic.Apm.AdoNet.NetStandard\Elastic.Apm.AdoNet.NetStandard.csproj", "{AAB983A1-6080-449D-95D8-7E7BA05DDFAA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySqlDataSample", "test\profiler\applications\MySqlDataSample\MySqlDataSample.csproj", "{346D3A9A-1296-4915-BB6C-8533731D3B3B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MySqlDataSample", "test\profiler\applications\MySqlDataSample\MySqlDataSample.csproj", "{346D3A9A-1296-4915-BB6C-8533731D3B3B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqliteSample", "test\profiler\applications\SqliteSample\SqliteSample.csproj", "{F72182DC-A933-4C4B-8321-830D0DFB857C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqliteSample", "test\profiler\applications\SqliteSample\SqliteSample.csproj", "{F72182DC-A933-4C4B-8321-830D0DFB857C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OracleManagedDataAccessSample", "test\profiler\applications\OracleManagedDataAccessSample\OracleManagedDataAccessSample.csproj", "{FFA9A7E4-954F-47A1-A9FD-0FE07EB846C6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OracleManagedDataAccessSample", "test\profiler\applications\OracleManagedDataAccessSample\OracleManagedDataAccessSample.csproj", "{FFA9A7E4-954F-47A1-A9FD-0FE07EB846C6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OracleManagedDataAccessCoreSample", "test\profiler\applications\OracleManagedDataAccessCoreSample\OracleManagedDataAccessCoreSample.csproj", "{8CF18906-150C-4AD9-B108-2A39B31105C5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OracleManagedDataAccessCoreSample", "test\profiler\applications\OracleManagedDataAccessCoreSample\OracleManagedDataAccessCoreSample.csproj", "{8CF18906-150C-4AD9-B108-2A39B31105C5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlClientSample", "test\profiler\applications\SqlClientSample\SqlClientSample.csproj", "{456A8639-FE1B-426A-9C72-5252AB4D3AD5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SqlClientSample", "test\profiler\applications\SqlClientSample\SqlClientSample.csproj", "{456A8639-FE1B-426A-9C72-5252AB4D3AD5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KafkaSample", "test\profiler\applications\KafkaSample\KafkaSample.csproj", "{2B23487A-B340-4F5C-A49B-9B829F437A5A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KafkaSample", "test\profiler\applications\KafkaSample\KafkaSample.csproj", "{2B23487A-B340-4F5C-A49B-9B829F437A5A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RabbitMqSample", "test\profiler\applications\RabbitMqSample\RabbitMqSample.csproj", "{1D6B0C67-42C8-4AB4-A795-B6FF8EF7196E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RabbitMqSample", "test\profiler\applications\RabbitMqSample\RabbitMqSample.csproj", "{1D6B0C67-42C8-4AB4-A795-B6FF8EF7196E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTelemetrySample", "test\opentelemetry\OpenTelemetrySample\OpenTelemetrySample.csproj", "{3D31589A-CA44-4D6D-9944-26CE9640A283}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetrySample", "test\opentelemetry\OpenTelemetrySample\OpenTelemetrySample.csproj", "{3D31589A-CA44-4D6D-9944-26CE9640A283}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteAssemblySample", "test\profiler\applications\SatelliteAssemblySample\SatelliteAssemblySample.csproj", "{2B62E740-A493-42D6-BE5E-709BD07F877E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SatelliteAssemblySample", "test\profiler\applications\SatelliteAssemblySample\SatelliteAssemblySample.csproj", "{2B62E740-A493-42D6-BE5E-709BD07F877E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.Functions.Tests", "test\azure\Elastic.Apm.Azure.Functions.Tests\Elastic.Apm.Azure.Functions.Tests.csproj", "{8E3D94CD-3378-4431-8956-07644A64D4E8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.Functions.Tests", "test\azure\Elastic.Apm.Azure.Functions.Tests\Elastic.Apm.Azure.Functions.Tests.csproj", "{8E3D94CD-3378-4431-8956-07644A64D4E8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.AzureFunctionApp.Isolated", "test\azure\applications\Elastic.AzureFunctionApp.Isolated\Elastic.AzureFunctionApp.Isolated.csproj", "{9879E646-63ED-474C-905B-1B469403F0A5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.AzureFunctionApp.Isolated", "test\azure\applications\Elastic.AzureFunctionApp.Isolated\Elastic.AzureFunctionApp.Isolated.csproj", "{9879E646-63ED-474C-905B-1B469403F0A5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Clients.Elasticsearch.Tests", "test\instrumentations\Elastic.Clients.Elasticsearch.Tests\Elastic.Clients.Elasticsearch.Tests.csproj", "{E6217549-8C21-4E95-BDF2-E782922CD104}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Clients.Elasticsearch.Tests", "test\instrumentations\Elastic.Clients.Elasticsearch.Tests\Elastic.Clients.Elasticsearch.Tests.csproj", "{E6217549-8C21-4E95-BDF2-E782922CD104}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = ".github", ".github\.github.csproj", "{A880940E-31FC-4934-80FC-5A9E3DFED7CA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = ".github", ".github\.github.csproj", "{A880940E-31FC-4934-80FC-5A9E3DFED7CA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Microsoft.Data.SqlClient", "sample\Sample.Microsoft.Data.SqlClient\Sample.Microsoft.Data.SqlClient.csproj", "{BCE93684-0A40-4F5F-8FB5-94DE94B111E1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Microsoft.Data.SqlClient", "sample\Sample.Microsoft.Data.SqlClient\Sample.Microsoft.Data.SqlClient.csproj", "{BCE93684-0A40-4F5F-8FB5-94DE94B111E1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azure", "azure", "{C6A7CA94-9D06-4CA1-BAEA-43B607BF939D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.CosmosDb", "src\azure\Elastic.Apm.Azure.CosmosDb\Elastic.Apm.Azure.CosmosDb.csproj", "{42F4F13C-0515-4501-A27B-9815BFF63807}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.CosmosDb", "src\azure\Elastic.Apm.Azure.CosmosDb\Elastic.Apm.Azure.CosmosDb.csproj", "{42F4F13C-0515-4501-A27B-9815BFF63807}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.Functions", "src\azure\Elastic.Apm.Azure.Functions\Elastic.Apm.Azure.Functions.csproj", "{F874E74D-73C7-452D-8ECD-352DE352C9A7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.Functions", "src\azure\Elastic.Apm.Azure.Functions\Elastic.Apm.Azure.Functions.csproj", "{F874E74D-73C7-452D-8ECD-352DE352C9A7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.ServiceBus", "src\azure\Elastic.Apm.Azure.ServiceBus\Elastic.Apm.Azure.ServiceBus.csproj", "{0F632E91-71D4-46EB-8926-E54C51F2878E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.ServiceBus", "src\azure\Elastic.Apm.Azure.ServiceBus\Elastic.Apm.Azure.ServiceBus.csproj", "{0F632E91-71D4-46EB-8926-E54C51F2878E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Azure.Storage", "src\azure\Elastic.Apm.Azure.Storage\Elastic.Apm.Azure.Storage.csproj", "{00F64981-E1EB-4B83-BA78-2F0591CEDF8A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Azure.Storage", "src\azure\Elastic.Apm.Azure.Storage\Elastic.Apm.Azure.Storage.csproj", "{00F64981-E1EB-4B83-BA78-2F0591CEDF8A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "profiler", "profiler", "{EAD9B32C-46FC-44AF-8A48-954259F846C5}" ProjectSection(SolutionItems) = preProject - Makefile.toml = Makefile.toml Cargo.toml = Cargo.toml + Makefile.toml = Makefile.toml EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "startuphook", "startuphook", "{A9D3E13A-7782-4E0D-9CBB-9954F583F0B3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "elastic_apm_profiler", "src\profiler\elastic_apm_profiler\elastic_apm_profiler.csproj", "{30C75D5A-84F1-4AD1-9761-D35F72C9FBE2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "elastic_apm_profiler", "src\profiler\elastic_apm_profiler\elastic_apm_profiler.csproj", "{30C75D5A-84F1-4AD1-9761-D35F72C9FBE2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Profiler.IntegrationsGenerator", "src\profiler\Elastic.Apm.Profiler.IntegrationsGenerator\Elastic.Apm.Profiler.IntegrationsGenerator.csproj", "{D40BBADA-0A1A-4AD2-BA90-89D27F1E4DF3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Profiler.IntegrationsGenerator", "src\profiler\Elastic.Apm.Profiler.IntegrationsGenerator\Elastic.Apm.Profiler.IntegrationsGenerator.csproj", "{D40BBADA-0A1A-4AD2-BA90-89D27F1E4DF3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Profiler.Managed", "src\profiler\Elastic.Apm.Profiler.Managed\Elastic.Apm.Profiler.Managed.csproj", "{6E388B69-72A1-467A-8645-039870D87446}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Profiler.Managed", "src\profiler\Elastic.Apm.Profiler.Managed\Elastic.Apm.Profiler.Managed.csproj", "{6E388B69-72A1-467A-8645-039870D87446}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Profiler.Managed.Core", "src\profiler\Elastic.Apm.Profiler.Managed.Core\Elastic.Apm.Profiler.Managed.Core.csproj", "{2B8565AA-D0DD-44CB-BCB7-E929198AEF26}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Profiler.Managed.Core", "src\profiler\Elastic.Apm.Profiler.Managed.Core\Elastic.Apm.Profiler.Managed.Core.csproj", "{2B8565AA-D0DD-44CB-BCB7-E929198AEF26}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Profiler.Managed.Loader", "src\profiler\Elastic.Apm.Profiler.Managed.Loader\Elastic.Apm.Profiler.Managed.Loader.csproj", "{322FFF76-6794-4B73-AA32-6A2E5C8D0A12}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Profiler.Managed.Loader", "src\profiler\Elastic.Apm.Profiler.Managed.Loader\Elastic.Apm.Profiler.Managed.Loader.csproj", "{322FFF76-6794-4B73-AA32-6A2E5C8D0A12}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integrations", "integrations", "{3AC678A8-121F-4E78-A926-66ACA382D5AA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Elasticsearch", "src\instrumentations\Elastic.Apm.Elasticsearch\Elastic.Apm.Elasticsearch.csproj", "{7B529958-B4CC-4415-AC45-13C020C6A4A5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Elasticsearch", "src\instrumentations\Elastic.Apm.Elasticsearch\Elastic.Apm.Elasticsearch.csproj", "{7B529958-B4CC-4415-AC45-13C020C6A4A5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.EntityFramework6", "src\instrumentations\Elastic.Apm.EntityFramework6\Elastic.Apm.EntityFramework6.csproj", "{C131822B-ACB2-4E3B-ADAD-3389E71A1349}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.EntityFramework6", "src\instrumentations\Elastic.Apm.EntityFramework6\Elastic.Apm.EntityFramework6.csproj", "{C131822B-ACB2-4E3B-ADAD-3389E71A1349}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.EntityFrameworkCore", "src\instrumentations\Elastic.Apm.EntityFrameworkCore\Elastic.Apm.EntityFrameworkCore.csproj", "{B0047AC4-2819-42C9-BD0A-E9FB48F9333E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.EntityFrameworkCore", "src\instrumentations\Elastic.Apm.EntityFrameworkCore\Elastic.Apm.EntityFrameworkCore.csproj", "{B0047AC4-2819-42C9-BD0A-E9FB48F9333E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.GrpcClient", "src\instrumentations\Elastic.Apm.GrpcClient\Elastic.Apm.GrpcClient.csproj", "{97AF29C9-C208-493C-9714-994C9760DEF6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.GrpcClient", "src\instrumentations\Elastic.Apm.GrpcClient\Elastic.Apm.GrpcClient.csproj", "{97AF29C9-C208-493C-9714-994C9760DEF6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.MongoDb", "src\instrumentations\Elastic.Apm.MongoDb\Elastic.Apm.MongoDb.csproj", "{CEDEF188-B975-4054-8CB1-D08CACB29F06}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.MongoDb", "src\instrumentations\Elastic.Apm.MongoDb\Elastic.Apm.MongoDb.csproj", "{CEDEF188-B975-4054-8CB1-D08CACB29F06}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.StackExchange.Redis", "src\instrumentations\Elastic.Apm.StackExchange.Redis\Elastic.Apm.StackExchange.Redis.csproj", "{096EE982-70B1-44F4-A9E8-5719F9160698}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.StackExchange.Redis", "src\instrumentations\Elastic.Apm.StackExchange.Redis\Elastic.Apm.StackExchange.Redis.csproj", "{096EE982-70B1-44F4-A9E8-5719F9160698}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.StartupHook.Loader", "src\startuphook\Elastic.Apm.StartupHook.Loader\Elastic.Apm.StartupHook.Loader.csproj", "{27AA610C-0A8C-4012-ADE8-E4D8DCE51E9C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.StartupHook.Loader", "src\startuphook\Elastic.Apm.StartupHook.Loader\Elastic.Apm.StartupHook.Loader.csproj", "{27AA610C-0A8C-4012-ADE8-E4D8DCE51E9C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElasticApmAgentStartupHook", "src\startuphook\ElasticApmAgentStartupHook\ElasticApmAgentStartupHook.csproj", "{00BF8113-BB06-4B5F-8935-F44E2F58FD53}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ElasticApmAgentStartupHook", "src\startuphook\ElasticApmAgentStartupHook\ElasticApmAgentStartupHook.csproj", "{00BF8113-BB06-4B5F-8935-F44E2F58FD53}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "instrumentations", "instrumentations", "{2E405876-0925-4B96-94B6-6C529E52D47D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.AspNetCore", "src\integrations\Elastic.Apm.AspNetCore\Elastic.Apm.AspNetCore.csproj", "{62BE33DF-5E53-49DF-97B4-95AB3ED8781E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.AspNetCore", "src\integrations\Elastic.Apm.AspNetCore\Elastic.Apm.AspNetCore.csproj", "{62BE33DF-5E53-49DF-97B4-95AB3ED8781E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.AspNetFullFramework", "src\integrations\Elastic.Apm.AspNetFullFramework\Elastic.Apm.AspNetFullFramework.csproj", "{6C6A54F2-6598-46AD-9432-9FEC037B7A97}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.AspNetFullFramework", "src\integrations\Elastic.Apm.AspNetFullFramework\Elastic.Apm.AspNetFullFramework.csproj", "{6C6A54F2-6598-46AD-9432-9FEC037B7A97}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Extensions.Hosting", "src\integrations\Elastic.Apm.Extensions.Hosting\Elastic.Apm.Extensions.Hosting.csproj", "{439BA5FA-5977-48E3-9FED-10F28CD2D3D1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Extensions.Hosting", "src\integrations\Elastic.Apm.Extensions.Hosting\Elastic.Apm.Extensions.Hosting.csproj", "{439BA5FA-5977-48E3-9FED-10F28CD2D3D1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Extensions.Logging", "src\integrations\Elastic.Apm.Extensions.Logging\Elastic.Apm.Extensions.Logging.csproj", "{CD8BF331-B689-48F8-9858-368B7196EBD5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.Extensions.Logging", "src\integrations\Elastic.Apm.Extensions.Logging\Elastic.Apm.Extensions.Logging.csproj", "{CD8BF331-B689-48F8-9858-368B7196EBD5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.NetCoreAll", "src\integrations\Elastic.Apm.NetCoreAll\Elastic.Apm.NetCoreAll.csproj", "{235596AC-E683-4D2E-B328-CDA79CDB7DC8}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.NetCoreAll", "src\integrations\Elastic.Apm.NetCoreAll\Elastic.Apm.NetCoreAll.csproj", "{235596AC-E683-4D2E-B328-CDA79CDB7DC8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "docs", "docs\docs.csproj", "{7DA216DD-F842-41FE-8D1B-D2925B46E551}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "docs", "docs\docs.csproj", "{7DA216DD-F842-41FE-8D1B-D2925B46E551}" EndProject -Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "build", "build\build.fsproj", "{69C34D4F-13A5-43DE-A126-954B85F8A33E}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "build", "build\build.fsproj", "{69C34D4F-13A5-43DE-A126-954B85F8A33E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "benchmarks", "benchmarks", "{2825A761-5372-4620-99AB-253AD953E8CD}" ProjectSection(SolutionItems) = preProject @@ -216,17 +217,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "applications", "application EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "opentelemetry", "opentelemetry", "{1CDE0A67-0245-4CB0-A1B9-D17CCC388E82}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.OpenTelemetry.Tests", "test\opentelemetry\Elastic.Apm.OpenTelemetry.Tests\Elastic.Apm.OpenTelemetry.Tests.csproj", "{8EF0BEC9-C979-42B9-9447-F03570CCAA24}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.OpenTelemetry.Tests", "test\opentelemetry\Elastic.Apm.OpenTelemetry.Tests\Elastic.Apm.OpenTelemetry.Tests.csproj", "{8EF0BEC9-C979-42B9-9447-F03570CCAA24}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iis", "iis", "{C770AFE9-5C16-4C7F-ABE7-2B839DF9E715}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.FullFramework.Tests", "test\iis\Elastic.Apm.FullFramework.Tests\Elastic.Apm.FullFramework.Tests.csproj", "{7CCA63B5-B3C7-44EB-9794-9AFE04527CC5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.FullFramework.Tests", "test\iis\Elastic.Apm.FullFramework.Tests\Elastic.Apm.FullFramework.Tests.csproj", "{7CCA63B5-B3C7-44EB-9794-9AFE04527CC5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.AzureFunctionApp.InProcess", "test\azure\applications\Elastic.AzureFunctionApp.InProcess\Elastic.AzureFunctionApp.InProcess.csproj", "{A1E60FBF-38AD-4B99-B697-D9F355AF9818}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.AzureFunctionApp.InProcess", "test\azure\applications\Elastic.AzureFunctionApp.InProcess\Elastic.AzureFunctionApp.InProcess.csproj", "{A1E60FBF-38AD-4B99-B697-D9F355AF9818}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "applications", "applications", "{09CE5AC1-01F6-48C8-B266-2F891C408051}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.AzureFunctionApp.Core", "test\azure\applications\Elastic.Apm.AzureFunctionApp.Core\Elastic.Apm.AzureFunctionApp.Core.csproj", "{50F14EA5-DF72-425B-81A6-C7D532D2DD07}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elastic.Apm.AzureFunctionApp.Core", "test\azure\applications\Elastic.Apm.AzureFunctionApp.Core\Elastic.Apm.AzureFunctionApp.Core.csproj", "{50F14EA5-DF72-425B-81A6-C7D532D2DD07}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elastic.Apm.Profiling", "benchmarks\Elastic.Apm.Profiling\Elastic.Apm.Profiling.csproj", "{CB6B3BA6-9D16-4CDC-95C2-7680CF50747D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -364,6 +367,10 @@ Global {B235B13F-42AE-42DA-A3C8-20D047F38685}.Debug|Any CPU.Build.0 = Debug|Any CPU {B235B13F-42AE-42DA-A3C8-20D047F38685}.Release|Any CPU.ActiveCfg = Release|Any CPU {B235B13F-42AE-42DA-A3C8-20D047F38685}.Release|Any CPU.Build.0 = Release|Any CPU + {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Release|Any CPU.Build.0 = Release|Any CPU {D9CC53B2-5F6B-434B-8689-2350F3A9FB2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D9CC53B2-5F6B-434B-8689-2350F3A9FB2D}.Debug|Any CPU.Build.0 = Debug|Any CPU {D9CC53B2-5F6B-434B-8689-2350F3A9FB2D}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -376,10 +383,6 @@ Global {37BD6194-A47B-4D17-BB9A-642E8909DED9}.Debug|Any CPU.Build.0 = Debug|Any CPU {37BD6194-A47B-4D17-BB9A-642E8909DED9}.Release|Any CPU.ActiveCfg = Release|Any CPU {37BD6194-A47B-4D17-BB9A-642E8909DED9}.Release|Any CPU.Build.0 = Release|Any CPU - {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB07C133-C353-4061-A308-B9A6EF48AB7E}.Release|Any CPU.Build.0 = Release|Any CPU {0EEA16C4-C7DF-4D90-94C2-009417D765AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0EEA16C4-C7DF-4D90-94C2-009417D765AC}.Debug|Any CPU.Build.0 = Debug|Any CPU {0EEA16C4-C7DF-4D90-94C2-009417D765AC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -568,22 +571,68 @@ Global {50F14EA5-DF72-425B-81A6-C7D532D2DD07}.Debug|Any CPU.Build.0 = Debug|Any CPU {50F14EA5-DF72-425B-81A6-C7D532D2DD07}.Release|Any CPU.ActiveCfg = Release|Any CPU {50F14EA5-DF72-425B-81A6-C7D532D2DD07}.Release|Any CPU.Build.0 = Release|Any CPU + {CB6B3BA6-9D16-4CDC-95C2-7680CF50747D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB6B3BA6-9D16-4CDC-95C2-7680CF50747D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB6B3BA6-9D16-4CDC-95C2-7680CF50747D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB6B3BA6-9D16-4CDC-95C2-7680CF50747D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {0ADF687D-4DB7-417E-80B4-27B3FD86875E} = {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} {90BC9629-C8D2-4FD5-863E-EA2D5FB37341} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} {4BEAD125-6F93-4566-A1D3-362F55D7AD4C} = {267A241E-571F-458F-B04C-B6C4DE79E735} + {36D72723-2161-4322-A04B-E97D0CB48EF6} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} {19C9C1BA-4BCC-4708-92C3-8F5AE18B44F8} = {3C791D9C-6F19-4F46-B367-2EC0F818762D} {1AAB1A30-42C0-4C76-AE2E-9D7293945D80} = {3C791D9C-6F19-4F46-B367-2EC0F818762D} + {F069CE99-F418-4BC2-9E44-8F03497D8DA8} = {2825A761-5372-4620-99AB-253AD953E8CD} + {C45DCD78-7E8A-437C-ABBB-01D154ABCFC4} = {C770AFE9-5C16-4C7F-ABE7-2B839DF9E715} + {319E2094-D2E1-46C5-8985-9693CD8DDCBD} = {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} + {40B47FD4-6E67-4D52-B9A4-607B9D01D9F5} = {4F060027-5614-4C64-9338-128C7E9CE8A4} + {4253798D-A160-40B3-8F16-5BF64C559B93} = {C770AFE9-5C16-4C7F-ABE7-2B839DF9E715} {AFFB238B-10C0-4229-9527-184EFCF0F5AC} = {267A241E-571F-458F-B04C-B6C4DE79E735} + {79BEA612-E2C8-47FD-84DC-A1B17AAD5038} = {4F060027-5614-4C64-9338-128C7E9CE8A4} + {968E1E85-E996-42DE-9845-D20DAE16165A} = {4F060027-5614-4C64-9338-128C7E9CE8A4} {A4EF875C-92AD-4538-AFF1-1DA277F1085A} = {267A241E-571F-458F-B04C-B6C4DE79E735} + {00AD0047-92A6-48CC-B67D-A3DB2812CE28} = {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} + {E30DEF03-4E0B-46A0-87D0-E80545D99BBA} = {4F060027-5614-4C64-9338-128C7E9CE8A4} {0FE5E852-E3AF-45F9-BF3A-8CD739C0807F} = {3C791D9C-6F19-4F46-B367-2EC0F818762D} + {6E6B9E49-EE42-4EB6-8248-BEEC8522937B} = {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} + {CC52EA80-5E18-4370-ACB3-9424B6BB6B68} = {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} + {3AD5584E-057A-4C52-84EA-32A9BBE12F03} = {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} + {3CCB9193-8416-49AF-A1A3-8D1118CFB25B} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} {9FBC8D8C-E600-464D-AE4E-AC1FB59485F6} = {3C791D9C-6F19-4F46-B367-2EC0F818762D} + {6D413E0A-1CB7-4A2D-8E99-DB4F58D3463E} = {4F060027-5614-4C64-9338-128C7E9CE8A4} {5D076C7F-1F8B-4B11-9910-48717D133963} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} + {2250D888-E4CC-4B2B-AF31-5C78D76EC73D} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} {43F9247D-544B-49FB-9E50-FC236D90DE1A} = {267A241E-571F-458F-B04C-B6C4DE79E735} + {CE0120A5-A094-40A3-905E-8E14526800D3} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} + {DC879845-353B-4C62-9640-6EA3008326F7} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} + {B168C594-0314-4201-A55B-13DBBE2796FE} = {93686A26-AD8A-498C-BC0E-FF8258F3D20C} + {9AE4805D-2586-4FA5-A0D0-885264EBC565} = {93686A26-AD8A-498C-BC0E-FF8258F3D20C} + {B235B13F-42AE-42DA-A3C8-20D047F38685} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} + {FB07C133-C353-4061-A308-B9A6EF48AB7E} = {4F060027-5614-4C64-9338-128C7E9CE8A4} + {D9CC53B2-5F6B-434B-8689-2350F3A9FB2D} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} {27563B4E-ECB1-4F1B-B9F1-22C2C165B270} = {3C791D9C-6F19-4F46-B367-2EC0F818762D} + {37BD6194-A47B-4D17-BB9A-642E8909DED9} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} + {0EEA16C4-C7DF-4D90-94C2-009417D765AC} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} + {BA2D3FCD-C25E-4E34-9A30-BE1FB16E1841} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {4983083A-87AD-496E-B0BC-84C8097D0590} = {E38F295C-05DD-4328-A2BD-2868754624B7} + {14BEE605-6180-4B9E-87F5-A24BA79461B5} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {AAB983A1-6080-449D-95D8-7E7BA05DDFAA} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {346D3A9A-1296-4915-BB6C-8533731D3B3B} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {F72182DC-A933-4C4B-8321-830D0DFB857C} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {FFA9A7E4-954F-47A1-A9FD-0FE07EB846C6} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {8CF18906-150C-4AD9-B108-2A39B31105C5} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {456A8639-FE1B-426A-9C72-5252AB4D3AD5} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {2B23487A-B340-4F5C-A49B-9B829F437A5A} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {1D6B0C67-42C8-4AB4-A795-B6FF8EF7196E} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {3D31589A-CA44-4D6D-9944-26CE9640A283} = {1CDE0A67-0245-4CB0-A1B9-D17CCC388E82} + {2B62E740-A493-42D6-BE5E-709BD07F877E} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} + {8E3D94CD-3378-4431-8956-07644A64D4E8} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} + {9879E646-63ED-474C-905B-1B469403F0A5} = {09CE5AC1-01F6-48C8-B266-2F891C408051} + {E6217549-8C21-4E95-BDF2-E782922CD104} = {4F060027-5614-4C64-9338-128C7E9CE8A4} {BCE93684-0A40-4F5F-8FB5-94DE94B111E1} = {3C791D9C-6F19-4F46-B367-2EC0F818762D} {C6A7CA94-9D06-4CA1-BAEA-43B607BF939D} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} {42F4F13C-0515-4501-A27B-9815BFF63807} = {C6A7CA94-9D06-4CA1-BAEA-43B607BF939D} @@ -591,21 +640,19 @@ Global {0F632E91-71D4-46EB-8926-E54C51F2878E} = {C6A7CA94-9D06-4CA1-BAEA-43B607BF939D} {00F64981-E1EB-4B83-BA78-2F0591CEDF8A} = {C6A7CA94-9D06-4CA1-BAEA-43B607BF939D} {EAD9B32C-46FC-44AF-8A48-954259F846C5} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} - {3AC678A8-121F-4E78-A926-66ACA382D5AA} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} {A9D3E13A-7782-4E0D-9CBB-9954F583F0B3} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} {30C75D5A-84F1-4AD1-9761-D35F72C9FBE2} = {EAD9B32C-46FC-44AF-8A48-954259F846C5} {D40BBADA-0A1A-4AD2-BA90-89D27F1E4DF3} = {EAD9B32C-46FC-44AF-8A48-954259F846C5} {6E388B69-72A1-467A-8645-039870D87446} = {EAD9B32C-46FC-44AF-8A48-954259F846C5} {2B8565AA-D0DD-44CB-BCB7-E929198AEF26} = {EAD9B32C-46FC-44AF-8A48-954259F846C5} {322FFF76-6794-4B73-AA32-6A2E5C8D0A12} = {EAD9B32C-46FC-44AF-8A48-954259F846C5} - + {3AC678A8-121F-4E78-A926-66ACA382D5AA} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} {7B529958-B4CC-4415-AC45-13C020C6A4A5} = {2E405876-0925-4B96-94B6-6C529E52D47D} {C131822B-ACB2-4E3B-ADAD-3389E71A1349} = {2E405876-0925-4B96-94B6-6C529E52D47D} {B0047AC4-2819-42C9-BD0A-E9FB48F9333E} = {2E405876-0925-4B96-94B6-6C529E52D47D} {97AF29C9-C208-493C-9714-994C9760DEF6} = {2E405876-0925-4B96-94B6-6C529E52D47D} {CEDEF188-B975-4054-8CB1-D08CACB29F06} = {2E405876-0925-4B96-94B6-6C529E52D47D} {096EE982-70B1-44F4-A9E8-5719F9160698} = {2E405876-0925-4B96-94B6-6C529E52D47D} - {27AA610C-0A8C-4012-ADE8-E4D8DCE51E9C} = {A9D3E13A-7782-4E0D-9CBB-9954F583F0B3} {00BF8113-BB06-4B5F-8935-F44E2F58FD53} = {A9D3E13A-7782-4E0D-9CBB-9954F583F0B3} {2E405876-0925-4B96-94B6-6C529E52D47D} = {3734A52F-2222-454B-BF58-1BA5C1F29D77} @@ -614,63 +661,22 @@ Global {439BA5FA-5977-48E3-9FED-10F28CD2D3D1} = {3AC678A8-121F-4E78-A926-66ACA382D5AA} {CD8BF331-B689-48F8-9858-368B7196EBD5} = {3AC678A8-121F-4E78-A926-66ACA382D5AA} {235596AC-E683-4D2E-B328-CDA79CDB7DC8} = {3AC678A8-121F-4E78-A926-66ACA382D5AA} - {F069CE99-F418-4BC2-9E44-8F03497D8DA8} = {2825A761-5372-4620-99AB-253AD953E8CD} {E38F295C-05DD-4328-A2BD-2868754624B7} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {4983083A-87AD-496E-B0BC-84C8097D0590} = {E38F295C-05DD-4328-A2BD-2868754624B7} {6BBD3167-D9DE-4165-9A95-84940CD37D93} = {E38F295C-05DD-4328-A2BD-2868754624B7} - {346D3A9A-1296-4915-BB6C-8533731D3B3B} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {8CF18906-150C-4AD9-B108-2A39B31105C5} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {FFA9A7E4-954F-47A1-A9FD-0FE07EB846C6} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {456A8639-FE1B-426A-9C72-5252AB4D3AD5} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {F72182DC-A933-4C4B-8321-830D0DFB857C} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {2B23487A-B340-4F5C-A49B-9B829F437A5A} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {1D6B0C67-42C8-4AB4-A795-B6FF8EF7196E} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {2B62E740-A493-42D6-BE5E-709BD07F877E} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {BA2D3FCD-C25E-4E34-9A30-BE1FB16E1841} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {14BEE605-6180-4B9E-87F5-A24BA79461B5} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} - {AAB983A1-6080-449D-95D8-7E7BA05DDFAA} = {6BBD3167-D9DE-4165-9A95-84940CD37D93} {C2378D3C-2BA8-410F-AEF7-547C411C71C7} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {0EEA16C4-C7DF-4D90-94C2-009417D765AC} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} - {8E3D94CD-3378-4431-8956-07644A64D4E8} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} - {D9CC53B2-5F6B-434B-8689-2350F3A9FB2D} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} - {37BD6194-A47B-4D17-BB9A-642E8909DED9} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} {4F060027-5614-4C64-9338-128C7E9CE8A4} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {E6217549-8C21-4E95-BDF2-E782922CD104} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {6D413E0A-1CB7-4A2D-8E99-DB4F58D3463E} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {968E1E85-E996-42DE-9845-D20DAE16165A} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {FB07C133-C353-4061-A308-B9A6EF48AB7E} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {E30DEF03-4E0B-46A0-87D0-E80545D99BBA} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {79BEA612-E2C8-47FD-84DC-A1B17AAD5038} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {40B47FD4-6E67-4D52-B9A4-607B9D01D9F5} = {4F060027-5614-4C64-9338-128C7E9CE8A4} {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} = {4F060027-5614-4C64-9338-128C7E9CE8A4} - {CC52EA80-5E18-4370-ACB3-9424B6BB6B68} = {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} - {6E6B9E49-EE42-4EB6-8248-BEEC8522937B} = {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} - {3AD5584E-057A-4C52-84EA-32A9BBE12F03} = {8B6EE9D6-8A1B-4F85-AE4C-D03E42DBDDEA} {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {2250D888-E4CC-4B2B-AF31-5C78D76EC73D} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} - {36D72723-2161-4322-A04B-E97D0CB48EF6} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} - {3CCB9193-8416-49AF-A1A3-8D1118CFB25B} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} - {B235B13F-42AE-42DA-A3C8-20D047F38685} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} - {DC879845-353B-4C62-9640-6EA3008326F7} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} - {CE0120A5-A094-40A3-905E-8E14526800D3} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} {93686A26-AD8A-498C-BC0E-FF8258F3D20C} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {9AE4805D-2586-4FA5-A0D0-885264EBC565} = {93686A26-AD8A-498C-BC0E-FF8258F3D20C} - {B168C594-0314-4201-A55B-13DBBE2796FE} = {93686A26-AD8A-498C-BC0E-FF8258F3D20C} {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} = {67A4BFE3-F96E-4BDE-9383-DD0ACE6D3BA1} - {319E2094-D2E1-46C5-8985-9693CD8DDCBD} = {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} - {0ADF687D-4DB7-417E-80B4-27B3FD86875E} = {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} - {00AD0047-92A6-48CC-B67D-A3DB2812CE28} = {59F3FB6E-4B48-4E87-AF3B-78DFED427EF1} {1CDE0A67-0245-4CB0-A1B9-D17CCC388E82} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {3D31589A-CA44-4D6D-9944-26CE9640A283} = {1CDE0A67-0245-4CB0-A1B9-D17CCC388E82} {8EF0BEC9-C979-42B9-9447-F03570CCAA24} = {1CDE0A67-0245-4CB0-A1B9-D17CCC388E82} {C770AFE9-5C16-4C7F-ABE7-2B839DF9E715} = {267A241E-571F-458F-B04C-B6C4DE79E735} - {C45DCD78-7E8A-437C-ABBB-01D154ABCFC4} = {C770AFE9-5C16-4C7F-ABE7-2B839DF9E715} - {4253798D-A160-40B3-8F16-5BF64C559B93} = {C770AFE9-5C16-4C7F-ABE7-2B839DF9E715} {7CCA63B5-B3C7-44EB-9794-9AFE04527CC5} = {C770AFE9-5C16-4C7F-ABE7-2B839DF9E715} - {09CE5AC1-01F6-48C8-B266-2F891C408051} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} {A1E60FBF-38AD-4B99-B697-D9F355AF9818} = {09CE5AC1-01F6-48C8-B266-2F891C408051} - {9879E646-63ED-474C-905B-1B469403F0A5} = {09CE5AC1-01F6-48C8-B266-2F891C408051} + {09CE5AC1-01F6-48C8-B266-2F891C408051} = {C2378D3C-2BA8-410F-AEF7-547C411C71C7} {50F14EA5-DF72-425B-81A6-C7D532D2DD07} = {09CE5AC1-01F6-48C8-B266-2F891C408051} + {CB6B3BA6-9D16-4CDC-95C2-7680CF50747D} = {2825A761-5372-4620-99AB-253AD953E8CD} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {69E02FD9-C9DE-412C-AB6B-5B8BECC6BFA5} diff --git a/benchmarks/Elastic.Apm.Benchmarks/CgroupMetricsProviderBenchmarks.cs b/benchmarks/Elastic.Apm.Benchmarks/CgroupMetricsProviderBenchmarks.cs new file mode 100644 index 000000000..0ee56032a --- /dev/null +++ b/benchmarks/Elastic.Apm.Benchmarks/CgroupMetricsProviderBenchmarks.cs @@ -0,0 +1,130 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections.Generic; +using System.IO; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; +using Elastic.Apm.Helpers; +using Elastic.Apm.Metrics.MetricsProvider; +using Elastic.Apm.Tests.Utilities; +using static Elastic.Apm.Metrics.MetricsProvider.CgroupMetricsProvider; +using static Elastic.Apm.Tests.TestHelpers.CgroupFileHelper; + +namespace Elastic.Apm.Benchmarks; + +[MemoryDiagnoser] +public class CgroupMetricsProviderBenchmarks +{ + private CgroupPaths _cgroupPaths; + private CgroupMetricsProvider _cgroupMetricsProvider; + private readonly Consumer _consumer = new(); + + [GlobalSetup] + public void Setup() + { + _cgroupPaths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV2); + _cgroupMetricsProvider = TestableCgroupMetricsProvider(new NoopLogger(), new List(), _cgroupPaths.RootPath, true); + } + + [GlobalSetup(Target = nameof(GetSamplesUnlimited))] + public void SetupUnlimited() + { + _cgroupPaths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV2); + UnlimitedMaxMemoryFiles(_cgroupPaths); + _cgroupMetricsProvider = TestableCgroupMetricsProvider(new NoopLogger(), new List(), _cgroupPaths.RootPath, true); + } + + private static void UnlimitedMaxMemoryFiles(CgroupPaths paths) + { + if (paths.CgroupVersion == CgroupVersion.CgroupV1) + { + using var sr = new StreamWriter(File.Create(Path.Combine(paths.CgroupV1MemoryControllerPath, "memory.limit_in_bytes"))); + sr.WriteAsync($"9223372036854771712\n"); + } + + if (paths.CgroupVersion == CgroupVersion.CgroupV2) + { + using var sr = new StreamWriter(File.Create(Path.Combine(paths.CgroupV2SlicePath, "memory.max"))); + sr.WriteAsync($"max\n"); + } + } + + [GlobalCleanup] + public void Cleanup() + => Directory.Delete(_cgroupPaths.RootPath, true); + + [Benchmark] + public void GetSamples() + { + foreach (var metricSet in _cgroupMetricsProvider.GetSamples()) + { + metricSet.Samples.Consume(_consumer); + } + } + + // WINDOWS: + //| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | + //|-------------------- |---------:|--------:|---------:|---------:|--------:|-------:|----------:|------------:| + //| GetSamplesOriginal | 433.0 us | 8.39 us | 11.20 us | baseline | | 1.9531 | 29.4 KB | | + //| GetSamplesOptimised | 409.9 us | 5.11 us | 4.53 us | -5% | 3.0% | - | 1.47 KB | -95% | + + // WINDOWS: After yield return + //| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | + //|-------------------- |---------:|--------:|---------:|---------:|--------:|-------:|----------:|------------:| + //| GetSamplesOriginal | 429.1 us | 8.08 us | 13.93 us | baseline | | 1.9531 | 29.44 KB | | + //| GetSamplesOptimised | 419.7 us | 6.83 us | 6.39 us | -5% | 3.3% | - | 1.46 KB | -95% | + + // WINDOWS: Remove metric + //| Method | Mean | Error | StdDev | Allocated | Alloc Ratio | + //|-------------------- |---------:|--------:|--------:|----------:|------------:| + //| GetSamples | 296.9 us | 3.46 us | 3.23 us | 1.05 KB | -96% | + + // LINUX: After yield return + //| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio | + //|-------------------- |---------:|----------:|----------:|---------:|--------:|-------:|-------:|----------:|------------:| + //| GetSamplesOriginal | 9.643 us | 0.1600 us | 0.1418 us | baseline | | 2.3346 | 0.0610 | 29328 B | | + //| GetSamplesOptimised | 5.525 us | 0.0580 us | 0.0569 us | -43% | 1.6% | 0.0534 | - | 680 B | -98% | + + // LINUX: Remove metric + //| Method | Mean | Error | Ratio | StdDev | Gen0 | Allocated | Alloc Ratio | + //|-------------------- |---------:|----------:|---------:|----------:|-------:|----------:| | + //| GetSamples | 4.363 us | 0.0458 us | -55% | 0.0382 us | 0.0381 | 496 B | -98% | + + [Benchmark] + public void GetSamplesUnlimited() + { + foreach (var metricSet in _cgroupMetricsProvider.GetSamples()) + { + metricSet.Samples.Consume(_consumer); + } + } + + // WINDOWS: + //| Method | Mean | Error | StdDev | Gen0 | Allocated | + //|-------------------- |---------:|--------:|--------:|-------:|----------:| + //| GetSamplesUnlimited | 467.1 us | 9.28 us | 9.11 us | 0.4883 | 9.5 KB | + + // WINDOWS: Optimised + //| Method | Mean | Error | StdDev | Allocated | + //|-------------------- |---------:|--------:|--------:|----------:| + //| GetSamplesUnlimited | 444.9 us | 8.46 us | 8.69 us | 1.88 KB | + + // WINDOWS: Remove metric + //| Method | Mean | Error | StdDev | Allocated | Alloc Ratio | + //|-------------------- |---------:|--------:|--------:|----------:| | + //| GetSamplesUnlimited | 305.4 us | 5.04 us | 4.71 us | 1.43 KB | -85% | + + // LINUX: Optimised + //| Method | Mean | Error | StdDev | Gen0 | Allocated | + //|-------------------- |---------:|----------:|----------:|-------:|----------:| + //| GetSamplesUnlimited | 7.217 us | 0.1375 us | 0.1350 us | 0.0687 | 864 B | + //** NOTE: This includes some overhead (176 bytes) for building the test path which is not incurred + //in production. This is there equivient to the limited benchmark when this is taken into account. + + // LINUX: Remove metric + //| Method | Mean | Error | StdDev | Gen0 | Allocated | + //|-------------------- |---------:|----------:|----------:|-------:|----------:| + //| GetSamplesUnlimited | 4.908 us | 0.0736 us | 0.0688 us | 0.0534 | 680 B | +} diff --git a/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj b/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj index 86cf07c71..665cefdda 100644 --- a/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj +++ b/benchmarks/Elastic.Apm.Benchmarks/Elastic.Apm.Benchmarks.csproj @@ -10,19 +10,13 @@ - + - - - - - - - - PreserveNewest - + + + diff --git a/benchmarks/Elastic.Apm.Benchmarks/FreeAndTotalMemoryProviderBenchmarks.cs b/benchmarks/Elastic.Apm.Benchmarks/FreeAndTotalMemoryProviderBenchmarks.cs new file mode 100644 index 000000000..b53e052d8 --- /dev/null +++ b/benchmarks/Elastic.Apm.Benchmarks/FreeAndTotalMemoryProviderBenchmarks.cs @@ -0,0 +1,55 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections.Generic; +using System.IO; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Engines; +using Elastic.Apm.Helpers; +using Elastic.Apm.Metrics.MetricsProvider; +using Elastic.Apm.Tests.Utilities; +using static Elastic.Apm.Tests.TestHelpers.CgroupFileHelper; + +namespace Elastic.Apm.Benchmarks; + +[MemoryDiagnoser] +public class FreeAndTotalMemoryProviderBenchmarks +{ + private CgroupPaths _cgroupPaths; + private FreeAndTotalMemoryProvider _freeAndTotalMemoryProvider; + private readonly Consumer _consumer = new(); + + [GlobalSetup] + public void Setup() + { + _cgroupPaths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV2); + _freeAndTotalMemoryProvider = FreeAndTotalMemoryProvider + .TestableFreeAndTotalMemoryProvider(new NoopLogger(), new List(), _cgroupPaths.RootPath, true); + } + + [GlobalCleanup] + public void Cleanup() + => Directory.Delete(_cgroupPaths.RootPath, true); + + [Benchmark] + public void GetSamples() + { + foreach (var metricSet in _freeAndTotalMemoryProvider.GetSamples()) + { + metricSet.Samples.Consume(_consumer); + } + } + + // WINDOWS + //| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | + //|------------------- |---------:|---------:|---------:|---------:|--------:|-------:|----------:|------------:| + //| GetSamplesOriginal | 600.1 ns | 12.00 ns | 17.22 ns | baseline | | 0.0277 | 352 B | | + //| GetSamples | 553.8 ns | 10.57 ns | 12.98 ns | -8% | 3.2% | 0.0162 | 208 B | -41% | + + // LINUX + //| Method | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio | + //|------------------- |-----------:|---------:|----------:|---------:|--------:|-------:|-------:|----------:|------------:| + //| GetSamplesOriginal | 3,693.2 ns | 73.86 ns | 108.27 ns | baseline | | 0.7324 | 0.0191 | 9216 B | | + //| GetSamples | 438.7 ns | 8.57 ns | 8.41 ns | -88% | 3.1% | 0.0215 | - | 272 B | -97% | +} diff --git a/benchmarks/Elastic.Apm.Benchmarks/MetricsBenchmarks.cs b/benchmarks/Elastic.Apm.Benchmarks/MetricsBenchmarks.cs index 41db0b685..112bf3117 100644 --- a/benchmarks/Elastic.Apm.Benchmarks/MetricsBenchmarks.cs +++ b/benchmarks/Elastic.Apm.Benchmarks/MetricsBenchmarks.cs @@ -58,7 +58,7 @@ public void CollectTotalCpuTime2X() [Benchmark] public void CollectTotalAndFreeMemory2X() { - var mockPayloadSender = new FreeAndTotalMemoryProvider(new List()); + var mockPayloadSender = new FreeAndTotalMemoryProvider(new NoopLogger(), new List()); mockPayloadSender.GetSamples(); mockPayloadSender.GetSamples(); diff --git a/benchmarks/Elastic.Apm.Benchmarks/Program.cs b/benchmarks/Elastic.Apm.Benchmarks/Program.cs index 93e59359e..d8c02a271 100644 --- a/benchmarks/Elastic.Apm.Benchmarks/Program.cs +++ b/benchmarks/Elastic.Apm.Benchmarks/Program.cs @@ -3,7 +3,10 @@ // See the LICENSE file in the project root for more information using System; +using System.IO; +using BenchmarkDotNet.Columns; using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Reports; using BenchmarkDotNet.Running; using Elastic.Apm.Benchmarks.Helpers; using Elastic.CommonSchema.BenchmarkDotNetExporter; @@ -14,6 +17,11 @@ public class Program { public static void Main(string[] args) { + //var thing = new FreeAndTotalMemoryProviderBenchmarks(); + //thing.Setup(); + //thing.GetSamplesOriginal(); + //thing.Cleanup(); + var esUrl = Environment.GetEnvironmentVariable("ES_URL"); var esPassword = Environment.GetEnvironmentVariable("ES_PASS"); var esUser = Environment.GetEnvironmentVariable("ES_USER"); @@ -46,8 +54,11 @@ public static void Main(string[] args) } } - var exporter = new ElasticsearchBenchmarkExporter(options); - var config = DefaultConfig.Instance.AddExporter(exporter); + //var exporter = new ElasticsearchBenchmarkExporter(options); + var config = DefaultConfig.Instance + //.AddExporter(exporter) + .WithSummaryStyle(new SummaryStyle(null, false, null, null, ratioStyle: RatioStyle.Percentage)); + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config); } } diff --git a/benchmarks/Elastic.Apm.Profiling/Elastic.Apm.Profiling.csproj b/benchmarks/Elastic.Apm.Profiling/Elastic.Apm.Profiling.csproj new file mode 100644 index 000000000..c6841ef0f --- /dev/null +++ b/benchmarks/Elastic.Apm.Profiling/Elastic.Apm.Profiling.csproj @@ -0,0 +1,21 @@ + + + + Exe + net7.0 + enable + enable + false + + + + + + + + + + + + + diff --git a/benchmarks/Elastic.Apm.Profiling/Program.cs b/benchmarks/Elastic.Apm.Profiling/Program.cs new file mode 100644 index 000000000..78f6bfcf1 --- /dev/null +++ b/benchmarks/Elastic.Apm.Profiling/Program.cs @@ -0,0 +1,63 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using Elastic.Apm.Helpers; +using Elastic.Apm.Logging; +using Elastic.Apm.Metrics.MetricsProvider; +using JetBrains.Profiler.Api; +using static Elastic.Apm.Metrics.MetricsProvider.CgroupMetricsProvider; +using static Elastic.Apm.Tests.TestHelpers.CgroupFileHelper; + +var paths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV1); +UnlimitedMaxMemoryFiles(paths); + +// WARMUP + +var sut = TestableCgroupMetricsProvider(new NoopLogger(), new List(), paths.RootPath, true); +//var sut = new FreeAndTotalMemoryProvider(new NoopLogger(), new List()); +foreach (var metricSet in sut.GetSamples()) + foreach (var _ in metricSet.Samples) + { + } + +// PROFILING + +MemoryProfiler.CollectAllocations(true); + +MemoryProfiler.GetSnapshot("Before create"); + +sut = TestableCgroupMetricsProvider(new NoopLogger(), new List(), paths.RootPath, true); +//sut = new FreeAndTotalMemoryProvider(new NoopLogger(), new List()); + +MemoryProfiler.GetSnapshot("After create"); + +foreach (var metricSet in sut.GetSamples()) + foreach (var _ in metricSet.Samples) + { + } + +MemoryProfiler.GetSnapshot("After get samples"); + +MemoryProfiler.CollectAllocations(false); + +static void UnlimitedMaxMemoryFiles(CgroupPaths paths) +{ + if (paths.CgroupVersion == CgroupVersion.CgroupV1) + { + using var sr = new StreamWriter(File.Create(Path.Combine(paths.CgroupV1MemoryControllerPath, "memory.limit_in_bytes"))); + sr.WriteAsync($"9223372036854771712\n"); + } + + if (paths.CgroupVersion == CgroupVersion.CgroupV2) + { + using var sr = new StreamWriter(File.Create(Path.Combine(paths.CgroupV2SlicePath, "memory.max"))); + sr.WriteAsync($"max\n"); + } +} + +internal sealed class NoopLogger : IApmLogger +{ + public bool IsEnabled(LogLevel level) => false; + public void Log(LogLevel level, TState state, Exception e, Func formatter) { } +} diff --git a/build/scripts/Build.fs b/build/scripts/Build.fs index bcd1deec3..25eda918f 100644 --- a/build/scripts/Build.fs +++ b/build/scripts/Build.fs @@ -202,7 +202,7 @@ module Build = //dotnet dotnet-format --exclude src/Elastic.Apm/Libraries/ DotNet.Exec ["dotnet-format"; "--check"; "--exclude"; "src/Elastic.Apm/Libraries/"] - let private copyDllsAndPdbs (destination: DirectoryInfo) (source: DirectoryInfo) = + let private copyDllsAndPdbs (destination: DirectoryInfo) (source: DirectoryInfo) = source.GetFiles() |> Seq.filter (fun file -> file.Extension = ".dll" || file.Extension = ".pdb") |> Seq.iter (fun file -> file.CopyTo(Path.combine destination.FullName file.Name, true) |> ignore) @@ -214,7 +214,7 @@ module Build = let versionedName = sprintf "%s_%s" name (currentAssemblyVersion.ToString()) - let agentDir = Paths.BuildOutput name |> DirectoryInfo + let agentDir = Paths.BuildOutput name |> DirectoryInfo agentDir.Create() // copy startup hook to root of agent directory diff --git a/src/Elastic.Apm/Elastic.Apm.csproj b/src/Elastic.Apm/Elastic.Apm.csproj index d1f7093c5..47589f7eb 100644 --- a/src/Elastic.Apm/Elastic.Apm.csproj +++ b/src/Elastic.Apm/Elastic.Apm.csproj @@ -26,6 +26,7 @@ + diff --git a/src/Elastic.Apm/Metrics/Linux/GlobalMemoryStatus.cs b/src/Elastic.Apm/Metrics/Linux/GlobalMemoryStatus.cs new file mode 100644 index 000000000..0cb69e84a --- /dev/null +++ b/src/Elastic.Apm/Metrics/Linux/GlobalMemoryStatus.cs @@ -0,0 +1,190 @@ +// Licensed to Elasticsearch B.V under +// one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.IO; +using System.Runtime.InteropServices; +using Elastic.Apm.Logging; + +#if NET6_0_OR_GREATER +using System.Buffers; +using System.Buffers.Text; +#endif + +namespace Elastic.Apm.Metrics.Linux +{ + internal static class GlobalMemoryStatus + { + public const string ProcMemInfo = "/proc/meminfo"; + +#if NET6_0_OR_GREATER + private static readonly FileStreamOptions Options = new() { BufferSize = 0, Mode = FileMode.Open, Access = FileAccess.Read }; + private static readonly byte Space = (byte)' '; + + private static ReadOnlySpan MemAvailable => "MemAvailable:"u8; + private static ReadOnlySpan MemTotal => "MemTotal:"u8; + private static ReadOnlySpan KB => " kB"u8; +#endif + + public static (long totalMemory, long availableMemory) GetTotalAndAvailableSystemMemory(IApmLogger logger) + => GetTotalAndAvailableSystemMemory(logger, null, false); + + internal static (long totalMemory, long availableMemory) GetTotalAndAvailableSystemMemory( + IApmLogger logger, string pathPrefix, bool ignoreOs) + { + (long, long) failure = (-1, -1); + long totalMemory = -1, availableMemory = -1; + + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !ignoreOs) + { + logger.Trace() + ?.Log("{ClassName} detected a non-Linux OS, therefore" + + " proc/meminfo will not be reported", nameof(GlobalMemoryStatus)); + + return failure; + } + + var memInfoPath = !string.IsNullOrEmpty(pathPrefix) + ? Path.Combine(pathPrefix, ProcMemInfo.Substring(1)) + : ProcMemInfo; + + if (!File.Exists(memInfoPath)) + { + logger.Error()?.Log("Unable to load memory information from {ProcMemInfo}", ProcMemInfo); + return failure; + } + try + { +#if NET6_0_OR_GREATER + using var fs = new FileStream(memInfoPath, Options); + var buffer = ArrayPool.Shared.Rent(8192); // Should easily be large enough for max meminfo file. + + try + { + // We read from the file into our rented buffer so that we can parse data from the meminfo file. + // Specifically, we try to parse the values for `MemAvailable` and `MemTotal`. When these values + // use the KB unit, we multiply them to return bytes. + + var read = fs.Read(buffer); + + if (read == 0) + return failure; + + var span = buffer.AsSpan().Slice(0, read); + + var memAvailable = span.IndexOf(MemAvailable); + if (memAvailable >= 0) + { + var slice = span.Slice(memAvailable + MemAvailable.Length + 1); + var position = 0; + while (true) + { + if (slice[position] != Space) + break; + + position++; + } + + if (position > 0 && Utf8Parser.TryParse(slice.Slice(position), out long value, out var consumed)) + { + availableMemory = slice.Slice(position + consumed, 3).SequenceEqual(KB) + ? value *= 1024 + : value; + } + } + + var memTotal = span.IndexOf(MemTotal); + if (memTotal >= 0) + { + var slice = span.Slice(memTotal + MemTotal.Length + 1); + var position = 0; + while (true) + { + if (slice[position] != Space) + break; + + position++; + } + + if (position > 0 && Utf8Parser.TryParse(slice.Slice(position), out long value, out var consumed)) + { + totalMemory = slice.Slice(position + consumed, 3).SequenceEqual(KB) + ? value *= 1024 + : value; + } + } + + return (totalMemory, availableMemory); + } + finally + { + ArrayPool.Shared.Return(buffer); + } +#else + using var sr = new StreamReader(memInfoPath); + + var hasMemFree = false; + var hasMemTotal = false; + var samples = 0; + + var line = sr.ReadLine(); + + while (samples != 2) + { + if (line != null && line.Contains("MemAvailable:")) + { + availableMemory = GetEntry(line, "MemAvailable:"); + samples++; + hasMemFree = true; + } + if (line != null && line.Contains("MemTotal:")) + { + totalMemory = GetEntry(line, "MemTotal:"); + samples++; + hasMemTotal = true; + } + + if (hasMemFree && hasMemTotal) + break; + + line = sr.ReadLine(); + + if (line is null) + break; + } + + return (totalMemory, availableMemory); + + static long GetEntry(string line, string name) + { + var nameIndex = line.IndexOf(name, StringComparison.Ordinal); + if (nameIndex < 0) + return -1; + + var values = line.Substring(line.IndexOf(name, StringComparison.Ordinal) + name.Length); + + if (string.IsNullOrWhiteSpace(values)) + return -1; + + var items = values.Trim().Split(' '); + + return items.Length switch + { + 1 when long.TryParse(items[0], out var res) => res, + 2 when items[1].ToLowerInvariant() == "kb" && long.TryParse(items[0], out var res) => res * 1024, + _ => -1, + }; + } +#endif + } + catch (IOException e) + { + logger.Info()?.LogException(e, "Error collecting memory data from {path}.", memInfoPath); + } + + return failure; + } + } +} diff --git a/src/Elastic.Apm/Metrics/MetricsCollector.cs b/src/Elastic.Apm/Metrics/MetricsCollector.cs index e02229cde..65dbfe71b 100644 --- a/src/Elastic.Apm/Metrics/MetricsCollector.cs +++ b/src/Elastic.Apm/Metrics/MetricsCollector.cs @@ -79,7 +79,7 @@ params IMetricsProvider[] metricsProvider AddIfEnabled(new ProcessTotalCpuTimeProvider(_logger)); AddIfEnabled(new SystemTotalCpuProvider(_logger)); AddIfEnabled(new ProcessWorkingSetAndVirtualMemoryProvider(disabledMetrics)); - AddIfEnabled(new FreeAndTotalMemoryProvider(disabledMetrics)); + AddIfEnabled(new FreeAndTotalMemoryProvider(_logger, disabledMetrics)); try { // We saw some Exceptions in GcMetricsProvider.ctor, so we try-catch it @@ -183,7 +183,7 @@ private List CollectMetricsFromProviders() { _logger.Trace()?.Log("Start collecting {MetricsProviderName}", metricsProvider.DbgName); - var samplesFromProvider = metricsProvider.GetSamples()?.ToArray(); + var samplesFromProvider = metricsProvider.GetSamples()?.ToArray(); // TODO - Perf if (samplesFromProvider != null && samplesFromProvider.Any()) { @@ -191,8 +191,11 @@ private List CollectMetricsFromProviders() foreach (var item in samplesFromProvider) { + if (item is null) + continue; + // filter out NaN and infinity - item.Samples = item.Samples.Where(x => !double.IsNaN(x.KeyValue.Value) && !double.IsInfinity(x.KeyValue.Value)).ToArray(); + item.Samples = item.Samples.Where(x => !double.IsNaN(x.KeyValue.Value) && !double.IsInfinity(x.KeyValue.Value)).ToArray(); // TODO - Perf if (item.Samples.Any()) { diff --git a/src/Elastic.Apm/Metrics/MetricsProvider/CgroupMetricsProvider.cs b/src/Elastic.Apm/Metrics/MetricsProvider/CgroupMetricsProvider.cs index a4ef2d09e..fad8b88d1 100644 --- a/src/Elastic.Apm/Metrics/MetricsProvider/CgroupMetricsProvider.cs +++ b/src/Elastic.Apm/Metrics/MetricsProvider/CgroupMetricsProvider.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Text.RegularExpressions; @@ -13,6 +12,14 @@ using Elastic.Apm.Helpers; using Elastic.Apm.Logging; +#if NET6_0_OR_GREATER +using System.Buffers.Text; +using System.Runtime.CompilerServices; +using System.Text; +#else +using System.Globalization; +#endif + namespace Elastic.Apm.Metrics.MetricsProvider { /// @@ -30,19 +37,25 @@ internal class CgroupMetricsProvider : IMetricsProvider private const string DefaultSysFsCgroup = "/sys/fs/cgroup"; private const string ProcSelfCgroup = "/proc/self/cgroup"; private const string ProcSelfMountinfo = "/proc/self/mountinfo"; + private const string ProcMeminfo = "/proc/meminfo"; internal const string SystemProcessCgroupMemoryMemLimitBytes = "system.process.cgroup.memory.mem.limit.bytes"; internal const string SystemProcessCgroupMemoryMemUsageBytes = "system.process.cgroup.memory.mem.usage.bytes"; - internal const string SystemProcessCgroupMemoryStatsInactiveFileBytes = "system.process.cgroup.memory.stats.inactive_file.bytes"; + internal static readonly Regex Cgroup1MountPoint = new("^\\d+? \\d+? .+? .+? (.*?) .*cgroup.*memory.*"); internal static readonly Regex Cgroup2MountPoint = new("^\\d+? \\d+? .+? .+? (.*?) .*cgroup2.*cgroup.*"); - internal static readonly Regex MemoryCgroup = new("^\\d+:memory:.*"); +#if NET6_0_OR_GREATER + private static readonly FileStreamOptions Options = new() { BufferSize = 0, Mode = FileMode.Open, Access = FileAccess.Read }; +#endif + private readonly CgroupFiles _cGroupFiles; private readonly bool _collectMemLimitBytes; private readonly bool _collectMemUsageBytes; - private readonly bool _collectStatsInactiveFileBytes; + private readonly bool _collectTotalMemory; + + private readonly string _pathPrefix; private readonly bool _ignoreOs; private readonly IApmLogger _logger; @@ -51,44 +64,41 @@ internal class CgroupMetricsProvider : IMetricsProvider /// /// the logger /// List of disabled metrics - public CgroupMetricsProvider(IApmLogger logger, IReadOnlyList disabledMetrics - ) - : this(ProcSelfCgroup, ProcSelfMountinfo, logger, disabledMetrics) { } + public CgroupMetricsProvider(IApmLogger logger, IReadOnlyList disabledMetrics) + : this(logger, disabledMetrics, null) { } /// - /// Initializes a new instance of + /// Get a testable instance. /// - /// the file - /// the file - /// the logger - /// List of disabled metrics - /// - /// Ignores the OS. If true then it tries to read CGroup metrics regardless of the - /// current OS - /// - /// - /// Used for testing - /// - internal CgroupMetricsProvider(string procSelfCGroup, string mountInfo, IApmLogger logger, IReadOnlyList disabledMetrics, - bool ignoreOs = false - ) + internal static CgroupMetricsProvider TestableCgroupMetricsProvider( + IApmLogger logger, + IReadOnlyList disabledMetrics, + string pathPrefix, + bool ignoreOs = false) => + new(logger, disabledMetrics, pathPrefix, ignoreOs); + + private CgroupMetricsProvider(IApmLogger logger, IReadOnlyList disabledMetrics, string pathPrefix, bool ignoreOs = false) { + _pathPrefix = pathPrefix ?? string.Empty; _ignoreOs = ignoreOs; + _collectMemLimitBytes = IsSystemProcessCgroupMemoryMemLimitBytesEnabled(disabledMetrics); _collectMemUsageBytes = IsSystemProcessCgroupMemoryMemUsageBytesEnabled(disabledMetrics); - _collectStatsInactiveFileBytes = IsSystemProcessCgroupMemoryStatsInactiveFileBytesEnabled(disabledMetrics); + _collectTotalMemory = IsTotalMemoryEnabled(disabledMetrics); + _logger = logger.Scoped(nameof(CgroupMetricsProvider)); if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !_ignoreOs) { _logger.Trace() - ?.Log("{MetricsProviderName} detected a non Linux OS, therefore" + ?.Log("{MetricsProviderName} detected a non-Linux OS, therefore" + " Cgroup metrics will not be reported", nameof(CgroupMetricsProvider)); return; } - _cGroupFiles = FindCGroupFiles(procSelfCGroup, mountInfo); + _cGroupFiles = FindCGroupFiles(); + IsMetricAlreadyCaptured = true; } @@ -97,8 +107,17 @@ internal CgroupMetricsProvider(string procSelfCGroup, string mountInfo, IApmLogg public bool IsMetricAlreadyCaptured { get; } - private CgroupFiles FindCGroupFiles(string procSelfCGroup, string mountInfo) + private CgroupFiles FindCGroupFiles() { + // PERF: There are some allocations in this method, which we have not optimised + // as this method is invoked once from the constructor and we only expect a single + // instance of this type. + + // This code block allocates only during profiling and testing + var procSelfCGroup = !string.IsNullOrEmpty(_pathPrefix) + ? Path.Combine(_pathPrefix, ProcSelfCgroup.Substring(1)) + : ProcSelfCgroup; + if (!File.Exists(procSelfCGroup)) { _logger.Debug()?.Log("{File} does not exist. Cgroup metrics will not be reported", procSelfCGroup); @@ -138,6 +157,10 @@ private CgroupFiles FindCGroupFiles(string procSelfCGroup, string mountInfo) CgroupFiles cgroupFiles; + var mountInfo = !string.IsNullOrEmpty(_pathPrefix) + ? Path.Combine(_pathPrefix, ProcSelfMountinfo.Substring(1)) + : ProcSelfMountinfo; + if (File.Exists(mountInfo)) { string mountLine = null; @@ -257,111 +280,122 @@ private string GetMaxMemoryFile(string maxMemoryFile, string cgroupUnlimitedCons public IEnumerable GetSamples() { - if (_cGroupFiles is null) - return null; - - var samples = new List(3); - - if (_collectStatsInactiveFileBytes) - GetStatsInactiveFileBytesMetric(samples); + if (_cGroupFiles is not null) + yield return new(TimeUtils.TimestampNow(), GetSamplesCore()); + } + private IEnumerable GetSamplesCore() + { if (_collectMemUsageBytes) - GetMemoryMemUsageBytes(samples); + { + var sample = GetMemoryMemUsageBytes(); + if (sample is not null) + yield return sample; + } if (_collectMemLimitBytes) - GetMemoryMemLimitBytes(samples); - - return new List { new(TimeUtils.TimestampNow(), samples) }; + { + var sample = GetMemoryMemLimitBytes(); + if (sample is not null) + yield return sample; + } } // ReSharper disable once SuggestBaseTypeForParameter - private void GetMemoryMemLimitBytes(List samples) + private MetricSample GetMemoryMemLimitBytes() { - if (_cGroupFiles.MaxMemoryFile is null) - return; - try { + if (_cGroupFiles.MaxMemoryFile is null) + { + // When the memory is unlimited, MaxMemoryFile will be null. + // Per the spec, we fall back to returning max memory instead. + var (totalMemory, _) = Linux.GlobalMemoryStatus.GetTotalAndAvailableSystemMemory(_logger, _pathPrefix, _ignoreOs); + + if (totalMemory >= 0) + return new MetricSample(SystemProcessCgroupMemoryMemLimitBytes, totalMemory); + } + +#if NET6_0_OR_GREATER // Optimised code for newer runtimes + return GetLongValueFromFile(_cGroupFiles.MaxMemoryFile, SystemProcessCgroupMemoryMemLimitBytes); +#else using var reader = new StreamReader(_cGroupFiles.MaxMemoryFile); var line = reader.ReadLine(); if (double.TryParse(line, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - samples.Add(new MetricSample(SystemProcessCgroupMemoryMemLimitBytes, value)); + return new MetricSample(SystemProcessCgroupMemoryMemLimitBytes, value); +#endif + } catch (IOException e) { _logger.Info()?.LogException(e, "error collecting {Metric} metric", SystemProcessCgroupMemoryMemLimitBytes); } + + return null; } // ReSharper disable once SuggestBaseTypeForParameter - private void GetMemoryMemUsageBytes(List samples) + private MetricSample GetMemoryMemUsageBytes() { try { +#if NET6_0_OR_GREATER // Optimised code for newer runtimes + return GetLongValueFromFile(_cGroupFiles.UsedMemoryFile, SystemProcessCgroupMemoryMemUsageBytes); +#else using var reader = new StreamReader(_cGroupFiles.UsedMemoryFile); var line = reader.ReadLine(); if (double.TryParse(line, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - samples.Add(new MetricSample(SystemProcessCgroupMemoryMemUsageBytes, value)); + return new MetricSample(SystemProcessCgroupMemoryMemUsageBytes, value); +#endif } catch (IOException e) { _logger.Info()?.LogException(e, "error collecting {metric} metric", SystemProcessCgroupMemoryMemUsageBytes); } + + return null; } - // ReSharper disable once SuggestBaseTypeForParameter - private void GetStatsInactiveFileBytesMetric(List samples) +#if NET6_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private MetricSample GetLongValueFromFile(string path, string sampleName) { - try - { - using var reader = new StreamReader(_cGroupFiles.StatMemoryFile); - string statLine; - string inactiveBytes = null; - while ((statLine = reader.ReadLine()) != null) - { - var statLineSplit = statLine.Split(' '); - if (statLineSplit.Length > 1) - { - if ("total_inactive_file".Equals(statLineSplit[0])) - { - inactiveBytes = statLineSplit[1]; - break; - } - - if ("inactive_file".Equals(statLineSplit[0])) - inactiveBytes = statLineSplit[1]; - } - } + using var fs = new FileStream(path, Options); + Span buffer = stackalloc byte[20]; // this size should always be sufficient to read the max long value as a string. + var bytes = fs.Read(buffer); +#if DEBUG + var fileValue = Encoding.UTF8.GetString(buffer); +#endif + if (bytes > 0 && Utf8Parser.TryParse(buffer, out long value, out _)) + return new MetricSample(sampleName, value); - if (inactiveBytes != null && double.TryParse(inactiveBytes, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) - samples.Add(new MetricSample(SystemProcessCgroupMemoryStatsInactiveFileBytes, value)); - } - catch (IOException e) - { - _logger.Info()?.LogException(e, "error collecting {Metric} metric", SystemProcessCgroupMemoryStatsInactiveFileBytes); - } + return null; } +#endif - public bool IsEnabled(IReadOnlyList disabledMetrics) => IsSystemProcessCgroupMemoryMemLimitBytesEnabled(disabledMetrics) || - IsSystemProcessCgroupMemoryMemUsageBytesEnabled(disabledMetrics) - || IsSystemProcessCgroupMemoryStatsInactiveFileBytesEnabled(disabledMetrics); + private const byte Newline = (byte)'\n'; + private const byte Space = (byte)' '; + private static ReadOnlySpan _totalInactiveFile => "total_inactive_file"u8; + private static ReadOnlySpan _inactiveFile => "inactive_file"u8; + public bool IsEnabled(IReadOnlyList disabledMetrics) => + IsSystemProcessCgroupMemoryMemLimitBytesEnabled(disabledMetrics) || + IsSystemProcessCgroupMemoryMemUsageBytesEnabled(disabledMetrics); - private bool IsSystemProcessCgroupMemoryMemLimitBytesEnabled(IReadOnlyList disabledMetrics) => !WildcardMatcher.IsAnyMatch( + private static bool IsSystemProcessCgroupMemoryMemLimitBytesEnabled(IReadOnlyList disabledMetrics) => !WildcardMatcher.IsAnyMatch( disabledMetrics, SystemProcessCgroupMemoryMemLimitBytes); - private bool IsSystemProcessCgroupMemoryMemUsageBytesEnabled(IReadOnlyList disabledMetrics) => !WildcardMatcher.IsAnyMatch( + private static bool IsSystemProcessCgroupMemoryMemUsageBytesEnabled(IReadOnlyList disabledMetrics) => !WildcardMatcher.IsAnyMatch( disabledMetrics, SystemProcessCgroupMemoryMemUsageBytes); - private bool IsSystemProcessCgroupMemoryStatsInactiveFileBytesEnabled(IReadOnlyList disabledMetrics) => - !WildcardMatcher.IsAnyMatch( - disabledMetrics, SystemProcessCgroupMemoryStatsInactiveFileBytes); + private static bool IsTotalMemoryEnabled(IReadOnlyList disabledMetrics) => + !WildcardMatcher.IsAnyMatch(disabledMetrics, FreeAndTotalMemoryProvider.TotalMemory); } /// /// Holds the collection of relevant cgroup files /// - internal class CgroupFiles + internal sealed class CgroupFiles { public CgroupFiles(string maxMemoryFile, string usedMemoryFile, string statMemoryFile) { diff --git a/src/Elastic.Apm/Metrics/MetricsProvider/FreeAndTotalMemoryProvider.cs b/src/Elastic.Apm/Metrics/MetricsProvider/FreeAndTotalMemoryProvider.cs index fedbe3aa1..0e6d09993 100644 --- a/src/Elastic.Apm/Metrics/MetricsProvider/FreeAndTotalMemoryProvider.cs +++ b/src/Elastic.Apm/Metrics/MetricsProvider/FreeAndTotalMemoryProvider.cs @@ -3,13 +3,11 @@ // Elasticsearch B.V licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information -using System; using System.Collections.Generic; -using System.IO; using System.Runtime.InteropServices; using Elastic.Apm.Api; using Elastic.Apm.Helpers; -using Elastic.Apm.Metrics.Windows; +using Elastic.Apm.Logging; namespace Elastic.Apm.Metrics.MetricsProvider { @@ -24,12 +22,27 @@ internal class FreeAndTotalMemoryProvider : IMetricsProvider private readonly bool _collectFreeMemory; private readonly bool _collectTotalMemory; + private readonly IApmLogger _logger; + private readonly string _pathPrefix; + private readonly bool _ignoreOs; - public FreeAndTotalMemoryProvider(IReadOnlyList disabledMetrics) + internal static FreeAndTotalMemoryProvider TestableFreeAndTotalMemoryProvider(IApmLogger logger, + IReadOnlyList disabledMetrics, string pathPrefix, bool ignoreOs) => + new(logger, disabledMetrics, pathPrefix, ignoreOs); + + public FreeAndTotalMemoryProvider(IApmLogger logger, IReadOnlyList disabledMetrics) : + this(logger, disabledMetrics, string.Empty) + { } + + private FreeAndTotalMemoryProvider(IApmLogger logger, IReadOnlyList disabledMetrics, + string pathPrefix, bool ignoreOs = false) { IsMetricAlreadyCaptured = true; _collectFreeMemory = IsFreeMemoryEnabled(disabledMetrics); _collectTotalMemory = IsTotalMemoryEnabled(disabledMetrics); + _logger = logger.Scoped(nameof(FreeAndTotalMemoryProvider)); + _pathPrefix = pathPrefix; + _ignoreOs = ignoreOs; } public int ConsecutiveNumberOfFailedReads { get; set; } @@ -40,96 +53,42 @@ public FreeAndTotalMemoryProvider(IReadOnlyList disabledMetrics public bool IsEnabled(IReadOnlyList disabledMetrics) => IsFreeMemoryEnabled(disabledMetrics) || IsTotalMemoryEnabled(disabledMetrics); - private bool IsFreeMemoryEnabled(IReadOnlyList disabledMetrics) => !WildcardMatcher.IsAnyMatch(disabledMetrics, FreeMemory); + private static bool IsFreeMemoryEnabled(IReadOnlyList disabledMetrics) => + !WildcardMatcher.IsAnyMatch(disabledMetrics, FreeMemory); - private bool IsTotalMemoryEnabled(IReadOnlyList disabledMetrics) => !WildcardMatcher.IsAnyMatch(disabledMetrics, TotalMemory); + private static bool IsTotalMemoryEnabled(IReadOnlyList disabledMetrics) => + !WildcardMatcher.IsAnyMatch(disabledMetrics, TotalMemory); public IEnumerable GetSamples() { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - var (success, totalMemory, freeMemory) = GlobalMemoryStatus.GetTotalPhysAndAvailPhys(); - - if (!success || totalMemory == 0 || freeMemory == 0) - return null; - - var samples = new List(); - - if (_collectFreeMemory) - samples.Add(new MetricSample(FreeMemory, freeMemory)); - - if (_collectTotalMemory) - samples.Add(new MetricSample(TotalMemory, totalMemory)); - - return new List { new MetricSet(TimeUtils.TimestampNow(), samples) }; - } + yield return new(TimeUtils.TimestampNow(), GetSamplesCore()); + } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + private IEnumerable GetSamplesCore() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - var samples = new List(); + var (success, total, available) = Windows.GlobalMemoryStatus.GetTotalPhysAndAvailPhys(); - using (var sr = new StreamReader("/proc/meminfo")) + if (success && total != 0 && available != 0) { - var hasMemFree = false; - var hasMemTotal = false; - - var line = sr.ReadLine(); - - while (line != null || samples.Count != 2) - { - //See: https://github.com/elastic/beats/issues/4202 - if (line != null && line.Contains("MemAvailable:") && _collectFreeMemory) - { - var (suc, res) = GetEntry(line, "MemAvailable:"); - if (suc) - samples.Add(new MetricSample(FreeMemory, res)); - hasMemFree = true; - } - if (line != null && line.Contains("MemTotal:") && _collectTotalMemory) - { - var (suc, res) = GetEntry(line, "MemTotal:"); - if (suc) - samples.Add(new MetricSample(TotalMemory, res)); - hasMemTotal = true; - } - - if ((hasMemFree || !_collectFreeMemory) && (hasMemTotal || !_collectTotalMemory)) - break; - - line = sr.ReadLine(); - } - } + if (_collectFreeMemory) + yield return new MetricSample(FreeMemory, available); - ConsecutiveNumberOfFailedReads = 0; - - return new List { new MetricSet(TimeUtils.TimestampNow(), samples) }; + if (_collectTotalMemory) + yield return new MetricSample(TotalMemory, total); + } } - - (bool, ulong) GetEntry(string line, string name) + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - var nameIndex = line.IndexOf(name, StringComparison.Ordinal); - if (nameIndex < 0) - return (false, 0); + var (totalMemory, availableMemory) = Linux.GlobalMemoryStatus.GetTotalAndAvailableSystemMemory(_logger); - var values = line.Substring(line.IndexOf(name, StringComparison.Ordinal) + name.Length); + if (_collectFreeMemory && availableMemory > -1) + yield return new MetricSample(FreeMemory, availableMemory); - if (string.IsNullOrWhiteSpace(values)) - return (false, 0); - - var items = values.Trim().Split(' '); - - switch (items.Length) - { - case 1 when ulong.TryParse(items[0], out var res): - return (true, res); - case 2 when items[1].ToLowerInvariant() == "kb" && ulong.TryParse(items[0], out var res): - return (true, res * 1024); - default: - return (false, 0); - } + if (_collectTotalMemory && totalMemory > -1) + yield return new MetricSample(TotalMemory, totalMemory); } - - return null; } } } diff --git a/src/Elastic.Apm/Metrics/Windows/GlobalMemoryStatusEx.cs b/src/Elastic.Apm/Metrics/Windows/GlobalMemoryStatus.cs similarity index 100% rename from src/Elastic.Apm/Metrics/Windows/GlobalMemoryStatusEx.cs rename to src/Elastic.Apm/Metrics/Windows/GlobalMemoryStatus.cs diff --git a/test/Elastic.Apm.Tests/Elastic.Apm.Tests.csproj b/test/Elastic.Apm.Tests/Elastic.Apm.Tests.csproj index 461333494..4a084c76f 100644 --- a/test/Elastic.Apm.Tests/Elastic.Apm.Tests.csproj +++ b/test/Elastic.Apm.Tests/Elastic.Apm.Tests.csproj @@ -14,6 +14,7 @@ + diff --git a/test/Elastic.Apm.Tests/Metrics/CgroupMetricsProviderTests.cs b/test/Elastic.Apm.Tests/Metrics/CgroupMetricsProviderTests.cs index 13fc72bf3..0aeecfa2b 100644 --- a/test/Elastic.Apm.Tests/Metrics/CgroupMetricsProviderTests.cs +++ b/test/Elastic.Apm.Tests/Metrics/CgroupMetricsProviderTests.cs @@ -6,151 +6,174 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; +using System.Text; using Elastic.Apm.Helpers; -using Elastic.Apm.Logging; -using Elastic.Apm.Metrics.MetricsProvider; using Elastic.Apm.Tests.Utilities; -using Elastic.Apm.Tests.Utilities.XUnit; using FluentAssertions; using Xunit; -using Xunit.Abstractions; using static Elastic.Apm.Metrics.MetricsProvider.CgroupMetricsProvider; +using static Elastic.Apm.Tests.TestHelpers.CgroupFileHelper; namespace Elastic.Apm.Tests.Metrics { public class CgroupMetricsProviderTests { - private readonly string _projectRoot; - private readonly IApmLogger _logger; - - public CgroupMetricsProviderTests(ITestOutputHelper output) + [Fact] + public void TestCgroup1Regex() { - var assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - _projectRoot = assemblyDirectory; - _logger = new XUnitLogger(LogLevel.Trace, output); + var actual = ApplyCgroupRegex(Cgroup1MountPoint, "39 30 0:36 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,memory"); + actual.Should().Be("/sys/fs/cgroup/memory"); } - [DisabledOnWindowsTheory] - [InlineData(964778496, "/proc/cgroup", "/proc/limited/memory", 7964778496)] - [InlineData(964778496, "/proc/cgroup2", "/proc/sys_cgroup2", 7964778496)] - // stat have different values to inactive_file and total_inactive_file - [InlineData(964778496, "/proc/cgroup2_only_0", "/proc/sys_cgroup2_unlimited", null)] - // stat have different values to inactive_file and total_inactive_file different order - [InlineData(964778496, "/proc/cgroup2_only_memory", "/proc/sys_cgroup2_unlimited_stat_different_order", null)] - public void TestFreeCgroupMemory(double value, string selfCGroup, string sysFsGroup, double? memLimit) + [Fact] + public void TestCgroup2Regex() { - var mountInfo = GetTestFilePath(sysFsGroup); - var tempFile = TempFile.CreateWithContents( - sysFsGroup.StartsWith("/proc/sys_cgroup2") - ? $"30 23 0:26 / {mountInfo} rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup rw,seclabel\n" - : $"39 30 0:35 / {mountInfo} rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,memory\n"); - - using (tempFile) - { - var provider = new CgroupMetricsProvider(GetTestFilePath(selfCGroup), tempFile.Path, _logger, new List(), ignoreOs: true); - - var samples = provider.GetSamples().ToList(); + var actual = ApplyCgroupRegex(Cgroup2MountPoint, "39 30 0:36 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup rw,seclabel"); + actual.Should().Be("/sys/fs/cgroup/memory"); + } - samples.First().Samples.Should().HaveCountGreaterOrEqualTo(2); + [Fact] + public void TestLimitedCgroup1() + { + using var paths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV1); - var inactiveFileBytesSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryStatsInactiveFileBytes); - inactiveFileBytesSample.Should().NotBeNull(); + var sut = TestableCgroupMetricsProvider(new NoopLogger(), new List(), paths.RootPath, true); + var samples = sut.GetSamples().ToList(); - var memUsageSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemUsageBytes); - memUsageSample.Should().NotBeNull(); - memUsageSample?.KeyValue.Value.Should().Be(value); + var memLimitSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemLimitBytes); + memLimitSample.Should().NotBeNull(); + memLimitSample.KeyValue.Value.Should().Be(DefaultMemoryLimitBytes); - if (memLimit.HasValue) - { - var memLimitSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemLimitBytes); - memLimitSample.Should().NotBeNull(); - memLimitSample?.KeyValue.Value.Should().Be(memLimit); - } - } + var memUsageSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemUsageBytes); + memUsageSample.Should().NotBeNull(); + memUsageSample.KeyValue.Value.Should().Be(DefaultMemoryUsageBytes); } - [Theory] - [InlineData("39 30 0:36 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,seclabel,memory", "/sys/fs/cgroup/memory")] - public void TestCgroup1Regex(string testString, string expected) + [Fact] + public void TestLimitedCgroup2() { - var actual = ApplyCgroupRegex(Cgroup1MountPoint, testString); - actual.Should().Be(expected); - } + using var paths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV2); - [Theory] - [InlineData("39 30 0:36 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:4 - cgroup2 cgroup rw,seclabel", "/sys/fs/cgroup/memory")] - public void TestCgroup2Regex(string testString, string expected) - { - var actual = ApplyCgroupRegex(Cgroup2MountPoint, testString); - actual.Should().Be(expected); + var sut = TestableCgroupMetricsProvider(new NoopLogger(), new List(), paths.RootPath, true); + var samples = sut.GetSamples().ToList(); + + var memLimitSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemLimitBytes); + memLimitSample.Should().NotBeNull(); + memLimitSample.KeyValue.Value.Should().Be(DefaultMemoryLimitBytes); + + var memUsageSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemUsageBytes); + memUsageSample.Should().NotBeNull(); + memUsageSample.KeyValue.Value.Should().Be(DefaultMemoryUsageBytes); } - [DisabledTestFact("Sometimes fails in CI with `System.ArgumentNullException : Value cannot be null.`")] + [Fact] public void TestUnlimitedCgroup1() { - var cgroupMetrics = CreateUnlimitedSystemCgroupMetricsProvider("/proc/cgroup", "/proc/unlimited/memory", "cgroup cgroup"); - var samples = cgroupMetrics.GetSamples().ToList(); + using var paths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV1); + UnlimitedMaxMemoryFiles(paths); + + var sut = TestableCgroupMetricsProvider(new NoopLogger(), new List(), paths.RootPath, true); + var samples = sut.GetSamples().ToList(); var memLimitSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemLimitBytes); - memLimitSample.Should().BeNull(); + memLimitSample.Should().NotBeNull(); + memLimitSample.KeyValue.Value.Should().Be(DefaultMemInfoTotalBytes); var memUsageSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemUsageBytes); memUsageSample.Should().NotBeNull(); - memUsageSample.KeyValue.Value.Should().Be(964778496); + memUsageSample.KeyValue.Value.Should().Be(DefaultMemoryUsageBytes); } - [DisabledTestFact("Flaky")] + [Fact] public void TestUnlimitedCgroup2() { - var cgroupMetrics = CreateUnlimitedSystemCgroupMetricsProvider("/proc/cgroup2", "/proc/sys_cgroup2_unlimited", "cgroup2 cgroup"); - var samples = cgroupMetrics.GetSamples().ToList(); + using var paths = CreateDefaultCgroupFiles(CgroupVersion.CgroupV2); + UnlimitedMaxMemoryFiles(paths); + + var sut = TestableCgroupMetricsProvider(new NoopLogger(), new List(), paths.RootPath, true); + var samples = sut.GetSamples().ToList(); var memLimitSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemLimitBytes); - memLimitSample.Should().BeNull(); + memLimitSample.Should().NotBeNull(); + memLimitSample.KeyValue.Value.Should().Be(DefaultMemInfoTotalBytes); var memUsageSample = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == SystemProcessCgroupMemoryMemUsageBytes); memUsageSample.Should().NotBeNull(); - memUsageSample.KeyValue.Value.Should().Be(964778496); + memUsageSample.KeyValue.Value.Should().Be(DefaultMemoryUsageBytes); } - /// - /// Makes sure that CGroup metrics collection exits with a log on non Linux OSs and only collects data on Linux. - /// - [Fact] - public void OsTest() + private void UnlimitedMaxMemoryFiles(CgroupPaths paths) { - var logger = new InMemoryBlockingLogger(LogLevel.Trace); - var cgroupMetricsProvider = new CgroupMetricsProvider(logger, new List()); - - var samples = cgroupMetricsProvider.GetSamples(); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + if (paths.CgroupVersion == CgroupVersion.CgroupV1) { - samples.Should().NotBeNullOrEmpty(); - logger.Lines.Where(line => line.Contains("detected a non Linux OS, therefore Cgroup metrics will not be reported")).Should().BeNullOrEmpty(); + using var sr = new StreamWriter(File.Create(Path.Combine(paths.CgroupV1MemoryControllerPath, "memory.limit_in_bytes"))); + sr.WriteAsync($"9223372036854771712\n"); } - else + + if (paths.CgroupVersion == CgroupVersion.CgroupV2) { - samples.Should().BeNullOrEmpty(); - logger.Lines.Where(line => line.Contains("detected a non Linux OS, therefore Cgroup metrics will not be reported")).Should().NotBeNullOrEmpty(); + using var sr = new StreamWriter(File.Create(Path.Combine(paths.CgroupV2SlicePath, "memory.max"))); + sr.WriteAsync($"max\n"); } - } - /// - /// Converts a test path into a path to a physical test file on disk - /// - private string GetTestFilePath(string linuxPath) => Path.GetFullPath(Path.Combine(_projectRoot, "TestResources" + linuxPath)); - - private CgroupMetricsProvider CreateUnlimitedSystemCgroupMetricsProvider(string cGroupPath, string mountPath, string cgroup) + private void ReplaceMemStatInactiveFile(CgroupPaths paths, double inactiveFileValue, double totalInactiveFileValue, bool inactiveFirst) { - var mountInfo = GetTestFilePath(mountPath).Replace("\\", "/"); - var tempFile = TempFile.CreateWithContents( - $"39 30 0:35 / {mountInfo} rw,nosuid,nodev,noexec,relatime shared:10 - {cgroup} rw,seclabel,memory\n"); + using var memoryStat = File.CreateText(Path.Combine(paths.CgroupV1MemoryControllerPath, "memory.stat")); + var sb = new StringBuilder(); + + sb.Append("cache 10407936").Append("\n"); + sb.Append("rss 778842112").Append("\n"); + sb.Append("rss_huge 0").Append("\n"); + sb.Append("shmem 0").Append("\n"); + sb.Append("mapped_file 0").Append("\n"); + sb.Append("dirty 0").Append("\n"); + sb.Append("writeback 0").Append("\n"); + sb.Append("swap 0").Append("\n"); + sb.Append("pgpgin 234465").Append("\n"); + sb.Append("pgpgout 41732").Append("\n"); + sb.Append("pgfault 233838").Append("\n"); + sb.Append("pgmajfault 0").Append("\n"); + sb.Append("inactive_anon 0").Append("\n"); + sb.Append("active_anon 778702848").Append("\n"); + + if (inactiveFirst) + { + sb.AppendLine($"inactive_file {inactiveFileValue}"); + sb.AppendLine($"total_inactive_file {totalInactiveFileValue}"); + } + else + { + sb.AppendLine($"total_inactive_file {totalInactiveFileValue}"); + sb.AppendLine($"inactive_file {inactiveFileValue}"); + } - return new CgroupMetricsProvider(GetTestFilePath(cGroupPath), tempFile.Path, new NoopLogger(), new List(), true); + sb.Append("active_file 0").Append("\n"); + sb.Append("unevictable 0").Append("\n"); + sb.Append("hierarchical_memory_limit 1073741824").Append("\n"); + sb.Append("hierarchical_memsw_limit 2147483648").Append("\n"); + sb.Append("total_cache 10407936").Append("\n"); + sb.Append("total_rss 778842112").Append("\n"); + sb.Append("total_rss_huge 0").Append("\n"); + sb.Append("total_shmem 0").Append("\n"); + sb.Append("total_mapped_file 0").Append("\n"); + sb.Append("total_dirty 0").Append("\n"); + sb.Append("total_writeback 0").Append("\n"); + sb.Append("total_swap 0").Append("\n"); + sb.Append("total_pgpgin 234465").Append("\n"); + sb.Append("total_pgpgout 41732").Append("\n"); + sb.Append("total_pgfault 233838").Append("\n"); + sb.Append("total_pgmajfault 0").Append("\n"); + sb.Append("total_inactive_anon 0").Append("\n"); + sb.Append("total_active_anon 778702848").Append("\n"); + sb.Append("total_active_file 0").Append("\n"); + sb.Append("total_unevictable 0").Append("\n"); + sb.Append("recent_rotated_anon 231947").Append("\n"); + sb.Append("recent_rotated_file 2").Append("\n"); + sb.Append("recent_scanned_anon 231947").Append("\n"); + sb.Append("recent_scanned_file 2622").Append("\n"); + memoryStat.Write(sb.ToString()); + memoryStat.Flush(); } } } diff --git a/test/Elastic.Apm.Tests/Metrics/FreeAndTotalMemoryProviderTests.cs b/test/Elastic.Apm.Tests/Metrics/FreeAndTotalMemoryProviderTests.cs new file mode 100644 index 000000000..13da6c0d9 --- /dev/null +++ b/test/Elastic.Apm.Tests/Metrics/FreeAndTotalMemoryProviderTests.cs @@ -0,0 +1,34 @@ +// Licensed to Elasticsearch B.V under +// one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System.Collections.Generic; +using System.Linq; +using Elastic.Apm.Helpers; +using Elastic.Apm.Metrics.MetricsProvider; +using Elastic.Apm.Tests.Utilities; +using FluentAssertions; +using Xunit; + +namespace Elastic.Apm.Tests.Metrics; + +public class FreeAndTotalMemoryProviderTests +{ + [Fact] + public void FreeAndTotalMemoryProvider_ShouldReturnValues() + { + var sut = new FreeAndTotalMemoryProvider(new NoopLogger(), new List()); + + var samples = sut.GetSamples().ToList(); + samples.First().Samples.Should().HaveCount(2); + + var freeMemory = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == FreeAndTotalMemoryProvider.FreeMemory); + freeMemory.Should().NotBeNull(); + freeMemory.KeyValue.Value.Should().BePositive(); + + var totalMemory = samples.First().Samples.SingleOrDefault(s => s.KeyValue.Key == FreeAndTotalMemoryProvider.TotalMemory); + totalMemory.Should().NotBeNull(); + totalMemory.KeyValue.Value.Should().BePositive(); + } +} diff --git a/test/Elastic.Apm.Tests/Metrics/Linux/GlobalMemoryStatusTests.cs b/test/Elastic.Apm.Tests/Metrics/Linux/GlobalMemoryStatusTests.cs new file mode 100644 index 000000000..d3bd2a8dc --- /dev/null +++ b/test/Elastic.Apm.Tests/Metrics/Linux/GlobalMemoryStatusTests.cs @@ -0,0 +1,128 @@ +// Licensed to Elasticsearch B.V under +// one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.IO; +using System.Text; +using Elastic.Apm.Tests.TestHelpers; +using Elastic.Apm.Tests.Utilities; +using FluentAssertions; +using Xunit; +using Xunit.Abstractions; + +namespace Elastic.Apm.Tests.Metrics.Linux; + +public class GlobalMemoryStatusTests +{ + private readonly ITestOutputHelper _output; + + public GlobalMemoryStatusTests(ITestOutputHelper output) => _output = output; + + [Fact] + public void GlobalMemoryStatus_ReturnsExpectedValues() + { + var rootPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var procPath = Path.Combine(rootPath, "proc"); + + Directory.CreateDirectory(procPath); + + var sb = new StringBuilder(); + sb.Append($"MemTotal: {CgroupFileHelper.DefaultMemInfoTotalBytes / 1024} kB").Append("\n"); + sb.Append("MemFree: 4806144 kB").Append("\n"); + sb.Append("Buffers: 211756 kB").Append("\n"); + sb.Append("Cached: 1071092 kB").Append("\n"); + sb.Append("SwapTotal: 4194296 kB").Append("\n"); + sb.Append("SwapFree: 4194296 kB").Append("\n"); + sb.Append($"MemAvailable: {CgroupFileHelper.DefaultMemInfoAvailableBytes / 1024} kB").Append("\n"); + + using (var memInfo = new StreamWriter(File.Create(Path.Combine(procPath, "meminfo")))) + { + memInfo.Write(sb.ToString()); + memInfo.Flush(); + } + + var (total, available) = Apm.Metrics.Linux.GlobalMemoryStatus + .GetTotalAndAvailableSystemMemory(new NoopLogger(), rootPath, ignoreOs: true); + + _output.WriteLine($"Root Path: {rootPath}"); + _output.WriteLine($"Available: {available}"); + _output.WriteLine($"Total: {total}"); + + available.Should().Be(CgroupFileHelper.DefaultMemInfoAvailableBytes); + total.Should().Be(CgroupFileHelper.DefaultMemInfoTotalBytes); + + Directory.Delete(rootPath, true); + } + + [Fact] + public void GlobalMemoryStatus_ReturnsExpectedValue_WhenTotalMemoryNotPresent() + { + var rootPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var procPath = Path.Combine(rootPath, "proc"); + + Directory.CreateDirectory(procPath); + + var sb = new StringBuilder(); + sb.Append("MemFree: 4806144 kB").Append("\n"); + sb.Append("Buffers: 211756 kB").Append("\n"); + sb.Append("Cached: 1071092 kB").Append("\n"); + sb.Append("SwapTotal: 4194296 kB").Append("\n"); + sb.Append("SwapFree: 4194296 kB").Append("\n"); + sb.Append($"MemAvailable: {CgroupFileHelper.DefaultMemInfoAvailableBytes / 1024} kB").Append("\n"); + + using (var memInfo = new StreamWriter(File.Create(Path.Combine(procPath, "meminfo")))) + { + memInfo.Write(sb.ToString()); + memInfo.Flush(); + } + + var (total, available) = Apm.Metrics.Linux.GlobalMemoryStatus + .GetTotalAndAvailableSystemMemory(new NoopLogger(), rootPath, ignoreOs: true); + + _output.WriteLine($"Root Path: {rootPath}"); + _output.WriteLine($"Available: {available}"); + _output.WriteLine($"Total: {total}"); + + available.Should().Be(CgroupFileHelper.DefaultMemInfoAvailableBytes); + total.Should().Be(-1); + + Directory.Delete(rootPath, true); + } + + [Fact] + public void GlobalMemoryStatus_ReturnsExpectedValue_WhenAvailableMemoryNotPresent() + { + var rootPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var procPath = Path.Combine(rootPath, "proc"); + + Directory.CreateDirectory(procPath); + + var sb = new StringBuilder(); + sb.Append($"MemTotal: {CgroupFileHelper.DefaultMemInfoTotalBytes / 1024} kB").Append("\n"); + sb.Append("MemFree: 4806144 kB").Append("\n"); + sb.Append("Buffers: 211756 kB").Append("\n"); + sb.Append("Cached: 1071092 kB").Append("\n"); + sb.Append("SwapTotal: 4194296 kB").Append("\n"); + sb.Append("SwapFree: 4194296 kB").Append("\n"); + + using (var memInfo = new StreamWriter(File.Create(Path.Combine(procPath, "meminfo")))) + { + memInfo.Write(sb.ToString()); + memInfo.Flush(); + } + + var (total, available) = Apm.Metrics.Linux.GlobalMemoryStatus + .GetTotalAndAvailableSystemMemory(new NoopLogger(), rootPath, ignoreOs: true); + + _output.WriteLine($"Root Path: {rootPath}"); + _output.WriteLine($"Available: {available}"); + _output.WriteLine($"Total: {total}"); + + available.Should().Be(-1); + total.Should().Be(CgroupFileHelper.DefaultMemInfoTotalBytes); + + Directory.Delete(rootPath, true); + } +} diff --git a/test/Elastic.Apm.Tests/TestHelpers/CgroupFileHelper.cs b/test/Elastic.Apm.Tests/TestHelpers/CgroupFileHelper.cs new file mode 100644 index 000000000..7c8eb509f --- /dev/null +++ b/test/Elastic.Apm.Tests/TestHelpers/CgroupFileHelper.cs @@ -0,0 +1,292 @@ +// Licensed to Elasticsearch B.V under +// one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.IO; +using System.Text; + +namespace Elastic.Apm.Tests.TestHelpers +{ + internal static class CgroupFileHelper + { + internal sealed class CgroupPaths : IDisposable + { + public CgroupPaths(CgroupVersion cgroupVersion) => CgroupVersion = cgroupVersion; + + public CgroupVersion CgroupVersion { get; } + public string RootPath { get; set; } + public string ProcPath { get; set; } + public string ProcSelfPath { get; set; } + public string CgroupPath { get; set; } + public string CgroupV1MemoryControllerPath { get; set; } + public string CgroupV2SlicePath { get; set; } + + public void Dispose() => Directory.Delete(RootPath, true); + } + + internal enum CgroupVersion + { + CgroupV1, CgroupV2 + } + + public const long DefaultMemoryLimitBytes = 7_964_778_496; + public const long DefaultMemoryUsageBytes = 585_965_568; + public const long DefaultMemInfoAvailableBytes = 15_758_585_856; + public const long DefaultMemInfoTotalBytes = 16_599_289_856; + + public static CgroupPaths CreateDefaultCgroupFiles(CgroupVersion cgroupVersion) + { + var rootPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + var procPath = Path.Combine(rootPath, "proc"); + var procSelfPath = Path.Combine(procPath, "self"); + var cgroupPath = Path.Combine(rootPath, "sys", "fs", "cgroup"); + var cgroupV1MemoryControllerPath = Path.Combine(cgroupPath, "memory"); + var cgroupV2SlicePath = Path.Combine(cgroupPath, "unified", "sample.slice"); + + Directory.CreateDirectory(procSelfPath); + Directory.CreateDirectory(cgroupV1MemoryControllerPath); + Directory.CreateDirectory(cgroupV2SlicePath); + + var sb = new StringBuilder(); + + // Create /proc/self/cgroup file + using (var cgroup = new StreamWriter(File.Create(Path.Combine(procSelfPath, "cgroup")))) + { + sb.Clear(); + + if (cgroupVersion == CgroupVersion.CgroupV1) + { + // Sample values retrieved from Ubuntu 22.04 (WSL2) running with cgroup v1 controllers + sb.Append("41:misc:/").Append("\n"); + sb.Append("40:rdma:/").Append("\n"); + sb.Append("39:hugetlb:/").Append("\n"); + sb.Append("38:net_prio:/").Append("\n"); + sb.Append("37:perf_event:/").Append("\n"); + sb.Append("36:net_cls:/").Append("\n"); + sb.Append("35:freezer:/").Append("\n"); + sb.Append("34:blkio:/").Append("\n"); + sb.Append("33:cpuacct:/").Append("\n"); + sb.Append("32:cpu:/").Append("\n"); + sb.Append("31:cpuset:/").Append("\n"); + sb.Append("15:name=systemd:/").Append("\n"); + sb.Append("12:pids:/").Append("\n"); + sb.Append("6:devices:/").Append("\n"); + sb.Append("5:memory:/").Append("\n"); + sb.Append("0::/").Append("\n"); + } + + if (cgroupVersion == CgroupVersion.CgroupV2) + { + sb.Append("1:name=systemd:/").Append("\n"); + sb.Append("0::/sample.slice").Append("\n"); + } + + cgroup.Write(sb.ToString()); + cgroup.Flush(); + } + + using (var memInfo = new StreamWriter(File.Create(Path.Combine(procPath, "meminfo")))) + { + sb.Clear(); + sb.Append($"MemTotal: {DefaultMemInfoTotalBytes / 1024} kB").Append("\n"); + sb.Append("MemFree: 4806144 kB").Append("\n"); + sb.Append("Buffers: 211756 kB").Append("\n"); + sb.Append("Cached: 1071092 kB").Append("\n"); + sb.Append("SwapTotal: 4194296 kB").Append("\n"); + sb.Append("SwapFree: 4194296 kB").Append("\n"); + sb.Append($"MemAvailable: {DefaultMemInfoAvailableBytes / 1024} kB").Append("\n"); + + memInfo.Write(sb.ToString()); + memInfo.Flush(); + } + + using (var memoryLimitInBytes = File.CreateText(Path.Combine(cgroupV1MemoryControllerPath, "memory.limit_in_bytes"))) + { + memoryLimitInBytes.WriteAsync($"{DefaultMemoryLimitBytes}\n"); + memoryLimitInBytes.Flush(); + } + + using (var cgroup = new StreamWriter(File.Create(Path.Combine(procSelfPath, "mountinfo")))) + { + sb.Clear(); + + if (cgroupVersion == CgroupVersion.CgroupV1) + { + // Based on WSL2 running with v1 controllers + sb.Append("95 112 0:26 / /mnt/wsl rw,relatime shared:1 - tmpfs none rw").Append("\n"); + sb.Append("96 112 0:28 / /usr/lib/wsl/drivers ro,nosuid,nodev,noatime - 9p none ro,dirsync,aname=drivers;fmask=222;dmask=222,mmap,access=client,msize=65536,trans=fd,rfd=7,wfd=7").Append("\n"); + sb.Append("110 112 0:32 / /usr/lib/wsl/lib rw,relatime - overlay none rw,lowerdir=/gpu_lib_packaged:/gpu_lib_inbox,upperdir=/gpu_lib/rw/upper,workdir=/gpu_lib/rw/work").Append("\n"); + sb.Append("112 87 8:32 / / rw,relatime - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered").Append("\n"); + sb.Append("113 112 0:43 / /mnt/wslg rw,relatime shared:2 - tmpfs none rw").Append("\n"); + sb.Append("114 113 8:32 / /mnt/wslg/distro ro,relatime shared:3 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered").Append("\n"); + sb.Append("132 112 0:2 /init /init ro - rootfs rootfs rw,size=8101876k,nr_inodes=2025469").Append("\n"); + sb.Append("156 112 0:5 / /dev rw,nosuid,relatime - devtmpfs none rw,size=8101904k,nr_inodes=2025476,mode=755").Append("\n"); + sb.Append("162 112 0:20 / /sys rw,nosuid,nodev,noexec,noatime - sysfs sysfs rw").Append("\n"); + sb.Append("165 112 0:79 / /proc rw,nosuid,nodev,noexec,noatime - proc proc rw").Append("\n"); + sb.Append("169 156 0:80 / /dev/pts rw,nosuid,noexec,noatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000").Append("\n"); + sb.Append("172 112 0:81 / /run rw,nosuid,nodev - tmpfs none rw,mode=755").Append("\n"); + sb.Append("174 172 0:82 / /run/lock rw,nosuid,nodev,noexec,noatime - tmpfs none rw").Append("\n"); + sb.Append("176 172 0:83 / /run/shm rw,nosuid,nodev,noatime - tmpfs none rw").Append("\n"); + sb.Append("177 156 0:83 / /dev/shm rw,nosuid,nodev,noatime - tmpfs none rw").Append("\n"); + sb.Append("178 172 0:84 / /run/user rw,nosuid,nodev,noexec,noatime - tmpfs none rw,mode=755").Append("\n"); + sb.Append("179 165 0:27 / /proc/sys/fs/binfmt_misc rw,relatime - binfmt_misc binfmt_misc rw").Append("\n"); + sb.Append("180 162 0:85 / {cgroupPath} ro,nosuid,nodev,noexec - tmpfs tmpfs ro,size=4096k,nr_inodes=1024,mode=755").Append("\n"); + sb.Append($"182 180 0:56 / {cgroupPath}/cpuset rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuset").Append("\n"); + sb.Append($"183 180 0:57 / {cgroupPath}/cpu rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu").Append("\n"); + sb.Append($"184 180 0:58 / {cgroupPath}/cpuacct rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpuacct").Append("\n"); + sb.Append($"185 180 0:59 / {cgroupPath}/blkio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,blkio").Append("\n"); + sb.Append($"186 180 0:60 / {cgroupPath}/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory").Append("\n"); + sb.Append($"187 180 0:61 / {cgroupPath}/devices rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,devices").Append("\n"); + sb.Append($"188 180 0:62 / {cgroupPath}/freezer rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,freezer").Append("\n"); + sb.Append($"189 180 0:63 / {cgroupPath}/net_cls rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_cls").Append("\n"); + sb.Append($"190 180 0:64 / {cgroupPath}/perf_event rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,perf_event").Append("\n"); + sb.Append($"191 180 0:65 / {cgroupPath}/net_prio rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,net_prio").Append("\n"); + sb.Append($"192 180 0:66 / {cgroupPath}/hugetlb rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,hugetlb").Append("\n"); + sb.Append($"193 180 0:67 / {cgroupPath}/pids rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,pids").Append("\n"); + sb.Append($"194 180 0:68 / {cgroupPath}/rdma rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,rdma").Append("\n"); + sb.Append($"195 180 0:69 / {cgroupPath}/misc rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,misc").Append("\n"); + sb.Append("64 113 0:45 /etc/versions.txt /mnt/wslg/versions.txt rw,relatime shared:4 - overlay none rw,lowerdir=/systemvhd,upperdir=/system/rw/upper,workdir=/system/rw/work").Append("\n"); + sb.Append("52 112 0:43 /.X11-unix /tmp/.X11-unix ro,relatime shared:2 - tmpfs none rw").Append("\n"); + sb.Append("56 112 0:38 / /mnt/c rw,noatime - 9p drvfs rw,dirsync,aname=drvfs;path=C:\\;uid=1000;gid=1000;symlinkroot=/mnt/,mmap,access=client,msize=262144,trans=virtio").Append("\n"); + sb.Append($"68 180 0:39 / {cgroupPath}/systemd rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,name=systemd").Append("\n"); + sb.Append("69 156 0:40 / /dev/hugepages rw,relatime - hugetlbfs hugetlbfs rw,pagesize=2M").Append("\n"); + sb.Append("70 156 0:42 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw").Append("\n"); + sb.Append("71 162 0:6 / /sys/kernel/debug rw,nosuid,nodev,noexec,relatime - debugfs debugfs rw").Append("\n"); + sb.Append("72 162 0:11 / /sys/kernel/tracing rw,nosuid,nodev,noexec,relatime - tracefs tracefs rw").Append("\n"); + sb.Append("73 162 0:41 / /sys/fs/fuse/connections rw,nosuid,nodev,noexec,relatime - fusectl fusectl rw").Append("\n"); + sb.Append("256 112 8:32 /snap /snap rw,relatime shared:6 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered").Append("\n"); + sb.Append("257 256 0:50 / /snap/bare/5 ro,nodev,relatime shared:44 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("258 256 0:51 / /snap/gtk-common-themes/1535 ro,nodev,relatime shared:54 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("259 256 0:52 / /snap/core22/607 ro,nodev,relatime shared:55 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("260 256 0:53 / /snap/snapd/18933 ro,nodev,relatime shared:56 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("261 256 0:54 / /snap/ubuntu-desktop-installer/967 ro,nodev,relatime shared:57 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + } + + if (cgroupVersion == CgroupVersion.CgroupV2) + { + sb.Append("71 77 0:26 / /mnt/wsl rw,relatime shared:1 - tmpfs none rw").Append("\n"); + sb.Append("72 77 0:28 / /usr/lib/wsl/drivers ro,nosuid,nodev,noatime - 9p none ro,dirsync,aname=drivers;fmask=222;dmask=222,mmap,access=client,msize=65536,trans=fd,rfd=7,wfd=7").Append("\n"); + sb.Append("76 77 0:32 / /usr/lib/wsl/lib rw,relatime - overlay none rw,lowerdir=/gpu_lib_packaged:/gpu_lib_inbox,upperdir=/gpu_lib/rw/upper,workdir=/gpu_lib/rw/work").Append("\n"); + sb.Append("77 63 8:32 / / rw,relatime - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered").Append("\n"); + sb.Append("78 77 0:37 / /mnt/wslg rw,relatime shared:2 - tmpfs none rw").Append("\n"); + sb.Append("79 78 8:32 / /mnt/wslg/distro ro,relatime shared:3 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered").Append("\n"); + sb.Append("97 77 0:2 /init /init ro - rootfs rootfs rw,size=8101876k,nr_inodes=2025469").Append("\n"); + sb.Append("98 77 0:5 / /dev rw,nosuid,relatime - devtmpfs none rw,size=8101904k,nr_inodes=2025476,mode=755").Append("\n"); + sb.Append("99 77 0:20 / /sys rw,nosuid,nodev,noexec,noatime - sysfs sysfs rw").Append("\n"); + sb.Append("100 77 0:49 / /proc rw,nosuid,nodev,noexec,noatime - proc proc rw").Append("\n"); + sb.Append("101 98 0:50 / /dev/pts rw,nosuid,noexec,noatime - devpts devpts rw,gid=5,mode=620,ptmxmode=000").Append("\n"); + sb.Append("102 77 0:51 / /run rw,nosuid,nodev - tmpfs none rw,mode=755").Append("\n"); + sb.Append("104 102 0:53 / /run/shm rw,nosuid,nodev,noatime - tmpfs none rw").Append("\n"); + sb.Append("105 98 0:53 / /dev/shm rw,nosuid,nodev,noatime - tmpfs none rw").Append("\n"); + sb.Append("106 102 0:54 / /run/user rw,nosuid,nodev,noexec,noatime - tmpfs none rw,mode=755").Append("\n"); + sb.Append("107 100 0:27 / /proc/sys/fs/binfmt_misc rw,relatime - binfmt_misc binfmt_misc rw").Append("\n"); + sb.Append("108 99 0:55 / /sys/fs/cgroup ro,nosuid,nodev,noexec - tmpfs tmpfs ro,size=4096k,nr_inodes=1024,mode=755").Append("\n"); + sb.Append($"109 108 0:21 / {cgroupPath}/unified rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw,nsdelegate").Append("\n"); + sb.Append("113 78 0:39 /etc/versions.txt /mnt/wslg/versions.txt rw,relatime shared:4 - overlay none rw,lowerdir=/systemvhd,upperdir=/system/rw/upper,workdir=/system/rw/work").Append("\n"); + sb.Append("115 78 0:39 /usr/share/doc /mnt/wslg/doc rw,relatime shared:5 - overlay none rw,lowerdir=/systemvhd,upperdir=/system/rw/upper,workdir=/system/rw/work").Append("\n"); + sb.Append("117 77 0:37 /.X11-unix /tmp/.X11-unix ro,relatime shared:2 - tmpfs none rw").Append("\n"); + sb.Append("118 77 0:58 / /mnt/c rw,noatime - 9p drvfs rw,dirsync,aname=drvfs;path=C:\\;uid=1000;gid=1000;symlinkroot=/mnt/,mmap,access=client,msize=262144,trans=virtio").Append("\n"); + sb.Append("119 108 0:59 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,xattr,name=systemd").Append("\n"); + sb.Append("120 98 0:60 / /dev/hugepages rw,relatime - hugetlbfs hugetlbfs rw,pagesize=2M").Append("\n"); + sb.Append("121 98 0:36 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw").Append("\n"); + sb.Append("122 99 0:6 / /sys/kernel/debug rw,nosuid,nodev,noexec,relatime - debugfs debugfs rw").Append("\n"); + sb.Append("123 99 0:11 / /sys/kernel/tracing rw,nosuid,nodev,noexec,relatime - tracefs tracefs rw").Append("\n"); + sb.Append("124 99 0:61 / /sys/fs/fuse/connections rw,nosuid,nodev,noexec,relatime - fusectl fusectl rw").Append("\n"); + sb.Append("125 77 8:32 /snap /snap rw,relatime shared:6 - ext4 /dev/sdc rw,discard,errors=remount-ro,data=ordered").Append("\n"); + sb.Append("203 125 0:62 / /snap/bare/5 ro,nodev,relatime shared:30 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("206 125 0:63 / /snap/core22/607 ro,nodev,relatime shared:42 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("209 125 0:64 / /snap/gtk-common-themes/1535 ro,nodev,relatime shared:44 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("212 125 0:65 / /snap/snapd/18933 ro,nodev,relatime shared:46 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("215 125 0:66 / /snap/ubuntu-desktop-installer/967 ro,nodev,relatime shared:48 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("516 106 0:37 /runtime-dir /run/user/1000 rw,relatime shared:2 - tmpfs none rw").Append("\n"); + sb.Append("517 125 0:71 / /snap/core22/864 ro,nodev,relatime shared:170 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + sb.Append("526 125 0:72 / /snap/ubuntu-desktop-installer/1271 ro,nodev,relatime shared:206 - fuse.snapfuse snapfuse ro,user_id=0,group_id=0,allow_other").Append("\n"); + } + + cgroup.Write(sb.ToString()); + cgroup.Flush(); + } + + using (var maxMemory = File.CreateText(Path.Combine(cgroupV2SlicePath, "memory.max"))) + { + maxMemory.WriteAsync($"{DefaultMemoryLimitBytes}\n"); + maxMemory.Flush(); + } + + using (var maxMemory = File.CreateText(Path.Combine(cgroupV2SlicePath, "memory.current"))) + { + maxMemory.WriteAsync($"{DefaultMemoryUsageBytes}\n"); + maxMemory.Flush(); + } + + using (var usageInBytes = File.CreateText(Path.Combine(cgroupV1MemoryControllerPath, "memory.usage_in_bytes"))) + { + usageInBytes.WriteAsync($"{DefaultMemoryUsageBytes}\n"); + usageInBytes.Flush(); + } + + var memoryStatePath = cgroupVersion == CgroupVersion.CgroupV1 + ? Path.Combine(cgroupV1MemoryControllerPath, "memory.stat") + : Path.Combine(cgroupV2SlicePath, "memory.stat"); + + using (var memoryStat = File.CreateText(memoryStatePath)) + { + sb.Clear(); + sb.Append("cache 10407936").Append("\n"); + sb.Append("rss 778842112").Append("\n"); + sb.Append("rss_huge 0").Append("\n"); + sb.Append("shmem 0").Append("\n"); + sb.Append("mapped_file 0").Append("\n"); + sb.Append("dirty 0").Append("\n"); + sb.Append("writeback 0").Append("\n"); + sb.Append("swap 0").Append("\n"); + sb.Append("pgpgin 234465").Append("\n"); + sb.Append("pgpgout 41732").Append("\n"); + sb.Append("pgfault 233838").Append("\n"); + sb.Append("pgmajfault 0").Append("\n"); + sb.Append("inactive_anon 0").Append("\n"); + sb.Append("active_anon 778702848").Append("\n"); + sb.Append("inactive_file 10407936").Append("\n"); + sb.Append("active_file 0").Append("\n"); + sb.Append("unevictable 0").Append("\n"); + sb.Append("hierarchical_memory_limit 1073741824").Append("\n"); + sb.Append("hierarchical_memsw_limit 2147483648").Append("\n"); + sb.Append("total_cache 10407936").Append("\n"); + sb.Append("total_rss 778842112").Append("\n"); + sb.Append("total_rss_huge 0").Append("\n"); + sb.Append("total_shmem 0").Append("\n"); + sb.Append("total_mapped_file 0").Append("\n"); + sb.Append("total_dirty 0").Append("\n"); + sb.Append("total_writeback 0").Append("\n"); + sb.Append("total_swap 0").Append("\n"); + sb.Append("total_pgpgin 234465").Append("\n"); + sb.Append("total_pgpgout 41732").Append("\n"); + sb.Append("total_pgfault 233838").Append("\n"); + sb.Append("total_pgmajfault 0").Append("\n"); + sb.Append("total_inactive_anon 0").Append("\n"); + sb.Append("total_active_anon 778702848").Append("\n"); + sb.Append("total_inactive_file 10407936").Append("\n"); + sb.Append("total_active_file 0").Append("\n"); + sb.Append("total_unevictable 0").Append("\n"); + sb.Append("recent_rotated_anon 231947").Append("\n"); + sb.Append("recent_rotated_file 2").Append("\n"); + sb.Append("recent_scanned_anon 231947").Append("\n"); + sb.Append("recent_scanned_file 2622").Append("\n"); + memoryStat.Write(sb.ToString()); + memoryStat.Flush(); + } + + return new(cgroupVersion) + { + RootPath = rootPath, + ProcPath = procPath, + ProcSelfPath = procSelfPath, + CgroupPath = cgroupPath, + CgroupV1MemoryControllerPath = cgroupV1MemoryControllerPath, + CgroupV2SlicePath = cgroupV2SlicePath, + }; + } + } +} diff --git a/test/Elastic.Apm.Tests/TestResources/proc/cgroup b/test/Elastic.Apm.Tests/TestResources/proc/cgroup deleted file mode 100644 index eb1f1ab1b..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/cgroup +++ /dev/null @@ -1,2 +0,0 @@ -9:memory:/ -0::/ diff --git a/test/Elastic.Apm.Tests/TestResources/proc/cgroup2 b/test/Elastic.Apm.Tests/TestResources/proc/cgroup2 deleted file mode 100644 index c4e95eb78..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/cgroup2 +++ /dev/null @@ -1,2 +0,0 @@ -0::/slicewrongdir -9:memory:/slice diff --git a/test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_0 b/test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_0 deleted file mode 100644 index 93fe96524..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_0 +++ /dev/null @@ -1 +0,0 @@ -0::/slice diff --git a/test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_memory b/test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_memory deleted file mode 100644 index 95e703b60..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/cgroup2_only_memory +++ /dev/null @@ -1 +0,0 @@ -9:memory:/slice diff --git a/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.limit_in_bytes b/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.limit_in_bytes deleted file mode 100644 index 1df8dd444..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.limit_in_bytes +++ /dev/null @@ -1 +0,0 @@ -7964778496 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.stat b/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.stat deleted file mode 100644 index bf248be31..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.stat +++ /dev/null @@ -1,40 +0,0 @@ -cache 10407936 -rss 778842112 -rss_huge 0 -shmem 0 -mapped_file 0 -dirty 0 -writeback 0 -swap 0 -pgpgin 234465 -pgpgout 41732 -pgfault 233838 -pgmajfault 0 -inactive_anon 0 -active_anon 778702848 -inactive_file 10407936 -active_file 0 -unevictable 0 -hierarchical_memory_limit 1073741824 -hierarchical_memsw_limit 2147483648 -total_cache 10407936 -total_rss 778842112 -total_rss_huge 0 -total_shmem 0 -total_mapped_file 0 -total_dirty 0 -total_writeback 0 -total_swap 0 -total_pgpgin 234465 -total_pgpgout 41732 -total_pgfault 233838 -total_pgmajfault 0 -total_inactive_anon 0 -total_active_anon 778702848 -total_inactive_file 10407936 -total_active_file 0 -total_unevictable 0 -recent_rotated_anon 231947 -recent_rotated_file 2 -recent_scanned_anon 231947 -recent_scanned_file 2622 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.usage_in_bytes b/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.usage_in_bytes deleted file mode 100644 index 237642783..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/limited/memory/memory.usage_in_bytes +++ /dev/null @@ -1 +0,0 @@ -964778496 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/meminfo b/test/Elastic.Apm.Tests/TestResources/proc/meminfo deleted file mode 100644 index 076cfca9f..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/meminfo +++ /dev/null @@ -1,6 +0,0 @@ -MemTotal: 7778104 kB -MemFree: 4806144 kB -Buffers: 211756 kB -Cached: 1071092 kB -SwapTotal: 4194296 kB -SwapFree: 4194296 kB diff --git a/test/Elastic.Apm.Tests/TestResources/proc/meminfo-3.14 b/test/Elastic.Apm.Tests/TestResources/proc/meminfo-3.14 deleted file mode 100644 index a8bd43cd7..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/meminfo-3.14 +++ /dev/null @@ -1,7 +0,0 @@ -MemTotal: 7778104 kB -MemFree: 4806144 kB -Buffers: 211756 kB -Cached: 1071092 kB -SwapTotal: 4194296 kB -SwapFree: 4194296 kB -MemAvailable: 543584 kB diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.current b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.current deleted file mode 100644 index 237642783..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.current +++ /dev/null @@ -1 +0,0 @@ -964778496 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.max b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.max deleted file mode 100644 index 1df8dd444..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.max +++ /dev/null @@ -1 +0,0 @@ -7964778496 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.stat b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.stat deleted file mode 100644 index bf248be31..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2/slice/memory.stat +++ /dev/null @@ -1,40 +0,0 @@ -cache 10407936 -rss 778842112 -rss_huge 0 -shmem 0 -mapped_file 0 -dirty 0 -writeback 0 -swap 0 -pgpgin 234465 -pgpgout 41732 -pgfault 233838 -pgmajfault 0 -inactive_anon 0 -active_anon 778702848 -inactive_file 10407936 -active_file 0 -unevictable 0 -hierarchical_memory_limit 1073741824 -hierarchical_memsw_limit 2147483648 -total_cache 10407936 -total_rss 778842112 -total_rss_huge 0 -total_shmem 0 -total_mapped_file 0 -total_dirty 0 -total_writeback 0 -total_swap 0 -total_pgpgin 234465 -total_pgpgout 41732 -total_pgfault 233838 -total_pgmajfault 0 -total_inactive_anon 0 -total_active_anon 778702848 -total_inactive_file 10407936 -total_active_file 0 -total_unevictable 0 -recent_rotated_anon 231947 -recent_rotated_file 2 -recent_scanned_anon 231947 -recent_scanned_file 2622 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.current b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.current deleted file mode 100644 index 237642783..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.current +++ /dev/null @@ -1 +0,0 @@ -964778496 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.max b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.max deleted file mode 100644 index 355295a05..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.max +++ /dev/null @@ -1 +0,0 @@ -max diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.stat b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.stat deleted file mode 100644 index 6339ecd45..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited/slice/memory.stat +++ /dev/null @@ -1,40 +0,0 @@ -cache 10407936 -rss 778842112 -rss_huge 0 -shmem 0 -mapped_file 0 -dirty 0 -writeback 0 -swap 0 -pgpgin 234465 -pgpgout 41732 -pgfault 233838 -pgmajfault 0 -inactive_anon 0 -active_anon 778702848 -inactive_file 500 -active_file 0 -unevictable 0 -hierarchical_memory_limit 1073741824 -hierarchical_memsw_limit 2147483648 -total_cache 10407936 -total_rss 778842112 -total_rss_huge 0 -total_shmem 0 -total_mapped_file 0 -total_dirty 0 -total_writeback 0 -total_swap 0 -total_pgpgin 234465 -total_pgpgout 41732 -total_pgfault 233838 -total_pgmajfault 0 -total_inactive_anon 0 -total_active_anon 778702848 -total_inactive_file 10407936 -total_active_file 0 -total_unevictable 0 -recent_rotated_anon 231947 -recent_rotated_file 2 -recent_scanned_anon 231947 -recent_scanned_file 2622 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.current b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.current deleted file mode 100644 index 237642783..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.current +++ /dev/null @@ -1 +0,0 @@ -964778496 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.max b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.max deleted file mode 100644 index 355295a05..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.max +++ /dev/null @@ -1 +0,0 @@ -max diff --git a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.stat b/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.stat deleted file mode 100644 index af871fa05..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/sys_cgroup2_unlimited_stat_different_order/slice/memory.stat +++ /dev/null @@ -1,40 +0,0 @@ -cache 10407936 -rss 778842112 -rss_huge 0 -shmem 0 -mapped_file 0 -dirty 0 -writeback 0 -swap 0 -pgpgin 234465 -pgpgout 41732 -pgfault 233838 -pgmajfault 0 -total_inactive_file 10407936 -inactive_anon 0 -active_anon 778702848 -inactive_file 500 -active_file 0 -unevictable 0 -hierarchical_memory_limit 1073741824 -hierarchical_memsw_limit 2147483648 -total_cache 10407936 -total_rss 778842112 -total_rss_huge 0 -total_shmem 0 -total_mapped_file 0 -total_dirty 0 -total_writeback 0 -total_swap 0 -total_pgpgin 234465 -total_pgpgout 41732 -total_pgfault 233838 -total_pgmajfault 0 -total_inactive_anon 0 -total_active_anon 778702848 -total_active_file 0 -total_unevictable 0 -recent_rotated_anon 231947 -recent_rotated_file 2 -recent_scanned_anon 231947 -recent_scanned_file 2622 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.limit_in_bytes b/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.limit_in_bytes deleted file mode 100644 index 564113cfa..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.limit_in_bytes +++ /dev/null @@ -1 +0,0 @@ -9223372036854771712 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.stat b/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.stat deleted file mode 100644 index bf248be31..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.stat +++ /dev/null @@ -1,40 +0,0 @@ -cache 10407936 -rss 778842112 -rss_huge 0 -shmem 0 -mapped_file 0 -dirty 0 -writeback 0 -swap 0 -pgpgin 234465 -pgpgout 41732 -pgfault 233838 -pgmajfault 0 -inactive_anon 0 -active_anon 778702848 -inactive_file 10407936 -active_file 0 -unevictable 0 -hierarchical_memory_limit 1073741824 -hierarchical_memsw_limit 2147483648 -total_cache 10407936 -total_rss 778842112 -total_rss_huge 0 -total_shmem 0 -total_mapped_file 0 -total_dirty 0 -total_writeback 0 -total_swap 0 -total_pgpgin 234465 -total_pgpgout 41732 -total_pgfault 233838 -total_pgmajfault 0 -total_inactive_anon 0 -total_active_anon 778702848 -total_inactive_file 10407936 -total_active_file 0 -total_unevictable 0 -recent_rotated_anon 231947 -recent_rotated_file 2 -recent_scanned_anon 231947 -recent_scanned_file 2622 diff --git a/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.usage_in_bytes b/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.usage_in_bytes deleted file mode 100644 index 237642783..000000000 --- a/test/Elastic.Apm.Tests/TestResources/proc/unlimited/memory/memory.usage_in_bytes +++ /dev/null @@ -1 +0,0 @@ -964778496