Skip to content

Commit

Permalink
Merge pull request #14 from newrelic/NR-259738_background_reporting
Browse files Browse the repository at this point in the history
feat: Log Forwarding and ANR reporting through android sdk.
  • Loading branch information
ndesai-newrelic authored Aug 1, 2024
2 parents 82f8c14 + 95920f5 commit 9294351
Show file tree
Hide file tree
Showing 121 changed files with 8,303 additions and 557 deletions.
25 changes: 21 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
# Changelog

## 1.2.0
## 1.3.0

## New Features

1. Application Exit Information
- Added ApplicationExitInfo to data reporting
- Enabled by default

2. Log Forwarding to New Relic
- Implement static API for sending logs to New Relic
- Can be enabled/disabled in your mobile application's entity settings page

## Improvements

- Native Android agent updated to version 7.5.0
- Native iOS agent updated to version 7.5.0

## 1.2

* Improvements
The native iOS Agent has been updated to version 7.4.12, bringing performance enhancements and bug fixes.
The native iOS Agent has been updated to version 7.4.11, bringing performance enhancements and bug fixes.

* New Features
A new backgroundReportingEnabled feature flag has been introduced to enable background reporting functionality. A new newEventSystemEnabled feature flag has been added to enable the new event system.


## 1.1.0
## 1.1

* Updated the native Android agent to version 7.3.1.
* Updated the native iOS agent to version 7.4.11.
Expand All @@ -22,4 +39,4 @@ A new backgroundReportingEnabled feature flag has been introduced to enable back
🎉🎊 Presenting the new New Relic Plugin for Unreal Engine:

Allows instrumenting Unreal Engine apps and getting valuable insights in the New Relic UI.
Features: error/crash reporting, info points, and many more. Thoroughly maintained and ready for production.
Features: error/crash reporting, info points, and many more. Thoroughly maintained and ready for production.
38 changes: 35 additions & 3 deletions Plugins/NewRelic/Source/NewRelic/NewRelic_UPL_Android.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<buildGradleAdditions>
<insert>
dependencies {
implementation 'com.newrelic.agent.android:android-agent:7.3.1'
implementation 'com.newrelic.agent.android:android-agent:7.5.0'
}
apply plugin: 'newrelic'
</insert>
Expand Down Expand Up @@ -69,7 +69,7 @@
NewRelic.enableFeature(FeatureFlag.NativeReporting);
NewRelic.withApplicationToken(applicationToken)
.withLogLevel(AgentLog.DEBUG)
.withApplicationFramework(ApplicationFramework.Unreal, "1.0")
.withApplicationFramework(ApplicationFramework.Unreal, "1.3")
.start(this);
}

Expand Down Expand Up @@ -144,6 +144,30 @@
return NewRelic.currentSessionId();
}

public void AndroidThunk_LogInfo(String message) {
NewRelic.logInfo(message);
}

public void AndroidThunk_LogError(String message) {
NewRelic.logError(message);
}

public void AndroidThunk_LogVerbose(String message) {
NewRelic.logVerbose(message);
}

public void AndroidThunk_LogWarning(String message) {
NewRelic.logVerbose(message);
}

public void AndroidThunk_LogDebug(String message) {
NewRelic.logDebug(message);
}

public void AndroidThunk_LogAttributes(Map&lt;String, Object&gt; attributes) {
NewRelic.logAttributes(attributes);
}

public void AndroidThunk_DisableFeatures(Map&lt;String, Boolean&gt; features) {

if (!Boolean.TRUE.equals(features.getOrDefault("crashReportingEnabled", true))) {
Expand All @@ -161,7 +185,15 @@

if (!Boolean.TRUE.equals(features.getOrDefault("offlineMonitoringEnabled", true))) {
NewRelic.disableFeature(FeatureFlag.OfflineStorage);
}
} else {
NewRelic.enableFeature(FeatureFlag.OfflineStorage);
}

if (!Boolean.TRUE.equals(features.getOrDefault("backgroundReportingEnabled", true))) {
NewRelic.disableFeature(FeatureFlag.BackgroundReporting);
} else {
NewRelic.enableFeature(FeatureFlag.BackgroundReporting);
}
}

</insert>
Expand Down
1 change: 1 addition & 0 deletions Plugins/NewRelic/Source/NewRelic/Private/LogLevel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "AgentLogLevel.h"
160 changes: 159 additions & 1 deletion Plugins/NewRelic/Source/NewRelic/Private/NewRelicBPLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ const UNewRelicSDKSettings *defaultSettings = GetDefault<UNewRelicSDKSettings>()
env->CallObjectMethod(map, putMethod, env->NewStringUTF("offlineMonitoringEnabled"), false);
}

if(!defaultSettings->backgroundReportingEnabled) {
env->CallObjectMethod(map, putMethod, env->NewStringUTF("backgroundReportingEnabled"), false);
}

jmethodID disableFeatures = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_DisableFeatures",
Expand Down Expand Up @@ -108,7 +112,9 @@ const UNewRelicSDKSettings *defaultSettings = GetDefault<UNewRelicSDKSettings>()
[NewRelic disableFeatures:NRFeatureFlag_NewEventSystem];
}
[NewRelic setPlatform:(NRMAApplicationPlatform)NRMAPlatform_Unreal];
[NewRelic startWithApplicationToken: token];
SEL selector = NSSelectorFromString(@"setPlatformVersion:");
[NewRelic performSelector:selector withObject:@"1.3.0"];
[NewRelic startWithApplicationToken: token];
});
#endif
}
Expand Down Expand Up @@ -536,6 +542,158 @@ void UNewRelicBPLibrary::recordError(FString errorMessage,TMap <FString, FString
#endif
}

void UNewRelicBPLibrary::logInfo(FString message)
{
#if PLATFORM_ANDROID
JNIEnv* env = FAndroidApplication::GetJavaEnv();
jmethodID logInfo = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_LogInfo",
"(Ljava/lang/String;)V", false);
jstring jMessage = env->NewStringUTF(TCHAR_TO_UTF8(*message));
FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, logInfo, jMessage);
return;
#elif PLATFORM_IOS
dispatch_async(dispatch_get_main_queue(), ^ {
[NewRelic logInfo:message.GetNSString()];
});
#else
return;
#endif

}

void UNewRelicBPLibrary::logVerbose(FString message)
{
#if PLATFORM_ANDROID
JNIEnv* env = FAndroidApplication::GetJavaEnv();
jmethodID logVerbose = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_LogVerbose",
"(Ljava/lang/String;)V", false);
jstring jMessage = env->NewStringUTF(TCHAR_TO_UTF8(*message));
FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, logVerbose, jMessage);
return;
#elif PLATFORM_IOS
dispatch_async(dispatch_get_main_queue(), ^ {
[NewRelic logVerbose:message.GetNSString()];
});
#else
return;
#endif
}

void UNewRelicBPLibrary::logError(FString message)
{
#if PLATFORM_ANDROID
JNIEnv* env = FAndroidApplication::GetJavaEnv();
jmethodID logError = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_LogError",
"(Ljava/lang/String;)V", false);
jstring jMessage = env->NewStringUTF(TCHAR_TO_UTF8(*message));
FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, logError, jMessage);
return;
#elif PLATFORM_IOS
dispatch_async(dispatch_get_main_queue(), ^ {
[NewRelic logError:message.GetNSString()];
});
#else
return;
#endif
}

void UNewRelicBPLibrary::logWarning(FString message)
{
#if PLATFORM_ANDROID
JNIEnv* env = FAndroidApplication::GetJavaEnv();
jmethodID logWarning = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_LogWarning",
"(Ljava/lang/String;)V", false);
jstring jMessage = env->NewStringUTF(TCHAR_TO_UTF8(*message));
FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, logWarning, jMessage);
return;
#elif PLATFORM_IOS
dispatch_async(dispatch_get_main_queue(), ^ {
[NewRelic logWarning:message.GetNSString()];
});
#else
return;
#endif
}

void UNewRelicBPLibrary::logDebug(FString message)
{
#if PLATFORM_ANDROID
JNIEnv* env = FAndroidApplication::GetJavaEnv();
jmethodID logDebug = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_LogDebug",
"(Ljava/lang/String;)V", false);
jstring jMessage = env->NewStringUTF(TCHAR_TO_UTF8(*message));
FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, logDebug, jMessage);
return;
#elif PLATFORM_IOS
dispatch_async(dispatch_get_main_queue(), ^ {
[NewRelic logDebug:message.GetNSString()];
});
#else
return;
#endif
}

void UNewRelicBPLibrary::log(AgentLogLevel level,FString message)
{

if (level == AgentLogLevel::INFO) {
logInfo(message);
} else if (level == AgentLogLevel::VERBOSE) {
logVerbose(message);
} else if (level == AgentLogLevel::ERROR) {
logError(message);
} else if (level == AgentLogLevel::WARNING) {
logWarning(message);
} else if (level == AgentLogLevel::DEBUG) {
logDebug(message);
} else
{
logError(message);
}
}

void UNewRelicBPLibrary::logAttributes(TMap <FString, FString> attributes)
{
#if PLATFORM_ANDROID
JNIEnv* env = FAndroidApplication::GetJavaEnv();
jmethodID logAttributes = FJavaWrapper::FindMethod(env,
FJavaWrapper::GameActivityClassID,
"AndroidThunk_LogAttributes",
"(Ljava/util/Map;)V", false);
jclass mapClass = env->FindClass("java/util/HashMap");
jmethodID mapConstructor = env->GetMethodID(mapClass, "<init>", "()V");
jobject map = env->NewObject(mapClass, mapConstructor);
jmethodID putMethod = env->GetMethodID(mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
for (const TPair<FString, FString>& pair : attributes) {
env->CallObjectMethod(map, putMethod, env->NewStringUTF(TCHAR_TO_UTF8(*pair.Key)), env->NewStringUTF(TCHAR_TO_UTF8(*pair.Value)));
}
FJavaWrapper::CallVoidMethod(env, FJavaWrapper::GameActivityThis, logAttributes, map);
return;
#elif PLATFORM_IOS
dispatch_async(dispatch_get_main_queue(), ^ {

NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
for (const TPair<FString, FString>& pair : attributes) {
[dictionary setValue:pair.Value.GetNSString() forKey:pair.Key.GetNSString()];
}

[NewRelic logAttributes:dictionary];

});
#else
return;
#endif
}



Expand Down
13 changes: 13 additions & 0 deletions Plugins/NewRelic/Source/NewRelic/Public/AgentLogLevel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include "CoreMinimal.h"
#include "AgentLogLevel.generated.h"

UENUM(BlueprintType)
enum class AgentLogLevel : uint8 {
INFO UMETA(DisplayName="Info"),
ERROR UMETA(DisplayName="Error"),
VERBOSE UMETA(DisplayName="Verbose"),
WARNING UMETA(DisplayName="Warning"),
DEBUG UMETA(DisplayName="Debug")
};
24 changes: 24 additions & 0 deletions Plugins/NewRelic/Source/NewRelic/Public/NewRelicBPLibrary.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#pragma once

#include "AgentLogLevel.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "NewRelicBPLibrary.generated.h"

Expand All @@ -26,6 +27,7 @@ UCLASS()
class UNewRelicBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()


UFUNCTION(BlueprintCallable, meta = (DisplayName = "Execute Sample function", Keywords = "NewRelic sample test testing"), Category = "NewRelicTesting")
static float NewRelicSampleFunction(float Param);
Expand Down Expand Up @@ -89,4 +91,26 @@ class UNewRelicBPLibrary : public UBlueprintFunctionLibrary

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Get Current Session ID")
static FString currentSessionId();

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs an informational message to the New Relic log.")
static void logInfo(FString message);

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs a verbose message to the New Relic log.")
static void logVerbose(FString message);

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs an error message to the New Relic log..")
static void logError(FString message);

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs a warning message to the New Relic log.")
static void logWarning(FString message);

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs a debug message to the New Relic log.")
static void logDebug(FString message);

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs a message with a specific log level to the New Relic log.")
static void log(AgentLogLevel level,FString message);

UFUNCTION(BlueprintCallable, Category = NewRelicSDK, DisplayName = "NewRelicSDK Logs a message with attributes to the New Relic log.")
static void logAttributes(TMap <FString, FString> attributes);

};
8 changes: 8 additions & 0 deletions Plugins/NewRelic/Source/NewRelic/Public/NewRelicSDKSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,12 @@ class UNewRelicSDKSettings: public UObject
// Enable/Disable Offline Monitoring
UPROPERTY(Config, EditAnywhere, config, Category = "New Relic", meta = (DisplayName = "Enable/Disable Offline Monitoring"))
bool offlineMonitoringEnabled;

// Enable/Disable automatic instrumentation of WebViews
UPROPERTY(Config, EditAnywhere, config, Category = "New Relic", meta = (DisplayName = "Enable or disable background reporting functionality."))
bool backgroundReportingEnabled;

// Enable/Disable Offline Monitoring
UPROPERTY(Config, EditAnywhere, config, Category = "New Relic", meta = (DisplayName = "able or disable to use our new, more stable, event system for iOS agent."))
bool newEventSystemEnabled;
};
Binary file not shown.
Loading

0 comments on commit 9294351

Please sign in to comment.