Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added entityframeworkcore instrumentation #929

Conversation

Place1
Copy link

@Place1 Place1 commented Jul 27, 2020

Fixes #928

Changes

This PR adds OpenTelemetry.Instrumentation.EntityFrameworkCore which is modified version of OpenTelementry.Instrumentation.SqlClient.

This new instrumentation listens to Microsoft.EntityFrameworkCore.Database.Command.* diagnostic events to support creating spans for database requests.

@Place1 Place1 requested a review from a team as a code owner July 27, 2020 01:01
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Jul 27, 2020

CLA Check
The committers are authorized under a signed CLA.

Copy link
Contributor

@eddynaka eddynaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments. Can you add some tests as well?

Copy link
Member

@MikeGoldsmith MikeGoldsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a great start - thanks! I've left some minor changes to clean up the commit.

Also, you'll need to sign the CLA before we can merge the PR 👍

@Place1
Copy link
Author

Place1 commented Jul 27, 2020

Added some comments. Can you add some tests as well?

Adding tests seems difficult and is more of a time commitment than I had in mind here. I don't actually use Open Telemetry yet (but it's a great project that i hope to use 😄).

I guess tests would need to run against a few of EF Core's supported backends:

  • sqlite3
  • postgres
  • mysql
  • mssql

I don't think I have the time to write all of this testing code. Apologies.

I'm happy for someone to take ownership of this PR.

@CodeBlanch
Copy link
Member

@Place1 Do you happen to have a link handy for the EF Core code sending the diagnostic source events? I just wanted to check out the other side of the equation to see how they are doing it, look if there's anything more interesting we can push into the data, etc.


private readonly EntityFrameworkInstrumentationOptions options;

public EntityFrameworkDiagnosticListener(string sourceName, EntityFrameworkInstrumentationOptions options)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see one potential issue. The SqlClient .NET code does not start Activities, it just fires events. This is why the SqlClientDiagnosticListener has SupportsNullActivity => true and is written to create Activity, not just populate them like some of the other instrumentation. This class is missing SupportsNullActivity => true but is still written in that style to create Activity always. Probably a mismatch somewhere. I need to go look at the EF code to figure out the correct behavior, will do later today.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: I went digging through the source. EF does not spin up Activity:
https://github.com/dotnet/efcore/blob/7d6cb86ff1facb1480a51519f8052043977831bc/src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs#L235-L238

So the code needed SupportsNullActivity => true. Since I was in there, I built a unit test on top of Sqlite in-memory DB. That led to some other bug fixes. Sorry @Place1 for jumping in there, I hope you don't mind.

I just pushed what I have so far. Could probably use a bit more unit testing and maybe some enhancements to the data being collected, but working well-enough I think we can merge PR and do that separate? Or move it to contrib?

@codecov
Copy link

codecov bot commented Jul 28, 2020

Codecov Report

Merging #929 into master will decrease coverage by 0.59%.
The diff coverage is 46.54%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #929      +/-   ##
==========================================
- Coverage   68.74%   68.14%   -0.60%     
==========================================
  Files         213      219       +6     
  Lines        5912     6068     +156     
  Branches      967      997      +30     
==========================================
+ Hits         4064     4135      +71     
- Misses       1580     1643      +63     
- Partials      268      290      +22     
Impacted Files Coverage Δ
...eworkCore/EntityFrameworkInstrumentationOptions.cs 0.00% <0.00%> (ø)
...ation/EntityFrameworkInstrumentationEventSource.cs 0.00% <0.00%> (ø)
...mplementation/EntityFrameworkDiagnosticListener.cs 44.08% <44.08%> (ø)
...ityFrameworkCore/OpenTelemetryBuilderExtensions.cs 57.14% <57.14%> (ø)
...ityFrameworkCore/Implementation/PropertyFetcher.cs 66.66% <66.66%> (ø)
...ityFrameworkCore/EntityFrameworkInstrumentation.cs 88.88% <88.88%> (ø)
...ient/Implementation/SqlClientDiagnosticListener.cs 61.53% <100.00%> (ø)
... and 3 more

using var shutdownSignal = Sdk.CreateTracerProvider(b =>
{
b.AddProcessorPipeline(c => c.AddProcessor(ap => activityProcessor.Object));
b.AddEntityFrameworkInstrumentation();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we enable SqlClient instrumentation and use SqlClient inside EF, do we get duplicate info - one from EF and one from SqlClient?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes in that case you get an outer span from EF instrumentation and an inner span from Sql instrumentation. I just tested to be sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for confirming. This is important to be noted in the readme.md for EF instrumentation and SqlClient instrumentation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also unit test this, to make nothing unexpected happens. Expected is 2 spans EF outer span and Sql inner span.

@cijothomas
Copy link
Member

@Place1 Let us know if you have time to make requested changes/tests. If not, we'll try to add them and merge. Please let us know.

@Place1
Copy link
Author

Place1 commented Jul 29, 2020 via email

@cijothomas cijothomas mentioned this pull request Jul 29, 2020
@CodeBlanch
Copy link
Member

@cijothomas I spent a little time on this to try and get it over the hump for @Place1. It will now push db.system using the ProviderName exposed by EF. There are a lot of providers. I picked what I felt were the top ones. I thought about adding an option so users can take over that decision if their provider isn't in our list? Let me know your thoughts on that.

As far as testing goes...

  • After Runtime context API #948 goes in we can use that to stop the double-collection case? I don't want to spend a bunch of time adding tests for it, would rather spend that time fixing the issue.
  • I added a test for exception case.
  • I tried to add a test for stored procedure case, but not supported by sqlite.
  • I don't have it in me to add tests for every provider EF supports. Open to ideas on this. Maybe we should move this to contrib and designate as quasi-experimental?

Copy link
Member

@MikeGoldsmith MikeGoldsmith left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good now. We can expand the known provider list if requested, I don't think we need to expose a hook for users to override it.

@eddynaka
Copy link
Contributor

@cijothomas I spent a little time on this to try and get it over the hump for @Place1. It will now push db.system using the ProviderName exposed by EF. There are a lot of providers. I picked what I felt were the top ones. I thought about adding an option so users can take over that decision if their provider isn't in our list? Let me know your thoughts on that.

As far as testing goes...

  • After Runtime context API #948 goes in we can use that to stop the double-collection case? I don't want to spend a bunch of time adding tests for it, would rather spend that time fixing the issue.
  • I added a test for exception case.
  • I tried to add a test for stored procedure case, but not supported by sqlite.
  • I don't have it in me to add tests for every provider EF supports. Open to ideas on this. Maybe we should move this to contrib and designate as quasi-experimental?

@CodeBlanch , i will start moving this changes to contrib. When i finish, we can close this pr.

@eddynaka
Copy link
Contributor

@cijothomas @MikeGoldsmith @CodeBlanch , we can close this, since we already merged in the contrib repo :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Npgsql Postgresql client instrumentation
5 participants