Skip to content

Commit e98beae

Browse files
authored
fix tracing client-server (#229)
* fix tracing client-server * parent-child http trace fixed * Update src/SymbolCollector.Core/Client.cs * Update src/SymbolCollector.Core/Client.cs * Update src/SymbolCollector.Core/Client.cs
1 parent de46301 commit e98beae

File tree

7 files changed

+93
-71
lines changed

7 files changed

+93
-71
lines changed

src/Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22
<PropertyGroup>
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4-
<SentryVersion>5.9.0</SentryVersion>
4+
<SentryVersion>5.11.0-alpha.1</SentryVersion>
55
</PropertyGroup>
66
<ItemGroup>
77
<PackageVersion Include="Sentry" Version="$(SentryVersion)" />

src/SymbolCollector.Android.Library/AndroidUploader.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,29 @@ public AndroidUploader(Client client, ILogger<AndroidUploader> logger)
1515
_logger = logger;
1616
}
1717

18-
public Task StartUpload(string friendlyName, CancellationToken token) =>
18+
public Task StartUpload(string friendlyName, ISpan uploadSpan, CancellationToken token) =>
1919
Task.Run(async () =>
2020
{
2121
var paths = new[] { "/system/lib", "/system/lib64", "/system/", "/vendor/lib" };
2222

2323
_logger.LogInformation("Using friendly name: {friendlyName} and paths: {paths}",
2424
friendlyName, paths);
2525

26+
var androidUploaderSpan = uploadSpan.StartChild("androidUpload", "uploading all paths async");
2627
try
2728
{
28-
await _client.UploadAllPathsAsync(friendlyName, BatchType.Android, paths, token);
29+
await _client.UploadAllPathsAsync(friendlyName, BatchType.Android, paths, androidUploaderSpan, token);
30+
androidUploaderSpan.Finish();
2931
}
3032
catch (OperationCanceledException)
3133
{
34+
androidUploaderSpan.Finish(SpanStatus.Cancelled);
3235
}
3336
catch (Exception e)
3437
{
3538
_logger.LogError(e, "Failed uploading {friendlyName} paths: {paths}",
3639
friendlyName, paths);
40+
androidUploaderSpan.Finish(e);
3741
// Make sure event is flushed and rethrow
3842
await SentrySdk.FlushAsync(TimeSpan.FromSeconds(3));
3943
throw;

src/SymbolCollector.Android.Library/AutoUploader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public void Run(Context context)
6767
s.Contexts.OperatingSystem.KernelVersion = uname.Release;
6868
}
6969
});
70-
var uploadTask = uploader.StartUpload(friendlyName, source.Token);
70+
var uploadTask = uploader.StartUpload(friendlyName, tran, source.Token);
7171
uploadTask.ContinueWith(t =>
7272
{
7373
tran.Finish(t.IsCompletedSuccessfully ? SpanStatus.Ok : SpanStatus.UnknownError);

src/SymbolCollector.Android/MainActivity.cs

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class MainActivity : Activity
2121
private string _friendlyName = null!; // set on OnCreate
2222
private IHost _host = null!; // set on OnCreate
2323
private IServiceProvider _serviceProvider = null!; // set on OnCreate
24-
private ITransactionTracer _startupTransaction = null!; // set on OnCreate
24+
private SentryTraceHeader _parentTraceHeader = null!;
2525

2626
protected override void OnCreate(Bundle? savedInstanceState)
2727
{
@@ -35,10 +35,12 @@ protected override void OnCreate(Bundle? savedInstanceState)
3535
_serviceProvider = _host.Services;
3636

3737
// It's set in Host.Init above
38-
SentrySdk.ConfigureScope(s => _startupTransaction = s.Transaction!);
38+
ITransactionTracer startupTransaction = null!;
39+
SentrySdk.ConfigureScope(s => startupTransaction = s.Transaction!);
40+
_parentTraceHeader = startupTransaction.GetTraceHeader();
3941
AddSentryContext();
4042

41-
var span = _startupTransaction.StartChild("OnCreate");
43+
var onCreateSpan = startupTransaction.StartChild("OnCreate");
4244
try
4345
{
4446
base.OnCreate(savedInstanceState);
@@ -71,10 +73,23 @@ protected override void OnCreate(Bundle? savedInstanceState)
7173
uploadButton.Click += OnUploadButtonOnClick;
7274
cancelButton.Click += OnCancelButtonOnClick;
7375

76+
onCreateSpan.Finish(SpanStatus.Ok);
77+
startupTransaction.Finish(SpanStatus.Ok);
78+
return;
79+
80+
void OnCancelButtonOnClick(object? sender, EventArgs args)
81+
{
82+
SentrySdk.AddBreadcrumb("OnCancelButtonOnClick", category: "ui.event");
83+
Unfocus();
84+
source.Cancel();
85+
}
86+
7487
async void OnUploadButtonOnClick(object? sender, EventArgs args)
7588
{
7689
// The scope tracks the overall app transaction while this is only batch uploading
77-
var uploadTransaction = SentrySdk.StartTransaction("BatchUpload", "batch.upload", _startupTransaction.GetTraceHeader());
90+
var uploadTransaction = SentrySdk.StartTransaction("BatchUpload", "batch.upload", _parentTraceHeader);
91+
// startup transaction has completed at this point, this starts when the user pressed Upload so make this transaction global:
92+
SentrySdk.ConfigureScope(s => s.Transaction = uploadTransaction);
7893

7994
try
8095
{
@@ -89,32 +104,23 @@ async void OnUploadButtonOnClick(object? sender, EventArgs args)
89104
uploadButton.Enabled = false;
90105
source = new CancellationTokenSource();
91106

92-
var uploadTask = uploader.StartUpload(_friendlyName, source.Token);
107+
var uploadTask = uploader.StartUpload(_friendlyName, uploadTransaction, source.Token);
93108
var updateUiTask = StartUiUpdater(source.Token, metrics);
94109

95-
await UploadAsync(uploadTask, updateUiTask, metrics, cancelButton, uploadButton, uploadTransaction, source);
110+
// Successful completion (or timeout) of the transaction is handled internally.
111+
await AwaitOnUploadAndCancellationTasks(uploadTask, updateUiTask, metrics, cancelButton, uploadButton, uploadTransaction, source);
96112
}
97113
catch (Exception e)
98114
{
99115
uploadTransaction.Finish(e);
100116
throw;
101117
}
102118
}
103-
104-
void OnCancelButtonOnClick(object? sender, EventArgs args)
105-
{
106-
SentrySdk.AddBreadcrumb("OnCancelButtonOnClick", category: "ui.event");
107-
Unfocus();
108-
source.Cancel();
109-
}
110-
111-
span.Finish(SpanStatus.Ok);
112-
_startupTransaction.Finish(SpanStatus.Ok);
113119
}
114120
catch (Exception e)
115121
{
116-
span.Finish(e);
117-
_startupTransaction.Finish(e);
122+
onCreateSpan.Finish(e);
123+
startupTransaction.Finish(e);
118124
throw;
119125
}
120126
}
@@ -128,13 +134,13 @@ private void Unfocus()
128134
}
129135
}
130136

