Skip to content

Commit ad074d1

Browse files
authored
Version 2.0.6 (#18)
* New BacktraceCredentials initialization + UnhandledThreadExeption event flow
1 parent 07a4acd commit ad074d1

9 files changed

Lines changed: 199 additions & 52 deletions

File tree

Lines changed: 73 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using Backtrace.Model;
1+
using Backtrace.Model;
72
using NUnit.Framework;
3+
using System;
84
namespace Backtrace.Tests.ClientTests
95
{
106
/// <summary>
@@ -21,23 +17,7 @@ public void TestInvalidSectionName(string sectionName)
2117
{
2218
Assert.Throws<InvalidOperationException>(() => new BacktraceClient(sectionName));
2319
}
24-
#endif
25-
26-
[TestCase("InvalidUrl")]
27-
[Test(Author = "Konrad Dysput", Description = "Test invalid api url section")]
28-
public void TestInvalidUrlArgument(string sectionName)
29-
{
30-
//if programmer pass invalid url should throw UriFormatException
31-
//if programmer pass null or empty string as token should throw ArgumentNullException
32-
33-
#if NET35 || NET45
34-
Assert.Throws<UriFormatException>(() => new BacktraceClient(sectionName));
35-
#endif
36-
Assert.Throws<ArgumentException>(() => new BacktraceClient(new BacktraceCredentials("https://test.backtrace.io", string.Empty)));
37-
}
3820

39-
40-
#if NET35 || NET45
4121
[TestCase("EmptyToken")]
4222
[Test(Author = "Konrad Dysput", Description = "Test invalid token section")]
4323
public void TestInvalidTokenArgument(string sectionName)
@@ -51,8 +31,78 @@ public void TestValidSectionConfiguration(string sectionName)
5131
{
5232
Assert.DoesNotThrow(() => new BacktraceClient(sectionName));
5333
}
54-
5534
#endif
5635

36+
[TestCase("https://backtrace.sp.backtrace.io")]
37+
[TestCase("http://backtrace.sp.backtrace.io")]
38+
[TestCase("http://backtrace.sp.backtrace.io:6098")]
39+
[TestCase("http://backtrace.sp.backtrace.io:7777")]
40+
[TestCase("http://backtrace.sp.backtrace.io:7777/")]
41+
[TestCase("http://backtrace.sp.backtrace.io/")]
42+
[Test(Author = "Konrad Dysput", Description = "Test valid submission url")]
43+
public void GenerateSubmissionUrl_FromValidHostName_ValidSubmissionUrl(string host)
44+
{
45+
const string token = "1234";
46+
var credentials = new BacktraceCredentials(host, token);
47+
48+
string expectedUrl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";
49+
Assert.AreEqual(credentials.GetSubmissionUrl(), expectedUrl);
50+
}
51+
52+
[TestCase("https://www.submit.backtrace.io")]
53+
[TestCase("http://www.submit.backtrace.io")]
54+
[TestCase("https://submit.backtrace.io")]
55+
[TestCase("https://submit.backtrace.io/12312/312312/")]
56+
[TestCase("https://submit.backtrace.io/uri/")]
57+
[TestCase("https://submit.backtrace.io/uri?sumbissionToken=123123134&value=123123/")]
58+
[TestCase("http://submit.backtrace.io")]
59+
[TestCase("http://submit.backtrace.io/")]
60+
public void GenerateBacktraceSubmitUrl_FromSubmitUrl_ValidSubmissionUrl(string host)
61+
{
62+
var credentials = new BacktraceCredentials(host);
63+
64+
if (!host.StartsWith("https://") && !host.StartsWith("http://"))
65+
{
66+
host = $"https://{host}";
67+
}
68+
69+
if (!host.EndsWith("/"))
70+
{
71+
host += '/';
72+
}
73+
Assert.AreEqual(host, credentials.GetSubmissionUrl().ToString());
74+
}
75+
76+
[TestCase("")]
77+
[TestCase("not url")]
78+
[TestCase("123123..")]
79+
[Test(Author = "Konrad Dysput", Description = "Test invalid api url")]
80+
public void ThrowInvalidUrlException_FromINvalidUrl_ThrowException(string host)
81+
{
82+
Assert.Throws<UriFormatException>(() => new BacktraceCredentials(host));
83+
Assert.Throws<UriFormatException>(() => new BacktraceCredentials(host, "123"));
84+
}
85+
86+
[TestCase("https://backtrace.sp.backtrace.io")]
87+
[TestCase("http://backtrace.sp.backtrace.io")]
88+
[TestCase("https://totallynoValidSubmitUrl.submit.backtrace.io/")]
89+
[Test(Author = "Konrad Dysput", Description = "Test invalid api url")]
90+
public void ThrowInvalidArgumentException_FromInvalidHostName_ThrowException(string host)
91+
{
92+
Assert.Throws<ArgumentException>(() => new BacktraceCredentials(host));
93+
}
94+
95+
[TestCase("InvalidUrl")]
96+
[Test(Author = "Konrad Dysput", Description = "Test invalid api url section")]
97+
public void TestInvalidUrlArgument(string sectionName)
98+
{
99+
//if programmer pass invalid url should throw UriFormatException
100+
//if programmer pass null or empty string as token should throw ArgumentNullException
101+
102+
#if NET35 || NET45
103+
Assert.Throws<UriFormatException>(() => new BacktraceClient(sectionName));
104+
#endif
105+
Assert.Throws<ArgumentException>(() => new BacktraceClient(new BacktraceCredentials("https://test.backtrace.io", string.Empty)));
106+
}
57107
}
58108
}

