예제 #1
1
static void ParseCodeLink(const FString &InternalLink)
{
	// Tokens used by the code parsing. Details in the parse section	
	static const FString ProjectSpecifier(TEXT("[PROJECTPATH]"));
	static const FString ProjectPathSpecifier(TEXT("[PROJECT]"));
	static const FString EnginePathSpecifier(TEXT("[ENGINEPATH]"));

	FString Path;
	int32 Line = 0;
	int32 Col = 0;

	TArray<FString> Tokens;
	InternalLink.ParseIntoArray(Tokens, TEXT(","), 0);
	int32 TokenStringsCount = Tokens.Num();
	if (TokenStringsCount > 0)
	{
		Path = Tokens[0];
	}
	if (TokenStringsCount > 1)
	{
		TTypeFromString<int32>::FromString(Line, *Tokens[1]);
	}
	if (TokenStringsCount > 2)
	{
		TTypeFromString<int32>::FromString(Col, *Tokens[2]);
	}

	ISourceCodeAccessModule& SourceCodeAccessModule = FModuleManager::LoadModuleChecked<ISourceCodeAccessModule>("SourceCodeAccess");
	ISourceCodeAccessor& SourceCodeAccessor = SourceCodeAccessModule.GetAccessor();

	if (Path.Contains(EnginePathSpecifier) == true)
	{
		// replace engine path specifier with path to engine
		Path.ReplaceInline(*EnginePathSpecifier, *FPaths::EngineDir());
	}

	if (Path.Contains(ProjectSpecifier) == true)
	{
		// replace project specifier with path to project
		Path.ReplaceInline(*ProjectSpecifier, FApp::GetGameName());
	}

	if (Path.Contains(ProjectPathSpecifier) == true)
	{
		// replace project specifier with path to project
		Path.ReplaceInline(*ProjectPathSpecifier, *FPaths::GetProjectFilePath());
	}

	Path = FPaths::ConvertRelativePathToFull(Path);

	SourceCodeAccessor.OpenFileAtLine(Path, Line, Col);

	if( FEngineAnalytics::IsAvailable() )
	{
		TArray<FAnalyticsEventAttribute> EventAttributes;
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("CodeLink"), InternalLink));

		FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.CodeLinkClicked"), EventAttributes );
	}
}
	/**
  	 * @EventName Editor.AbnormalShutdown
	 *
	 * @Trigger Fired only by the editor at startup, once for each "abnormal shutdown" detected that has not already been sent.
	 *
	 * @Type Static
	 *
	 * @EventParam SessionId Analytics SessionID of the session that abnormally terminated.
	 * @EventParam EngineVersion EngineVersion of the session that abnormally terminated.
	 * @EventParam ShutdownType - one of Crashed, Debugger, or AbormalShutdown
	 *               * Crashed - we definitely detected a crash (whether or not a debugger was attached)
	 *               * Debugger - the session crashed or shutdown abnormally, but we had a debugger attached at startup, so abnormal termination is much more likely because the user was debugging.
	 *               * AbnormalShutdown - this happens when we didn't detect a normal shutdown, but none of the above cases is the cause.
	 * @EventParam Timestamp - the UTC time of the last known time the crashed session was running, within 5 minutes.
	 *
	 * @TODO: Debugger should be a completely separate flag, since it's orthogonal to whether we detect a crash or shutdown.
	 *
	 * @Comments The editor will only try to check for abnormal terminations if it determines it is a real editor run (not a commandlet or PIE, or editor -game run), and the user has not disabled sending Engine Usage data to Epic via the Editor global preferences.
	 *
	 * SessionId can be used to find the actual session associated with this crash in the data.
	 *
	 * Use THIS instead of the current event's analytics AppVersion field, since the crash could be from an old version. Could technically be found by searching the data for the SessionId and checking the version there, but sending it here simplifies the backend processing and ensure we have the version here even if we never got the original events.
	 *
	 * If multiple versions of the editor or launched, this code will properly track each one and its shutdown status. So during startup, an editor instance may need to fire off several events.
	 *
	 * When attributing abnormal terminations to engine versions, be sure to use the EngineVersion associated with this event, and not the AppVersion. AppVersion is for the session that is currently sending the event, not for the session that crashed. That is why EngineVersion is sent separately.
	 *
	 * The editor updates this timestamp every 5 minutes, so we should know the time of the crash within 5 minutes. It should technically correlate with the last heartbeat we receive in the data for that session.
	 */
	void SendAbnormalShutdownReport(const FSessionRecord& Record)
	{
		FGameProjectGenerationModule& GameProjectModule = FModuleManager::LoadModuleChecked<FGameProjectGenerationModule>(TEXT("GameProjectGeneration"));
		bool bHasCode = GameProjectModule.Get().ProjectHasCodeFiles();

#if PLATFORM_WINDOWS
		const FString PlatformName(TEXT("Windows"));
#elif PLATFORM_MAC
		const FString PlatformName(TEXT("Mac"));
#elif PLATFORM_LINUX
		const FString PlatformName(TEXT("Linux"));
#else
		const FString PlatformName(TEXT("Unknown"));
#endif

		FGuid SessionId;
		FString SessionIdString = Record.SessionId;
		if (FGuid::Parse(SessionIdString, SessionId))
		{
			// convert session guid to one with braces for sending to analytics
			SessionIdString = SessionId.ToString(EGuidFormats::DigitsWithHyphensInBraces);
		}

		FString ShutdownTypeString = Record.bCrashed ? EditorAnalyticsDefs::CrashSessionToken :
			(Record.bIsDebugger ? EditorAnalyticsDefs::DebuggerSessionToken : EditorAnalyticsDefs::AbnormalSessionToken);

		TArray< FAnalyticsEventAttribute > AbnormalShutdownAttributes;
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("SessionId"), SessionIdString));
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("EngineVersion"), Record.EngineVersion));
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("ShutdownType"), ShutdownTypeString));
		AbnormalShutdownAttributes.Add(FAnalyticsEventAttribute(FString("Timestamp"), Record.Timestamp.ToIso8601()));

		FEditorAnalytics::ReportEvent(TEXT("Editor.AbnormalShutdown"), PlatformName, bHasCode, AbnormalShutdownAttributes);
	}
