diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml
index 9b45e5f1..de4def33 100644
--- a/.buildkite/pipeline.full.yml
+++ b/.buildkite/pipeline.full.yml
@@ -21,14 +21,14 @@ steps:
upload:
- "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
artifact_paths: [Build/Plugin/*.zip]
- timeout_in_minutes: 30
+ timeout_in_minutes: 60
key: plugin_4_25
# UE 4.26
- label: 'Build Plugin - 4.26 Mac'
env:
UE_VERSION: "4.26"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
commands:
- rm -rf "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
- make package
@@ -37,14 +37,14 @@ steps:
upload:
- "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
artifact_paths: [Build/Plugin/*.zip]
- timeout_in_minutes: 30
+ timeout_in_minutes: 60
key: plugin_4_26
# UE 5.0
- label: 'Build Plugin - 5.0 Mac'
env:
UE_VERSION: "5.0"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
commands:
- rm -rf "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
- make package
@@ -53,19 +53,19 @@ steps:
upload:
- "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
artifact_paths: [Build/Plugin/*.zip]
- timeout_in_minutes: 30
+ timeout_in_minutes: 60
key: plugin_5_0
#
# Build Test Fixtures
#
- # UE 5.0EA
+ # UE 5.0
- name: ':android: Build E2E - 5.0 Android'
depends_on: plugin_5_0
env:
UE_VERSION: "5.0"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
plugins:
artifacts#v1.5.0:
download: Build/Plugin/Bugsnag-*-UE_5.0-macOS.zip
@@ -83,7 +83,7 @@ steps:
depends_on: plugin_5_0
env:
UE_VERSION: "5.0"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
plugins:
artifacts#v1.5.0:
download: Build/Plugin/Bugsnag-*-UE_5.0-macOS.zip
@@ -101,7 +101,7 @@ steps:
depends_on: plugin_5_0
env:
UE_VERSION: "5.0"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
plugins:
artifacts#v1.5.0:
download: Build/Plugin/Bugsnag-*-UE_5.0-macOS.zip
@@ -137,7 +137,7 @@ steps:
- "--device=ANDROID_11_0"
- "--farm=bs"
- "--order=random"
- concurrency: 9
+ concurrency: 24
concurrency_group: browserstack-app
concurrency_method: eager
retry:
@@ -164,7 +164,7 @@ steps:
- "--device=ANDROID_11_0"
- "--farm=bs"
- "--order=random"
- concurrency: 9
+ concurrency: 24
concurrency_group: browserstack-app
concurrency_method: eager
retry:
@@ -191,7 +191,7 @@ steps:
- "--device=IOS_14"
- "--farm=bs"
- "--order=random"
- concurrency: 9
+ concurrency: 24
concurrency_group: browserstack-app
concurrency_method: eager
retry:
diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml
index e5439f3e..c4f958b4 100644
--- a/.buildkite/pipeline.yml
+++ b/.buildkite/pipeline.yml
@@ -22,14 +22,14 @@ steps:
upload:
- "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
artifact_paths: [Build/Plugin/*.zip]
- timeout_in_minutes: 30
+ timeout_in_minutes: 60
key: plugin_4_23
# UE 4.27
- label: 'Build Plugin - 4.27 Mac'
env:
UE_VERSION: "4.27"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
commands:
- rm -rf "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
- make package
@@ -38,7 +38,7 @@ steps:
upload:
- "/Users/administrator/Library/Logs/Unreal Engine/LocalBuildLogs/*"
artifact_paths: [Build/Plugin/*.zip]
- timeout_in_minutes: 30
+ timeout_in_minutes: 60
key: plugin_4_27
- label: 'Build Plugin - 4.27 Win'
@@ -48,7 +48,7 @@ steps:
UE_VERSION: "4.27"
command: build.bat
artifact_paths: [Bugsnag-*.zip]
- timeout_in_minutes: 30
+ timeout_in_minutes: 60
#
# Build Test Fixtures
@@ -59,7 +59,7 @@ steps:
depends_on: plugin_4_27
env:
UE_VERSION: "4.27"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
plugins:
artifacts#v1.5.0:
download: Build/Plugin/Bugsnag-*-UE_4.27-macOS.zip
@@ -77,7 +77,7 @@ steps:
depends_on: plugin_4_27
env:
UE_VERSION: "4.27"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
plugins:
artifacts#v1.5.0:
download: Build/Plugin/Bugsnag-*-UE_4.27-macOS.zip
@@ -95,7 +95,7 @@ steps:
depends_on: plugin_4_27
env:
UE_VERSION: "4.27"
- DEVELOPER_DIR: "/Applications/Xcode13.app"
+ DEVELOPER_DIR: "/Applications/Xcode13.2.1.app"
plugins:
artifacts#v1.5.0:
download: Build/Plugin/Bugsnag-*-UE_4.27-macOS.zip
@@ -131,7 +131,7 @@ steps:
- "--device=ANDROID_11_0"
- "--farm=bs"
- "--order=random"
- concurrency: 9
+ concurrency: 24
concurrency_group: browserstack-app
concurrency_method: eager
retry:
@@ -158,7 +158,7 @@ steps:
- "--device=IOS_12"
- "--farm=bs"
- "--order=random"
- concurrency: 9
+ concurrency: 24
concurrency_group: browserstack-app
concurrency_method: eager
retry:
diff --git a/.cspell.json b/.cspell.json
index 380ebafe..ff548713 100644
--- a/.cspell.json
+++ b/.cspell.json
@@ -6,12 +6,20 @@
"BSGJSON",
"Bugsnag",
"Expojs",
+ "FORCENOINLINE",
"GRHI",
+ "Gameplay",
"JNICALL",
"JNIEXPORT",
+ "LOCTEXT",
+ "Landroid",
"Lcom",
"Ljava",
+ "Memzero",
+ "Millis",
+ "NSJSON",
"Reactnativejs",
+ "Timespan",
"UCLASS",
"UENUM",
"UFUNCTION",
@@ -20,6 +28,7 @@
"checkf",
"clazz",
"cronut",
+ "jailbroken",
"jboolean",
"jbyte",
"jclass",
@@ -30,6 +39,7 @@
"jobject",
"jsize",
"ooms",
+ "symbolicate",
"uproject",
],
"ignorePaths": [
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 7b560822..7b1f640a 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -10,4 +10,4 @@ jobs:
- name: clang-format
run: find Source Plugins/Bugsnag/Source/Bugsnag features/fixtures/generic/Source -name '*.h' -o -name '*.cpp' | xargs /usr/bin/clang-format-12 --dry-run --Werror
- name: cspell
- run: npm install -g cspell && cspell **/*.{cpp,h}
+ run: npm install -g cspell && cspell Plugins/Bugsnag/**/*.{cpp,h}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bcd7713f..8fac4556 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,12 @@
Changelog
=========
+## 1.5.0 (2022-07-06)
+
+* Adds the `Telemetry` configuration property.
+* Updates the bugsnag-android dependency from v5.22.1 to [v5.24.0](/~https://github.com/bugsnag/bugsnag-android/blob/master/CHANGELOG.md#5240-2022-06-30)
+* Updates the bugsnag-cocoa dependency from v6.16.8 to [v6.19.0](/~https://github.com/bugsnag/bugsnag-cocoa/blob/master/CHANGELOG.md#6190-2022-06-29)
+
## 1.4.0 (2022-05-11)
* Adds official support for Unreal Engine 5.0 🚀
diff --git a/Makefile b/Makefile
index 0b2ba1db..6c6a93a0 100644
--- a/Makefile
+++ b/Makefile
@@ -95,7 +95,7 @@ format: ## format all c/c++ source to match .clang-format
.PHONY: lint
lint: ## check the project for formatting or spelling issues
find Source Plugins/Bugsnag/Source/Bugsnag features/fixtures/generic/Source -name '*.h' -o -name '*.cpp' | xargs clang-format --dry-run --Werror
- cspell **/*.{cpp,h}
+ cspell Plugins/Bugsnag/**/*.{cpp,h}
#-------------------------------------------------------------------------------
# E2E test run
diff --git a/Plugins/Bugsnag/Bugsnag.uplugin b/Plugins/Bugsnag/Bugsnag.uplugin
index 02d1ce18..fe339a68 100644
--- a/Plugins/Bugsnag/Bugsnag.uplugin
+++ b/Plugins/Bugsnag/Bugsnag.uplugin
@@ -1,7 +1,7 @@
{
"FileVersion": 3,
- "Version": 8,
- "VersionName": "1.4.0",
+ "Version": 9,
+ "VersionName": "1.5.0",
"FriendlyName": "Bugsnag",
"Description": "Bugsnag is an error monitoring and application stability management solution.",
"Category": "Developer",
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Bugsnag_UPL.xml b/Plugins/Bugsnag/Source/Bugsnag/Bugsnag_UPL.xml
index de349266..604c04f0 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Bugsnag_UPL.xml
+++ b/Plugins/Bugsnag/Source/Bugsnag/Bugsnag_UPL.xml
@@ -73,8 +73,8 @@
- com.bugsnag,bugsnag-plugin-android-unreal,1.4.0
- com.bugsnag,bugsnag-android,5.22.1
+ com.bugsnag,bugsnag-plugin-android-unreal,1.5.0
+ com.bugsnag,bugsnag-android,5.24.0
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/AndroidPlatformConfiguration.cpp b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/AndroidPlatformConfiguration.cpp
index 5ff3581d..37720cf0 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/AndroidPlatformConfiguration.cpp
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/AndroidPlatformConfiguration.cpp
@@ -91,6 +91,11 @@ jobject FAndroidPlatformConfiguration::Parse(JNIEnv* Env,
jniCallWithObjects(Env, jConfig, Cache->ConfigSetMaxPersistedSessions, Config->GetMaxPersistedSessions());
jniCallWithObjects(Env, jConfig, Cache->ConfigSetMaxReportedThreads, Config->GetMaxReportedThreads());
jniCallWithBool(Env, jConfig, Cache->ConfigSetPersistUser, Config->GetPersistUser());
+
+ jobject jTelemetry = FAndroidPlatformJNI::ParseTelemetryTypeSet(Env, Cache, Config->GetTelemetry());
+ ReturnNullOnFail(jTelemetry);
+ jniCallWithObjects(Env, jConfig, Cache->ConfigSetTelemetry, jTelemetry);
+
if (Config->GetRedactedKeys().Num())
{
jniCallWithSet(Env, Cache, jConfig, Cache->ConfigSetRedactedKeys, Config->GetRedactedKeys());
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.cpp b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.cpp
index 32ddc594..17dd2ef7 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.cpp
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.cpp
@@ -81,6 +81,7 @@ bool FAndroidPlatformJNI::LoadReferenceCache(JNIEnv* env, JNIReferenceCache* cac
CacheExternalJavaClass(env, cache->SessionClass, "com.bugsnag.android.Session");
CacheExternalJavaClass(env, cache->SeverityClass, "com.bugsnag.android.Severity");
CacheExternalJavaClass(env, cache->StackframeClass, "com.bugsnag.android.Stackframe");
+ CacheExternalJavaClass(env, cache->TelemetryClass, "com.bugsnag.android.Telemetry");
CacheExternalJavaClass(env, cache->ThreadClass, "com.bugsnag.android.Thread");
CacheExternalJavaClass(env, cache->UserClass, "com.bugsnag.android.User");
CacheExternalJavaClass(env, cache->EndpointConfigurationClass, "com.bugsnag.android.EndpointConfiguration");
@@ -200,6 +201,7 @@ bool FAndroidPlatformJNI::LoadReferenceCache(JNIEnv* env, JNIReferenceCache* cac
CacheInstanceJavaMethod(env, cache->ConfigSetReleaseStage, cache->ConfigClass, "setReleaseStage", "(Ljava/lang/String;)V");
CacheInstanceJavaMethod(env, cache->ConfigSetSendLaunchCrashesSynchronously, cache->ConfigClass, "setSendLaunchCrashesSynchronously", "(Z)V");
CacheInstanceJavaMethod(env, cache->ConfigSetSendThreads, cache->ConfigClass, "setSendThreads", "(Lcom/bugsnag/android/ThreadSendPolicy;)V");
+ CacheInstanceJavaMethod(env, cache->ConfigSetTelemetry, cache->ConfigClass, "setTelemetry", "(Ljava/util/Set;)V");
CacheInstanceJavaMethod(env, cache->ConfigSetUser, cache->ConfigClass, "setUser", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
CacheInstanceJavaMethod(env, cache->ConfigSetVersionCode, cache->ConfigClass, "setVersionCode", "(Ljava/lang/Integer;)V");
@@ -365,6 +367,7 @@ bool FAndroidPlatformJNI::LoadReferenceCache(JNIEnv* env, JNIReferenceCache* cac
CacheStaticJavaField(env, cache->BreadcrumbTypeUser, cache->BreadcrumbTypeClass, "USER", "Lcom/bugsnag/android/BreadcrumbType;");
CacheStaticJavaField(env, cache->ErrorTypeAndroid, cache->ErrorTypeClass, "ANDROID", "Lcom/bugsnag/android/ErrorType;");
CacheStaticJavaField(env, cache->ErrorTypeC, cache->ErrorTypeClass, "C", "Lcom/bugsnag/android/ErrorType;");
+ CacheStaticJavaField(env, cache->TelemetryInternalErrors, cache->TelemetryClass, "INTERNAL_ERRORS", "Lcom/bugsnag/android/Telemetry;");
CacheStaticJavaField(env, cache->ThreadSendPolicyAlways, cache->ThreadSendPolicyClass, "ALWAYS", "Lcom/bugsnag/android/ThreadSendPolicy;");
CacheStaticJavaField(env, cache->ThreadSendPolicyUnhandledOnly, cache->ThreadSendPolicyClass, "UNHANDLED_ONLY", "Lcom/bugsnag/android/ThreadSendPolicy;");
CacheStaticJavaField(env, cache->ThreadSendPolicyNever, cache->ThreadSendPolicyClass, "NEVER", "Lcom/bugsnag/android/ThreadSendPolicy;");
@@ -489,17 +492,18 @@ jobject FAndroidPlatformJNI::ParseJsonObject(JNIEnv* Env, const JNIReferenceCach
* Adds a value to a set if enabled
*
* @param Env A JNI environment for the current thread
+ * @param Cache the JNI reference cache
* @param ShouldAdd true if the value should be added
* @param TypeClass the enum class
* @param FieldName the name of the field to add to the set
*
* @return true if operation completed without error
*/
-static bool addTypeToSet(JNIEnv* Env, jobject jSet, bool ShouldAdd, const JNIReferenceCache* Cache, jfieldID FieldName)
+static bool addTypeToSet(JNIEnv* Env, const JNIReferenceCache* Cache, jobject jSet, bool ShouldAdd, jclass TypeClass, jfieldID FieldName)
{
if (ShouldAdd)
{
- jobject jType = (*Env).GetStaticObjectField(Cache->BreadcrumbTypeClass, FieldName);
+ jobject jType = (*Env).GetStaticObjectField(TypeClass, FieldName);
if (FAndroidPlatformJNI::CheckAndClearException(Env))
{
return false;
@@ -551,13 +555,29 @@ jobject FAndroidPlatformJNI::ParseBreadcrumbTypeSet(JNIEnv* Env, const JNIRefere
{
return nullptr;
}
- if (addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Error), Cache, Cache->BreadcrumbTypeError) &&
- addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Log), Cache, Cache->BreadcrumbTypeLog) &&
- addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Navigation), Cache, Cache->BreadcrumbTypeNavigation) &&
- addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Process), Cache, Cache->BreadcrumbTypeProcess) &&
- addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Request), Cache, Cache->BreadcrumbTypeRequest) &&
- addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::State), Cache, Cache->BreadcrumbTypeState) &&
- addTypeToSet(Env, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::User), Cache, Cache->BreadcrumbTypeUser))
+ jclass TypeClass = Cache->BreadcrumbTypeClass;
+ if (addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Error), TypeClass, Cache->BreadcrumbTypeError) &&
+ addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Log), TypeClass, Cache->BreadcrumbTypeLog) &&
+ addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Navigation), TypeClass, Cache->BreadcrumbTypeNavigation) &&
+ addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Process), TypeClass, Cache->BreadcrumbTypeProcess) &&
+ addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::Request), TypeClass, Cache->BreadcrumbTypeRequest) &&
+ addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::State), TypeClass, Cache->BreadcrumbTypeState) &&
+ addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagEnabledBreadcrumbTypes::User), TypeClass, Cache->BreadcrumbTypeUser))
+ {
+ return jSet;
+ }
+ return nullptr;
+}
+
+jobject FAndroidPlatformJNI::ParseTelemetryTypeSet(JNIEnv* Env, const JNIReferenceCache* Cache, const EBugsnagTelemetryTypes Value)
+{
+ jobject jSet = Env->NewObject(Cache->HashSetClass, Cache->HashSetConstructor);
+ if (FAndroidPlatformJNI::CheckAndClearException(Env))
+ {
+ return nullptr;
+ }
+ jclass TypeClass = Cache->TelemetryClass;
+ if (addTypeToSet(Env, Cache, jSet, EnumHasAllFlags(Value, EBugsnagTelemetryTypes::InternalErrors), TypeClass, Cache->TelemetryInternalErrors))
{
return jSet;
}
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.h b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.h
index 10200ea5..d909dfec 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.h
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/JNIUtilities.h
@@ -7,6 +7,7 @@
#include "BugsnagBreadcrumb.h"
#include "BugsnagEvent.h"
#include "BugsnagSettings.h"
+#include "BugsnagTelemetryTypes.h"
typedef struct
{
@@ -31,6 +32,7 @@ typedef struct
jclass MetadataParserClass;
jclass MetadataSerializerClass;
jclass NotifierClass;
+ jclass TelemetryClass;
jclass ThreadClass;
jclass ThreadSendPolicyClass;
jclass ThreadTypeClass;
@@ -141,6 +143,7 @@ typedef struct
jmethodID ConfigSetReleaseStage;
jmethodID ConfigSetSendLaunchCrashesSynchronously;
jmethodID ConfigSetSendThreads;
+ jmethodID ConfigSetTelemetry;
jmethodID ConfigSetUser;
jmethodID ConfigSetVersionCode;
jmethodID ContextGetApplication;
@@ -283,6 +286,7 @@ typedef struct
jfieldID BreadcrumbTypeUser;
jfieldID ErrorTypeAndroid;
jfieldID ErrorTypeC;
+ jfieldID TelemetryInternalErrors;
jfieldID ThreadSendPolicyAlways;
jfieldID ThreadSendPolicyUnhandledOnly;
jfieldID ThreadSendPolicyNever;
@@ -368,6 +372,8 @@ class FAndroidPlatformJNI
*/
static jobject ParseBreadcrumbTypeSet(JNIEnv* Env, const JNIReferenceCache* Cache, const EBugsnagEnabledBreadcrumbTypes Value);
+ static jobject ParseTelemetryTypeSet(JNIEnv* Env, const JNIReferenceCache* Cache, const EBugsnagTelemetryTypes Value);
+
/**
* Convert a value into a Java Severity
*
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/Specs/AndroidPlatformConfiguration.spec.cpp b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/Specs/AndroidPlatformConfiguration.spec.cpp
new file mode 100644
index 00000000..25ea2ec8
--- /dev/null
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/Specs/AndroidPlatformConfiguration.spec.cpp
@@ -0,0 +1,65 @@
+// Copyright 2022 Bugsnag. All Rights Reserved.
+
+#include "Android/AndroidJavaEnv.h"
+#include "AutomationTest.h"
+
+#include "../AndroidPlatformConfiguration.h"
+
+//
+// To run the unit tests on Android:
+// * Build & run the example app on a connected Android device.
+// * Open Unreal Editor's "Session Frontend" and find the running game in "My Sessions"
+// * Click the "Automation" tab, select the tests to run, and click "Start Tests"!
+//
+BEGIN_DEFINE_SPEC(FAndroidPlatformConfigurationSpec, "Bugsnag.FAndroidPlatformConfigurationSpec",
+ EAutomationTestFlags::ProductFilter | EAutomationTestFlags::ApplicationContextMask)
+END_DEFINE_SPEC(FAndroidPlatformConfigurationSpec)
+void FAndroidPlatformConfigurationSpec::Define()
+{
+ static const FString ApiKey = TEXT("0192837465afbecd0192837465afbecd");
+
+ static JNIReferenceCache JNICache;
+ if (!JNICache.loaded)
+ {
+ JNICache.loaded = FAndroidPlatformJNI::LoadReferenceCache(AndroidJavaEnv::GetJavaEnv(), &JNICache);
+ }
+
+ Describe("Telemetry", [this]()
+ {
+ It("Should contain all types by default", [this]()
+ {
+ JNIEnv* Env = AndroidJavaEnv::GetJavaEnv();
+ jmethodID SizeMethod = Env->GetMethodID(Env->FindClass("java/util/Set"), "size", "()I");
+ jmethodID GetTelemetryMethod = Env->GetMethodID(JNICache.ConfigClass, "getTelemetry", "()Ljava/util/Set;");
+ TEST_FALSE(Env->ExceptionCheck());
+
+ TSharedRef Configuration = MakeShared(ApiKey);
+
+ jobject AndroidConfig = FAndroidPlatformConfiguration::Parse(Env, &JNICache, Configuration);
+ jobject AndroidTelemetry = Env->CallObjectMethod(AndroidConfig, GetTelemetryMethod);
+ TEST_TRUE(AndroidTelemetry != nullptr);
+ TEST_FALSE(Env->ExceptionCheck());
+ int Size = Env->CallIntMethod(AndroidTelemetry, SizeMethod);
+ TEST_FALSE(Env->ExceptionCheck());
+ TestEqual(TEXT("Telemetry Set should contain [INTERNAL_ERRORS]"), Size, 1);
+ });
+
+ It("Should be empty after setting EBugsnagTelemetryTypes::None", [this]()
+ {
+ JNIEnv* Env = AndroidJavaEnv::GetJavaEnv();
+ jmethodID SizeMethod = Env->GetMethodID(Env->FindClass("java/util/Set"), "size", "()I");
+ jmethodID GetTelemetryMethod = Env->GetMethodID(JNICache.ConfigClass, "getTelemetry", "()Ljava/util/Set;");
+
+ TSharedRef Configuration = MakeShared(ApiKey);
+ Configuration->SetTelemetry(EBugsnagTelemetryTypes::None);
+
+ jobject AndroidConfig = FAndroidPlatformConfiguration::Parse(Env, &JNICache, Configuration);
+ jobject AndroidTelemetry = Env->CallObjectMethod(AndroidConfig, GetTelemetryMethod);
+ TEST_TRUE(AndroidTelemetry != nullptr);
+ TEST_FALSE(Env->ExceptionCheck());
+ int Size = Env->CallIntMethod(AndroidTelemetry, SizeMethod);
+ TEST_FALSE(Env->ExceptionCheck());
+ TestEqual(TEXT("Telemetry Set should be empty"), Size, 0);
+ });
+ });
+}
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Android/Specs/AutomationTest.h b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/Specs/AutomationTest.h
new file mode 100644
index 00000000..d851d5cc
--- /dev/null
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Android/Specs/AutomationTest.h
@@ -0,0 +1,12 @@
+// Copyright 2022 Bugsnag. All Rights Reserved.
+
+#include "Misc/AutomationTest.h"
+
+#define TEST_TRUE(expression) \
+ TestTrue(TEXT(#expression), expression)
+
+#define TEST_FALSE(expression) \
+ TestFalse(TEXT(#expression), expression)
+
+#define TEST_EQUAL(expression, expected) \
+ TestEqual(TEXT(#expression), expression, expected)
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/AppleBugsnagUtils.h b/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/AppleBugsnagUtils.h
index 646ed275..70a640ad 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/AppleBugsnagUtils.h
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/AppleBugsnagUtils.h
@@ -8,8 +8,6 @@
#include "Serialization/LargeMemoryReader.h"
#include "Serialization/LargeMemoryWriter.h"
-#import
-
// String conversion
static inline FString FStringFromNSString(NSString* _Nullable String)
@@ -61,7 +59,11 @@ static inline NSNumber* NSNumberFromOptional(const TOptional& Value)
static inline TSharedPtr FJsonObjectFromNSDictionary(NSDictionary* Dictionary, NSError** Error = nil)
{
- NSData* Data = [BSGJSONSerialization dataWithJSONObject:Dictionary options:0 error:Error];
+ if (!Dictionary || ![NSJSONSerialization isValidJSONObject:Dictionary])
+ {
+ return nullptr;
+ }
+ NSData* Data = [NSJSONSerialization dataWithJSONObject:Dictionary options:0 error:Error];
if (Data)
{
TSharedPtr JsonObject;
@@ -86,7 +88,7 @@ static inline NSDictionary* _Nullable NSDictionaryFromFJsonObject(const TSharedP
{
JsonWriter->Close();
NSData* Data = [NSData dataWithBytesNoCopy:Archive.GetData() length:Archive.TotalSize() freeWhenDone:NO];
- return [BSGJSONSerialization JSONObjectWithData:Data options:0 error:Error];
+ return [NSJSONSerialization JSONObjectWithData:Data options:0 error:Error];
}
return nil;
}
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/ApplePlatformConfiguration.cpp b/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/ApplePlatformConfiguration.cpp
index 62091dae..815cdda9 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/ApplePlatformConfiguration.cpp
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/ApplePlatformConfiguration.cpp
@@ -12,10 +12,14 @@
#import
#import
-#import
#import
#import
+static BSGTelemetryOptions GetTelemetryTypes(EBugsnagTelemetryTypes Value)
+{
+ return (EnumHasAllFlags(Value, EBugsnagTelemetryTypes::InternalErrors) ? BSGTelemetryInternalErrors : 0);
+}
+
static BSGThreadSendPolicy GetThreadSendPolicy(EBugsnagSendThreadsPolicy Policy)
{
switch (Policy)
@@ -111,6 +115,8 @@ BugsnagConfiguration* FApplePlatformConfiguration::Configuration(const TSharedRe
CocoaConfig.persistUser = Configuration->GetPersistUser();
+ CocoaConfig.telemetry = GetTelemetryTypes(Configuration->GetTelemetry());
+
if (Configuration->GetReleaseStage().IsSet())
{
CocoaConfig.releaseStage = NSStringFromFString(Configuration->GetReleaseStage().GetValue());
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/Specs/ApplePlatformConfiguration.spec.cpp b/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/Specs/ApplePlatformConfiguration.spec.cpp
index 83a62776..05e5b29b 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/Specs/ApplePlatformConfiguration.spec.cpp
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Apple/Specs/ApplePlatformConfiguration.spec.cpp
@@ -46,7 +46,6 @@ void FApplePlatformConfigurationSpec::Define()
TEST_TRUE([CocoaConfig.appType isEqual:DefaultConfig.appType]);
TEST_TRUE([CocoaConfig.bundleVersion isEqual:DefaultConfig.bundleVersion]);
TEST_TRUE([CocoaConfig.redactedKeys isEqual:DefaultConfig.redactedKeys]);
- TEST_TRUE([CocoaConfig.releaseStage isEqual:DefaultConfig.releaseStage]);
});
It("ApiKey", [this]()
@@ -185,6 +184,16 @@ void FApplePlatformConfigurationSpec::Define()
TEST_EQUAL(CocoaConfig.persistUser, NO);
});
+ It("Telemetry", [this]()
+ {
+ TSharedRef Configuration = MakeShared(ApiKey);
+ BugsnagConfiguration* CocoaConfig = FApplePlatformConfiguration::Configuration(Configuration);
+ TEST_TRUE(CocoaConfig.telemetry == BSGTelemetryInternalErrors);
+ Configuration->SetTelemetry(EBugsnagTelemetryTypes::None);
+ CocoaConfig = FApplePlatformConfiguration::Configuration(Configuration);
+ TEST_TRUE(CocoaConfig.telemetry == 0);
+ });
+
It("ReleaseStage", [this]()
{
TSharedRef Configuration = MakeShared(ApiKey);
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/BugsnagConfiguration.cpp b/Plugins/Bugsnag/Source/Bugsnag/Private/BugsnagConfiguration.cpp
index ac520c8a..0ba9ee93 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/BugsnagConfiguration.cpp
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/BugsnagConfiguration.cpp
@@ -33,6 +33,11 @@ static EBugsnagEnabledBreadcrumbTypes Convert(FBugsnagEnabledBreadcrumbTypes Val
(Value.bUser ? EBugsnagEnabledBreadcrumbTypes::User : EBugsnagEnabledBreadcrumbTypes::None);
}
+static EBugsnagTelemetryTypes Convert(const FBugsnagTelemetryTypes& Value)
+{
+ return (Value.bInternalErrors ? EBugsnagTelemetryTypes::InternalErrors : EBugsnagTelemetryTypes::None);
+}
+
uint64 const FBugsnagConfiguration::AppHangThresholdFatalOnly = INT_MAX;
FBugsnagConfiguration::FBugsnagConfiguration(const FString& ApiKey)
@@ -56,6 +61,7 @@ FBugsnagConfiguration::FBugsnagConfiguration(const UBugsnagSettings& Settings)
, MaxPersistedEvents(Settings.MaxPersistedEvents)
, MaxPersistedSessions(Settings.MaxPersistedSessions)
, bPersistUser(Settings.bPersistUser)
+ , Telemetry(Convert(Settings.Telemetry))
, ReleaseStage(UnsetIfEmpty(Settings.ReleaseStage))
, AppType(UnsetIfEmpty(Settings.AppType))
, AppVersion(UnsetIfEmpty(Settings.AppVersion))
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Private/Version.h b/Plugins/Bugsnag/Source/Bugsnag/Private/Version.h
index 4ea30b1c..6dde5ae2 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Private/Version.h
+++ b/Plugins/Bugsnag/Source/Bugsnag/Private/Version.h
@@ -4,4 +4,4 @@
#define BUGSNAG_UNREAL_NAME "Unreal Bugsnag Notifier"
#define BUGSNAG_UNREAL_URL "/~https://github.com/bugsnag/bugsnag-unreal"
-#define BUGSNAG_UNREAL_VERSION_STRING "1.4.0"
+#define BUGSNAG_UNREAL_VERSION_STRING "1.5.0"
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagConfiguration.h b/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagConfiguration.h
index 0f7a24ab..75545c6b 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagConfiguration.h
+++ b/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagConfiguration.h
@@ -9,6 +9,7 @@
#include "BugsnagMetadataStore.h"
#include "BugsnagSession.h"
#include "BugsnagSettings.h"
+#include "BugsnagTelemetryTypes.h"
#include "BugsnagUser.h"
#include "Dom/JsonObject.h"
@@ -298,6 +299,18 @@ class BUGSNAG_API FBugsnagConfiguration final : public IBugsnagFeatureFlagStore,
*/
void SetPersistUser(bool Value) { bPersistUser = Value; }
+ /**
+ * The types of telemetry that may be sent to Bugsnag for product improvement purposes.
+ *
+ * By default all types of telemetry are enabled.
+ */
+ EBugsnagTelemetryTypes GetTelemetry() const { return Telemetry; }
+
+ /**
+ * @param Value The types of telemetry that may be sent to Bugsnag for product improvement purposes.
+ */
+ void SetTelemetry(EBugsnagTelemetryTypes Value) { Telemetry = Value; }
+
/**
* The release stage of the application, such as `"production"`, `"development"`, `"beta"` etc.
*/
@@ -573,6 +586,7 @@ class BUGSNAG_API FBugsnagConfiguration final : public IBugsnagFeatureFlagStore,
uint32 MaxPersistedSessions = 128;
uint32 MaxReportedThreads = 200;
bool bPersistUser = true;
+ EBugsnagTelemetryTypes Telemetry = EBugsnagTelemetryTypes::All;
FBugsnagUser User;
TOptional ReleaseStage;
TOptional AppType;
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagSettings.h b/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagSettings.h
index 14fcba1e..685a7d2f 100644
--- a/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagSettings.h
+++ b/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagSettings.h
@@ -68,6 +68,19 @@ struct FBugsnagErrorTypes
bool bThermalKills = true;
};
+/**
+ * Types of telemetry that may be sent to Bugsnag for product improvement purposes.
+ */
+USTRUCT()
+struct FBugsnagTelemetryTypes
+{
+ GENERATED_BODY()
+
+ // Errors within the Bugsnag SDK.
+ UPROPERTY(GlobalConfig, EditAnywhere, Category = "Advanced Configuration")
+ bool bInternalErrors = true;
+};
+
/**
* Controls whether Bugsnag events should include the state of all threads at the time of an error.
*/
@@ -133,7 +146,7 @@ class BUGSNAG_API UBugsnagSettings : public UObject
UPROPERTY(GlobalConfig, EditAnywhere, Category = "Advanced Configuration", DisplayName = "Auto Upload Symbol Files (Android only)")
bool bAutoUploadSymbolFiles = true;
- // A general summary of what was occuring in the application.
+ // A general summary of what was occurring in the application.
UPROPERTY(GlobalConfig, EditAnywhere, Category = "Advanced Configuration")
FString Context;
@@ -186,6 +199,10 @@ class BUGSNAG_API UBugsnagSettings : public UObject
UPROPERTY(GlobalConfig, EditAnywhere, Category = "Advanced Configuration")
bool bPersistUser = true;
+ // The types of telemetry that may be sent to Bugsnag for product improvement purposes.
+ UPROPERTY(GlobalConfig, EditAnywhere, Category = "Advanced Configuration")
+ FBugsnagTelemetryTypes Telemetry;
+
///////////////////////////////////////////////////////////////////////////
//
// App Information
diff --git a/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagTelemetryTypes.h b/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagTelemetryTypes.h
new file mode 100644
index 00000000..5243e090
--- /dev/null
+++ b/Plugins/Bugsnag/Source/Bugsnag/Public/BugsnagTelemetryTypes.h
@@ -0,0 +1,16 @@
+// Copyright 2022 Bugsnag. All Rights Reserved.
+
+#pragma once
+
+#include "CoreMinimal.h"
+
+/**
+ * Types of telemetry that may be sent to Bugsnag for product improvement purposes.
+ */
+enum class EBugsnagTelemetryTypes : uint8
+{
+ None = 0,
+ InternalErrors = 1 << 0,
+ All = InternalErrors
+};
+ENUM_CLASS_FLAGS(EBugsnagTelemetryTypes)
diff --git a/VERSION b/VERSION
index 88c5fb89..bc80560f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.4.0
+1.5.0
diff --git a/deps/bugsnag-cocoa b/deps/bugsnag-cocoa
index 450d2172..5aeb6387 160000
--- a/deps/bugsnag-cocoa
+++ b/deps/bugsnag-cocoa
@@ -1 +1 @@
-Subproject commit 450d21727f99727d42d5d484b5c07df16c119b16
+Subproject commit 5aeb63871cc68d6a2533fef203859de0d021dca9
diff --git a/deps/bugsnag-plugin-android-unreal/build.gradle b/deps/bugsnag-plugin-android-unreal/build.gradle
index d7177ace..1e97cf75 100644
--- a/deps/bugsnag-plugin-android-unreal/build.gradle
+++ b/deps/bugsnag-plugin-android-unreal/build.gradle
@@ -28,7 +28,7 @@ android {
}
dependencies {
- api "com.bugsnag:bugsnag-android-core:5.22.1"
+ api "com.bugsnag:bugsnag-android-core:5.24.0"
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'junit:junit:4.12'
@@ -40,7 +40,7 @@ task generatePom {
pom {
project {
groupId 'com.bugsnag'
- version '1.4.0'
+ version '1.5.0'
packaging 'aar'
}
}.writeTo("$buildDir/outputs/aar/bugsnag-plugin-android-unreal-release.pom")
diff --git a/deps/bugsnag-plugin-android-unreal/src/main/java/com/bugsnag/android/unreal/UnrealPlugin.java b/deps/bugsnag-plugin-android-unreal/src/main/java/com/bugsnag/android/unreal/UnrealPlugin.java
index 0f19bc34..ddd3cd13 100644
--- a/deps/bugsnag-plugin-android-unreal/src/main/java/com/bugsnag/android/unreal/UnrealPlugin.java
+++ b/deps/bugsnag-plugin-android-unreal/src/main/java/com/bugsnag/android/unreal/UnrealPlugin.java
@@ -1,26 +1,24 @@
package com.bugsnag.android.unreal;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import com.bugsnag.android.Bugsnag;
+import com.bugsnag.android.Breadcrumb;
import com.bugsnag.android.Client;
import com.bugsnag.android.Configuration;
-import com.bugsnag.android.Breadcrumb;
import com.bugsnag.android.Error;
import com.bugsnag.android.ErrorType;
import com.bugsnag.android.Event;
import com.bugsnag.android.OnBreadcrumbCallback;
import com.bugsnag.android.OnErrorCallback;
-import com.bugsnag.android.OnSessionCallback;
import com.bugsnag.android.OnSendCallback;
+import com.bugsnag.android.OnSessionCallback;
import com.bugsnag.android.Plugin;
import com.bugsnag.android.Session;
-import com.bugsnag.android.Severity;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class UnrealPlugin implements Plugin {
static final String DEFAULT_HANDLED_REASON = "handledError";
@@ -37,16 +35,6 @@ public boolean onBreadcrumb(Breadcrumb crumb) {
OnSendCallback onSendRunner = new OnSendCallback() {
@Override
public boolean onSend(Event event) {
- // discard if the error class is in (the currently configured) discardClasses
- if (discardClasses != null && discardClasses.size() > 0) {
- for (Error err : event.getErrors()) {
- String errorClass = err.getErrorClass();
- if (errorClass != null && discardClasses.contains(errorClass)) {
- return false;
- }
- }
- }
-
// if for some reason the plugin is unloaded when a callback is invoked, skip processing
return loaded ? runEventCallbacks(event) : true;
}
@@ -102,7 +90,7 @@ public boolean onSession(Session session) {
*/
static native void setSeverityReason(Event event, String reasonType);
- private Set discardClasses;
+ static private Set discardClasses;
public UnrealPlugin(Configuration config) {
config.addOnBreadcrumb(onBreadcrumbRunner);
@@ -130,6 +118,10 @@ static void notify(String name, String message, StackTraceElement[] stacktrace,
if (client == null || name == null) {
return;
}
+ if (discardClasses != null && discardClasses.contains(name)) {
+ return;
+ }
+
Throwable exc = new RuntimeException();
exc.setStackTrace(stacktrace);