Backtrace/Backtrace.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,20 @@
44
<TargetFrameworks>netstandard2.0;net45;net35</TargetFrameworks>
55
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
66
<PackageTags>Backtrace Error Diagnostic Tools Debug Bug Bugs StackTrace</PackageTags>
7-
<PackageVersion>2.0.5</PackageVersion>
7+
<PackageVersion>2.0.6</PackageVersion>
88
<Product>Backtrace</Product>
99
<PackageLicenseUrl>https://github.com/backtrace-labs/backtrace-csharp/blob/master/LICENSE</PackageLicenseUrl>
1010
<PackageProjectUrl>https://github.com/backtrace-labs/backtrace-csharp</PackageProjectUrl>
1111
<PackageIconUrl>http://backtrace.io/images/icon.png</PackageIconUrl>
1212
<Description>Backtrace's integration with C# applications allows customers to capture and report handled and unhandled C# exceptions to their Backtrace instance, instantly offering the ability to prioritize and debug software errors.</Description>
1313
<RepositoryUrl>https://github.com/backtrace-labs/backtrace-csharp</RepositoryUrl>
1414
<NeutralLanguage>en</NeutralLanguage>
15-
<Version>2.0.5</Version>
15+
<Version>2.0.6</Version>
1616
<Copyright>Backtrace I/O</Copyright>
1717
<Authors>Backtrace I/O</Authors>
1818
<Company>Backtrace I/O</Company>
19-
<AssemblyVersion>2.0.5.0</AssemblyVersion>
20-
<FileVersion>2.0.5.0</FileVersion>
19+
<AssemblyVersion>2.0.6.0</AssemblyVersion>
20+
<FileVersion>2.0.6.0</FileVersion>
2121
</PropertyGroup>
2222

2323
<ItemGroup>

Backtrace/Base/BacktraceBase.cs

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,46 @@ public class BacktraceBase
2929
/// </summary>
3030
public Func<string, string, BacktraceData, BacktraceResult> RequestHandler
3131
{
32-
get => BacktraceApi.RequestHandler;
33-
set => BacktraceApi.RequestHandler = value;
32+
get
33+
{
34+
return BacktraceApi.RequestHandler;
35+
}
36+
37+
set
38+
{
39+
BacktraceApi.RequestHandler = value;
40+
}
3441
}
3542
/// <summary>
3643
/// Set an event executed when received bad request, unauthorize request or other information from server
3744
/// </summary>
3845
public Action<Exception> OnServerError
3946
{
40-
get => BacktraceApi.OnServerError;
41-
set => BacktraceApi.OnServerError = value;
47+
get
48+
{
49+
return BacktraceApi.OnServerError;
50+
}
51+
52+
set
53+
{
54+
BacktraceApi.OnServerError = value;
55+
}
4256
}
4357