void STutorialButton::DismissAlert()
{
	RefreshStatus();

	if( FEngineAnalytics::IsAvailable() )
	{
		TArray<FAnalyticsEventAttribute> EventAttributes;
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Context"), Context.ToString()));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TimeSinceAlertStarted"), (AlertStartTime != 0.0f && ShouldShowAlert()) ? (FPlatformTime::Seconds() - AlertStartTime) : -1.0f));

		FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.DismissedTutorialAlert"), EventAttributes );
	}

	// If they actually right click and choose "Dismiss Alert", we'll go ahead and suppress the tutorial reminder for this feature for good (all sessions.)
	const bool bDismissAcrossSessions = true;
	if (CachedAttractTutorial != nullptr)
	{
		GetMutableDefault<UTutorialStateSettings>()->DismissTutorial(CachedAttractTutorial, bDismissAcrossSessions);
		CachedAttractTutorial = nullptr;
	}
	if( CachedLaunchTutorial != nullptr)
	{
		GetMutableDefault<UTutorialStateSettings>()->DismissTutorial(CachedLaunchTutorial, bDismissAcrossSessions);
		CachedLaunchTutorial = nullptr;
	}
	GetMutableDefault<UTutorialStateSettings>()->SaveProgress();
	bTutorialDismissed = true;

	RefreshStatus();
}
FReply STutorialButton::HandleButtonClicked()
{
	if (bPendingClickAction)
	{
		//There's already a click pending
		return FReply::Handled();
	}

	RefreshStatus();

	if (FEngineAnalytics::IsAvailable())
	{
		TArray<FAnalyticsEventAttribute> EventAttributes;
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Context"), Context.ToString()));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TimeSinceAlertStarted"), (AlertStartTime != 0.0f && ShouldShowAlert()) ? (FPlatformTime::Seconds() - AlertStartTime) : -1.0f));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("LaunchedBrowser"), ShouldLaunchBrowser()));

		FEngineAnalytics::GetProvider().RecordEvent(TEXT("Rocket.Tutorials.ClickedContextButton"), EventAttributes);
	}

	bPendingClickAction = true;
	RegisterActiveTimer(0.f, FWidgetActiveTimerDelegate::CreateSP(this, &STutorialButton::HandleButtonClicked_AssetRegistryChecker));
	FIntroTutorials& IntroTutorials = FModuleManager::GetModuleChecked<FIntroTutorials>(TEXT("IntroTutorials"));
	IntroTutorials.AttachWidget(LoadingWidget);
	return FReply::Handled();
}
void FEditorAnalytics::ReportEvent(FString EventName, FString PlatformName, bool bHasCode)
{
	if( FEngineAnalytics::IsAvailable() )
	{
		const UGeneralProjectSettings& ProjectSettings = *GetDefault<UGeneralProjectSettings>();
		TArray<FAnalyticsEventAttribute> ParamArray;
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("ProjectID"), ProjectSettings.ProjectID.ToString()));
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("Platform"), PlatformName));
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("ProjectType"), bHasCode ? TEXT("C++ Code") : TEXT("Content Only")));

		FEngineAnalytics::GetProvider().RecordEvent( EventName, ParamArray );
	}
}
void FAnalyticsProviderFlurry::RecordCurrencyGiven(const FString& GameCurrencyType, int GameCurrencyAmount)
{
	FString EventName = "Currency Given";

	// Build the dictionary
	TArray<FAnalyticsEventAttribute> AttributesDict;
	AttributesDict.Add(FAnalyticsEventAttribute("GameCurrencyType", GameCurrencyType));
	AttributesDict.Add(FAnalyticsEventAttribute("GameCurrencyAmount", FString::FromInt(GameCurrencyAmount)));
	
	// Send the event
	RecordEvent(EventName, AttributesDict);

	UE_LOG(LogAnalytics, Display, TEXT("AndroidFlurry::RecordCurrencyGiven('%s', %d)"), *GameCurrencyType, GameCurrencyAmount);
}
void FAnalyticsProviderFlurry::RecordItemPurchase(const FString& ItemId, int ItemQuantity, const TArray<FAnalyticsEventAttribute>& EventAttrs)
{
	FString EventName = "Item Purchase";

	// Build the dictionary
	TArray<FAnalyticsEventAttribute> AttributesDict;
	AttributesDict.Add(FAnalyticsEventAttribute("ItemId", ItemId));
	AttributesDict.Add(FAnalyticsEventAttribute("ItemQuantity", FString::FromInt(ItemQuantity)));
	AttributesDict.Append(EventAttrs);

	// Send the event
	RecordEvent(EventName, AttributesDict);

	UE_LOG(LogAnalytics, Display, TEXT("AndroidFlurry::RecordItemPurchase('%s', %d, %d)"), *ItemId, ItemQuantity, EventAttrs.Num());
}
void FAnalyticsProviderFlurry::RecordProgress(const FString& ProgressType, const FString& ProgressHierarchy, const TArray<FAnalyticsEventAttribute>& EventAttrs)
{
	FString EventName = "Progress";

	// Build the dictionary
	TArray<FAnalyticsEventAttribute> AttributesDict;
	AttributesDict.Add(FAnalyticsEventAttribute("ProgressType", ProgressType));
	AttributesDict.Add(FAnalyticsEventAttribute("ProgressHierarchy", ProgressHierarchy));
	AttributesDict.Append(EventAttrs);

	// Send the event
	RecordEvent(EventName, AttributesDict);

	UE_LOG(LogAnalytics, Display, TEXT("AndroidFlurry::RecordProgress('%s', %s, %d)"), *ProgressType, *ProgressHierarchy, EventAttrs.Num());
}
예제 #9
0
	virtual void FireEvent_FriendRemoved(const FUniqueNetId& LocalUserId, const IFriendItem& Friend, const FString& RemoveReason) const override
	{
		static const FString EventName = TEXT("Social.FriendRemoved");
		if (AnalyticsProvider.IsValid())
		{
			if (LocalUserId.IsValid())
			{
				TArray<FAnalyticsEventAttribute> Attributes;
				Attributes.Add(FAnalyticsEventAttribute(TEXT("User"), LocalUserId.ToString()));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("Friend"), Friend.GetUniqueID()->ToString()));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("RemoveReason"), RemoveReason));
				AddPresenceAttributes(LocalUserId, Attributes);
				AnalyticsProvider->RecordEvent(EventName, Attributes);
			}
		}
	}
