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

Fix return value on error in delegate instrumentation #6153

Merged
merged 2 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="DelegateInstrumentation.cs" company="Datadog">
// <copyright file="DelegateInstrumentation.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>
Expand Down Expand Up @@ -404,7 +404,7 @@ async Task<TInnerReturn> AddContinuation(Task<TInnerReturn>? originalTask, IRetu
}
}

TInnerReturn? continuationResult = default;
TInnerReturn? continuationResult;
try
{
// *
Expand All @@ -415,6 +415,7 @@ async Task<TInnerReturn> AddContinuation(Task<TInnerReturn>? originalTask, IRetu
catch (Exception ex)
{
asyncCallback.OnException(sender, ex);
continuationResult = taskResult;
}

// *
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="FuncInstrumentationTests.cs" company="Datadog">
// <copyright file="FuncInstrumentationTests.cs" company="Datadog">
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License.
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>
Expand Down Expand Up @@ -65,6 +65,31 @@ public void Func0Test()
value.Should().Be(3);
}

[Fact]
public void Func0CallbackFailureTest()
{
var value = 0;
CustomFunc<int> func = () =>
{
Interlocked.Increment(ref value);
return 42;
};
func = DelegateInstrumentation.Wrap(func, new DelegateFunc0Callbacks(
target =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
using var scope = new AssertionScope();
func().Should().Be(42);
value.Should().Be(3);
}

public readonly struct Func0Callbacks : IBegin0Callbacks, IReturnCallback
{
public Func0Callbacks()
Expand Down Expand Up @@ -142,6 +167,31 @@ public void Func1Test()
value.Should().Be(3);
}

[Fact]
public void Func1CallbackFailureTest()
{
var value = 0;
CustomFunc<string, int> func = _ =>
{
Interlocked.Increment(ref value);
return 42;
};
func = DelegateInstrumentation.Wrap(func, new DelegateFunc1Callbacks(
(target, _) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
using var scope = new AssertionScope();
func(default).Should().Be(42);
value.Should().Be(3);
}

public readonly struct Func1Callbacks : IBegin1Callbacks, IReturnCallback
{
public Func1Callbacks()
Expand Down Expand Up @@ -206,6 +256,31 @@ public void Func2Test()
value.Should().Be(3);
}

[Fact]
public void Func2CallbackFailureTest()
{
var value = 0;
CustomFunc<string, string, int> func = (_, _) =>
{
Interlocked.Increment(ref value);
return 42;
};
func = DelegateInstrumentation.Wrap(func, new DelegateFunc2Callbacks(
(target, _, _) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
using var scope = new AssertionScope();
func(default, default).Should().Be(42);
value.Should().Be(3);
}

public readonly struct Func2Callbacks : IBegin2Callbacks, IReturnCallback
{
public Func2Callbacks()
Expand Down Expand Up @@ -272,6 +347,31 @@ public void Func3Test()
value.Should().Be(3);
}

[Fact]
public void Func3CallbackFailureTest()
{
var value = 0;
CustomFunc<string, string, string, int> func = (_, _, _) =>
{
Interlocked.Increment(ref value);
return 42;
};
func = DelegateInstrumentation.Wrap(func, new DelegateFunc3Callbacks(
(target, _, _, _) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
using var scope = new AssertionScope();
func(default, default, default).Should().Be(42);
value.Should().Be(3);
}

public readonly struct Func3Callbacks : IBegin3Callbacks, IReturnCallback
{
public Func3Callbacks()
Expand Down Expand Up @@ -340,6 +440,31 @@ public void Func4Test()
value.Should().Be(3);
}

[Fact]
public void Func4CallbackFailureTest()
{
var value = 0;
CustomFunc<string, string, string, string, int> func = (_, _, _, _) =>
{
Interlocked.Increment(ref value);
return 42;
};
func = DelegateInstrumentation.Wrap(func, new DelegateFunc4Callbacks(
(target, _, _, _, _) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
using var scope = new AssertionScope();
func(default, default, default, default).Should().Be(42);
value.Should().Be(3);
}

public readonly struct Func4Callbacks : IBegin4Callbacks, IReturnCallback
{
public Func4Callbacks()
Expand Down Expand Up @@ -410,6 +535,31 @@ public void Func5Test()
value.Should().Be(3);
}

[Fact]
public void Func5CallbackFailureTest()
{
var value = 0;
CustomFunc<string, string, string, string, string, int> func = (_, _, _, _, _) =>
{
Interlocked.Increment(ref value);
return 42;
};
func = DelegateInstrumentation.Wrap(func, new DelegateFunc5Callbacks(
(target, _, _, _, _, _) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
using var scope = new AssertionScope();
func(default, default, default, default, default).Should().Be(42);
value.Should().Be(3);
}

public readonly struct Func5Callbacks : IBegin5Callbacks, IReturnCallback
{
public Func5Callbacks()
Expand Down Expand Up @@ -473,12 +623,14 @@ public async Task Async1Test()
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value).Should().Be(3);
// 3 or 4 because we can't predict if onDelegateEnd or onDelegateAsyncEnd will be called first
Interlocked.Increment(ref value).Should().BeOneOf(3, 4);
return returnValue;
},
onDelegateAsyncEnd: async (sender, returnValue, exception, state) =>
{
Interlocked.Increment(ref value).Should().Be(4);
// 3 or 4 because we can't predict if onDelegateEnd or onDelegateAsyncEnd will be called first
Interlocked.Increment(ref value).Should().BeOneOf(3, 4);
await Task.Delay(100).ConfigureAwait(false);
return ((int)returnValue) + 1;
}));
Expand All @@ -488,6 +640,40 @@ public async Task Async1Test()
value.Should().Be(4);
}

[Fact]
public async Task Async1CallbackFailureTest()
{
int value = 0;

CustomFunc<string, Task<int>> func = async (arg1) =>
{
Interlocked.Increment(ref value);
await Task.Delay(100).ConfigureAwait(false);
return 42;
};

func = DelegateInstrumentation.Wrap(func, new DelegateFunc1Callbacks(
(target, arg1) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
(target, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
},
onDelegateAsyncEnd: (sender, returnValue, exception, state) =>
{
Interlocked.Increment(ref value);
throw new InvalidOperationException("Expected");
}));
var result = await func("Arg01").ConfigureAwait(false);
using var scope = new AssertionScope();
value.Should().Be(4);
result.Should().Be(42);
}

[Fact]
public async Task Async1WithAsyncExceptionTest()
{
Expand Down
Loading