4458
/// <summary>
4559
/// Set an event executed when Backtrace API return information about send report
4660
/// </summary>
4761
public Action<BacktraceResult> OnServerResponse
4862
{
49-
get => BacktraceApi.OnServerResponse;
50-
set => BacktraceApi.OnServerResponse = value;
63+
get
64+
{
65+
return BacktraceApi.OnServerResponse;
66+
}
67+
68+
set
69+
{
70+
BacktraceApi.OnServerResponse = value;
71+
}
5172
}
5273

5374
/// <summary>
@@ -60,7 +81,10 @@ public Action<BacktraceResult> OnServerResponse
6081
/// </summary>
6182
public Action<BacktraceReport> OnClientReportLimitReached
6283
{
63-
set => BacktraceApi.SetClientRateLimitEvent(value);
84+
set
85+
{
86+
BacktraceApi.SetClientRateLimitEvent(value);
87+
}
6488
}
6589

6690
/// <summary>
@@ -89,7 +113,11 @@ public Action<BacktraceReport> OnClientReportLimitReached
89113
/// </summary>
90114
internal IBacktraceApi BacktraceApi
91115
{
92-
get => _backtraceApi;
116+
get
117+
{
118+
return _backtraceApi;
119+
}
120+
93121
set
94122
{
95123
_backtraceApi = value;
@@ -218,7 +246,7 @@ public virtual async Task<BacktraceResult> SendAsync(BacktraceReport report)
218246

219247
private async Task<BacktraceResult> HandleAggregateException(BacktraceReport report)
220248
{
221-
AggregateException aggregateException = report.Exception as AggregateException;
249+
var aggregateException = report.Exception as AggregateException;
222250
BacktraceResult result = null;
223251

224252
foreach (var ex in aggregateException.InnerExceptions)
@@ -232,6 +260,7 @@ private async Task<BacktraceResult> HandleAggregateException(BacktraceReport rep
232260
Factor = report.Factor,
233261
Fingerprint = report.Fingerprint
234262
};
263+
235264
if (result == null)
236265
{
237266
result = await SendAsync(innerReport);
@@ -272,7 +301,8 @@ public virtual void HandleApplicationException()
272301
/// </summary>
273302
public virtual void HandleApplicationThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
274303
{
275-
SendAsync(new BacktraceReport(e.Exception)).Wait();
304+
var exception = e.Exception as Exception;
305+
Send(new BacktraceReport(exception));
276306
OnUnhandledApplicationException?.Invoke(e.Exception);
277307
}
278308

@@ -283,7 +313,8 @@ public virtual void HandleApplicationThreadException(object sender, System.Threa
283313

284314
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
285315
{
286-
SendAsync(new BacktraceReport(e.Exception)).Wait();
316+
var exception = e.Exception as Exception;
317+
Send(new BacktraceReport(exception));
287318
OnUnhandledApplicationException?.Invoke(e.Exception);
288319
}
289320

Backtrace/Model/BacktraceCredentials.cs

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Collections.Specialized;
43
using System.Configuration;
54
using System.Text;
@@ -20,7 +19,13 @@ public class BacktraceCredentials
2019
/// <summary>
2120
/// Get a Uri to Backtrace servcie
2221
/// </summary>
23-
public Uri BacktraceHostUri => _backtraceHostUri;
22+
public Uri BacktraceHostUri
23+
{
24+
get
25+
{
26+
return _backtraceHostUri;
27+
}
28+
}
2429

2530
/// <summary>
2631
/// Get an access token
@@ -33,6 +38,71 @@ internal string Token
3338
}
3439
}
3540

41+
/// <summary>
42+
/// Create submission url to Backtrace API
43+
/// </summary>
44+
/// <returns></returns>
45+
internal Uri GetSubmissionUrl()
46+
{
47+
if (_backtraceHostUri == null)
48+
{
49+
throw new ArgumentException(nameof(BacktraceHostUri));
50+
}
51+
52+
var uriBuilder = new UriBuilder(BacktraceHostUri);
53+
if (submitUrl)
54+
{
55+
return uriBuilder.Uri;
56+
}
57+
if (string.IsNullOrEmpty(Token))
58+
{
59+
throw new ArgumentException(nameof(Token));
60+
}
61+
62+
if (!uriBuilder.Scheme.StartsWith("http"))
63+
{
64+
uriBuilder.Scheme = $"https://{uriBuilder.Scheme}";
65+
}
66+
if(!uriBuilder.Path.EndsWith("/") && !string.IsNullOrEmpty(uriBuilder.Path))
67+
{
68+
uriBuilder.Path += "/";
69+
}
70+
uriBuilder.Path = $"{uriBuilder.Path}post";
71+
uriBuilder.Query = $"format=json&token={Token}";
72+
return uriBuilder.Uri;
73+
}
74+
private readonly bool submitUrl = false;
75+
76+
/// <summary>
77+
/// Initialize Backtrace credentials with Backtrace submit url.
78+
/// If you pass backtraceSubmitUrl you have to make sure url to API is valid and contains token
79+
/// </summary>
80+
/// <param name="backtraceSubmitUrl">Backtrace submit url</param>
81+
public BacktraceCredentials(
82+
string backtraceSubmitUrl)
83+
: this(new Uri(backtraceSubmitUrl))
84+
{ }
85+
86+
/// <summary>
87+
/// Initialize Backtrace credentials with Backtrace submit url.
88+
/// If you pass backtraceSubmitUrl you have to make sure url to API is valid and contains token
89+
/// </summary>
90+
/// <param name="backtraceSubmitUrl">Backtrace submit url</param>
91+
public BacktraceCredentials(Uri backtraceSubmitUrl)
92+
{
93+
var hostToCheck = backtraceSubmitUrl.Host;
94+
if (!hostToCheck.StartsWith("www."))
95+
{
96+
hostToCheck = $"www.{hostToCheck}";
97+
}
98+
submitUrl = hostToCheck.StartsWith("www.submit.backtrace.io");
99+
if (!submitUrl)
100+
{
101+
throw new ArgumentException(nameof(backtraceSubmitUrl));
102+
}
103+
_backtraceHostUri = backtraceSubmitUrl;
104+
}
105+
36106
/// <summary>
37107
/// Initialize Backtrace credencials
38108
/// </summary>
@@ -69,7 +139,7 @@ public BacktraceCredentials(
69139
public BacktraceCredentials(
70140
string backtraceHostUrl,
71141
string accessToken)
72-
: this(new Uri(backtraceHostUrl), Encoding.UTF8.GetBytes(accessToken))
142+
: this(backtraceHostUrl, Encoding.UTF8.GetBytes(accessToken))
73143
{ }
74144

75145
/// <summary>

Backtrace/Services/BacktraceApi.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public BacktraceApi(BacktraceCredentials credentials, uint reportPerMin = 3)
5252
{
5353
throw new ArgumentException($"{nameof(BacktraceCredentials)} cannot be null");
5454
}
55-
_serverurl = $"{credentials.BacktraceHostUri.AbsoluteUri}post?format=json&token={credentials.Token}";
55+
_serverurl = credentials.GetSubmissionUrl().ToString();
5656
reportLimitWatcher = new ReportLimitWatcher(reportPerMin);
5757
}
5858
#region asyncRequest

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Backtrace C# Release Notes
22

3+
## Version 2.0.6 - 20.12.2018
4+
- New `BacktraceCredentials` constructor,
5+
- UnhandledThreadException flow
6+
37
## Version 2.0.5 - 03.12.2018
48
- Removed unused usings,
59
- `BacktraceDatabase` conditions with maximum number of records/maximum disk space fix,

Examples/Backtrace.WinFoms/Form1.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.ComponentModel;
4-
using System.Data;
5-
using System.Drawing;
6-
using System.Linq;
7-
using System.Text;
8-
using System.Threading.Tasks;
92
using System.Windows.Forms;
103

114
namespace Backtrace.WinFoms

Examples/Backtrace.WinFoms/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ static void Main()
4444
backtraceClient = new BacktraceClient(configuartion, database);
4545
//Setting application exceptions
4646
backtraceClient.HandleApplicationException();
47-
backtraceClient.SendAsync("WPF Application crash report started").Wait();
4847
Application.EnableVisualStyles();
4948
Application.ThreadException += backtraceClient.HandleApplicationThreadException;
5049
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

0 commit comments

Comments
 (0)