Skip to content

Commit

Permalink
Set Java/Android SDK options (#1694)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattjohnsonpint authored Jun 9, 2022
1 parent 4b52b7b commit d39477c
Show file tree
Hide file tree
Showing 14 changed files with 701 additions and 71 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- Update Android Support ([#1669](https://github.com/getsentry/sentry-dotnet/pull/1669))
- Update Sentry-Android to 6.0.0-rc.1 ([#1686](https://github.com/getsentry/sentry-dotnet/pull/1686))
- Update Sentry-Android to 6.0.0 ([#1697](https://github.com/getsentry/sentry-dotnet/pull/1697))
- Set Java/Android SDK options ([#1694](https://github.com/getsentry/sentry-dotnet/pull/1694))

### Fixes

Expand Down
31 changes: 31 additions & 0 deletions src/Sentry/Android/BeforeBreadcrumbCallback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Sentry.Extensibility;

namespace Sentry.Android
{
internal class BeforeBreadcrumbCallback : JavaObject, Java.SentryOptions.IBeforeBreadcrumbCallback
{
private readonly Func<Breadcrumb, Breadcrumb?> _beforeBreadcrumb;
private readonly IDiagnosticLogger? _logger;
private readonly Java.SentryOptions _javaOptions;

public BeforeBreadcrumbCallback(
Func<Breadcrumb, Breadcrumb?> beforeBreadcrumb,
IDiagnosticLogger? logger,
Java.SentryOptions javaOptions)
{
_beforeBreadcrumb = beforeBreadcrumb;
_logger = logger;
_javaOptions = javaOptions;
}

public Java.Breadcrumb? Execute(Java.Breadcrumb b, Java.Hint h)
{
// Note: Hint is unused due to:
// https://github.com/getsentry/sentry-dotnet/issues/1469

var breadcrumb = b.ToBreadcrumb(_javaOptions);
var result = _beforeBreadcrumb.Invoke(breadcrumb);
return result?.ToJavaBreadcrumb(_logger, _javaOptions);
}
}
}
31 changes: 31 additions & 0 deletions src/Sentry/Android/BeforeSendCallback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Sentry.Extensibility;

namespace Sentry.Android
{
internal class BeforeSendCallback : JavaObject, Java.SentryOptions.IBeforeSendCallback
{
private readonly Func<SentryEvent, SentryEvent?> _beforeSend;
private readonly IDiagnosticLogger? _logger;
private readonly Java.SentryOptions _javaOptions;

public BeforeSendCallback(
Func<SentryEvent, SentryEvent?> beforeSend,
IDiagnosticLogger? logger,
Java.SentryOptions javaOptions)
{
_beforeSend = beforeSend;
_logger = logger;
_javaOptions = javaOptions;
}

public Java.SentryEvent? Execute(Java.SentryEvent e, Java.Hint h)
{
// Note: Hint is unused due to:
// https://github.com/getsentry/sentry-dotnet/issues/1469

var evnt = e.ToSentryEvent(_javaOptions);
var result = _beforeSend.Invoke(evnt);
return result?.ToJavaSentryEvent(_logger, _javaOptions);
}
}
}
158 changes: 158 additions & 0 deletions src/Sentry/Android/JavaExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
using System.Text.Json;
using Sentry.Extensibility;

namespace Sentry.Android
{
internal static class JavaExtensions
{
public static SentryLevel ToSentryLevel(this Java.SentryLevel level)
{
// note: switch doesn't work here because JNI enums are not constants
if (level == Java.SentryLevel.Debug)
return SentryLevel.Debug;
if (level == Java.SentryLevel.Info)
return SentryLevel.Info;
if (level == Java.SentryLevel.Warning)
return SentryLevel.Warning;
if (level == Java.SentryLevel.Error)
return SentryLevel.Error;
if (level == Java.SentryLevel.Fatal)
return SentryLevel.Fatal;

throw new ArgumentOutOfRangeException(nameof(level), level, message: default);
}

public static Java.SentryLevel ToJavaSentryLevel(this SentryLevel level) =>
level switch
{
SentryLevel.Debug => Java.SentryLevel.Debug!,
SentryLevel.Info => Java.SentryLevel.Info!,
SentryLevel.Warning => Java.SentryLevel.Warning!,
SentryLevel.Error => Java.SentryLevel.Error!,
SentryLevel.Fatal => Java.SentryLevel.Fatal!,
_ => throw new ArgumentOutOfRangeException(nameof(level), level, message: default)
};

public static SentryId ToSentryId(this Java.Protocol.SentryId sentryId) =>
new(Guid.Parse(sentryId.ToString()));

public static SpanId ToSpanId(this Java.SpanId spanId) =>
new(spanId.ToString());

public static SpanStatus ToSpanStatus(this Java.SpanStatus status)
{
// note: switch doesn't work here because JNI enums are not constants
if (status == Java.SpanStatus.Ok)
return SpanStatus.Ok;
if (status == Java.SpanStatus.DeadlineExceeded)
return SpanStatus.DeadlineExceeded;
if (status == Java.SpanStatus.Unauthenticated)
return SpanStatus.Unauthenticated;
if (status == Java.SpanStatus.PermissionDenied)
return SpanStatus.PermissionDenied;
if (status == Java.SpanStatus.NotFound)
return SpanStatus.NotFound;
if (status == Java.SpanStatus.ResourceExhausted)
return SpanStatus.ResourceExhausted;
if (status == Java.SpanStatus.InvalidArgument)
return SpanStatus.InvalidArgument;
if (status == Java.SpanStatus.Unimplemented)
return SpanStatus.Unimplemented;
if (status == Java.SpanStatus.Unavailable)
return SpanStatus.Unavailable;
if (status == Java.SpanStatus.InternalError)
return SpanStatus.InternalError;
if (status == Java.SpanStatus.UnknownError)
return SpanStatus.UnknownError;
if (status == Java.SpanStatus.Cancelled)
return SpanStatus.Cancelled;
if (status == Java.SpanStatus.AlreadyExists)
return SpanStatus.AlreadyExists;
if (status == Java.SpanStatus.FailedPrecondition)
return SpanStatus.FailedPrecondition;
if (status == Java.SpanStatus.Aborted)
return SpanStatus.Aborted;
if (status == Java.SpanStatus.OutOfRange)
return SpanStatus.OutOfRange;
if (status == Java.SpanStatus.DataLoss)
return SpanStatus.DataLoss;

throw new ArgumentOutOfRangeException(nameof(status), status, message: default);
}

public static SentryEvent ToSentryEvent(this Java.SentryEvent sentryEvent, Java.SentryOptions javaOptions)
{
using var stream = new MemoryStream();
using var streamWriter = new JavaOutputStreamWriter(stream);
using var jsonWriter = new Java.JsonObjectWriter(streamWriter, javaOptions.MaxDepth);
sentryEvent.Serialize(jsonWriter, javaOptions.Logger);
jsonWriter.Flush();
stream.Seek(0, SeekOrigin.Begin);

using var json = JsonDocument.Parse(stream);
return SentryEvent.FromJson(json.RootElement, sentryEvent.Throwable);
}

public static Java.SentryEvent ToJavaSentryEvent(this SentryEvent sentryEvent, IDiagnosticLogger? logger, Java.SentryOptions javaOptions)
{
using var stream = new MemoryStream();
using var jsonWriter = new Utf8JsonWriter(stream);
sentryEvent.WriteTo(jsonWriter, logger);
jsonWriter.Flush();
stream.Seek(0, SeekOrigin.Begin);

using var streamReader = new JavaInputStreamReader(stream);
using var jsonReader = new Java.JsonObjectReader(streamReader);
using var deserializer = new Java.SentryEvent.Deserializer();
return deserializer.Deserialize(jsonReader, javaOptions.Logger);
}

public static Breadcrumb ToBreadcrumb(this Java.Breadcrumb breadcrumb, Java.SentryOptions javaOptions)
{
using var stream = new MemoryStream();
using var streamWriter = new JavaOutputStreamWriter(stream);
using var jsonWriter = new Java.JsonObjectWriter(streamWriter, javaOptions.MaxDepth);
breadcrumb.Serialize(jsonWriter, javaOptions.Logger);
jsonWriter.Flush();
stream.Seek(0, SeekOrigin.Begin);

using var json = JsonDocument.Parse(stream);
return Breadcrumb.FromJson(json.RootElement);
}

public static Java.Breadcrumb ToJavaBreadcrumb(this Breadcrumb breadcrumb, IDiagnosticLogger? logger, Java.SentryOptions javaOptions)
{
using var stream = new MemoryStream();
using var jsonWriter = new Utf8JsonWriter(stream);
breadcrumb.WriteTo(jsonWriter, logger);
jsonWriter.Flush();
stream.Seek(0, SeekOrigin.Begin);

using var streamReader = new JavaInputStreamReader(stream);
using var jsonReader = new Java.JsonObjectReader(streamReader);
using var deserializer = new Java.Breadcrumb.Deserializer();
return deserializer.Deserialize(jsonReader, javaOptions.Logger);
}

public static TransactionSamplingContext ToTransactionSamplingContext(this Java.SamplingContext context)
{
var tc = context.TransactionContext;
var transactionContext = new TransactionContext(
tc.SpanId.ToSpanId(),
tc.ParentSpanId?.ToSpanId(),
tc.TraceId.ToSentryId(),
tc.Name,
tc.Operation,
tc.Description,
tc.Status?.ToSpanStatus(),
tc.Sampled?.BooleanValue(),
tc.ParentSampled?.BooleanValue());

var customContext = context.CustomSamplingContext?
.Data.ToDictionary(x => x.Key, x => (object?)x.Value)
?? new(capacity: 0);

return new TransactionSamplingContext(transactionContext, customContext);
}
}
}
21 changes: 21 additions & 0 deletions src/Sentry/Android/JavaLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Sentry.Android
{
internal class JavaLogger : JavaObject, Java.ILogger
{
private readonly SentryOptions _options;

public JavaLogger(SentryOptions options) => _options = options;

public void Log(Java.SentryLevel level, string message, JavaObject[]? args) =>
_options.DiagnosticLogger?.Log(level.ToSentryLevel(), message, null, args?.Cast<object?>());

public void Log(Java.SentryLevel level, string message, Throwable? throwable) =>
_options.DiagnosticLogger?.Log(level.ToSentryLevel(), message, throwable);

public void Log(Java.SentryLevel level, Throwable? throwable, string message, params JavaObject[]? args) =>
_options.DiagnosticLogger?.Log(level.ToSentryLevel(), message, throwable, args?.Cast<object?>());

public bool IsEnabled(Java.SentryLevel? level) =>
level != null && _options.DiagnosticLogger?.IsEnabled(level.ToSentryLevel()) == true;
}
}
16 changes: 16 additions & 0 deletions src/Sentry/Android/OptionsConfigurationCallback.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Sentry.Android
{
internal class OptionsConfigurationCallback : JavaObject, Java.Sentry.IOptionsConfiguration
{
private readonly Action<SentryAndroidOptions> _configureOptions;

public OptionsConfigurationCallback(Action<SentryAndroidOptions> configureOptions) =>
_configureOptions = configureOptions;

public void Configure(JavaObject optionsObject)
{
var options = (SentryAndroidOptions)optionsObject;
_configureOptions(options);
}
}
}
21 changes: 21 additions & 0 deletions src/Sentry/Android/Sentry.Android.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<Project>

<PropertyGroup>
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
<!-- BG8605 and BG8606 happen because there's a missing androidx.lifecycle dependency, but we don't need it here. (The native Android Sentry SDK will use it if it exists.) -->
<NoWarn>$(NoWarn);BG8605;BG8606</NoWarn>
<SentryAndroidSdkVersion>6.0.0</SentryAndroidSdkVersion>
<AndroidLibsDirectory>$(MSBuildProjectDirectory)/../../libs/Android/</AndroidLibsDirectory>
<LangVersion>10</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<None Remove="Android/Transforms/*.xml" />
<TransformFile Include="Android/Transforms/*.xml" />
Expand All @@ -14,9 +18,25 @@
<AndroidLibrary Include="$(AndroidLibsDirectory)/sentry-android-core-$(SentryAndroidSdkVersion).aar" />
<AndroidLibrary Include="$(AndroidLibsDirectory)/sentry-android-ndk-$(SentryAndroidSdkVersion).aar" />
</ItemGroup>

<ItemGroup>
<Compile Include="Android/*.cs" />
</ItemGroup>

<ItemGroup>
<Using Include="System.Globalization" />
<Using Include="System.Text.Json" />
<Using Include="Android.Runtime" />
<Using Include="Android.Content.Context" Alias="AndroidContext" />
<Using Include="Android.OS.Build" Alias="AndroidBuild" />
<Using Include="Java.Lang.Class" Alias="JavaClass" />
<Using Include="Java.Lang.Double" Alias="JavaDouble" />
<Using Include="Java.Lang.Object" Alias="JavaObject" />
<Using Include="Java.Lang.Throwable" Alias="Throwable" />
<Using Include="Java.IO.InputStreamReader" Alias="JavaInputStreamReader" />
<Using Include="Java.IO.OutputStreamWriter" Alias="JavaOutputStreamWriter" />
</ItemGroup>

<!-- Update Android SDK: Update SentryAndroidSdkVersion and run:
dotnet msbuild src/Sentry /t:DownloadSentryAndroidSdk /p:TargetFramework=net6.0-android -->
<Target Name="DownloadSentryAndroidSdk">
Expand All @@ -37,4 +57,5 @@
<Output TaskParameter="DownloadedFile" ItemName="Content" />
</DownloadFile>
</Target>

</Project>
Loading

0 comments on commit d39477c

Please sign in to comment.