131-
private async Task UploadAsync(
137+
private async Task AwaitOnUploadAndCancellationTasks(
132138
Task uploadTask,
133139
Task updateUiTask,
134140
ClientMetrics metrics,
135141
View cancelButton,
136142
View uploadButton,
137-
ISpan span,
143+
ISpan uploadTransaction,
138144
CancellationTokenSource source)
139145
{
140146
var container = base.FindViewById(Resource.Id.metrics_container)!;
@@ -159,28 +165,28 @@ private async Task UploadAsync(
159165
ranForContainer.Visibility = ViewStates.Visible;
160166

161167
ranForLabel.Text = metrics.RanFor.ToString();
162-
span.Finish(SpanStatus.Ok);
168+
uploadTransaction.Finish(SpanStatus.Ok);
163169
}
164170
else if (uploadTask.IsFaulted)
165171
{
166172
await ShowError(uploadTask.Exception);
167-
span.Finish(SpanStatus.InternalError);
173+
uploadTransaction.Finish(SpanStatus.InternalError);
168174
}
169175
else
170176
{
171177
cancelButton.Enabled = false;
172178
uploadButton.Enabled = true;
173-
span.Finish(SpanStatus.Cancelled);
179+
uploadTransaction.Finish(SpanStatus.Cancelled);
174180
}
175181
}
176182
catch (Exception e)
177183
{
178184
await ShowError(e);
179-
span.Finish(e);
185+
uploadTransaction.Finish(e);
180186
}
181187
finally
182188
{
183-
source.Cancel();
189+
await source.CancelAsync();
184190
}
185191
}
186192

