using System;
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
using UnityEngine.Analytics;
namespace Unity.Play.Publisher.Editor
{
///
/// Options for representing the result of the upload process
///
public enum UploadResult
{
///
/// The upload process was manually interrupted by the user
///
Cancelled,
///
/// The upload process was automatically interrupted by an error
///
Failed,
///
/// The upload process succeeded
///
Succeeded
}
class AnalyticsHelper : ScriptableObject
{
const int MaxEventsPerHour = 1000;
const int MaxNumberOfElements = 1000;
const string VendorKey = "unity.webglPublisher"; // the format needs to be "unity.xxx"
const string EventBuildStarted = "webglPublisher_buildStarted";
const string EventBuildCompleted = "webglPublisher_buildCompleted";
const string EventUploadStarted = "webglPublisher_uploadStarted";
const string EventUploadCompleted = "webglPublisher_uploadCompleted";
const string EventButtonClicked = "webglPublisher_buttonClicked";
static string ProjectID
{
get
{
//we use a combination of company name + product name to reduce the chance of clash with other projects
return string.IsNullOrEmpty(CloudProjectSettings.projectId) ? string.Format("{0}_{1}", PlayerSettings.companyName, PlayerSettings.productName)
: CloudProjectSettings.projectId;
}
}
DateTime lastBuildStartTime;
DateTime lastUploadStartTime;
///
/// The instance of the analytics helper
///
public static AnalyticsHelper Instance
{
get
{
if (!s_Instance)
{
var instance = Resources.FindObjectsOfTypeAll();
if (instance.Length == 0)
{
s_Instance = CreateInstance();
s_Instance.hideFlags = HideFlags.HideAndDontSave;
}
else
{
s_Instance = instance[0] as AnalyticsHelper;
}
}
return s_Instance;
}
}
static AnalyticsHelper s_Instance;
static void DebugWarning(string message, params object[] args)
{
#if DEBUG_TUTORIALS
Debug.LogWarningFormat(message, args);
#endif
}
static void DebugLog(string message, params object[] args)
{
#if DEBUG_TUTORIALS
Debug.LogFormat(message, args);
#endif
}
static void DebugError(string message, params object[] args)
{
#if DEBUG_TUTORIALS
Debug.LogErrorFormat(message, args);
#endif
}
internal static void BuildStarted(bool fromTool)
{
Instance.lastBuildStartTime = DateTime.UtcNow;
SendBuildStartedEvent(ProjectID, fromTool);
}
internal static void BuildCompleted(BuildResult result)
{
BuildCompleted(result, DateTime.UtcNow - Instance.lastBuildStartTime);
}
internal static void BuildCompleted(BuildResult result, TimeSpan lastBuildDuration)
{
SendBuildCompletedEvent(ProjectID, lastBuildDuration, result);
}
internal static void UploadStarted()
{
Instance.lastUploadStartTime = DateTime.UtcNow;
SendUploadStartedEvent(ProjectID);
}
internal static void UploadCompleted(UploadResult result)
{
TimeSpan lastUploadDuration = DateTime.UtcNow - Instance.lastUploadStartTime;
SendUploadCompletedEvent(ProjectID, lastUploadDuration, result);
}
///
/// Tracks the click on a specific button
///
///
internal static void ButtonClicked(string buttonID)
{
SendButtonClickedEvent(ProjectID, buttonID);
}
#region Events Structure
public struct BuildStartedEventData
{
public int ts; // timestamp
public string id;
public bool fromTool;
}
public struct BuildCompletedEventData
{
public int ts; // timestamp
public string id;
public int duration;
public int result;
}
public struct UploadStartedEventData
{
public int ts; // timestamp
public string id;
}
public struct UploadCompletedEventData
{
public int ts; // timestamp
public string id;
public int duration;
public int result;
}
public struct ButtonClickedEventData
{
public int ts; // timestamp
public string id;
public string buttonID;
}
public static AnalyticsResult SendBuildCompletedEvent(string projectID, TimeSpan duration, BuildResult result)
{
if (!EditorAnalytics.enabled || !RegisterEvent(EventBuildCompleted)) { return AnalyticsResult.AnalyticsDisabled; }
var data = new BuildCompletedEventData
{
ts = DateTime.UtcNow.Millisecond,
id = projectID,
duration = (int)duration.TotalSeconds,
result = (int)result
};
return SendEvent(EventBuildCompleted, data);
}
public static AnalyticsResult SendBuildStartedEvent(string projectID, bool fromTool)
{
if (!EditorAnalytics.enabled || !RegisterEvent(EventBuildStarted)) { return AnalyticsResult.AnalyticsDisabled; }
var data = new BuildStartedEventData
{
ts = DateTime.UtcNow.Millisecond,
id = projectID,
fromTool = fromTool
};
return SendEvent(EventBuildStarted, data);
}
public static AnalyticsResult SendUploadCompletedEvent(string projectID, TimeSpan duration, UploadResult result)
{
if (!EditorAnalytics.enabled || !RegisterEvent(EventUploadCompleted)) { return AnalyticsResult.AnalyticsDisabled; }
var data = new UploadCompletedEventData
{
ts = DateTime.UtcNow.Millisecond,
id = projectID,
duration = (int)duration.TotalSeconds,
result = (int)result
};
return SendEvent(EventUploadCompleted, data);
}
public static AnalyticsResult SendUploadStartedEvent(string projectID)
{
if (!EditorAnalytics.enabled || !RegisterEvent(EventUploadStarted)) { return AnalyticsResult.AnalyticsDisabled; }
var data = new UploadStartedEventData
{
ts = DateTime.UtcNow.Millisecond,
id = projectID
};
return SendEvent(EventUploadStarted, data);
}
public static AnalyticsResult SendButtonClickedEvent(string projectID, string buttonID)
{
if (!EditorAnalytics.enabled || !RegisterEvent(EventButtonClicked)) { return AnalyticsResult.AnalyticsDisabled; }
var data = new ButtonClickedEventData
{
ts = DateTime.UtcNow.Millisecond,
id = projectID,
buttonID = buttonID
};
return SendEvent(EventButtonClicked, data);
}
#endregion
static bool RegisterEvent(string name)
{
AnalyticsResult result = EditorAnalytics.RegisterEventWithLimit(name, MaxEventsPerHour, MaxNumberOfElements, VendorKey);
if (result != AnalyticsResult.Ok)
{
DebugError("Error in RegisterEvent: {0}", result);
return false;
}
return true;
}
static AnalyticsResult SendEvent(string eventName, object parameters)
{
AnalyticsResult result = EditorAnalytics.SendEventWithLimit(eventName, parameters);
if (result != AnalyticsResult.Ok)
{
DebugError("Error in {0}: {1}", eventName, result);
}
return result;
}
}
}