Skip to content

Commit

Permalink
Feat/better thread handling (#1)
Browse files Browse the repository at this point in the history
* -Added IsolatedTracking for isolating the code to be measured.
-Added ThreadTracking for Isolating the SentryTracingId.
-Reworked how the Sdk is initialized.
-More test case

* Increased version due to breaking changes

* cleaned using files and removed required line
  • Loading branch information
lucas-zimerman authored Aug 16, 2020
1 parent 9144265 commit 5fc7060
Show file tree
Hide file tree
Showing 17 changed files with 443 additions and 88 deletions.
6 changes: 1 addition & 5 deletions Testing/Helpers/DsnHelper.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Testing.Helpers
namespace Testing.Helpers
{
/// <summary>
/// Based on DsnSamples from Sentry.Net
Expand Down
19 changes: 19 additions & 0 deletions Testing/Initializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Sentry;
using sentry_dotnet_transaction_addon;
using Testing.Helpers;

namespace Testing
{
public static class Initializer
{
public static void Init()
{
if (!SentryTracingSdk.IsEnabled())
{
var integration = new SentryTracingSdkIntegration();
integration.Register(null, new SentryOptions());
SentryTracingSdk.SetDsn(new Dsn(DsnHelper.ValidDsnWithoutSecret));
}
}
}
}
196 changes: 196 additions & 0 deletions Testing/Internals/ThreadTrackingTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using sentry_dotnet_transaction_addon.Internals;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;

namespace Testing.Internals
{
public class ThreadTrackingTests
{
private readonly ITestOutputHelper _testOutputHelper;
public ThreadTrackingTests(ITestOutputHelper testOutputHelper)
{
_testOutputHelper = testOutputHelper;
}

private async Task TaskWaiter(int? expectedId, ThreadTracking tracking)
{
await Task.Delay(30);
Assert.True(tracking.Created);
Assert.Equal(expectedId, tracking.Id);
}

[Fact]
public async Task ThreadTracking_CreateUnique_Numbers()
{
var tracker = new ThreadTracking();
var numbers = new int[1000];
for (int i = 0; i < 300; i++)
{
numbers[i] = ThreadTracking.InternalNewId();
}
var task = new Task(() =>
{
new Task(() =>
{
for (int i = 300; i < 600; i += 2)
numbers[i] = ThreadTracking.InternalNewId();
}).Start();
new Task(() =>
{
for (int i = 301; i < 600; i += 2)
numbers[i] = ThreadTracking.InternalNewId();
}).Start();
});
var task2 = new Thread(() =>
{
new Thread(() =>
{
for (int i = 600; i < 1000; i += 2)
numbers[i] = ThreadTracking.InternalNewId();
}).Start();
new Thread(() =>
{
for (int i = 601; i < 800; i += 2)
numbers[i] = ThreadTracking.InternalNewId();
}).Start();
});
task.Start();
task2.Start();
await Task.Delay(100);
Assert.True(numbers.Distinct().Count() > 0);
}


[Fact]
public void ThreadTracking_UnsafeTracking_Not_Created()
{
var tracker = new ThreadTracking();
var id = tracker.StartUnsafeTrackingId();
Assert.False(tracker.Created);
Assert.Null(tracker.Id);
}



[Fact]
public async Task ThreadTracking_CreateTrackTask_newTask_ReturnSameId()
{
var tracker = new ThreadTracking();
await tracker.StartCallbackTrackingIdAsync(async () =>
{
Assert.True(tracker.Created);
var idEqual = tracker.Id;
Task task = new Task(async () =>
{
await Task.Delay(10);
Assert.True(tracker.Created);
Assert.Equal(idEqual, tracker.Id);
});
task.Start();
await task;

});
Assert.False(tracker.Created);
}

[Fact]
public async Task ThreadTracking_CreateTrackTask_Using_UnsafeId()
{
var tracker = new ThreadTracking();
var unsafeId = tracker.StartUnsafeTrackingId();
await tracker.StartCallbackTrackingIdAsync(async () =>
{
Assert.True(tracker.Created);
var idEqual = tracker.Id;
Task task = new Task(async () =>
{
await Task.Delay(10);
Assert.True(tracker.Created);
Assert.Equal(idEqual, tracker.Id);
Assert.Equal(unsafeId, tracker.Id);
});
task.Start();
await task;

}, unsafeId);
Assert.False(tracker.Created);
}

[Fact]
public void ThreadTracking_Different_ThreadsCallbacks_Async_Return_DifferentIds()
{
var tracker = new ThreadTracking();
int?[] ids = new int?[3];
var Semaphores = new Semaphore[3] { new Semaphore(0, 1), new Semaphore(0, 1), new Semaphore(0, 1) };
new Thread(async () =>
{
await tracker.StartCallbackTrackingIdAsync(async () =>
{

ids[0] = tracker.Id;
await TaskWaiter(ids[0], tracker);
Assert.Equal(ids[0], tracker.Id);
Semaphores[0].Release();
});
}).Start();
new Thread(async () =>
{
await tracker.StartCallbackTrackingIdAsync(async () =>
{

ids[1] = tracker.Id;
await TaskWaiter(ids[1], tracker);
Assert.Equal(ids[1], tracker.Id);
Semaphores[1].Release();
});
}).Start();
new Thread(async () =>
{
await tracker.StartCallbackTrackingIdAsync(async () =>
{

ids[2] = tracker.Id;
await TaskWaiter(ids[2], tracker);
Assert.Equal(ids[2], tracker.Id);
Semaphores[2].Release();
});
}).Start();
Semaphores[0].WaitOne();
Semaphores[1].WaitOne();
Semaphores[2].WaitOne();

Assert.False(tracker.Created);
Assert.NotNull(ids[0]);
Assert.NotNull(ids[1]);
Assert.NotNull(ids[2]);
Assert.NotEqual(ids[0], ids[1]);
Assert.NotEqual(ids[2], ids[1]);
}

[Fact]
private async Task ThreadTracking_On_Function_Error()
{
var tracker = new ThreadTracking();
bool receivedError = false;
try
{
await tracker.StartCallbackTrackingIdAsync(() =>
{
throw new Exception(".");
});
}
catch
{
receivedError = true;
}
finally
{
Assert.True(receivedError);
}
}
}
}
54 changes: 5 additions & 49 deletions Testing/StartChildTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,61 +4,21 @@
using sentry_dotnet_transaction_addon.Interface;
using sentry_dotnet_transaction_addon.Internals;
using System.Threading.Tasks;
using Testing.Helpers;
using Xunit;

namespace Testing
{
public class StartChildTest
{
public ISpanBase AddSpan(string name) => SentryTracingSdk.StartChild(name);

[Fact]
public void SentryTracingSdkStartChildConcurrenceFindsCorrectParents()
{
SentryTracingSdk.Init(DsnHelper.ValidDsnWithoutSecret);
ISentryTracing a = null, b = null, c = null;
ISpanBase sa = null, sb = null, sc = null;
Task []tasks = new Task[3];
tasks[0] = new Task(() =>
{
a = SentryTracingSdk.StartTransaction("a");
sa = AddSpan("a");
sa.Finish();
});
tasks[1] = new Task(() =>
{
b = SentryTracingSdk.StartTransaction("b");
sb = AddSpan("b");
sb.Finish();
});
tasks[2] = new Task(() =>
{
c = SentryTracingSdk.StartTransaction("c");
sc = AddSpan("c");
sc.Finish();
});

tasks[1].Start();
tasks[0].Start();
tasks[2].Start();

Task.WaitAll(tasks);

//Check if all Tracings have only one Span
Assert.True(a.Spans.Count.Equals(1));
Assert.True(b.Spans.Count.Equals(1));
Assert.True(c.Spans.Count.Equals(1));

//Check if all Tracing have the correct Spans
Assert.Equal(sa, a.Spans[0]);
Assert.Equal(sb, b.Spans[0]);
Assert.Equal(sc, c.Spans[0]);
a.Finish();
b.Finish();
c.Finish();
public StartChildTest()
{
Initializer.Init();
}

public ISpanBase AddSpan(string name) => SentryTracingSdk.StartChild(name);

[Fact]
public void SentryTracingSdkStartChildWithoutTransactionReturnDisabledSpan()
{
Expand All @@ -71,7 +31,6 @@ public void SentryTracingSdkStartChildWithoutTransactionReturnDisabledSpan()
[Fact]
public void SentryTracingSdkStartChildCanDispose()
{
SentryTracingSdk.Init(DsnHelper.ValidDsnWithoutSecret);
ISentryTracing transaction = SentryTracingSdk.StartTransaction("tran");
using (var span = transaction.StartChild("span"))
{
Expand All @@ -84,7 +43,6 @@ public void SentryTracingSdkStartChildCanDispose()
[Fact]
public void SentryTracingSdkStartSubChild()
{
SentryTracingSdk.Init(DsnHelper.ValidDsnWithoutSecret);
ISentryTracing transaction = SentryTracingSdk.StartTransaction("tran");
using (var span = transaction.StartChild("span"))
{
Expand All @@ -104,7 +62,6 @@ public void SentryTracingSdkStartSubChild()
[Fact]
public void SentryTracingSdkStartRequestChildOkStatus()
{
SentryTracingSdk.Init(DsnHelper.ValidDsnWithoutSecret);
ISentryTracing transaction = SentryTracingSdk.StartTransaction("tran");
using (var span = transaction.StartChild("span"))
{
Expand All @@ -127,7 +84,6 @@ public void SentryTracingSdkStartRequestChildOkStatus()
[Fact]
public void SentryTracingSdkStartRequestChildErrorStatus()
{
SentryTracingSdk.Init(DsnHelper.ValidDsnWithoutSecret);
ISentryTracing transaction = SentryTracingSdk.StartTransaction("tran");
using (var span = transaction.StartChild("span"))
{
Expand Down
2 changes: 1 addition & 1 deletion Testing/Testing.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
Expand Down
Loading

0 comments on commit 5fc7060

Please sign in to comment.