void FEditorAnalytics::ReportBuildRequirementsFailure(FString EventName, FString PlatformName, bool bHasCode, int32 Requirements)
{
	TArray<FAnalyticsEventAttribute> ParamArray;
	ParamArray.Add(FAnalyticsEventAttribute(TEXT("Time"), 0.0));
	if (Requirements & ETargetPlatformReadyStatus::SDKNotFound)
	{
		ReportEvent(EventName, PlatformName, bHasCode, EAnalyticsErrorCodes::SDKNotFound, ParamArray);
	}
	if (Requirements & ETargetPlatformReadyStatus::ProvisionNotFound)
	{
		ReportEvent(EventName, PlatformName, bHasCode, EAnalyticsErrorCodes::ProvisionNotFound, ParamArray);
	}
	if (Requirements & ETargetPlatformReadyStatus::SigningKeyNotFound)
	{
		ReportEvent(EventName, PlatformName, bHasCode, EAnalyticsErrorCodes::CertificateNotFound, ParamArray);
	}
	if (Requirements & ETargetPlatformReadyStatus::CodeUnsupported)
	{
		ReportEvent(EventName, PlatformName, bHasCode, EAnalyticsErrorCodes::CodeUnsupported, ParamArray);
	}
	if (Requirements & ETargetPlatformReadyStatus::PluginsUnsupported)
	{
		ReportEvent(EventName, PlatformName, bHasCode, EAnalyticsErrorCodes::PluginsUnsupported, ParamArray);
	}
}
예제 #11
0
static void ParseAssetLink(const FString& InternalLink, const FString* Action)
{
	UObject* RequiredObject = LoadObject<UObject>(nullptr, *InternalLink);
	if (RequiredObject != nullptr)
	{
		if(Action && *Action == TEXT("select"))
		{
			FContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>("ContentBrowser");
			TArray<UObject*> AssetToBrowse;
			AssetToBrowse.Add(RequiredObject);
			ContentBrowserModule.Get().SyncBrowserToAssets(AssetToBrowse);
		}
		else
		{
			FAssetEditorManager::Get().OpenEditorForAsset(RequiredObject);
		}

		if( FEngineAnalytics::IsAvailable() )
		{
			TArray<FAnalyticsEventAttribute> EventAttributes;
			EventAttributes.Add(FAnalyticsEventAttribute(TEXT("AssetLink"), InternalLink));

			FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.AssetLinkClicked"), EventAttributes );
		}
	}
}
예제 #12
0
	virtual void FireEvent_SendGameInvite(const FUniqueNetId& LocalUserId, const FUniqueNetId& ToUser) const override
	{
		static const FString EventName = TEXT("Social.GameInvite.Send");

		if (AnalyticsProvider.IsValid())
		{
			if (LocalUserId.IsValid())
			{
				TArray<FAnalyticsEventAttribute> Attributes;
				Attributes.Add(FAnalyticsEventAttribute(TEXT("User"), LocalUserId.ToString()));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("Friend"), ToUser.ToString()));
				AddPresenceAttributes(LocalUserId, Attributes);
				AnalyticsProvider->RecordEvent(EventName, Attributes);
			}
		}
	}
