Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow some mobile options to be modified from defaults #1857

Merged
merged 14 commits into from
Aug 18, 2022
Merged
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- Fix logging loop with NLog sentry ([#1824](https://github.com/getsentry/sentry-dotnet/pull/1824))
- Fix logging loop with Serilog sentry ([#1828](https://github.com/getsentry/sentry-dotnet/pull/1828))
- Skip attachment if stream is empty ([#1854](https://github.com/getsentry/sentry-dotnet/pull/1854))
- Allow some mobile options to be modified from defaults ([#1857](https://github.com/getsentry/sentry-dotnet/pull/1857))

## 3.20.1

Expand Down
2 changes: 1 addition & 1 deletion samples/Sentry.Samples.Android/MainActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public class MainActivity : Activity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
SentrySdk.Init(this, o =>
SentrySdk.Init(o =>
mattjohnsonpint marked this conversation as resolved.
Show resolved Hide resolved
{
o.Dsn = "https://eb18e953812b41c3aeb042e666fd3b5c@o447951.ingest.sentry.io/5428537";
o.SendDefaultPii = true; // adds the user's IP address automatically
Expand Down
4 changes: 2 additions & 2 deletions samples/Sentry.Samples.Maui/MainPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ protected override void OnAppearing()
JavaCrashBtn.IsVisible = false;
#endif

#if !(ANDROID || IOS || MACCATALYST)
#if !__MOBILE__
NativeCrashBtn.IsVisible = false;
#endif
base.OnAppearing();
Expand Down Expand Up @@ -73,7 +73,7 @@ private void OnJavaCrashClicked(object sender, EventArgs e)

private void OnNativeCrashClicked(object sender, EventArgs e)
{
#if ANDROID || IOS || MACCATALYST
#if __MOBILE__
mattjohnsonpint marked this conversation as resolved.
Show resolved Hide resolved
SentrySdk.CauseCrash(CrashType.Native);
#endif
}
Expand Down
7 changes: 1 addition & 6 deletions src/Sentry.Maui/Internal/SentryMauiInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,8 @@ public void Initialize(IServiceProvider services)
{
var options = services.GetRequiredService<IOptions<SentryMauiOptions>>().Value;
var disposer = services.GetRequiredService<Disposer>();

#if ANDROID
var context = global::Android.App.Application.Context;
var disposable = SentrySdk.Init(context, options);
#else

var disposable = SentrySdk.Init(options);
#endif

// Register the return value from initializing the SDK with the disposer.
// This will ensure that it gets disposed when the service provider is disposed.
Expand Down
3 changes: 3 additions & 0 deletions src/Sentry.Maui/Internal/SentryMauiOptionsSetup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public override void Configure(SentryMauiOptions options)
{
base.Configure(options);

// NOTE: Anything set here will overwrite options set by the user.
// For option defaults that can be changed, use the constructor in SentryMauiOptions instead.

// We'll initialize the SDK in SentryMauiInitializer
options.InitializeSdk = false;

Expand Down
14 changes: 14 additions & 0 deletions src/Sentry.Maui/SentryMauiOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ namespace Sentry.Maui;
/// </summary>
public class SentryMauiOptions : SentryLoggingOptions
{
/// <summary>
/// Creates a new instance of <see cref="SentryMauiOptions"/>.
/// </summary>
public SentryMauiOptions()
{
// Set defaults for options that are different for MAUI.
// The user can change these. If you want to force a value, use SentryMauiOptionsSetup instead.
// Also, some of these are already set in the base Sentry SDK, but since we don't yet have native targets
// there for all MAUI targets, we'll set them again here.

AutoSessionTracking = true;
DetectStartupTime = StartupTimeDetectionMode.Fast;
}

/// <summary>
/// Gets or sets whether elements that implement <see cref="IText"/>
/// (such as <see cref="Button"/>, <see cref="Label"/>, <see cref="Entry"/>, and others)
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/CrashType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public enum CrashType
JavaBackgroundThread,
#endif

#if ANDROID || IOS || MACCATALYST
#if __MOBILE__
/// <summary>
/// A native operation that will crash the appliction will be performed by a C library.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/Internal/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal static class Constants
// See: https://github.com/getsentry/sentry-release-registry
#if ANDROID
public const string SdkName = "sentry.dotnet.android";
#elif IOS || MACCATALYST
#elif __IOS__
public const string SdkName = "sentry.dotnet.cocoa";
#else
public const string SdkName = "sentry.dotnet";
Expand Down
4 changes: 2 additions & 2 deletions src/Sentry/Internal/ProcessInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ internal ProcessInfo(
// https://issuetracker.unity3d.com/issues/il2cpp-player-crashes-when-calling-process-dot-getcurrentprocess-dot-starttime
if (options.DetectStartupTime == StartupTimeDetectionMode.Best)
{
#if ANDROID || IOS || MACCATALYST
#if __MOBILE__
options.LogWarning("StartupTimeDetectionMode.Best is not available on this platform. Using 'Fast' mode.");
#else
// StartupTime is set to UtcNow in this constructor.
Expand All @@ -98,7 +98,7 @@ internal ProcessInfo(
}
}

#if !(ANDROID || IOS || MACCATALYST)
#if !__MOBILE__
private static DateTimeOffset GetStartupTime()
{
using var proc = Process.GetCurrentProcess();
Expand Down
1 change: 1 addition & 0 deletions src/Sentry/Internal/SentryScopeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public SentryScopeManager(
ISentryClient rootClient)
{
ScopeStackContainer = scopeStackContainer;

_options = options;
NewStack = () => new[] { new KeyValuePair<Scope, ISentryClient>(new Scope(options), rootClient) };
}
Expand Down
13 changes: 13 additions & 0 deletions src/Sentry/PlatformAbstractions/DeviceInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Sentry.PlatformAbstractions
{
internal static class DeviceInfo
{
#if ANDROID
public const string PlatformName = "Android";
#elif IOS
public const string PlatformName = "iOS";
#elif MACCATALYST
public const string PlatformName = "Mac Catalyst";
#endif
}
}
46 changes: 15 additions & 31 deletions src/Sentry/Platforms/Android/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@
using Sentry.Android;
using Sentry.Android.Callbacks;
using Sentry.Android.Extensions;
using Sentry.Extensibility;
using Sentry.Protocol;

// ReSharper disable once CheckNamespace
namespace Sentry;

public static partial class SentrySdk
{
private static AndroidContext? AndroidContext;
private static AndroidContext AppContext { get; set; } = Application.Context;

/// <summary>
/// Initializes the SDK for Android, with an optional configuration options callback.
/// </summary>
/// <param name="context">The Android application context.</param>
/// <param name="configureOptions">The configuration options callback.</param>
/// <returns>An object that should be disposed when the application terminates.</returns>
[Obsolete("It is no longer required to provide the application context when calling Init. " +
"This method may be removed in a future major release.")]
public static IDisposable Init(AndroidContext context, Action<SentryOptions>? configureOptions)
{
var options = new SentryOptions();
configureOptions?.Invoke(options);
return Init(context, options);
AppContext = context;
return Init(configureOptions);
}

/// <summary>
Expand All @@ -32,40 +32,26 @@ public static IDisposable Init(AndroidContext context, Action<SentryOptions>? co
/// <param name="context">The Android application context.</param>
/// <param name="options">The configuration options instance.</param>
/// <returns>An object that should be disposed when the application terminates.</returns>
[Obsolete("It is no longer required to provide the application context when calling Init. " +
"This method may be removed in a future major release.")]
public static IDisposable Init(AndroidContext context, SentryOptions options)
{
AndroidContext = context;
AppContext = context;
return Init(options);
}

private static void InitSentryAndroidSdk(SentryOptions options)
{
// Set options for the managed SDK that don't depend on the Android SDK
options.AutoSessionTracking = true;
options.IsGlobalModeEnabled = true;

// Set default release and distribution
options.Release ??= GetDefaultReleaseString();
options.Distribution ??= GetDefaultDistributionString();

// "Best" mode throws permission exception on Android
options.DetectStartupTime = StartupTimeDetectionMode.Fast;

// Make sure we capture managed exceptions from the Android environment
AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;

// Now initialize the Android SDK if we have been given an AndroidContext
var context = AndroidContext;
if (context == null)
{
options.LogWarning("Running on Android, but did not initialize Sentry with an AndroidContext. " +
"The embedded Sentry Android SDK is disabled. " +
"Call SentrySdk.Init(AndroidContext, SentryOptions) instead.");
return;
}

// Now initialize the Android SDK
SentryAndroidOptions? androidOptions = null;
SentryAndroid.Init(context, new JavaLogger(options),
SentryAndroid.Init(AppContext, new JavaLogger(options),
new OptionsConfigurationCallback(o =>
{
// Capture the android options reference on the outer scope
Expand Down Expand Up @@ -179,7 +165,7 @@ private static void InitSentryAndroidSdk(SentryOptions options)
o.AddIgnoredExceptionForType(JavaClass.ForName("android.runtime.JavaProxyThrowable"));
}));

// Set options for the managed SDK that depend on the Android SDK
// Set options for the managed SDK that depend on the Android SDK. (The user will not be able to modify these.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user will not be able to modify these

does this mean "there is no API what the user can use to modify these" or "we ignore/overwrite the options the user sets"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means, we set these options ourselves during init, ignoring whatever the user provided. These should be limited to what is needed to make the native and managed SDKs work together.

options.AddEventProcessor(new AndroidEventProcessor(androidOptions!));
options.CrashedLastRun = () => Java.Sentry.IsCrashedLastRun()?.BooleanValue() is true;
options.EnableScopeSync = true;
Expand All @@ -201,29 +187,27 @@ private static void AndroidEnvironment_UnhandledExceptionRaiser(object? _, Raise

private static string? GetDefaultReleaseString()
{
var context = AndroidContext ?? Application.Context;
var packageName = context.PackageName;
var packageName = AppContext.PackageName;
if (packageName == null)
{
return null;
}

var packageInfo = context.PackageManager?.GetPackageInfo(packageName, PackageInfoFlags.Permissions);
var packageInfo = AppContext.PackageManager?.GetPackageInfo(packageName, PackageInfoFlags.Permissions);
return packageInfo == null ? null : $"{packageName}@{packageInfo.VersionName}+{packageInfo.GetVersionCode()}";
}

private static string? GetDefaultDistributionString() => GetAndroidPackageVersionCode()?.ToString();

private static long? GetAndroidPackageVersionCode()
{
var context = AndroidContext ?? Application.Context;
var packageName = context.PackageName;
var packageName = AppContext.PackageName;
if (packageName == null)
{
return null;
}

var packageInfo = context.PackageManager?.GetPackageInfo(packageName, PackageInfoFlags.Permissions);
var packageInfo = AppContext.PackageManager?.GetPackageInfo(packageName, PackageInfoFlags.Permissions);
return packageInfo?.GetVersionCode();
}

Expand Down
9 changes: 1 addition & 8 deletions src/Sentry/Platforms/iOS/SentrySdk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,10 @@ private static void InitSentryCocoaSdk(SentryOptions options)
args.ExceptionMode = ObjCRuntime.MarshalManagedExceptionMode.UnwindNativeCode;
};

// Set options for the managed SDK that don't depend on the Cocoa SDK
options.AutoSessionTracking = true;
options.IsGlobalModeEnabled = true;

// Set default release and distribution
options.Release ??= GetDefaultReleaseString();
options.Distribution ??= GetDefaultDistributionString();

// "Best" mode throws platform not supported exception. Use "Fast" mode instead.
options.DetectStartupTime = StartupTimeDetectionMode.Fast;

// Set options for the Cocoa SDK
var cocoaOptions = new SentryCocoaOptions();

Expand Down Expand Up @@ -170,7 +163,7 @@ private static void InitSentryCocoaSdk(SentryOptions options)
// Now initialize the Cocoa SDK
SentryCocoaSdk.StartWithOptionsObject(cocoaOptions);

// Set options for the managed SDK that depend on the Cocoa SDK
// Set options for the managed SDK that depend on the Cocoa SDK. (The user will not be able to modify these.)
options.AddEventProcessor(new IosEventProcessor(cocoaOptions!));
options.CrashedLastRun = () => SentryCocoaSdk.CrashedLastRun;
options.EnableScopeSync = true;
Expand Down
2 changes: 1 addition & 1 deletion src/Sentry/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@


// The targets for these platforms are not CLS Compliant
#if !(ANDROID || IOS || MACCATALYST)
#if !__MOBILE__
[assembly: CLSCompliant(true)]
#endif
43 changes: 36 additions & 7 deletions src/Sentry/SentryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
using Sentry.Internal;
using Sentry.Internal.Http;
using Sentry.Internal.ScopeStack;
using Sentry.PlatformAbstractions;
using static Sentry.Constants;
using Runtime = Sentry.PlatformAbstractions.Runtime;

#if HAS_DIAGNOSTIC_INTEGRATION
using Sentry.Internals.DiagnosticSource;
#endif
Expand All @@ -26,6 +27,26 @@ public partial class SentryOptions
{
private Dictionary<string, string>? _defaultTags;

#if __MOBILE__

internal IScopeStackContainer? ScopeStackContainer { get; } = new GlobalScopeStackContainer();

/// <summary>
/// Specifies whether to use global scope management mode.
/// Always <c>true</c> for mobile targets.
/// </summary>
public bool IsGlobalModeEnabled
{
get => true;
set
{
if (value is false)
{
_diagnosticLogger?.LogWarning("Cannot disable Global Mode on {0}", DeviceInfo.PlatformName);
}
}
}
#else
internal IScopeStackContainer? ScopeStackContainer { get; set; }

/// <summary>
Expand All @@ -36,6 +57,7 @@ public bool IsGlobalModeEnabled
get => ScopeStackContainer is GlobalScopeStackContainer;
set => ScopeStackContainer = value ? new GlobalScopeStackContainer() : new AsyncLocalScopeStackContainer();
}
#endif

/// <summary>
/// A scope set outside of Sentry SDK. If set, the global parameters from the SDK's scope will be sent to the observed scope.<br/>
Expand Down Expand Up @@ -573,13 +595,19 @@ public StackTraceMode StackTraceMode
public long MaxAttachmentSize { get; set; } = 20 * 1024 * 1024;

/// <summary>
/// Whether the SDK should attempt to detect the app's and device's startup time.
/// The mode that the SDK should use when attempting to detect the app's and device's startup time.
/// </summary>
/// <remarks>
/// Note that the highest precision value relies on <see cref="System.Diagnostics.Process.GetCurrentProcess"/>
/// which might not be available. For example on Unity's IL2CPP.
/// Additionally, "Best" mode is not available on mobile platforms.
/// </remarks>
public StartupTimeDetectionMode DetectStartupTime { get; set; } = StartupTimeDetectionMode.Best;
public StartupTimeDetectionMode DetectStartupTime { get; set; } =
#if __MOBILE__
StartupTimeDetectionMode.Fast;
#else
StartupTimeDetectionMode.Best;
#endif

/// <summary>
/// Determines the duration of time a session can stay paused before it's considered ended.
Expand All @@ -589,10 +617,11 @@ public StackTraceMode StackTraceMode
/// </remarks>
public TimeSpan AutoSessionTrackingInterval { get; set; } = TimeSpan.FromSeconds(30);

#if ANDROID || IOS || MACCATALYST
#if __MOBILE__
/// <summary>
/// Whether the SDK should start a session automatically when it's initialized and
/// end the session when it's closed.
/// On mobile application platforms, this is enabled by default.
/// </summary>
public bool AutoSessionTracking { get; set; } = true;
#else
Expand All @@ -601,8 +630,8 @@ public StackTraceMode StackTraceMode
/// end the session when it's closed.
/// </summary>
/// <remarks>
/// Note: this is disabled by default in the current version, but will become
/// enabled by default in the next major version.
/// Note: this is disabled by default in the current version (except for mobile targets and MAUI),
/// but will become enabled by default in the next major version.
/// Currently this only works for release health in client mode
/// (desktop, mobile applications, but not web servers).
/// </remarks>
Expand Down Expand Up @@ -691,7 +720,7 @@ public SentryOptions()

#if ANDROID
Android = new AndroidOptions(this);
#elif IOS || MACCATALYST
#elif __IOS__
iOS = new IosOptions(this);
#endif

Expand Down
Loading