Skip to content
Closed
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
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ jobs:
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
password: ${{ secrets.PAT_TOKEN }}

- name: Start Docker container
run: |
docker run -td `
--name unreal `
--volume "${{ github.workspace }}:C:\workspace" `
--workdir C:\workspace `
--env SENTRY_DSN="${{ secrets.SENTRY_DSN }}" `
--env SENTRY_ORG="${{ secrets.SENTRY_ORG }}" `
--env SENTRY_PROJECT="${{ secrets.SENTRY_PROJECT }}" `
--env SENTRY_AUTH_TOKEN="${{ secrets.SENTRY_AUTH_TOKEN }}" `
ghcr.io/getsentry/unreal-docker:${{ env.UE_VERSION }}

- uses: actions/checkout@v4
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/run-demo.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: run-demo

on:
# schedule:
# - cron: '0 */2 * * *' # every two hours
schedule:
- cron: '*/50 * * * *' # every 50 minutes
workflow_dispatch:

jobs:
Expand All @@ -28,6 +28,8 @@ jobs:
run-id: ${{ steps.get-run.outputs.run-id }}

- name: Run Simulation
env:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
run: |
$downloadPath = "${{ steps.download.outputs.download-path }}"
Write-Output "Download path: $downloadPath"
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
Expand Down
1 change: 0 additions & 1 deletion .ignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@
/Plugins/Sentry/Gradle
/Plugins/Sentry/Scripts
/Plugins/Sentry/Intermediate
/*.code-workspace
3 changes: 2 additions & 1 deletion Config/DefaultEngine.ini
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ KeyPassword=android
+CollisionChannelRedirects=(OldName="PawnMovement",NewName="Pawn")

[/Script/Sentry.SentrySettings]
InitAutomatically=False
EnableAutoLogAttachment=True
SendDefaultPii=True
AttachScreenshot=True
Expand All @@ -293,7 +294,7 @@ IncludeSources=True
AutomaticBreadcrumbsForLogs=(bOnFatalLog=True,bOnErrorLog=False,bOnWarningLog=False,bOnInfoLog=False,bOnDebugLog=False)
EnableTracing=True
TracesSampleRate=1.000000
Dsn="https://f1818b87d128882c28e8a876858d2d1e@o447951.ingest.us.sentry.io/4508816831873030"
Dsn="https://694ee0c1bc90596005001e4acef50cd7@o87286.ingest.us.sentry.io/4509724070903808"

[/Script/MacTargetPlatform.MacTargetSettings]
-TargetedRHIs=SF_METAL_SM5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,9 @@ TSharedPtr<ISentryTransaction> FGenericPlatformSentrySubsystem::StartTransaction
{
if (sentry_transaction_t* nativeTransaction = sentry_transaction_start(platformTransactionContext->GetNativeObject(), sentry_value_new_null()))
{
// TODO: Replace this hack with a proper transaction binding to the current scope
sentry_set_transaction_object(nativeTransaction);

return MakeShareable(new FGenericPlatformSentryTransaction(nativeTransaction));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ TSharedPtr<ISentrySpan> FGenericPlatformSentryTransaction::StartChildSpan(const
{
if (sentry_span_t* nativeSpan = sentry_transaction_start_child(Transaction, TCHAR_TO_ANSI(*operation), TCHAR_TO_ANSI(*description)))
{
// TODO: Replace this hack with a proper span binding to the current scope
sentry_set_span(nativeSpan);
return MakeShareable(new FGenericPlatformSentrySpan(nativeSpan));
}
else
Expand Down
Binary file not shown.
93 changes: 87 additions & 6 deletions Source/SentryTower/SentryTowerGameInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,45 @@

#include "HttpModule.h"
#include "SentryLibrary.h"
#include "SentrySettings.h"
#include "SentrySpan.h"
#include "SentrySubsystem.h"
#include "SentryTransaction.h"
#include "SentryTransactionContext.h"
#include "Interfaces/IHttpResponse.h"

void USentryTowerGameInstance::Init()
{
Super::Init();

// Initialize Sentry with environment variable override for DSN
USentrySubsystem* SentrySubsystem = GEngine->GetEngineSubsystem<USentrySubsystem>();
if (SentrySubsystem)
{
FString EnvironmentDsn = FPlatformMisc::GetEnvironmentVariable(TEXT("SENTRY_DSN"));
if (!EnvironmentDsn.IsEmpty())
{
// Override DSN with environment variable
UE_LOG(LogTemp, Log, TEXT("Using SENTRY_DSN environment variable"));
SentrySubsystem->InitializeWithSettings(FConfigureSettingsNativeDelegate::CreateLambda([EnvironmentDsn](USentrySettings* Settings)
{
Settings->Dsn = EnvironmentDsn;
}));
}
else
{
// Use default settings
UE_LOG(LogTemp, Log, TEXT("SENTRY_DSN environment variable not set, using default settings"));
SentrySubsystem->Initialize();
}
}

if (FParse::Param(FCommandLine::Get(), TEXT("NullRHI")))
{
// For CI simulation (no RHI available) copy pre-made screenshot to dest where Unreal SDK can pick it up during crash handling
const FString FakeScreenshotPath = FPaths::Combine(FPaths::ProjectContentDir(), TEXT("Resources"), TEXT("screenshot.png"));

// Get the Sentry subsystem
USentrySubsystem* SentrySubsystem = GEngine->GetEngineSubsystem<USentrySubsystem>();
// Add screenshot attachment to Sentry
if (SentrySubsystem)
{
// Create the attachment
Expand All @@ -46,9 +69,7 @@ void USentryTowerGameInstance::BuyUpgrade(const FOnBuyComplete& OnBuyComplete)

USentrySpan* ProcessSpan = CheckoutTransaction->StartChildSpan(TEXT("task"), TEXT("process_upgrade_data"));

TSharedPtr<FJsonObject> UpgradeDataJsonObject = MakeShareable(new FJsonObject());
UpgradeDataJsonObject->SetStringField(TEXT("UpgradeName"), TEXT("NewTower"));
UpgradeDataJsonObject->SetStringField(TEXT("PlayerEmail"), TEXT("[email protected]"));
TSharedPtr<FJsonObject> UpgradeDataJsonObject = BuildCheckoutRequestJson();

FString JsonString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&JsonString);
Expand All @@ -61,7 +82,8 @@ void USentryTowerGameInstance::BuyUpgrade(const FOnBuyComplete& OnBuyComplete)

ProcessSpan->Finish();

FString Domain = TEXT("https://aspnetcore.empower-plant.com");
USentrySpan* CheckoutSpan = CheckoutTransaction->StartChildSpan(TEXT("task"), TEXT("checkout_request"));
FString Domain = TEXT("https://flask.empower-plant.com");
FString Endpoint = TEXT("/checkout");
FString CheckoutURL = Domain + Endpoint;

Expand All @@ -72,10 +94,21 @@ void USentryTowerGameInstance::BuyUpgrade(const FOnBuyComplete& OnBuyComplete)
HttpRequest->SetVerb("POST");
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));

FString TraceKey;
FString TraceValue;
CheckoutSpan->GetTrace(TraceKey, TraceValue);

UE_LOG(LogTemp, Log, TEXT("TraceValue - %s"), *TraceValue);

HttpRequest->SetHeader(TraceKey, TraceValue);

HttpRequest->SetContentAsString(JsonString);

HttpRequest->OnProcessRequestComplete().BindLambda([=](FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
CheckoutSpan->Finish();

USentrySpan* ResponseSpan = CheckoutTransaction->StartChildSpan(TEXT("task"), TEXT("process_checkout_response"));
ensureMsgf(bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == 200, TEXT("Checkout HTTP request failed"));

if (bWasSuccessful && Response.IsValid() && Response->GetResponseCode() == 200)
Expand All @@ -89,8 +122,56 @@ void USentryTowerGameInstance::BuyUpgrade(const FOnBuyComplete& OnBuyComplete)
OnBuyComplete.ExecuteIfBound(false);
}

ResponseSpan->Finish();
CheckoutTransaction->Finish();
});

HttpRequest->ProcessRequest();
}

TSharedPtr<FJsonObject> USentryTowerGameInstance::BuildCheckoutRequestJson()
{
TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject());

// Build cart object
TSharedPtr<FJsonObject> CartObject = MakeShareable(new FJsonObject());

// Build items array
TArray<TSharedPtr<FJsonValue>> ItemsArray;
TSharedPtr<FJsonObject> ItemObject = MakeShareable(new FJsonObject());
ItemObject->SetStringField(TEXT("description"), TEXT("The mood ring for plants."));
ItemObject->SetStringField(TEXT("descriptionfull"), TEXT("This is an example of what you can do with just a few things, a little imagination and a happy dream in your heart. I'm a water fanatic. I love water. There's not a thing in the world wrong with washing your brush. Everybody needs a friend. Here we're limited by the time we have."));
ItemObject->SetNumberField(TEXT("id"), 3);
ItemObject->SetStringField(TEXT("img"), TEXT("https://storage.googleapis.com/application-monitoring/mood-planter.jpg"));
ItemObject->SetStringField(TEXT("imgcropped"), TEXT("https://storage.googleapis.com/application-monitoring/mood-planter-cropped.jpg"));
ItemObject->SetNumberField(TEXT("price"), 155);
ItemObject->SetArrayField(TEXT("reviews"), TArray<TSharedPtr<FJsonValue>>());
ItemObject->SetStringField(TEXT("title"), TEXT("Plant Mood"));
ItemsArray.Add(MakeShareable(new FJsonValueObject(ItemObject)));
CartObject->SetArrayField(TEXT("items"), ItemsArray);

// Build quantities object
TSharedPtr<FJsonObject> QuantitiesObject = MakeShareable(new FJsonObject());
QuantitiesObject->SetNumberField(TEXT("3"), 3);
CartObject->SetObjectField(TEXT("quantities"), QuantitiesObject);
CartObject->SetNumberField(TEXT("total"), 465);

// Build form object
TSharedPtr<FJsonObject> FormObject = MakeShareable(new FJsonObject());
FormObject->SetStringField(TEXT("address"), TEXT(""));
FormObject->SetStringField(TEXT("city"), TEXT(""));
FormObject->SetStringField(TEXT("country"), TEXT(""));
FormObject->SetStringField(TEXT("email"), TEXT("[email protected]"));
FormObject->SetStringField(TEXT("firstName"), TEXT(""));
FormObject->SetStringField(TEXT("lastName"), TEXT(""));
FormObject->SetStringField(TEXT("state"), TEXT(""));
FormObject->SetStringField(TEXT("subscribe"), TEXT(""));
FormObject->SetStringField(TEXT("zipCode"), TEXT(""));

// Set all objects to main JSON
JsonObject->SetObjectField(TEXT("cart"), CartObject);
JsonObject->SetObjectField(TEXT("form"), FormObject);
JsonObject->SetStringField(TEXT("validate_inventory"), TEXT("true"));

return JsonObject;
}
3 changes: 3 additions & 0 deletions Source/SentryTower/SentryTowerGameInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ class SENTRYTOWER_API USentryTowerGameInstance : public UGameInstance

UFUNCTION(BlueprintCallable, Meta = (AutoCreateRefTerm = "OnBuyComplete"))
void BuyUpgrade(const FOnBuyComplete& OnBuyComplete);

private:
TSharedPtr<FJsonObject> BuildCheckoutRequestJson();
};