Skip to content

Fix automatic game log attachment (Android) #309

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

Merged
merged 9 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Fixes

- Fix automatic game log attachment (Android) ([#309](https://github.com/getsentry/sentry-unreal/pull/309))

### Dependencies

- Bump Java SDK (Android) from v6.23.0 to v6.24.0 ([#312](https://github.com/getsentry/sentry-unreal/pull/312))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
package io.sentry.unreal;

import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;

import androidx.annotation.NonNull;

Expand All @@ -13,6 +11,7 @@

import io.sentry.Attachment;
import io.sentry.Breadcrumb;
import io.sentry.Hint;
import io.sentry.IHub;
import io.sentry.Scope;
import io.sentry.ScopeCallback;
Expand All @@ -33,6 +32,7 @@ public static void init(
final String releaseName,
final String environment,
final String gameLogPath,
final String gameBackupLogPath,
final boolean enableAutoSessionTracking,
final long sessionTimeout,
final boolean enableStackTrace) {
Expand All @@ -45,15 +45,24 @@ public void configure(SentryAndroidOptions options) {
options.setEnableAutoSessionTracking(enableAutoSessionTracking);
options.setSessionTrackingIntervalMillis(sessionTimeout);
options.setAttachStacktrace(enableStackTrace);
}
});

Sentry.configureScope(new ScopeCallback() {
@Override
public void run(@NonNull Scope scope) {
if(!gameLogPath.isEmpty()) {
scope.addAttachment(new Attachment(gameLogPath));
}
options.setBeforeSend(new SentryOptions.BeforeSendCallback() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not entirely sure how that works underneath but can that callback be overwritten by users?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We don't expose any APIs allowing users to do that, so it should be safe to set the beforeSend hook like this.

Copy link
Contributor

@bitsandfoxes bitsandfoxes Jun 21, 2023

Choose a reason for hiding this comment

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

Considering that we want to expose that API in the future, we could add this as an event-processor/integration instead?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, I think it should be feasible.

@Override
public SentryEvent execute(SentryEvent event, Hint hint) {
if(event.isCrashed() && event.isErrored())
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't that mean that if the app crashed in the run before the gamelogs from the current run won't be part of any current events?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No, after sending the crash event on app startup all subsequent events should be treated as usual with a current session's game log attached.

{
if(!gameBackupLogPath.isEmpty()) {
hint.addAttachment(new Attachment(gameBackupLogPath));
}
}
else
{
if(!gameLogPath.isEmpty()) {
hint.addAttachment(new Attachment(gameLogPath));
}
}
return event;
}
});
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,30 @@
#include "Infrastructure/SentryConvertorsAndroid.h"
#include "Infrastructure/SentryJavaClasses.h"

#include "GenericPlatform/GenericPlatformOutputDevices.h"
#include "HAL/FileManager.h"
#include "Utils/SentryFileUtils.h"

void SentrySubsystemAndroid::InitWithSettings(const USentrySettings* settings)
{
const FString LogFilePath = settings->EnableAutoLogAttachment
? IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*FGenericPlatformOutputDevices::GetAbsoluteLogFilename())
: FString();
? SentryFileUtils::GetGameLogPath()
: FString("");

const FString BackupLogFilePath = settings->EnableAutoLogAttachment
? SentryFileUtils::GetGameLogBackupPath()
: FString("");

const FString ReleaseName = settings->OverrideReleaseName
? settings->Release
: settings->GetFormattedReleaseName();

FSentryJavaObjectWrapper::CallStaticMethod<void>(SentryJavaClasses::SentryBridgeJava,
"init", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZJZ)V",
"init", "(Landroid/app/Activity;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZJZ)V",
FJavaWrapper::GameActivityThis,
*FSentryJavaObjectWrapper::GetJString(settings->DsnUrl),
*FSentryJavaObjectWrapper::GetJString(ReleaseName),
*FSentryJavaObjectWrapper::GetJString(settings->Environment),
*FSentryJavaObjectWrapper::GetJString(LogFilePath),
*FSentryJavaObjectWrapper::GetJString(BackupLogFilePath),
settings->EnableAutoSessionTracking,
(jlong)settings->SessionTimeout,
settings->EnableStackTrace);
Expand Down
45 changes: 45 additions & 0 deletions plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2023 Sentry. All Rights Reserved.

#include "SentryFileUtils.h"
#include "SentryDefines.h"

#include "HAL/FileManager.h"
#include "GenericPlatform/GenericPlatformOutputDevices.h"
#include "Misc/Paths.h"

struct FSentrySortFileByDatePredicate
{
bool operator()(const FString& A, const FString& B) const
{
const FDateTime TimestampA = IFileManager::Get().GetTimeStamp(*A);
const FDateTime TimestampB = IFileManager::Get().GetTimeStamp(*B);
return TimestampB < TimestampA;
}
};

FString SentryFileUtils::GetGameLogPath()
{
return IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*FGenericPlatformOutputDevices::GetAbsoluteLogFilename());
}

FString SentryFileUtils::GetGameLogBackupPath()
{
TArray<FString> GameLogBackupFiles;
IFileManager::Get().FindFiles(GameLogBackupFiles, *FString::Printf(TEXT("%s*-backup-*.*"), *FPaths::ProjectLogDir()), true, false);

if(GameLogBackupFiles.IsEmpty())
{
UE_LOG(LogSentrySdk, Log, TEXT("There are no game log backups available."));
return FString("");
}

for (int i = 0; i < GameLogBackupFiles.Num(); ++i)
{
FString GameLogFullPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*(FPaths::ProjectLogDir() / GameLogBackupFiles[i]));
GameLogBackupFiles[i] = GameLogFullPath;
}

GameLogBackupFiles.Sort(FSentrySortFileByDatePredicate());

return GameLogBackupFiles[0];
}
12 changes: 12 additions & 0 deletions plugin-dev/Source/Sentry/Private/Utils/SentryFileUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2023 Sentry. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"

class SentryFileUtils
{
public:
static FString GetGameLogPath();
static FString GetGameLogBackupPath();
};
3 changes: 3 additions & 0 deletions scripts/packaging/package.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ Source/Sentry/Private/Tests/SentryBreadcrumb.spec.cpp
Source/Sentry/Private/Tests/SentryEvent.spec.cpp
Source/Sentry/Private/Tests/SentrySubsystem.spec.cpp
Source/Sentry/Private/Tests/SentryUser.spec.cpp
Source/Sentry/Private/Utils/
Source/Sentry/Private/Utils/SentryFileUtils.cpp
Source/Sentry/Private/Utils/SentryFileUtils.h
Source/Sentry/Public/
Source/Sentry/Public/SentryAttachment.h
Source/Sentry/Public/SentryBreadcrumb.h
Expand Down