예제 #13
0
	virtual void FireEvent_RecordToggleChat(const FUniqueNetId& LocalUserId, const FString& Channel, bool bEnabled) const override
	{
		static const FString EventName = TEXT("Social.Chat.Toggle");
		if (AnalyticsProvider.IsValid())
		{
			if (LocalUserId.IsValid())
			{
				TArray<FAnalyticsEventAttribute> Attributes;
				Attributes.Add(FAnalyticsEventAttribute(TEXT("User"), LocalUserId.ToString()));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("Channel"), Channel));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("bEnabled"), bEnabled));
				AddPresenceAttributes(LocalUserId, Attributes);
				AnalyticsProvider->RecordEvent(EventName, Attributes);
			}
		}
	}
void FPrimaryCrashProperties::SendPostUploadAnalytics()
{
	TArray<FAnalyticsEventAttribute> CrashAttributes;

	CrashAttributes.Add(FAnalyticsEventAttribute(TEXT("CrashGUID"), CrashGUID));

	if (FCrashReportAnalytics::IsAvailable())
	{
		// Connect the crash report client analytics provider.
		IAnalyticsProvider& Analytics = FCrashReportAnalytics::GetProvider();

		if (bIsEnsure)
		{
			Analytics.RecordEvent(TEXT("CrashReportClient.ReportEnsureUploaded"), CrashAttributes);
		}
		else
		{
			Analytics.RecordEvent(TEXT("CrashReportClient.ReportCrashUploaded"), CrashAttributes);
		}
	}

	// duplicate the event to QoS Reporter
	if (FQoSReporter::IsAvailable())
	{
		if (bIsEnsure)
		{
			FQoSReporter::GetProvider().RecordEvent(TEXT("CrashReportClient.ReportEnsureUploaded"), CrashAttributes);
		}
		else
		{
			FQoSReporter::GetProvider().RecordEvent(TEXT("CrashReportClient.ReportCrashUploaded"), CrashAttributes);
		}
	}
}
void FAnalyticsProviderFlurry::RecordItemPurchase(const FString& ItemId, const FString& Currency, int PerItemCost, int ItemQuantity)
{
	FString EventName = "Item Purchase";
	
	// Build the dictionary
	TArray<FAnalyticsEventAttribute> AttributesDict;
	AttributesDict.Add(FAnalyticsEventAttribute("ItemId", ItemId));
	AttributesDict.Add(FAnalyticsEventAttribute("Currency", Currency));
	AttributesDict.Add(FAnalyticsEventAttribute("PerItemCost", FString::FromInt(PerItemCost)));
	AttributesDict.Add(FAnalyticsEventAttribute("ItemQuantity", FString::FromInt(ItemQuantity)));

	// Send the event
	RecordEvent(EventName, AttributesDict);

	UE_LOG(LogAnalytics, Display, TEXT("AndroidFlurry::RecordItemPurchase('%s', '%s', %d, %d)"), *ItemId, *Currency, PerItemCost, ItemQuantity);
}
void FEditorAnalytics::ReportEvent(FString EventName, FString PlatformName, bool bHasCode, int32 ErrorCode, TArray<FAnalyticsEventAttribute>& ExtraParams)
{
	if( FEngineAnalytics::IsAvailable() )
	{
		const UGeneralProjectSettings& ProjectSettings = *GetDefault<UGeneralProjectSettings>();
		TArray<FAnalyticsEventAttribute> ParamArray;
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("ProjectID"), ProjectSettings.ProjectID.ToString()));
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("Platform"), PlatformName));
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("ProjectType"), bHasCode ? TEXT("C++ Code") : TEXT("Content Only")));
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("ErrorCode"), ErrorCode));
		const FString ErrorMessage = TranslateErrorCode(ErrorCode);
		ParamArray.Add(FAnalyticsEventAttribute(TEXT("ErrorName"), ErrorMessage));
		ParamArray.Append(ExtraParams);

		FEngineAnalytics::GetProvider().RecordEvent( EventName, ParamArray );
	}
}
void FAnalyticsProviderFlurry::RecordCurrencyPurchase(const FString& GameCurrencyType, int GameCurrencyAmount, const FString& RealCurrencyType, float RealMoneyCost, const FString& PaymentProvider)
{
	FString EventName = "Currency Purchase";

	// Build the dictionary
	TArray<FAnalyticsEventAttribute> AttributesDict;
	AttributesDict.Add(FAnalyticsEventAttribute("GameCurrencyType", GameCurrencyType));
	AttributesDict.Add(FAnalyticsEventAttribute("GameCurrencyAmount", FString::FromInt(GameCurrencyAmount)));
	AttributesDict.Add(FAnalyticsEventAttribute("RealCurrencyType", RealCurrencyType));
	AttributesDict.Add(FAnalyticsEventAttribute("RealMoneyCost", FString::Printf(TEXT("%.02f"), RealMoneyCost)));
	AttributesDict.Add(FAnalyticsEventAttribute("PaymentProvider", PaymentProvider));

	// Send the event
	RecordEvent(EventName, AttributesDict);

	UE_LOG(LogAnalytics, Display, TEXT("AndroidFlurry::RecordCurrencyPurchase('%s', %d, '%s', %.02f, %s)"), *GameCurrencyType, GameCurrencyAmount, *RealCurrencyType, RealMoneyCost, *PaymentProvider);
}
예제 #18
0
	void AddPresenceAttributes(const FUniqueNetId& UserId, TArray<FAnalyticsEventAttribute>& Attributes) const
	{
		IOnlinePresencePtr OnlinePresence = Online::GetPresenceInterface(TEXT("MCP"));
		if (OnlinePresence.IsValid())
		{
			TSharedPtr<FOnlineUserPresence> Presence;
			OnlinePresence->GetCachedPresence(UserId, Presence);
			if (Presence.IsValid())
			{
				FVariantData* ClientIdData = Presence->Status.Properties.Find(DefaultClientIdKey);
				if (ClientIdData != nullptr)
				{
					Attributes.Add(FAnalyticsEventAttribute(TEXT("ClientId"), ClientIdData->ToString()));
				}
				Attributes.Add(FAnalyticsEventAttribute(TEXT("Status"), Presence->Status.StatusStr));
			}
		}
	}
