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

use async/await when instrumenting asynchronous methods (redux) #212

Merged
merged 8 commits into from
Nov 19, 2018

Conversation

lucaspimentel
Copy link
Member

Goal
The main goal of this PR is to avoid wrapping exceptions in an AggregateException when instrumenting asynchronous methods.

Changes
I inlined all uses of extension method Span.Trace() and used async/await instead of Task.ContinueWith() to close spans after async tasks are completed.

Result
This changes provide better handling of Task and Task<T> overall, with cleaner code (no callbacks!) that doesn't wrap exceptions and ensures spans are not disposed before a Task finishes.

@lucaspimentel lucaspimentel added type:bug area:automatic-instrumentation Automatic instrumentation managed C# code (Datadog.Trace.ClrProfiler.Managed) labels Nov 15, 2018
@lucaspimentel lucaspimentel added this to the 0.5.1-beta milestone Nov 15, 2018
@lucaspimentel lucaspimentel self-assigned this Nov 15, 2018
@lucaspimentel lucaspimentel changed the base branch from master to develop November 15, 2018 19:35
@lucaspimentel
Copy link
Member Author

lucaspimentel commented Nov 15, 2018

The Elasticsearch tests fail on Windows because we don't have an Elasticsearch server to connect to. The same tests pass on Linux and on my local Windows machine. I'll figure out how to run these tests on Windows CI soon.

@@ -49,34 +58,58 @@ public static T ExecuteSyncImpl<T>(object multiplexer, object message, object pr
/// <param name="server">The server to call.</param>
/// <returns>An asynchronous task.</returns>
public static object ExecuteAsyncImpl<T>(object multiplexer, object message, object processor, object state, object server)
{
return ExecuteAsyncImplInternal<T>(multiplexer, message, processor, state, server);
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the purpose of forwarding the call to ExecuteAsyncImplInternal that takes exactly the same arguments?

Copy link
Member Author

Choose a reason for hiding this comment

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

The "internal" methods use async/await which require a return type of Task or Task<T>, but we inject methods with object return type. The method signatures must match (including the return type), which is why I split them into 2 methods.

Copy link
Contributor

@bmermet bmermet left a comment

Choose a reason for hiding this comment

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

LGTM! I have a nitpick about the purpose of the Internal functions that I have not understood.

@lucaspimentel lucaspimentel merged commit 1177a31 into develop Nov 19, 2018
@lucaspimentel lucaspimentel deleted the lpimentel/use-async-await branch November 19, 2018 14:48
lucaspimentel added a commit that referenced this pull request Nov 19, 2018
* clean up code

* use async/awaot instead of `Span.Trace()` in Web API integration

* use async/awaot instead of `Span.Trace()` in StackExchange.Redis integration

* use async/await instead of `Span.Trace()` in ServiceStack.Redis integration

* use async/await instead of `Span.Trace()` in Elasticsearch integration

* remove unused optional parameters

* remove unused extension method `Span.Trace()`

* use specific method return type instead of `object`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:automatic-instrumentation Automatic instrumentation managed C# code (Datadog.Trace.ClrProfiler.Managed) type:bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants