Fix ServiceStack SendReceive instrumentation#3084
Conversation
This comment has been minimized.
This comment has been minimized.
pierotibou
left a comment
There was a problem hiding this comment.
Thanks a lot for the great PR description and the fix. Though you say that the tests pass, but they are failing :)
This comment has been minimized.
This comment has been minimized.
017ae22 to
4214040
Compare
This comment has been minimized.
This comment has been minimized.
|
|
||
| <PropertyGroup> | ||
| <ApiVersion Condition="'$(ApiVersion)' == ''">5.2.0</ApiVersion> | ||
| <TargetFrameworks>net461;netcoreapp3.1;net5.0;net6.0</TargetFrameworks> |
There was a problem hiding this comment.
If we want to still build/test older package versions like 6.1.0 or 5.2.0 on netcoreapp3.0, I recommend removing both changes in this file so we still build the application for all of the frameworks, and we can test locally in VS by setting ApiVersion to a version that's compatible with all of the TFM's we test against.
The changes you've made in tracer/build/PackageVersionsGeneratorDefinitions.json alone should be enough to ensure that CI won't build an incompatible package version/TFM
There was a problem hiding this comment.
Ah yeah good point on that this removes the ability to test older versions
The issue that I was having with this specifically is that when I bumped the version to 6.2.0 it would attempt to build NET Core 2.1/3.0 here (which would fail).
I'll see if making Framework conditionals for the <ItemGroup> to have multiple PackageReference entries for ServiceStack does the trick.
There was a problem hiding this comment.
I've swapped it to use two conditional ItemGroup one for .NET Core 2.1/3.0 and one for anything other than those.
Let me know if that looks good otherwise I can just revert it back to the original.
I was thinking that this way wouldn't work at first because there's this <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute> in the sample csproj and I thought that'd break the $(TargetFramework) value, but apparently not.
There was a problem hiding this comment.
Oh right, the <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute> property controls whether the C# compilation should generate a [TargetFrameworkAttribute] that is applied to the resulting assembly. All the <GenerateXXXAttribute> flags operate just like this, so it doesn't affect the MSBuild properties but assembly attributes on the compiled application 👍🏼
| /// ServiceStack.Redis.RedisNativeClient.SendReceive[T] calltarget instrumentation (v6.2.0+) | ||
| /// <para> | ||
| /// 6.2.0 of ServiceStack.Redis changed the signature of SendReceive (added string parameter). | ||
| /// See: https://github.com/ServiceStack/ServiceStack/commit/950155db0d1b358920eab307c61e334e24f1d174 |
There was a problem hiding this comment.
Nice, thanks for the link 👍🏼
| /// Also, 6.2.0 broke .NET Core 2.1 and .NET Core 3.0 compatibility as ServiceStack | ||
| /// accidentally added a dependency that claimed it was .NET Standard 2.0 compliant | ||
| /// but in reality wasn't. |
There was a problem hiding this comment.
This comment is helpful, but maybe it could be placed somewhere else where we build/test? My first thought was adding it to tracer/build/PackageVersionsGeneratorDefinitions.json but I don't know if we can add comments there without breaking our JSON parsing 😞 I think the instrumentation here is only concerned with the method signature and the assembly dependency issue that was also introduced in 6.2.0 is a separate concern
There was a problem hiding this comment.
Yeah I didn't really know where to put this, but it doesn't make a ton of sense here
I didn't think of attempting to add a comment to the ackageVersionsGeneratorDefinitions.json, so I'll try that and maybe also adding it as a comment in the sample csproj as well?
There was a problem hiding this comment.
So I tossed a variation of the comment in the sample project.
I also learned that comments just aren't allowed in JSON whatsoever.
zacharycmontoya
left a comment
There was a problem hiding this comment.
I think the test application csproj needs to be updated, otherwise LGTM!
4214040 to
eca7682
Compare
This comment has been minimized.
This comment has been minimized.
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ItemGroup Condition="'$(TargetFramework)'=='netcoreapp2.1' OR '$(TargetFramework)'=='netcoreapp3.0'"> |
There was a problem hiding this comment.
It looks like you're setting the same version value regardless of the TargetFramework, so maybe we can remove the PackageReference changes
There was a problem hiding this comment.
The case I'm attempting to avoid with this setup is if you set the NuGet to 6.2.0 it'll cause the .NET Core 2.1/3.0 builds to fail in VS and then you can't run the tests.
So if you were wanting to test that version (or maybe higher versions?) you can just swap out the $(ApiVersion) in <ItemGroup Condition="'$(TargetFramework)'!='netcoreapp2.1' AND '$(TargetFramework)'!='netcoreapp3.0'">'s and avoid breaking the other NET Core targets. I don't think I did a good job explaining that reasoning in the comment in that csproj or maybe I'm just overthinking it
There was a problem hiding this comment.
Ohhh I see what you're saying now. Maybe a more bulletproof (maybe not as clean?) way to do this is to just override the ApiVersion if we ever detect the bad combination of 6.2.0 and netcoreapp2.1/netcoreapp3.0. To do that you could restore the csproj to its original contents and then add a second ApiVersion line like this. What do you think?
<ApiVersion Condition="('$(TargetFramework)'=='netcoreapp2.1' OR '$(TargetFramework)'=='netcoreapp3.0') AND '$(ApiVersion)' == '6.2.0'">6.1.0</ApiVersion>
There was a problem hiding this comment.
I like it, very nice 👍
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
pierotibou
left a comment
There was a problem hiding this comment.
Cool thanks a lot for investigating and fixing this one.
| /// <param name="sendWithoutRead">Send without read boolean</param> | ||
| /// <param name="operation">The calling member name</param> | ||
| /// <returns>Calltarget state value</returns> | ||
| internal static CallTargetState OnMethodBegin<TTarget, TFunc, TAction>(TTarget instance, byte[][] cmdWithBinaryArgs, TFunc fn, TAction completePipelineFn, bool sendWithoutRead, string operation) |
There was a problem hiding this comment.
Do you know what this string can contain and if it would be interesting to add it as a tag? I tried to check quickly but I'm not sure what it contains (if you don't know, don't mind me).
There was a problem hiding this comment.
This has the function name of whatever called the SendReceive
I'm not really sure whether or not that'd be interesting information to add as a tag for us
In 6.2.0 a dependency was added to ServiceStack that isn't .NET Standard 2.0 compliant and broke these two targeted frameworks.
This was updated with version 6.2.0 of ServiceStack.
In 6.2.0 support for these broke, so excluding them.
Content of the comment is in the Samples project.
377325a to
0a272bf
Compare
Benchmarks Report 🐌Benchmarks for #3084 compared to master:
The following thresholds were used for comparing the benchmark speeds:
Allocation changes below 0.5% are ignored. Benchmark detailsBenchmarks.Trace.AgentWriterBenchmark - Same speed ✔️ Same allocations ✔️Raw results
Benchmarks.Trace.AppSecBodyBenchmark - Faster 🎉 Same allocations ✔️
|
| Benchmark | base/diff | Base Median (ns) | Diff Median (ns) | Modality |
|---|---|---|---|---|
| Benchmarks.Trace.AppSecBodyBenchmark.AllCycleMoreComplexBody‑net472 | 1.253 | 232.64 | 185.70 |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | AllCycleSimpleBody |
net472 | 185ns | 0.0773ns | 0.3ns | 0.0676 | 0 | 0 | 425 B |
| master | AllCycleSimpleBody |
netcoreapp3.1 | 237ns | 0.338ns | 1.31ns | 0.00585 | 0 | 0 | 424 B |
| master | AllCycleMoreComplexBody |
net472 | 234ns | 1.06ns | 4.11ns | 0.0637 | 0 | 0 | 401 B |
| master | AllCycleMoreComplexBody |
netcoreapp3.1 | 247ns | 0.28ns | 1.09ns | 0.00549 | 0 | 0 | 400 B |
| master | BodyExtractorSimpleBody |
net472 | 262ns | 0.175ns | 0.655ns | 0.0574 | 0 | 0 | 361 B |
| master | BodyExtractorSimpleBody |
netcoreapp3.1 | 219ns | 0.322ns | 1.2ns | 0.00376 | 0 | 0 | 272 B |
| master | BodyExtractorMoreComplexBody |
net472 | 14.5μs | 8.62ns | 32.3ns | 1.21 | 0.0217 | 0 | 7.62 KB |
| master | BodyExtractorMoreComplexBody |
netcoreapp3.1 | 12μs | 17.6ns | 65.9ns | 0.0897 | 0 | 0 | 6.75 KB |
| #3084 | AllCycleSimpleBody |
net472 | 187ns | 0.203ns | 0.73ns | 0.0675 | 0 | 0 | 425 B |
| #3084 | AllCycleSimpleBody |
netcoreapp3.1 | 237ns | 0.158ns | 0.591ns | 0.00579 | 0 | 0 | 424 B |
| #3084 | AllCycleMoreComplexBody |
net472 | 186ns | 0.132ns | 0.493ns | 0.0637 | 0 | 0 | 401 B |
| #3084 | AllCycleMoreComplexBody |
netcoreapp3.1 | 241ns | 0.317ns | 1.23ns | 0.00543 | 0 | 0 | 400 B |
| #3084 | BodyExtractorSimpleBody |
net472 | 259ns | 0.334ns | 1.29ns | 0.0573 | 0 | 0 | 361 B |
| #3084 | BodyExtractorSimpleBody |
netcoreapp3.1 | 216ns | 0.364ns | 1.36ns | 0.00367 | 0 | 0 | 272 B |
| #3084 | BodyExtractorMoreComplexBody |
net472 | 15.1μs | 8.51ns | 33ns | 1.21 | 0.0151 | 0 | 7.62 KB |
| #3084 | BodyExtractorMoreComplexBody |
netcoreapp3.1 | 12μs | 22.1ns | 85.7ns | 0.09 | 0 | 0 | 6.75 KB |
Benchmarks.Trace.AspNetCoreBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendRequest |
net472 | 0ns | 0ns | 0ns | 0 | 0 | 0 | 0 b |
| master | SendRequest |
netcoreapp3.1 | 181μs | 114ns | 427ns | 0.271 | 0 | 0 | 20.57 KB |
| #3084 | SendRequest |
net472 | 0ns | 0ns | 0ns | 0 | 0 | 0 | 0 b |
| #3084 | SendRequest |
netcoreapp3.1 | 182μs | 217ns | 839ns | 0.275 | 0 | 0 | 20.57 KB |
Benchmarks.Trace.DbCommandBenchmark - Faster 🎉 Same allocations ✔️
Faster 🎉 in #3084
Benchmark
base/diff
Base Median (ns)
Diff Median (ns)
Modality
Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery‑netcoreapp3.1
1.146
1,612.13
1,406.73
| Benchmark | base/diff | Base Median (ns) | Diff Median (ns) | Modality |
|---|---|---|---|---|
| Benchmarks.Trace.DbCommandBenchmark.ExecuteNonQuery‑netcoreapp3.1 | 1.146 | 1,612.13 | 1,406.73 |
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteNonQuery |
net472 | 1.8μs | 0.753ns | 2.71ns | 0.15 | 0.000899 | 0 | 947 B |
| master | ExecuteNonQuery |
netcoreapp3.1 | 1.61μs | 0.786ns | 3.04ns | 0.0121 | 0 | 0 | 936 B |
| #3084 | ExecuteNonQuery |
net472 | 1.88μs | 1.08ns | 4.2ns | 0.15 | 0.000946 | 0 | 947 B |
| #3084 | ExecuteNonQuery |
netcoreapp3.1 | 1.41μs | 0.484ns | 1.81ns | 0.012 | 0 | 0 | 936 B |
Benchmarks.Trace.ElasticsearchBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | CallElasticsearch |
net472 | 2.53μs | 1.19ns | 4.62ns | 0.183 | 0 | 0 | 1.16 KB |
| master | CallElasticsearch |
netcoreapp3.1 | 1.62μs | 0.771ns | 2.89ns | 0.0146 | 0 | 0 | 1.1 KB |
| master | CallElasticsearchAsync |
net472 | 2.64μs | 0.732ns | 2.74ns | 0.204 | 0 | 0 | 1.29 KB |
| master | CallElasticsearchAsync |
netcoreapp3.1 | 1.64μs | 2.07ns | 7.74ns | 0.0165 | 0 | 0 | 1.22 KB |
| #3084 | CallElasticsearch |
net472 | 2.47μs | 1.32ns | 4.77ns | 0.183 | 0 | 0 | 1.16 KB |
| #3084 | CallElasticsearch |
netcoreapp3.1 | 1.53μs | 0.925ns | 3.34ns | 0.0152 | 0 | 0 | 1.1 KB |
| #3084 | CallElasticsearchAsync |
net472 | 2.6μs | 1.14ns | 4.28ns | 0.205 | 0 | 0 | 1.29 KB |
| #3084 | CallElasticsearchAsync |
netcoreapp3.1 | 1.64μs | 0.867ns | 3.25ns | 0.0164 | 0 | 0 | 1.22 KB |
Benchmarks.Trace.GraphQLBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | ExecuteAsync |
net472 | 2.65μs | 5.89ns | 22.8ns | 0.226 | 0 | 0 | 1.42 KB |
| master | ExecuteAsync |
netcoreapp3.1 | 1.68μs | 4.42ns | 17.1ns | 0.0185 | 0 | 0 | 1.34 KB |
| #3084 | ExecuteAsync |
net472 | 2.66μs | 5.09ns | 19.7ns | 0.225 | 0 | 0 | 1.42 KB |
| #3084 | ExecuteAsync |
netcoreapp3.1 | 1.68μs | 3.23ns | 12.5ns | 0.0183 | 0 | 0 | 1.34 KB |
Benchmarks.Trace.HttpClientBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendAsync |
net472 | 5.64μs | 8.3ns | 32.2ns | 0.439 | 0 | 0 | 2.77 KB |
| master | SendAsync |
netcoreapp3.1 | 3.62μs | 10.3ns | 39.7ns | 0.0348 | 0 | 0 | 2.6 KB |
| #3084 | SendAsync |
net472 | 5.77μs | 13.9ns | 53.8ns | 0.438 | 0 | 0 | 2.77 KB |
| #3084 | SendAsync |
netcoreapp3.1 | 3.65μs | 10.5ns | 40.7ns | 0.034 | 0 | 0 | 2.6 KB |
Benchmarks.Trace.ILoggerBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 3.23μs | 3.78ns | 14.6ns | 0.287 | 0 | 0 | 1.81 KB |
| master | EnrichedLog |
netcoreapp3.1 | 2.53μs | 1.19ns | 4.43ns | 0.0253 | 0 | 0 | 1.85 KB |
| #3084 | EnrichedLog |
net472 | 3.23μs | 2.58ns | 10ns | 0.287 | 0 | 0 | 1.81 KB |
| #3084 | EnrichedLog |
netcoreapp3.1 | 2.59μs | 1.08ns | 3.88ns | 0.0247 | 0 | 0 | 1.85 KB |
Benchmarks.Trace.Log4netBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 150μs | 109ns | 392ns | 0.672 | 0.224 | 0 | 4.65 KB |
| master | EnrichedLog |
netcoreapp3.1 | 117μs | 213ns | 826ns | 0.0595 | 0 | 0 | 4.49 KB |
| #3084 | EnrichedLog |
net472 | 153μs | 178ns | 691ns | 0.691 | 0.23 | 0 | 4.65 KB |
| #3084 | EnrichedLog |
netcoreapp3.1 | 119μs | 110ns | 426ns | 0.0594 | 0 | 0 | 4.49 KB |
Benchmarks.Trace.NLogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 5.62μs | 7.97ns | 29.8ns | 0.568 | 0.00278 | 0 | 3.59 KB |
| master | EnrichedLog |
netcoreapp3.1 | 4.33μs | 9.47ns | 36.7ns | 0.0535 | 0 | 0 | 3.91 KB |
| #3084 | EnrichedLog |
net472 | 5.45μs | 14ns | 54.1ns | 0.568 | 0.00269 | 0 | 3.59 KB |
| #3084 | EnrichedLog |
netcoreapp3.1 | 4.31μs | 7.65ns | 29.6ns | 0.0532 | 0 | 0 | 3.91 KB |
Benchmarks.Trace.RedisBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | SendReceive |
net472 | 2.32μs | 4.05ns | 15.2ns | 0.217 | 0 | 0 | 1.37 KB |
| master | SendReceive |
netcoreapp3.1 | 1.85μs | 1.37ns | 5.12ns | 0.0176 | 0 | 0 | 1.32 KB |
| #3084 | SendReceive |
net472 | 2.39μs | 7.76ns | 26.9ns | 0.218 | 0 | 0 | 1.37 KB |
| #3084 | SendReceive |
netcoreapp3.1 | 1.83μs | 1.02ns | 3.94ns | 0.0182 | 0 | 0 | 1.32 KB |
Benchmarks.Trace.SerilogBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | EnrichedLog |
net472 | 5.02μs | 1.33ns | 5.15ns | 0.352 | 0 | 0 | 2.23 KB |
| master | EnrichedLog |
netcoreapp3.1 | 4.23μs | 1.3ns | 5.05ns | 0.0233 | 0 | 0 | 1.8 KB |
| #3084 | EnrichedLog |
net472 | 4.98μs | 1.93ns | 7.21ns | 0.352 | 0 | 0 | 2.23 KB |
| #3084 | EnrichedLog |
netcoreapp3.1 | 4.49μs | 1.7ns | 6.38ns | 0.0244 | 0 | 0 | 1.8 KB |
Benchmarks.Trace.SpanBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | StartFinishSpan |
net472 | 1.15μs | 0.556ns | 2.15ns | 0.129 | 0 | 0 | 810 B |
| master | StartFinishSpan |
netcoreapp3.1 | 935ns | 3.25ns | 12.1ns | 0.0106 | 0 | 0 | 760 B |
| master | StartFinishScope |
net472 | 1.45μs | 0.761ns | 2.95ns | 0.141 | 0 | 0 | 891 B |
| master | StartFinishScope |
netcoreapp3.1 | 1.06μs | 0.62ns | 2.32ns | 0.0123 | 0 | 0 | 880 B |
| #3084 | StartFinishSpan |
net472 | 1.18μs | 0.283ns | 1.06ns | 0.128 | 0 | 0 | 810 B |
| #3084 | StartFinishSpan |
netcoreapp3.1 | 931ns | 0.353ns | 1.32ns | 0.0101 | 0 | 0 | 760 B |
| #3084 | StartFinishScope |
net472 | 1.39μs | 0.805ns | 3.12ns | 0.141 | 0 | 0 | 891 B |
| #3084 | StartFinishScope |
netcoreapp3.1 | 1.11μs | 0.573ns | 2.22ns | 0.0117 | 0 | 0 | 880 B |
Benchmarks.Trace.TraceAnnotationsBenchmark - Same speed ✔️ Same allocations ✔️
Raw results
| Branch | Method | Toolchain | Mean | StdError | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|---|---|---|---|---|---|---|---|---|---|
| master | RunOnMethodBegin |
net472 | 1.5μs | 0.828ns | 3.1ns | 0.141 | 0 | 0 | 891 B |
| master | RunOnMethodBegin |
netcoreapp3.1 | 1.12μs | 0.342ns | 1.28ns | 0.0118 | 0 | 0 | 880 B |
| #3084 | RunOnMethodBegin |
net472 | 1.47μs | 0.611ns | 2.2ns | 0.141 | 0 | 0 | 891 B |
| #3084 | RunOnMethodBegin |
netcoreapp3.1 | 1.15μs | 0.428ns | 1.66ns | 0.0119 | 0 | 0 | 880 B |
Code Coverage Report 📊✔️ Merging #3084 into master will not change line coverage
View the full report for further details: Datadog.Trace Breakdown ✔️
The following classes have significant coverage changes.
The following classes were added in #3084:
View the full reports for further details: |
Summary of changes
Fixes our
ServiceStack.Redisinstrumentation as the signature of it changed in v6.2.0. Additionally, in v6.2.0 .NET Standard 2.0 compliance was broken by accident, so I removed v6.2.0 from being run on .NET Core 2.1 and 3.0 integration tests.Reason for change
Version 6.2.0 of
ServiceStack.Redismodified itsSendReceive<T>function to add on an additionalstringparameter:Additionally, a transitive dependency was added to
System.Diagnostics.DiagnosticSourcev6.0.0, which doesn't actually support .NET Standard 2.0, so our .NET Core 2.1 and .NET Core 3.0ServiceStack.Redisintegration tests have been excluded from v6.2.0+ ofServiceStack.Redis.Implementation details
Added a new
InstrumentMethodattribute inRedisNativeClientSendReceiveIntegration.csand retargeted the min/max versions.Added an exclusion in the
PackageVersionsGeneratorDefinitions.jsonto exclude .NET Core 2.1 and 3.0 integration tests forServiceStack.RedisTest coverage
Other details
I committed the changes to the various
PackageVersions*generated files - not 100% sure if that is ideal as it appears to contain changes to other packages outside the scope of this PR.AIT-3788