@@ -278,8 +284,6 @@ private void AddSentryContext()
278284

279285
SentrySdk.ConfigureScope(s =>
280286
{
281-
s.Transaction = _startupTransaction;
282-
283287
if (uname is { })
284288
{
285289
s.Contexts["uname"] = new

src/SymbolCollector.Console/ConsoleUploader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public async Task StartUploadSymbols(IEnumerable<string> paths, string bundleId,
5959
var type = batchType ?? DeviceBatchType();
6060
_logger.LogInformation("Uploading bundle {bundleId} of type {type} and paths: {paths}",
6161
bundleId, type, paths);
62-
await _client.UploadAllPathsAsync(bundleId, type, paths, token);
62+
await _client.UploadAllPathsAsync(bundleId, type, paths, transaction, token);
6363
transaction.Finish(SpanStatus.Ok);
6464
}
6565
catch (Exception e)
@@ -87,4 +87,4 @@ static BatchType DeviceBatchType()
8787

8888
throw new InvalidOperationException("No BatchType available for the current device.");
8989
}
90-
}
90+
}

src/SymbolCollector.Core/Client.cs

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -30,59 +30,73 @@ public Client(
3030
SentrySdk.ConfigureScope(s => s.SetExtra(nameof(Metrics), Metrics));
3131
}
3232

33-
public async Task UploadAllPathsAsync(
34-
string friendlyName,
33+
public async Task UploadAllPathsAsync(string friendlyName,
3534
BatchType type,
3635
IEnumerable<string> topLevelPaths,
36+
ISpan span,
3737
CancellationToken cancellationToken)
3838
{
39-
var groupsSpan = SentrySdk.GetSpan()?.StartChild("group.get", "Get the group of directories to search in parallel");
39+
List<List<string>> groups;
4040
var counter = 0;
41-
var groups =
42-
(from topPath in topLevelPaths
43-
from lookupDirectory in SafeGetDirectories(topPath)
44-
where _blockListedPaths?.Contains(lookupDirectory) != true
45-
let c = counter++
46-
group lookupDirectory by c / ParallelTasks
47-
into grp
48-
select grp.ToList()).ToList();
49-
groupsSpan?.Finish();
50-
51-
var startSpan = SentrySdk.GetSpan()?.StartChild("batch.start");
52-
Guid batchId;
53-
try
5441
{
55-
batchId = await _symbolClient.Start(friendlyName, type, cancellationToken);
56-
startSpan?.Finish(SpanStatus.Ok);
42+
var groupsSpan = span.StartChild("group.get", "Get the group of directories to search in parallel");
43+
groups =
44+
(from topPath in topLevelPaths
45+
from lookupDirectory in SafeGetDirectories(topPath)
46+
where _blockListedPaths?.Contains(lookupDirectory) != true
47+
let c = counter++
48+
group lookupDirectory by c / ParallelTasks
49+
into grp
50+
select grp.ToList()).ToList();
51+
groupsSpan.Finish();
5752
}
58-
catch (Exception e)
53+
54+
Guid batchId;
5955
{
60-
startSpan?.Finish(e);
61-
throw;
56+
var startSpan = span.StartChild("batch.start");
57+
try
58+
{
59+
batchId = await _symbolClient.Start(friendlyName, type, cancellationToken);
60+
startSpan.Finish(SpanStatus.Ok);
61+
}
62+
catch (Exception e)
63+
{
64+
startSpan.Finish(e);
65+
throw;
66+
}
6267
}
6368

64-
var uploadSpan = SentrySdk.GetSpan()?.StartChild("batch.upload");
65-
uploadSpan?.SetTag("groups", groups.Count.ToString());
66-
uploadSpan?.SetTag("total_items", counter.ToString());
67-
try
6869
{
69-
foreach (var group in groups)
70+
var uploadSpan = span.StartChild("batch.upload", "concurrent batch upload");
71+
uploadSpan.SetData("groups", groups.Count.ToString());
72+
uploadSpan.SetData("total_items", counter.ToString());
73+
74+
// use this as parent to all outgoing HTTP requests now:
75+
SentrySdk.ConfigureScope(s => s.Span = uploadSpan);
76+
try
7077
{
71-
await UploadParallel(batchId, group, cancellationToken);
78+
foreach (var group in groups)
79+
{
80+
await UploadParallel(batchId, group, cancellationToken);
81+
}
82+
uploadSpan.Finish(SpanStatus.Ok);
83+
}
84+
catch (Exception e)
85+
{
86+
_logger.LogError(e, "Failed processing files for {batchId}. Rethrowing and leaving the batch open.",
87+
batchId);
88+
uploadSpan.Finish(e);
89+
throw;
7290
}
73-
uploadSpan?.Finish(SpanStatus.Ok);
7491
}
75-
catch (Exception e)
92+
7693
{
77-
uploadSpan?.Finish(e);
78-
_logger.LogError(e, "Failed processing files for {batchId}. Rethrowing and leaving the batch open.",
79-
batchId);
80-
throw;
94+
var stopSpan = span.StartChild("batch.close");
95+
await _symbolClient.Close(batchId, cancellationToken);
96+
stopSpan.Finish(SpanStatus.Ok);
8197
}
8298

83-
var stopSpan = SentrySdk.GetSpan()?.StartChild("batch.close");
84-
await _symbolClient.Close(batchId, cancellationToken);
85-
stopSpan?.Finish(SpanStatus.Ok);
99+
return;
86100

87101
IEnumerable<string> SafeGetDirectories(string path)
88102
{

test/SymbolCollector.Core.Tests/ClientTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public async Task UploadAllPathsAsync_TestFilesDirectory_FilesDetected()
7070
new HttpClient(_fixture.HttpMessageHandler));
7171

7272
var sut = _fixture.GetSut();
73-
await sut.UploadAllPathsAsync("friendly name", BatchType.IOS, new[] {"TestFiles"}, CancellationToken.None);
73+
await sut.UploadAllPathsAsync("friendly name", BatchType.IOS, new[] {"TestFiles"}, SentrySdk.StartTransaction("test", "test-op"), CancellationToken.None);
7474

7575
// number of valid test files in TestFiles
7676
Assert.Equal(12, counter);
@@ -84,7 +84,7 @@ public async Task UploadAllPathsAsync_TestFilesDirectory_FileCorrectlySent()
8484
Substitute.For<ILogger<ObjectFileParser>>(), new FatBinaryReader());
8585

8686
var sut = _fixture.GetSut();
87-
await sut.UploadAllPathsAsync("friendly name", BatchType.IOS, new[] {"TestFiles"}, CancellationToken.None);
87+
await sut.UploadAllPathsAsync("friendly name", BatchType.IOS, new[] {"TestFiles"}, SentrySdk.StartTransaction("test", "test-op"), CancellationToken.None);
8888

8989
// Make sure all valid test files were picked up
9090
var testFiles = new ObjectFileResultTestCases()

0 commit comments

Comments
 (0)