You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
13 KiB
C#
374 lines
13 KiB
C#
1 year ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEditor.Analytics;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Analytics;
|
||
|
|
||
|
namespace UnityEditor.Performance.ProfileAnalyzer
|
||
|
{
|
||
|
class ProfileAnalyzerAnalytics
|
||
|
{
|
||
|
const int k_MaxEventsPerHour = 100;
|
||
|
const int k_MaxEventItems = 1000;
|
||
|
const string k_VendorKey = "unity.profileanalyzer";
|
||
|
const string k_EventTopicName = "usability";
|
||
|
|
||
|
static bool s_EnableAnalytics = false;
|
||
|
|
||
|
public static void EnableAnalytics()
|
||
|
{
|
||
|
AnalyticsResult result = EditorAnalytics.RegisterEventWithLimit(k_EventTopicName, k_MaxEventsPerHour, k_MaxEventItems, k_VendorKey);
|
||
|
if (result == AnalyticsResult.Ok)
|
||
|
s_EnableAnalytics = true;
|
||
|
}
|
||
|
|
||
|
public enum UIButton
|
||
|
{
|
||
|
Pull,
|
||
|
OpenProfiler,
|
||
|
CloseProfiler,
|
||
|
JumpToFrame,
|
||
|
ExportSingleFrames,
|
||
|
ExportComparisonFrames,
|
||
|
};
|
||
|
|
||
|
public enum UIUsageMode
|
||
|
{
|
||
|
Single,
|
||
|
Comparison,
|
||
|
};
|
||
|
|
||
|
public enum UIVisibility
|
||
|
{
|
||
|
FrameTimeContextMenu,
|
||
|
Filters,
|
||
|
TopTen,
|
||
|
Frames,
|
||
|
Threads,
|
||
|
Markers,
|
||
|
};
|
||
|
|
||
|
public enum UIResizeView
|
||
|
{
|
||
|
Single,
|
||
|
Comparison,
|
||
|
};
|
||
|
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIButtonEventParameters
|
||
|
{
|
||
|
public string name;
|
||
|
|
||
|
public ProfileAnalyzerUIButtonEventParameters(string name)
|
||
|
{
|
||
|
this.name = name;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// camelCase since these events get serialized to Json and naming convention in analytics is camelCase
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIButtonEvent
|
||
|
{
|
||
|
public ProfileAnalyzerUIButtonEvent(string name, float durationInTicks)
|
||
|
{
|
||
|
subtype = "profileAnalyzerUIButton";
|
||
|
|
||
|
// ts is auto added so no need to include it here
|
||
|
//ts = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
|
||
|
this.duration = durationInTicks;
|
||
|
|
||
|
parameters = new ProfileAnalyzerUIButtonEventParameters(name);
|
||
|
}
|
||
|
|
||
|
public string subtype;
|
||
|
//public int ts;
|
||
|
public float duration; // Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
public ProfileAnalyzerUIButtonEventParameters parameters;
|
||
|
}
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIUsageEventParameters
|
||
|
{
|
||
|
public string name;
|
||
|
|
||
|
public ProfileAnalyzerUIUsageEventParameters(string name)
|
||
|
{
|
||
|
this.name = name;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIUsageEvent
|
||
|
{
|
||
|
public ProfileAnalyzerUIUsageEvent(string name, float durationInTicks)
|
||
|
{
|
||
|
subtype = "profileAnalyzerModeUsage";
|
||
|
|
||
|
this.duration = durationInTicks;
|
||
|
|
||
|
parameters = new ProfileAnalyzerUIUsageEventParameters(name);
|
||
|
}
|
||
|
|
||
|
public string subtype;
|
||
|
public float duration; // Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
public ProfileAnalyzerUIUsageEventParameters parameters;
|
||
|
}
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIVisibilityEventParameters
|
||
|
{
|
||
|
public string name;
|
||
|
public bool show;
|
||
|
|
||
|
public ProfileAnalyzerUIVisibilityEventParameters(string name, bool show)
|
||
|
{
|
||
|
this.name = name;
|
||
|
this.show = show;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIVisibilityEvent
|
||
|
{
|
||
|
public ProfileAnalyzerUIVisibilityEvent(string name, float durationInTicks, bool show)
|
||
|
{
|
||
|
subtype = "profileAnalyzerUIVisibility";
|
||
|
|
||
|
this.duration = durationInTicks;
|
||
|
|
||
|
parameters = new ProfileAnalyzerUIVisibilityEventParameters(name, show);
|
||
|
}
|
||
|
|
||
|
public string subtype;
|
||
|
public float duration; // Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
public ProfileAnalyzerUIVisibilityEventParameters parameters;
|
||
|
}
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIResizeEventParameters
|
||
|
{
|
||
|
public string name;
|
||
|
public float width;
|
||
|
public float height;
|
||
|
public float screenWidth;
|
||
|
public float screenHeight;
|
||
|
public bool docked;
|
||
|
|
||
|
public ProfileAnalyzerUIResizeEventParameters(string name, float width, float height, float screenWidth, float screenHeight, bool isDocked)
|
||
|
{
|
||
|
this.name = name;
|
||
|
this.width = width;
|
||
|
this.height = height;
|
||
|
this.screenWidth = screenWidth;
|
||
|
this.screenHeight = screenHeight;
|
||
|
docked = isDocked;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[Serializable]
|
||
|
struct ProfileAnalyzerUIResizeEvent
|
||
|
{
|
||
|
public ProfileAnalyzerUIResizeEvent(string name, float durationInTicks, float width, float height, float screenWidth, float screenHeight, bool isDocked)
|
||
|
{
|
||
|
subtype = "profileAnalyzerUIResize";
|
||
|
|
||
|
this.duration = durationInTicks;
|
||
|
|
||
|
parameters = new ProfileAnalyzerUIResizeEventParameters(name, width, height, screenWidth, screenHeight, isDocked);
|
||
|
}
|
||
|
|
||
|
public string subtype;
|
||
|
public float duration; // Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
public ProfileAnalyzerUIResizeEventParameters parameters;
|
||
|
}
|
||
|
|
||
|
static float SecondsToTicks(float durationInSeconds)
|
||
|
{
|
||
|
return durationInSeconds * 10000;
|
||
|
}
|
||
|
|
||
|
public static bool SendUIButtonEvent(UIButton uiButton, float durationInSeconds)
|
||
|
{
|
||
|
if (!s_EnableAnalytics)
|
||
|
return false;
|
||
|
|
||
|
// Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
float durationInTicks = SecondsToTicks(durationInSeconds);
|
||
|
|
||
|
ProfileAnalyzerUIButtonEvent uiButtonEvent;
|
||
|
switch (uiButton)
|
||
|
{
|
||
|
case UIButton.Pull:
|
||
|
uiButtonEvent = new ProfileAnalyzerUIButtonEvent("profilerAnalyzerGrab", durationInTicks);
|
||
|
break;
|
||
|
case UIButton.OpenProfiler:
|
||
|
uiButtonEvent = new ProfileAnalyzerUIButtonEvent("profilerAnalyzerOpenProfiler", durationInTicks);
|
||
|
break;
|
||
|
case UIButton.CloseProfiler:
|
||
|
uiButtonEvent = new ProfileAnalyzerUIButtonEvent("profilerAnalyzerCloseProfiler", durationInTicks);
|
||
|
break;
|
||
|
case UIButton.JumpToFrame:
|
||
|
uiButtonEvent = new ProfileAnalyzerUIButtonEvent("profilerAnalyzerJumpToFrame", durationInTicks);
|
||
|
break;
|
||
|
case UIButton.ExportSingleFrames:
|
||
|
uiButtonEvent = new ProfileAnalyzerUIButtonEvent("profilerAnalyzerExportSingleFrames", durationInTicks);
|
||
|
break;
|
||
|
case UIButton.ExportComparisonFrames:
|
||
|
uiButtonEvent = new ProfileAnalyzerUIButtonEvent("profilerAnalyzerExportComparisonFrames", durationInTicks);
|
||
|
break;
|
||
|
default:
|
||
|
Debug.LogFormat("SendUIButtonEvent: Unsupported button type : {0}", uiButton);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
AnalyticsResult result = EditorAnalytics.SendEventWithLimit(k_EventTopicName, uiButtonEvent);
|
||
|
if (result != AnalyticsResult.Ok)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public static bool SendUIUsageModeEvent(UIUsageMode uiUsageMode, float durationInSeconds)
|
||
|
{
|
||
|
if (!s_EnableAnalytics)
|
||
|
return false;
|
||
|
|
||
|
// Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
float durationInTicks = SecondsToTicks(durationInSeconds);
|
||
|
|
||
|
ProfileAnalyzerUIUsageEvent uiUsageEvent;
|
||
|
switch (uiUsageMode)
|
||
|
{
|
||
|
case UIUsageMode.Single:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIUsageEvent("profileAnalyzerSingle", durationInTicks);
|
||
|
break;
|
||
|
case UIUsageMode.Comparison:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIUsageEvent("profileAnalyzerCompare", durationInTicks);
|
||
|
break;
|
||
|
default:
|
||
|
Debug.LogFormat("SendUsageEvent: Unsupported usage mode : {0}", uiUsageMode);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
AnalyticsResult result = EditorAnalytics.SendEventWithLimit(k_EventTopicName, uiUsageEvent);
|
||
|
if (result != AnalyticsResult.Ok)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public static bool SendUIVisibilityEvent(UIVisibility uiVisibility, float durationInSeconds, bool show)
|
||
|
{
|
||
|
if (!s_EnableAnalytics)
|
||
|
return false;
|
||
|
|
||
|
// Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
float durationInTicks = SecondsToTicks(durationInSeconds);
|
||
|
|
||
|
ProfileAnalyzerUIVisibilityEvent uiUsageEvent;
|
||
|
switch (uiVisibility)
|
||
|
{
|
||
|
case UIVisibility.FrameTimeContextMenu:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIVisibilityEvent("profilerAnalyzerFrameTimeContextMenu", durationInTicks, show);
|
||
|
break;
|
||
|
case UIVisibility.Filters:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIVisibilityEvent("profilerAnalyzerFilters", durationInTicks, show);
|
||
|
break;
|
||
|
case UIVisibility.TopTen:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIVisibilityEvent("profilerAnalyzerTopTen", durationInTicks, show);
|
||
|
break;
|
||
|
case UIVisibility.Frames:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIVisibilityEvent("profilerAnalyzerFrames", durationInTicks, show);
|
||
|
break;
|
||
|
case UIVisibility.Threads:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIVisibilityEvent("profilerAnalyzerThreads", durationInTicks, show);
|
||
|
break;
|
||
|
case UIVisibility.Markers:
|
||
|
uiUsageEvent = new ProfileAnalyzerUIVisibilityEvent("profilerAnalyzerMarkers", durationInTicks, show);
|
||
|
break;
|
||
|
default:
|
||
|
Debug.LogFormat("SendUIVisibilityEvent: Unsupported visibililty item : {0}", uiVisibility);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
AnalyticsResult result = EditorAnalytics.SendEventWithLimit(k_EventTopicName, uiUsageEvent);
|
||
|
if (result != AnalyticsResult.Ok)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public static bool SendUIResizeEvent(UIResizeView uiResizeView, float durationInSeconds, float width, float height, bool isDocked)
|
||
|
{
|
||
|
if (!s_EnableAnalytics)
|
||
|
return false;
|
||
|
|
||
|
// Duration is in "ticks" 100 nanosecond intervals. I.e. 0.1 microseconds
|
||
|
float durationInTicks = SecondsToTicks(durationInSeconds);
|
||
|
|
||
|
ProfileAnalyzerUIResizeEvent uiResizeEvent;
|
||
|
switch (uiResizeView)
|
||
|
{
|
||
|
case UIResizeView.Single:
|
||
|
// Screen.width, Screen.height is game view size
|
||
|
uiResizeEvent = new ProfileAnalyzerUIResizeEvent("profileAnalyzerSingle", durationInTicks, width, height, Screen.currentResolution.width, Screen.currentResolution.height, isDocked);
|
||
|
break;
|
||
|
case UIResizeView.Comparison:
|
||
|
uiResizeEvent = new ProfileAnalyzerUIResizeEvent("profileAnalyzerCompare", durationInTicks, width, height, Screen.currentResolution.width, Screen.currentResolution.height, isDocked);
|
||
|
break;
|
||
|
default:
|
||
|
Debug.LogFormat("SendUIResizeEvent: Unsupported view : {0}", uiResizeView);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
AnalyticsResult result = EditorAnalytics.SendEventWithLimit(k_EventTopicName, uiResizeEvent);
|
||
|
if (result != AnalyticsResult.Ok)
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
internal class Analytic
|
||
|
{
|
||
|
double m_StartTime;
|
||
|
float m_DurationInSeconds;
|
||
|
|
||
|
public Analytic()
|
||
|
{
|
||
|
m_StartTime = EditorApplication.timeSinceStartup;
|
||
|
m_DurationInSeconds = 0;
|
||
|
}
|
||
|
|
||
|
public void End()
|
||
|
{
|
||
|
m_DurationInSeconds = (float)(EditorApplication.timeSinceStartup - m_StartTime);
|
||
|
}
|
||
|
|
||
|
public float GetDurationInSeconds()
|
||
|
{
|
||
|
return m_DurationInSeconds;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static public Analytic BeginAnalytic()
|
||
|
{
|
||
|
return new Analytic();
|
||
|
}
|
||
|
|
||
|
static public void SendUIButtonEvent(UIButton uiButton, Analytic instance)
|
||
|
{
|
||
|
instance.End();
|
||
|
SendUIButtonEvent(uiButton, instance.GetDurationInSeconds());
|
||
|
}
|
||
|
|
||
|
static public void SendUIUsageModeEvent(UIUsageMode uiUsageMode, Analytic instance)
|
||
|
{
|
||
|
instance.End();
|
||
|
SendUIUsageModeEvent(uiUsageMode, instance.GetDurationInSeconds());
|
||
|
}
|
||
|
}
|
||
|
}
|