Skip to content

Commit

Permalink
Merge branch 'main' into trim-warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescrosswell authored Dec 18, 2024
2 parents 46712a0 + 1ecab82 commit 9e40b76
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 7 deletions.
11 changes: 7 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

### Fixes
- Fixed JNI Error when accessing Android device data from multiple threads ([#3802](https://github.com/getsentry/sentry-dotnet/pull/3802))
- Android - fix bug that prevents logcat.log from getting attached to unhandled events (SIGSEGV Segfault) ([#3694](https://github.com/getsentry/sentry-dotnet/pull/3694))
- Fix "System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'idData')" error propagating OpenTelemetry span ids ([#3850](https://github.com/getsentry/sentry-dotnet/pull/3850))
- Address Trim warnings so that MAUI applications can be compiled AOT ([#3841](https://github.com/getsentry/sentry-dotnet/pull/3841))

### Dependencies
Expand Down Expand Up @@ -44,6 +46,7 @@

### Fixes

- Fixed ArgumentNullException in FormRequestPayloadExtractor when handling invalid form data on ASP.NET ([#3734](https://github.com/getsentry/sentry-dotnet/pull/3734))
- Fixed NullReferenceException in SentryTraceHeader when parsing null or empty values ([#3757](https://github.com/getsentry/sentry-dotnet/pull/3757))
- ArgumentNullException in FormRequestPayloadExtractor when handling invalid form data on ASP.NET ([#3734](https://github.com/getsentry/sentry-dotnet/pull/3734))
- Crash when using NLog with FailedRequestStatusCodes options in a Maui app with Trimming enabled ([#3743](https://github.com/getsentry/sentry-dotnet/pull/3743))
Expand Down Expand Up @@ -81,16 +84,16 @@

## 4.12.2

### Fixes

- Events from NDK on Android will report sdk.name `sentry.native.android.dotnet` ([#3682](https://github.com/getsentry/sentry-dotnet/pull/3682))

### Features

- Android - allow logcat attachments to be previewed in Sentry ([#3711](https://github.com/getsentry/sentry-dotnet/pull/3711))
- Added a `SetBeforeScreenshotCapture` callback to the options: allowing the user to set an action before the screenshot is taken ([#3661](https://github.com/getsentry/sentry-dotnet/pull/3661))
- Make `Sentry.AspNetCore.Blazor.WebAssembly` generally available. ([#3674](https://github.com/getsentry/sentry-dotnet/pull/3674))

### Fixes

- Events from NDK on Android will report sdk.name `sentry.native.android.dotnet` ([#3682](https://github.com/getsentry/sentry-dotnet/pull/3682))

### Dependencies

- Bump Java SDK from v7.14.0 to v7.16.0 ([#3670](https://github.com/getsentry/sentry-dotnet/pull/3670), [#3707](https://github.com/getsentry/sentry-dotnet/pull/3707))
Expand Down
2 changes: 2 additions & 0 deletions src/Sentry/Platforms/Android/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ private static void InitSentryAndroidSdk(SentryOptions options)

// Define the configuration for the Android SDK
SentryAndroidOptions? nativeOptions = null;

var configuration = new OptionsConfigurationCallback(o =>
{
// Capture the android options reference on the outer scope
Expand Down Expand Up @@ -59,6 +60,7 @@ private static void InitSentryAndroidSdk(SentryOptions options)
o.ServerName = options.ServerName;
o.SessionTrackingIntervalMillis = (long)options.AutoSessionTrackingInterval.TotalMilliseconds;
o.ShutdownTimeoutMillis = (long)options.ShutdownTimeout.TotalMilliseconds;
o.SetNativeHandlerStrategy(JavaSdk.Android.Core.NdkHandlerStrategy.SentryHandlerStrategyChainAtStart);

if (options.CacheDirectoryPath is { } cacheDirectoryPath)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/SpanId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace Sentry;
public override int GetHashCode() => StringComparer.Ordinal.GetHashCode(_value);

/// <inheritdoc />
public override string ToString() => _value.ToString("x8");
public override string ToString() => _value.ToString("x8").PadLeft(16, '0');

/// <summary>
/// Generates a new Sentry ID.
Expand Down
169 changes: 169 additions & 0 deletions test/Sentry.Maui.Tests/SentryMauiLogcatsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,165 @@ public Fixture()
options.CacheDirectoryPath = null; //Do not wrap our FakeTransport with a caching transport
options.FlushTimeout = TimeSpan.FromSeconds(10);
});

Builder = builder;
}
}

private readonly Fixture _fixture = new();


#if ANDROID
[SkippableFact]
public async Task CaptureException_WhenAttachLogcats_DefaultAsync()
{
// Arrange
var builder = _fixture.Builder.UseSentry();

// Act
using var app = builder.Build();
var client = app.Services.GetRequiredService<ISentryClient>();
var sentryId = client.CaptureException(new Exception());
await client.FlushAsync();

var options = app.Services.GetRequiredService<IOptions<SentryMauiOptions>>().Value;

var envelope = _fixture.Transport.GetSentEnvelopes().FirstOrDefault(e => e.TryGetEventId() == sentryId);
envelope.Should().NotBeNull("Envelope with sentryId {0} should be sent", sentryId);
var envelopeItem = envelope!.Items.FirstOrDefault(item => item.TryGetType() == "attachment");

// Assert
envelopeItem.Should().BeNull();
}

[SkippableFact]
public async Task CaptureException_WhenAttachLogcats_AllExceptionsAsync()
{

// Arrange
var builder = _fixture.Builder.UseSentry(options =>
{
options.Android.LogCatIntegration = Android.LogCatIntegrationType.All;
});

// Act
using var app = builder.Build();
var client = app.Services.GetRequiredService<ISentryClient>();
var sentryId = client.CaptureException(new Exception());
await client.FlushAsync();

var options = app.Services.GetRequiredService<IOptions<SentryMauiOptions>>().Value;

var envelope = _fixture.Transport.GetSentEnvelopes().FirstOrDefault(e => e.TryGetEventId() == sentryId);
envelope.Should().NotBeNull("Envelope with sentryId {0} should be sent", sentryId);

// Assert
envelope!.Items.Any(env => env.TryGetFileName() == "logcat.log").Should().BeTrue();
}

[SkippableFact]
public async Task CaptureException_WhenAttachLogcats_UnhandledExceptionsAsync()
{

// Arrange
var builder = _fixture.Builder.UseSentry(options =>
{
options.Android.LogCatIntegration = Android.LogCatIntegrationType.Unhandled;
});

// Act
using var app = builder.Build();
var client = app.Services.GetRequiredService<ISentryClient>();
var sentryId = client.CaptureException(BuildUnhandledException());

await client.FlushAsync();

var envelope = _fixture.Transport.GetSentEnvelopes().FirstOrDefault(e => e.TryGetEventId() == sentryId);
envelope.Should().NotBeNull("Envelope with sentryId {0} should be sent", sentryId);
var envelopeItem = envelope!.Items.FirstOrDefault(item => item.TryGetType() == "attachment");

// Assert
envelopeItem.Should().NotBeNull();
envelopeItem!.TryGetFileName().Should().Be("logcat.log");
}

[SkippableFact]
public async Task CaptureException_WhenAttachLogcats_HandledExceptionsAsync()
{

// Arrange
var builder = _fixture.Builder.UseSentry(options =>
{
options.Android.LogCatIntegration = Android.LogCatIntegrationType.Unhandled;
});

// Act
using var app = builder.Build();
var client = app.Services.GetRequiredService<ISentryClient>();
var sentryId = client.CaptureException(new Exception());

await client.FlushAsync();

var envelope = _fixture.Transport.GetSentEnvelopes().FirstOrDefault(e => e.TryGetEventId() == sentryId);
envelope.Should().NotBeNull("Envelope with sentryId {0} should be sent", sentryId);

// Assert
envelope!.Items.Any(item => item.TryGetType() == "attachment").Should().BeFalse();
}

[SkippableFact]
public async Task CaptureException_WhenAttachLogcats_ErrorsAsync()
{

// Arrange
var builder = _fixture.Builder.UseSentry(options =>
{
options.Android.LogCatIntegration = Android.LogCatIntegrationType.Errors;
});

// Act
using var app = builder.Build();
var client = app.Services.GetRequiredService<ISentryClient>();
var sentryId = client.CaptureException(new Exception());
await client.FlushAsync();

var options = app.Services.GetRequiredService<IOptions<SentryMauiOptions>>().Value;

var envelope = _fixture.Transport.GetSentEnvelopes().FirstOrDefault(e => e.TryGetEventId() == sentryId);
envelope.Should().NotBeNull("Envelope with sentryId {0} should be sent", sentryId);
var envelopeItem = envelope!.Items.FirstOrDefault(item => item.TryGetType() == "attachment");

// Assert
envelopeItem.Should().NotBeNull();
envelopeItem!.TryGetFileName().Should().Be("logcat.log");
}

[SkippableFact]
public async Task CaptureException_WhenAttachLogcats_NoneAsync()
{

// Arrange
var builder = _fixture.Builder.UseSentry(options =>
{
options.Android.LogCatIntegration = Android.LogCatIntegrationType.None;
});

// Act
using var app = builder.Build();
var client = app.Services.GetRequiredService<ISentryClient>();
var sentryId = client.CaptureException(new Exception());
await client.FlushAsync();

var options = app.Services.GetRequiredService<IOptions<SentryMauiOptions>>().Value;

var envelope = _fixture.Transport.GetSentEnvelopes().FirstOrDefault(e => e.TryGetEventId() == sentryId);
envelope.Should().NotBeNull("Envelope with sentryId {0} should be sent", sentryId);
var envelopeItem = envelope!.Items.FirstOrDefault(item => item.TryGetType() == "attachment");

// Assert
envelopeItem.Should().BeNull();
}

[Fact]
public void CaptureException_CheckLogcatType()
{
Expand Down Expand Up @@ -63,5 +215,22 @@ public void CaptureException_CheckLogcatType()
hint.Should().NotBeNull();
hint.Attachments.First().ContentType.Should().Be("text/plain", hint.Attachments.First().ContentType);
}

private static Exception BuildUnhandledException()
{
try
{
// Throwing will put a stack trace on the exception
throw new Exception("Error");
}
catch (Exception exception)
{
// Add extra data to test fully
exception.Data[Mechanism.HandledKey] = false;
exception.Data[Mechanism.MechanismKey] = "AppDomain.UnhandledException";
exception.Data["foo"] = "bar";
return exception;
}
}
#endif
}
24 changes: 22 additions & 2 deletions test/Sentry.Maui.Tests/SentryMauiOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,32 @@ public void CacheDirectoryPath_Default()
#endif
}

#if ANDROID
[Fact]
public void AttachScreenshots_Default()
public void HandlerStrategy_Default()
{
// Arrange
var expected = Android.LogCatIntegrationType.None;
var options = new SentryMauiOptions();

// Assert
Assert.Equal(expected, options.Android.LogCatIntegration);
}

[Fact]
public void HandlerStrategy_Set()
{
// Arrange
var expected = Android.LogCatIntegrationType.None;
var options = new SentryMauiOptions();
Assert.False(options.AttachScreenshot);

// Act
options.Android.LogCatIntegration = Android.LogCatIntegrationType.All;

// Assert
Assert.NotEqual(expected, options.Android.LogCatIntegration);
}
#endif

[Fact]
public void BeforeCaptureScreenshot_Set()
Expand Down
11 changes: 11 additions & 0 deletions test/Sentry.Tests/Protocol/Context/TraceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,15 @@ public void Clone_CopyValues()
Assert.Equal(trace.SpanId, clone.SpanId);
Assert.Equal(trace.TraceId, clone.TraceId);
}

[Fact]
public void SpanId_LeadingZero_ToStringValid()
{
// Arrange
const string spanIdInput = "0ecd6f15f72015cb";
var spanId = new SpanId(spanIdInput);

// Assert
Assert.Equal(spanIdInput, spanId.ToString());
}
}

0 comments on commit 9e40b76

Please sign in to comment.