Last active
December 4, 2024 06:53
-
-
Save regner/592bb2cfca82f064ccd5322ea4c5deb8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Very simple backend to recieve Studio Analytics telemetry from Unreal Engine.""" | |
import os | |
from datetime import datetime, timezone | |
import sentry_sdk | |
from flask import Flask, Response, request | |
from sqlalchemy import create_engine, Column, Integer, TIMESTAMP, MetaData, Table | |
from sqlalchemy.dialects.postgresql import JSONB | |
from sentry_sdk.integrations.flask import FlaskIntegration | |
FLASK_ENVIRONMENT = os.environ.get("FLASK_ENVIRONMENT", "development") | |
if FLASK_ENVIRONMENT != "development": | |
sentry_sdk.init( | |
# Sentry DSN are OK to be public, they even have to be when using in web frontends | |
dsn="", | |
integrations=[ | |
FlaskIntegration(), | |
], | |
traces_sample_rate=float(os.environ.get("SENTRY_TRACE_SAMPLE_RATE", "0.5")), | |
environment=FLASK_ENVIRONMENT, | |
) | |
app = Flask(__name__) | |
PG_CONNECTION_STRING = os.environ.get("PG_DB_CONNECTION_STRING", None) | |
db = create_engine(PG_CONNECTION_STRING) | |
engine = db.connect() | |
meta = MetaData(engine) | |
EVENTS = Table( | |
"events", | |
meta, | |
Column("id", Integer, primary_key=True), | |
Column("ingest_time", TIMESTAMP), | |
Column("event", JSONB), | |
) | |
meta.create_all() | |
@app.route("/health", methods=["GET"]) | |
def health() -> Response: | |
"""Super simple healthcheck.""" | |
connection = engine.connect() | |
connection.execute("SELECT 1") | |
connection.close() | |
return Response("{}", status=200, mimetype="application/json") | |
@app.route("/datarouter/api/v1/public/data", methods=["POST"]) | |
def studio_analytics_v1() -> Response: | |
"""Super simple implementation of the Epic public data endpoint.""" | |
args = request.args | |
content = request.get_json() | |
if content is not None: | |
ingest_time = datetime.now(tz=timezone.utc) | |
for event in content["Events"]: | |
event.update(args) | |
insert = EVENTS.insert().values(event=event, ingest_time=ingest_time) | |
connection = engine.connect() | |
connection.execute(insert) | |
connection.close() | |
return Response("{}", status=201, mimetype="application/json") | |
if __name__ == "__main__": | |
app.run(host="0.0.0.0", port=5000) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM python:3.10-slim-buster | |
WORKDIR /app | |
COPY reiquirements.txt main.py | |
RUN pip install -r requirements.txt | |
CMD [ "python", "waitress_server" ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
flask==2.2.2 | |
psycopg2==2.9.5 | |
sentry-sdk[flask]==1.10.1 | |
sqlalchemy==1.4.42 | |
waitress==2.1.2 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Simple Waitress wrapper for the backend in production.""" | |
import logging | |
from waitress import serve | |
from analytics_backend import app | |
logger = logging.getLogger("waitress") | |
logger.setLevel(logging.DEBUG) | |
serve( | |
app, | |
host="0.0.0.0", | |
port=5000, | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AppID": "SomethingUniqueToCompany", | |
"UserID": "regnerblokandersen", | |
"P4Branch": "++project+main", | |
"FirstTime": true, | |
"SessionID": "{40FD32AB-44A1-BD58-05E0-37A2A12E5300}", | |
"AppVersion": "++project+main-CL-1111111", | |
"DateOffset": "+00:00:52.108", | |
"UploadType": "eteventstream", | |
"LoadingName": "InitializeEditor", | |
"ProjectName": "Project", | |
"ComputerName": "Workstation", | |
"AppEnvironment": "datacollector-binary", | |
"LoadingSeconds": 112.776953 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AppID": "SomethingUniqueToCompany", | |
"UserID": "regnerblokandersen", | |
"MapName": "Map", | |
"P4Branch": "++project+main", | |
"EventName": "Performance.Loading", | |
"FirstTime": true, | |
"SessionID": "{40FD32AB-44A1-BD58-05E0-37A2A12E5300}", | |
"AppVersion": "++project+main-CL-1111111", | |
"DateOffset": "+00:00:00.686", | |
"UploadType": "eteventstream", | |
"LoadingName": "LoadMap", | |
"ProjectName": "Project", | |
"ComputerName": "Workstation", | |
"AppEnvironment": "datacollector-binary", | |
"LoadingSeconds": 51.419099 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AppID": "SomethingUniqueToCompany", | |
"UserID": "regnerblokandersen", | |
"P4Branch": "++project+main", | |
"AssetPath": "World /Game/Maps/Map", | |
"AssetType": "World", | |
"EventName": "Performance.Loading", | |
"SessionID": "{4D8224C9-4978-A127-A6EC-2A87FC619BC3}", | |
"AppVersion": "++project+main-CL-1111111", | |
"DateOffset": "+00:00:00.096", | |
"UploadType": "eteventstream", | |
"LoadingName": "OpenAssetEditor", | |
"ProjectName": "Project", | |
"ComputerName": "Workstation", | |
"AppEnvironment": "datacollector-binary", | |
"LoadingSeconds": 3.051511 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AppID": "SomethingUniqueToCompany", | |
"UserID": "regnerblokandersen", | |
"P4Branch": "++project+main", | |
"EventName": "Performance.Loading", | |
"FirstTime": true, | |
"SessionID": "{40FD32AB-44A1-BD58-05E0-37A2A12E5300}", | |
"AppVersion": "++project+main-CL-1111111", | |
"DateOffset": "+00:00:00.685", | |
"UploadType": "eteventstream", | |
"LoadingName": "TotalEditorStartup", | |
"ProjectName": "Project", | |
"ComputerName": "Workstation", | |
"AppEnvironment": "datacollector-binary", | |
"LoadingSeconds": 164.196052 | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnrealBuildTool; | |
public class CustomStudioAnalytics : ModuleRules | |
{ | |
public CustomStudioAnalytics(ReadOnlyTargetRules Target) : base(Target) | |
{ | |
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; | |
bEnforceIWYU = true; | |
PrivateDependencyModuleNames.AddRange( | |
new string[] | |
{ | |
"Core", | |
"Engine", | |
"Analytics", | |
"AnalyticsET", | |
} | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "CustomStudioAnalytics.h" | |
#include <Analytics.h> | |
#include <AnalyticsET.h> | |
#include <IAnalyticsProviderET.h> | |
#include <StudioAnalytics.h> | |
DEFINE_LOG_CATEGORY_STATIC(LogCustomStudioAnalytics, Display, All); | |
void FCustomStudioAnalyticsModule::StartupModule() | |
{ | |
const FAnalytics::ConfigFromIni AnalyticsConfig; | |
const TSharedPtr<IAnalyticsProviderET> Provider = StaticCastSharedPtr<IAnalyticsProviderET>( | |
FAnalyticsET::Get().CreateAnalyticsProvider( | |
FAnalyticsProviderConfigurationDelegate::CreateRaw( | |
&AnalyticsConfig, | |
&FAnalytics::ConfigFromIni::GetValue | |
) | |
) | |
); | |
if (!Provider) | |
{ | |
UE_LOG(LogCustomStudioAnalytics, Error, TEXT("Failed create AnalyticsProviderET for CustomStudioAnalytics. Ensure required config values are set.")); | |
return; | |
} | |
Provider->StartSession(); | |
Provider->SetUserID(FString(FPlatformProcess::UserName(false))); | |
Provider->SetDefaultEventAttributes( | |
MakeAnalyticsEventAttributeArray( | |
TEXT("ComputerName"), FString(FPlatformProcess::ComputerName()), | |
TEXT("ProjectName"), FString(FApp::GetProjectName()), | |
TEXT("P4Branch"), FApp::GetBranchName() | |
) | |
); | |
FStudioAnalytics::SetProvider(Provider.ToSharedRef()); | |
} | |
IMPLEMENT_MODULE(FCustomStudioAnalyticsModule, CustomStudioAnalytics) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "CoreMinimal.h" | |
#include "Modules/ModuleManager.h" | |
class FCustomStudioAnalyticsModule : public IModuleInterface | |
{ | |
public: | |
/** IModuleInterface implementation */ | |
virtual void StartupModule() override; | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"FileVersion": 3, | |
"Version": 1, | |
"VersionName": "1.0", | |
"FriendlyName": "CustomStudioAnalytics", | |
"Description": "A simple plugin to initialize and StudioAnalytics to send to our backend.", | |
"Category": "Example", | |
"CreatedBy": "Example", | |
"CreatedByURL": "", | |
"DocsURL": "", | |
"MarketplaceURL": "", | |
"SupportURL": "", | |
"CanContainContent": false, | |
"IsBetaVersion": false, | |
"IsExperimentalVersion": false, | |
"Installed": false, | |
"Modules": [ | |
{ | |
"Name": "CustomStudioAnalytics", | |
"Type": "Runtime", | |
"LoadingPhase": "EarliestPossible" | |
} | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[AnalyticsDevelopment] | |
APIServerET=https://example.local | |
APIKeyET=SomethingUniqueToCompany |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment