Skip to content

Commit

Permalink
Merge pull request #228 from bugsnag/PLAT-6364/create-universal-confi…
Browse files Browse the repository at this point in the history
…guration

Create universal implementation of Configuration class
  • Loading branch information
fractalwrench authored Apr 26, 2021
2 parents b60a3b0 + 9ed1e8a commit 50de844
Show file tree
Hide file tree
Showing 22 changed files with 289 additions and 499 deletions.
20 changes: 20 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ If you alter Bugsnag's default behaviour via `Configuration`, you must supply al

Any change to the value of `Configuration` options after `Bugsnag.Start()` is called will have no effect on Bugsnag's behaviour.

### Configuration constructor removed

The previous constructor for `Configuration` allowed passing `AutoNotify` as its 2nd parameter:

```c#
new Configuration("your-api-key", true);
```

This has been removed - `AutoNotify` should be set using the property instead:

```c#
Configuration config = new Configuration("your-api-key");
config.AutoNotify = true;
```

### Bugsnag.Configuration accessor removed

The `Bugsnag.Configuration` accessor has been removed. You should supply all your configuration options up-front as recommended [here](#new-recommended-way-for-initializing-bugsnag).


## 4.1 to 4.2

4.2.0 adds support for reporting C/C++ crashes in Android code. If you are using
Expand Down
10 changes: 5 additions & 5 deletions features/breadcrumbs.feature
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Feature: Leaving breadcrumbs to attach to reports
And the exception "errorClass" equals "ExecutionEngineException"
And the exception "message" equals "Invalid runtime"
And the event has a "log" breadcrumb named "Warning"
And the payload field "events.0.breadcrumbs.1.metaData.message" equals "Failed to validate credentials"
And the payload field "events.0.breadcrumbs.0.metaData.message" equals "Failed to validate credentials"

Scenario: Attaching a complex breadcrumb to a report
When I run the game in the "ComplexBreadcrumbNotify" state
Expand All @@ -27,7 +27,7 @@ Feature: Leaving breadcrumbs to attach to reports
And the exception "errorClass" equals "Exception"
And the exception "message" equals "Collective failure"
And the event has a "navigation" breadcrumb named "Reload"
And the payload field "events.0.breadcrumbs.1.metaData.preload" equals "launch"
And the payload field "events.0.breadcrumbs.0.metaData.preload" equals "launch"

Scenario: Attaching an error report breadcrumb
When I run the game in the "DoubleNotify" state
Expand All @@ -38,6 +38,6 @@ Feature: Leaving breadcrumbs to attach to reports
And the payload field "events.0.exceptions.0.message" equals "Rollback failed" for request 0
And the payload field "events.0.exceptions.0.errorClass" equals "ExecutionEngineException" for request 1
And the payload field "events.0.exceptions.0.message" equals "Invalid runtime" for request 1
And the payload field "events.0.breadcrumbs.1.type" equals "error" for request 1
And the payload field "events.0.breadcrumbs.1.name" equals "Exception" for request 1
And the payload field "events.0.breadcrumbs.1.metaData.message" equals "Rollback failed" for request 1
And the payload field "events.0.breadcrumbs.0.type" equals "error" for request 1
And the payload field "events.0.breadcrumbs.0.name" equals "Exception" for request 1
And the payload field "events.0.breadcrumbs.0.metaData.message" equals "Rollback failed" for request 1
191 changes: 153 additions & 38 deletions features/fixtures/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ public static void CreateScene() {
var scene = UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects, UnityEditor.SceneManagement.NewSceneMode.Single);
UnityEngine.SceneManagement.SceneManager.SetActiveScene(scene);
var obj = new GameObject("Bugsnag");
var bugsnag = obj.AddComponent<BugsnagBehaviour>();
bugsnag.BugsnagApiKey = System.Environment.GetEnvironmentVariable("BUGSNAG_APIKEY");
bugsnag.AutoCaptureSessions = false;
obj.AddComponent<Main>();
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene, "Assets/MainScene.unity");
var scenes = new List<EditorBuildSettingsScene>(EditorBuildSettings.scenes);
Expand All @@ -34,6 +31,10 @@ public static void CreateScene() {
bool sent = false;

public void Start() {
var scenario = Environment.GetEnvironmentVariable("BUGSNAG_SCENARIO");
var config = PrepareConfig(scenario);
Bugsnag.Start(config);

// Add different varieties of custom metadata
Bugsnag.Metadata.Add("init", new Dictionary<string, string>(){
{"foo", "bar" },
Expand All @@ -49,19 +50,15 @@ public void Start() {
});
// Remove a tab
Bugsnag.Metadata.Remove("init");

// trigger the crash
RunScenario(scenario);
}

void Update() {
// only send one crash
if (!sent) {
var scenario = Environment.GetEnvironmentVariable("BUGSNAG_SCENARIO");
Bugsnag.Configuration.AutoCaptureSessions = scenario.Contains("AutoSession");
sent = true;
var endpoint =
new System.Uri(Environment.GetEnvironmentVariable("MAZE_ENDPOINT"));
Bugsnag.Configuration.Endpoint = endpoint;
Bugsnag.Configuration.SessionEndpoint = endpoint;
LoadScenario();
// wait for 5 seconds before exiting the application
StartCoroutine(WaitForBugsnag());
}
Expand All @@ -72,27 +69,127 @@ IEnumerator WaitForBugsnag() {
Application.Quit();
}

void LoadScenario() {
var scenario = Environment.GetEnvironmentVariable("BUGSNAG_SCENARIO");
/**
* Creates a configuration object and prepares it for the given scenario
*/
Configuration PrepareConfig(string scenario) {
string apiKey = System.Environment.GetEnvironmentVariable("BUGSNAG_APIKEY");
var config = new Configuration(apiKey);

// setup default endpoints etc
var endpoint = new System.Uri(Environment.GetEnvironmentVariable("MAZE_ENDPOINT"));
config.Endpoint = endpoint;
config.SessionEndpoint = endpoint;
config.AutoCaptureSessions = scenario.Contains("AutoSession");

// replacement for BugsnagBehaviour as not practical to load script in fixture
config.ScriptingBackend = FindScriptingBackend();
config.DotnetScriptingRuntime = FindDotnetScriptingRuntime();
config.DotnetApiCompatibility = FindDotnetApiCompatibility();

// prepare scenario-specific config
PrepareConfigForScenario(config, scenario);
return config;
}

/**
* Prepares the configuration object for a given scenario
*/
void PrepareConfigForScenario(Configuration config, string scenario) {
switch (scenario) {
case "LogExceptionOutsideNotifyReleaseStages":
config.ReleaseStage = "dev";
config.NotifyReleaseStages = new [] { "production" };
break;
case "NotifyOutsideNotifyReleaseStages":
config.ReleaseStage = "dev";
config.NotifyReleaseStages = new [] { "production" };
break;
case "NativeCrashOutsideNotifyReleaseStages":
config.ReleaseStage = "dev";
config.NotifyReleaseStages = new [] { "production" };
break;
case "UncaughtExceptionOutsideNotifyReleaseStages":
config.ReleaseStage = "dev";
config.NotifyReleaseStages = new [] { "production" };
break;
case "UncaughtExceptionAsUnhandled":
config.ReportUncaughtExceptionsAsHandled = false;
break;
case "LogUnthrownAsUnhandled":
config.ReportUncaughtExceptionsAsHandled = false;
break;
case "ReportLoggedWarning":
config.NotifyLevel = LogType.Warning;
break;
case "ReportLoggedError":
config.NotifyLevel = LogType.Warning;
break;
case "ReportLoggedWarningWithHandledConfig":
config.ReportUncaughtExceptionsAsHandled = false;
config.NotifyLevel = LogType.Warning;
break;
case "ManualSessionCrash":
config.ReportUncaughtExceptionsAsHandled = false;
break;
case "AutoSessionInNotifyReleaseStages":
config.ReleaseStage = "production";
config.NotifyReleaseStages = new [] { "production" };
break;
case "ManualSessionInNotifyReleaseStages":
config.ReleaseStage = "production";
config.NotifyReleaseStages = new [] { "production" };
break;
case "AutoSessionNotInNotifyReleaseStages":
config.NotifyReleaseStages = new [] { "no-op" };
break;
case "ManualSessionNotInNotifyReleaseStages":
config.NotifyReleaseStages = new [] { "no-op" };
break;
case "ManualSessionMixedEvents":
config.ReportUncaughtExceptionsAsHandled = false;
config.NotifyLevel = LogType.Warning;
break;
case "UncaughtExceptionWithoutAutoNotify":
config.AutoNotify = false;
break;
case "NotifyWithoutAutoNotify":
config.AutoNotify = false;
break;
case "LoggedExceptionWithoutAutoNotify":
config.AutoNotify = false;
config.ReportUncaughtExceptionsAsHandled = false;
break;
case "NativeCrashWithoutAutoNotify":
config.AutoNotify = false;
break;
case "NativeCrashReEnableAutoNotify":
config.AutoNotify = false;
config.AutoNotify = true;
break;
case "ReportLoggedWarningThreaded":
config.NotifyLevel = LogType.Warning;
break;
default: // no special config required
break;
}
}

/**
* Runs the crashy code for a given scenario.
*/
void RunScenario(string scenario) {
switch (scenario) {
case "LogExceptionOutsideNotifyReleaseStages":
Bugsnag.Configuration.ReleaseStage = "dev";
Bugsnag.Configuration.NotifyReleaseStages = new [] { "production" };
DoLogUnthrown();
break;
case "NotifyOutsideNotifyReleaseStages":
Bugsnag.Configuration.ReleaseStage = "dev";
Bugsnag.Configuration.NotifyReleaseStages = new [] { "production" };
DoNotify();
break;
case "NativeCrashOutsideNotifyReleaseStages":
Bugsnag.Configuration.ReleaseStage = "dev";
Bugsnag.Configuration.NotifyReleaseStages = new [] { "production" };
crashy_signal_runner(8);
break;
case "UncaughtExceptionOutsideNotifyReleaseStages":
Bugsnag.Configuration.ReleaseStage = "dev";
Bugsnag.Configuration.NotifyReleaseStages = new [] { "production" };
DoUnhandledException(0);
break;
case "DebugLogBreadcrumbNotify":
Expand Down Expand Up @@ -158,19 +255,13 @@ void LoadScenario() {
DoNotify();
break;
case "AutoSessionInNotifyReleaseStages":
Bugsnag.Configuration.ReleaseStage = "production";
Bugsnag.Configuration.NotifyReleaseStages = new [] { "production" };
break;
case "ManualSessionInNotifyReleaseStages":
Bugsnag.Configuration.ReleaseStage = "production";
Bugsnag.Configuration.NotifyReleaseStages = new [] { "production" };
Bugsnag.StartSession();
break;
case "AutoSessionNotInNotifyReleaseStages":
Bugsnag.Configuration.NotifyReleaseStages = new [] { "no-op" };
break;
case "ManualSessionNotInNotifyReleaseStages":
Bugsnag.Configuration.NotifyReleaseStages = new [] { "no-op" };
Bugsnag.StartSession();
break;
case "ManualSessionMixedEvents":
Expand All @@ -194,24 +285,18 @@ void LoadScenario() {
crashy_signal_runner(8);
break;
case "UncaughtExceptionWithoutAutoNotify":
Bugsnag.Configuration.AutoNotify = false;
DoUnhandledException(0);
break;
case "NotifyWithoutAutoNotify":
Bugsnag.Configuration.AutoNotify = false;
DoNotify();
break;
case "LoggedExceptionWithoutAutoNotify":
Bugsnag.Configuration.AutoNotify = false;
DoLogUnthrownAsUnhandled();
break;
case "NativeCrashWithoutAutoNotify":
Bugsnag.Configuration.AutoNotify = false;
crashy_signal_runner(8);
break;
case "NativeCrashReEnableAutoNotify":
Bugsnag.Configuration.AutoNotify = false;
Bugsnag.Configuration.AutoNotify = true;
crashy_signal_runner(8);
break;
case "AutoSessionNativeCrash":
Expand All @@ -220,6 +305,13 @@ void LoadScenario() {
crashy_signal_runner(8);
}).Start();
break;
case "AutoSession":
break;
case "(noop)":
break;
default:
throw new ArgumentException("Unable to run unexpected scenario: " + scenario);
break;
}
}

Expand Down Expand Up @@ -248,23 +340,18 @@ void RunNewSession() {
}

void UncaughtExceptionAsUnhandled() {
Bugsnag.Configuration.ReportUncaughtExceptionsAsHandled = false;
throw new ExecutionEngineException("Invariant state failure");
}

void DoLogWarning() {
Bugsnag.Configuration.NotifyLevel = LogType.Warning;
Debug.LogWarning("Something went terribly awry");
}

void DoLogError() {
Bugsnag.Configuration.NotifyLevel = LogType.Warning;
Debug.LogError("Bad bad things");
}

void DoLogWarningWithHandledConfig() {
Bugsnag.Configuration.ReportUncaughtExceptionsAsHandled = false;
Bugsnag.Configuration.NotifyLevel = LogType.Warning;
Debug.LogWarning("Something went terribly awry");
}

Expand Down Expand Up @@ -314,7 +401,6 @@ void DoNotify() {
}

void DoLogUnthrownAsUnhandled() {
Bugsnag.Configuration.ReportUncaughtExceptionsAsHandled = false;
Debug.LogException(new System.Exception("WAT"));
}

Expand All @@ -332,6 +418,35 @@ void MakeAssertionFailure(int counter) {
var items = new int[]{1, 2, 3};
Debug.Log("Item4 is: " + items[counter]);
}


/*** Determine runtime versions ***/

private static string FindScriptingBackend() {
#if ENABLE_MONO
return "Mono";
#elif ENABLE_IL2CPP
return "IL2CPP";
#else
return "Unknown";
#endif
}

private static string FindDotnetScriptingRuntime() {
#if NET_4_6
return ".NET 4.6 equivalent";
#else
return ".NET 3.5 equivalent";
#endif
}

private static string FindDotnetApiCompatibility() {
#if NET_2_0_SUBSET
return ".NET 2.0 Subset";
#else
return ".NET 2.0";
#endif
}
}

class OtherMetadata {
Expand Down
Loading

0 comments on commit 50de844

Please sign in to comment.