void SDocumentationToolTip::Tick( const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime )
{
	const FModifierKeysState ModifierKeys = FSlateApplication::Get().GetModifierKeys();
	const bool NeedsUpdate = IsDisplayingDocumentationLink != GEditor->EditorUserSettings->bDisplayDocumentationLink;

	if ( !IsShowingFullTip && ModifierKeys.IsAltDown() && ModifierKeys.IsControlDown() )
	{
		if ( !FullTipContent.IsValid() && DocumentationPage.IsValid() && DocumentationPage->HasExcerpt( ExcerptName ) )
		{
			ConstructFullTipContent();
		}
		else if ( GEditor->EditorUserSettings->bDisplayDocumentationLink )
		{
			ReloadDocumentation();
		}

		if ( FullTipContent.IsValid() )
		{
			WidgetContent->SetContent( FullTipContent.ToSharedRef() );
			IsShowingFullTip = true;

			// Analytics event
			if (FEngineAnalytics::IsAvailable())
			{
				TArray<FAnalyticsEventAttribute> Params;
				Params.Add(FAnalyticsEventAttribute(TEXT("Page"), DocumentationLink));
				Params.Add(FAnalyticsEventAttribute(TEXT("Excerpt"), ExcerptName));

				FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.Documentation.FullTooltipShown"), Params);
			}
		}
	}
	else if ( ( IsShowingFullTip || NeedsUpdate )  && ( !ModifierKeys.IsAltDown() || !ModifierKeys.IsControlDown() ) )
	{
		if ( NeedsUpdate )
		{
			ReloadDocumentation();
			IsDisplayingDocumentationLink = GEditor->EditorUserSettings->bDisplayDocumentationLink;
		}

		WidgetContent->SetContent( SimpleTipContent.ToSharedRef() );
		IsShowingFullTip = false;
	}
}
예제 #20
0
	virtual void FireEvent_AddFriend(const FUniqueNetId& LocalUserId, const FString& FriendName, const FUniqueNetId& FriendId, EFindFriendResult::Type Result, bool bRecentPlayer) const override
	{
		static const FString EventName = TEXT("Social.AddFriend");

		if (AnalyticsProvider.IsValid())
		{
			if (LocalUserId.IsValid())
			{
				TArray<FAnalyticsEventAttribute> Attributes;
				Attributes.Add(FAnalyticsEventAttribute(TEXT("User"), LocalUserId.ToString()));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("Friend"), FriendId.ToString()));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("FriendName"), FriendName));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("Result"), EFindFriendResult::ToString(Result)));
				Attributes.Add(FAnalyticsEventAttribute(TEXT("bRecentPlayer"), bRecentPlayer));
				AddPresenceAttributes(LocalUserId, Attributes);
				AnalyticsProvider->RecordEvent(EventName, Attributes);
			}
		}
	}
예제 #21
0
void SSuperSearchBox::OnMenuOpenChanged( bool bIsOpen )
{
#if WITH_EDITOR
	if (bIsOpen == false)
	{
		if(FEngineAnalytics::IsAvailable())
		{
			TArray< FAnalyticsEventAttribute > SearchAttribs;
			SearchAttribs.Add(FAnalyticsEventAttribute(TEXT("SearchTerm"), InputText->GetText().ToString() ));
			SearchAttribs.Add(FAnalyticsEventAttribute(TEXT("NumFoundResults"), GetNumRealSuggestions(Suggestions)));
			SearchAttribs.Add(FAnalyticsEventAttribute(TEXT("ClickedTitle"), EntryClicked.Get() ? EntryClicked->Title : "") );
			SearchAttribs.Add(FAnalyticsEventAttribute(TEXT("ClickedOnSomething"), EntryClicked.IsValid()) );

			FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.SuperSearch"), SearchAttribs);
		}

		InputText->SetText(FText::GetEmpty());
	}
#endif
	EntryClicked = NULL;
}
예제 #22
0
void STutorialRoot::HandleBackClicked()
{
	if( FEngineAnalytics::IsAvailable() && CurrentTutorial != nullptr)
	{
		TArray<FAnalyticsEventAttribute> EventAttributes;
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Context.Tutorial"), FIntroTutorials::AnalyticsEventNameFromTutorial(CurrentTutorial)));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Context.StageIndex"), CurrentTutorialStage));

		FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.ClickedBackButton"), EventAttributes );
	}

	GoToPreviousStage();

	for(auto& TutorialWidget : TutorialWidgets)
	{
		if(TutorialWidget.Value.IsValid())
		{
			TSharedPtr<SEditorTutorials> PinnedTutorialWidget = TutorialWidget.Value.Pin();
			PinnedTutorialWidget->RebuildCurrentContent();
		}
	}
}
예제 #23
0
void STutorialRoot::HandleCloseClicked()
{
	if(CurrentTutorial != nullptr)
	{
		CurrentTutorial->HandleTutorialClosed();
		// Update the current stage when we close
		bool bHaveSeenTutorial = false;
		CurrentTutorialStage = GetDefault<UTutorialStateSettings>()->GetProgress(CurrentTutorial, bHaveSeenTutorial);
		GetMutableDefault<UTutorialStateSettings>()->RecordProgress(CurrentTutorial, CurrentTutorialStage);
		GetMutableDefault<UTutorialStateSettings>()->SaveProgress();
	}

	// submit analytics data
	if( FEngineAnalytics::IsAvailable() && CurrentTutorial != nullptr && CurrentTutorialStage < CurrentTutorial->Stages.Num() )
	{
		UEditorTutorial* AttractTutorial = nullptr;
		UEditorTutorial* LaunchTutorial = nullptr;
		FString BrowserFilter;
		GetDefault<UEditorTutorialSettings>()->FindTutorialInfoForContext(TEXT("LevelEditor"), AttractTutorial, LaunchTutorial, BrowserFilter);

		// prepare and send analytics data
		bool const bClosedInitialAttract = (CurrentTutorial == AttractTutorial);

		FString const CurrentExcerptTitle = bClosedInitialAttract ? TEXT("InitialAttract") : CurrentTutorial->Stages[CurrentTutorialStage].Name.ToString();
		int32 const CurrentExcerptIndex = bClosedInitialAttract ? -1 : CurrentTutorialStage;
		float const CurrentPageElapsedTime = bClosedInitialAttract ? 0.f : (float)(FPlatformTime::Seconds() - CurrentTutorialStartTime);

		TArray<FAnalyticsEventAttribute> EventAttributes;
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("LastStageIndex"), CurrentExcerptIndex));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("LastStageTitle"), CurrentExcerptTitle));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TimeSpentInTutorial"), CurrentPageElapsedTime));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TutorialAsset"), FIntroTutorials::AnalyticsEventNameFromTutorial(CurrentTutorial)));
			
		FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.Closed"), EventAttributes );
	}

	//Tutorial is no longer current
	CurrentTutorial = nullptr;
}
void FAnalyticsProviderFlurry::RecordError(const FString& Error, const TArray<FAnalyticsEventAttribute>& EventAttrs)
{
	FString EventName = "Error";

	// Build the dictionary
	TArray<FAnalyticsEventAttribute> AttributesDict;
	AttributesDict.Add(FAnalyticsEventAttribute("Error", Error));
	AttributesDict.Append(EventAttrs);

	// Send the event
	RecordEvent(EventName, AttributesDict);

	UE_LOG(LogAnalytics, Display, TEXT("AndroidFlurry::RecordError('%s', %d)"), *Error, EventAttrs.Num());
}
예제 #25
0
void STutorialRoot::HandleHomeClicked()
{
	if(CurrentTutorial != nullptr)
	{
		CurrentTutorial->HandleTutorialClosed();
		GetMutableDefault<UTutorialStateSettings>()->RecordProgress(CurrentTutorial, CurrentTutorialStage);
		GetMutableDefault<UTutorialStateSettings>()->SaveProgress();
	}

	// submit analytics data
	if( FEngineAnalytics::IsAvailable() && CurrentTutorial != nullptr && CurrentTutorialStage < CurrentTutorial->Stages.Num() )
	{
		FString const CurrentExcerptTitle = CurrentTutorial->Stages[CurrentTutorialStage].Name.ToString();
		int32 const CurrentExcerptIndex = CurrentTutorialStage;
		float const CurrentPageElapsedTime = (float)(FPlatformTime::Seconds() - CurrentTutorialStartTime);

		TArray<FAnalyticsEventAttribute> EventAttributes;
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("LastStageIndex"), CurrentExcerptIndex));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("LastStageTitle"), CurrentExcerptTitle));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TimeSpentInTutorial"), CurrentPageElapsedTime));
		EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TutorialAsset"), FIntroTutorials::AnalyticsEventNameFromTutorial(CurrentTutorial)));
			
		FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.Home"), EventAttributes );
	}

	CurrentTutorial = nullptr;
	CurrentTutorialStage = 0;

	for(auto& TutorialWidget : TutorialWidgets)
	{
		if(TutorialWidget.Value.IsValid())
		{
			TSharedPtr<SEditorTutorials> PinnedTutorialWidget = TutorialWidget.Value.Pin();
			PinnedTutorialWidget->RebuildCurrentContent();
		}
	}
}
예제 #26
0
static void OnBrowserLinkClicked(const FSlateHyperlinkRun::FMetadata& Metadata)
{
	const FString* Url = Metadata.Find(TEXT("href"));
	if(Url)
	{
		if( FEngineAnalytics::IsAvailable() )
		{
			TArray<FAnalyticsEventAttribute> EventAttributes;
			EventAttributes.Add(FAnalyticsEventAttribute(TEXT("BrowserLink"), *Url));

			FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.BrowserLinkClicked"), EventAttributes );
		}

		FPlatformProcess::LaunchURL(**Url, nullptr, nullptr);
	}
}
예제 #27
0
static void OnDocLinkClicked(const FSlateHyperlinkRun::FMetadata& Metadata)
{
	const FString* Url = Metadata.Find(TEXT("href"));
	if(Url)
	{
		if( FEngineAnalytics::IsAvailable() )
		{
			TArray<FAnalyticsEventAttribute> EventAttributes;
			EventAttributes.Add(FAnalyticsEventAttribute(TEXT("DocLink"), *Url));

			FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.DocLinkClicked"), EventAttributes );
		}

		IDocumentation::Get()->Open(*Url, FDocumentationSourceInfo(TEXT("tutorials")));
	}
}
예제 #28
0
static void ParseTutorialLink(const FString &InternalLink)
{
	UBlueprint* Blueprint = LoadObject<UBlueprint>(nullptr, *InternalLink);
	if (Blueprint && Blueprint->GeneratedClass)
	{
		FIntroTutorials& IntroTutorials = FModuleManager::GetModuleChecked<FIntroTutorials>(TEXT("IntroTutorials"));
		IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame"));
		IntroTutorials.LaunchTutorial(Blueprint->GeneratedClass->GetDefaultObject<UEditorTutorial>(), IIntroTutorials::ETutorialStartType::TST_RESTART, MainFrameModule.GetParentWindow());

		if( FEngineAnalytics::IsAvailable() )
		{
			TArray<FAnalyticsEventAttribute> EventAttributes;
			EventAttributes.Add(FAnalyticsEventAttribute(TEXT("TutorialLink"), InternalLink));

			FEngineAnalytics::GetProvider().RecordEvent( TEXT("Rocket.Tutorials.TutorialLinkClicked"), EventAttributes );
		}
	}
}
예제 #29
0
void FEpicSurvey::OpenEpicSurveyWindow()
{
	if ( SurveyWindow.IsValid() )
	{
		SurveyWindow.Pin()->BringToFront();
	}
	else
	{
		auto Window = SNew(SWindow)
			.Title(LOCTEXT( "WindowTitle", "Epic Survey" ))
			.ClientSize(FVector2D(1000.0f, 600.0f))
			.SupportsMaximize(true)
			.SupportsMinimize(false);

		Window->SetOnWindowClosed( FOnWindowClosed::CreateRaw(this, &FEpicSurvey::OnEpicSurveyWindowClosed ) );

		if ( ActiveSurvey->GetInitializationState() == EContentInitializationState::NotStarted )
		{
			ActiveSurvey->Initialize();

			auto* Settings = GetMutableDefault<UEditorSettings>();
			if ( !Settings->InProgressSurveys.Contains( ActiveSurvey->GetIdentifier() ) )
			{
				Settings->InProgressSurveys.Add( ActiveSurvey->GetIdentifier() );
				Settings->PostEditChange();

				if ( FEngineAnalytics::IsAvailable() )
				{
					TArray< FAnalyticsEventAttribute > EventAttributes;

					EventAttributes.Add( FAnalyticsEventAttribute( TEXT("SurveyID"), ActiveSurvey->GetIdentifier().ToString() ) );

					FEngineAnalytics::GetProvider().RecordEvent( TEXT("OpenedSurvey"), EventAttributes);
				}
			}
		}

		Window->SetContent( SNew( SSurvey, SharedThis( this ), ActiveSurvey.ToSharedRef() ) );

		SurveyWindow = Window;

		FSlateApplication::Get().AddWindowAsNativeChild(Window, RootWindow.Pin().ToSharedRef());
	}
}
void FPrimaryCrashProperties::SendAnalytics()
{
	// Connect the crash report client analytics provider.
	FCrashReportAnalytics::Initialize();

	IAnalyticsProvider& Analytics = FCrashReportAnalytics::GetProvider();

	TArray<FAnalyticsEventAttribute> CrashAttributes;

	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "bHasPrimaryData" ), bHasPrimaryData ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "CrashVersion" ), (int32)CrashVersion ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "CrashGUID" ), CrashGUID ) );

	//	AppID = GameName
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "GameName" ), GameName ) );

	//	AppVersion = EngineVersion
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "EngineVersion" ), EngineVersion.ToString() ) );

	// @see UpdateIDs()
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "MachineID" ), MachineId.AsString() ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "UserName" ), UserName.AsString() ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "EpicAccountId" ), EpicAccountId.AsString() ) );

	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "Platform" ), PlatformFullName.AsString() ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "TimeOfCrash" ), TimeOfCrash.AsString() ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "EngineMode" ), EngineMode ) );
	CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "AppDefaultLocale" ), AppDefaultLocale ) );

	Analytics.RecordEvent( TEXT( "CrashReportClient.ReportCrash" ), CrashAttributes );

	// Shutdown analytics.
	FCrashReportAnalytics::Shutdown();
}