| | using System; |
| | using System.Collections.Generic; |
| | using System.Diagnostics; |
| | using Unity.MLAgents.Actuators; |
| | using Unity.MLAgents.Sensors; |
| | using UnityEngine; |
| | #if MLA_UNITY_ANALYTICS_MODULE |
| |
|
| | #if ENABLE_CLOUD_SERVICES_ANALYTICS |
| | using UnityEngine.Analytics; |
| | #endif |
| |
|
| | #if UNITY_EDITOR |
| | using UnityEditor.Analytics; |
| | #endif |
| | #endif |
| |
|
| | #if UNITY_EDITOR |
| | using UnityEditor; |
| | #endif |
| |
|
| | namespace Unity.MLAgents.Analytics |
| | { |
| | internal static class TrainingAnalytics |
| | { |
| | const string k_VendorKey = "unity.ml-agents"; |
| | const string k_TrainingEnvironmentInitializedEventName = "ml_agents_training_environment_initialized"; |
| | const string k_TrainingBehaviorInitializedEventName = "ml_agents_training_behavior_initialized"; |
| | const string k_RemotePolicyInitializedEventName = "ml_agents_remote_policy_initialized"; |
| |
|
| | private static readonly string[] s_EventNames = |
| | { |
| | k_TrainingEnvironmentInitializedEventName, |
| | k_TrainingBehaviorInitializedEventName, |
| | k_RemotePolicyInitializedEventName |
| | }; |
| |
|
| | |
| | |
| | |
| | const int k_MaxEventsPerHour = 1000; |
| |
|
| | |
| | |
| | |
| | const int k_MaxNumberOfElements = 1000; |
| |
|
| | private static bool s_SentEnvironmentInitialized; |
| |
|
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | |
| | |
| | |
| | static bool s_EventsRegistered; |
| |
|
| | |
| | |
| | |
| | private static HashSet<string> s_SentRemotePolicyInitialized; |
| | private static HashSet<string> s_SentTrainingBehaviorInitialized; |
| | #endif |
| |
|
| | private static Guid s_TrainingSessionGuid; |
| |
|
| | |
| | private static string s_TrainerPackageVersion = ""; |
| | private static string s_TrainerCommunicationVersion = ""; |
| |
|
| | internal static bool EnableAnalytics() |
| | { |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | if (s_EventsRegistered) |
| | { |
| | return true; |
| | } |
| | foreach (var eventName in s_EventNames) |
| | { |
| | AnalyticsResult result = EditorAnalytics.RegisterEventWithLimit(eventName, k_MaxEventsPerHour, k_MaxNumberOfElements, k_VendorKey); |
| | if (result != AnalyticsResult.Ok) |
| | { |
| | return false; |
| | } |
| | } |
| | s_EventsRegistered = true; |
| |
|
| | if (s_SentRemotePolicyInitialized == null) |
| | { |
| | s_SentRemotePolicyInitialized = new HashSet<string>(); |
| | s_SentTrainingBehaviorInitialized = new HashSet<string>(); |
| | s_TrainingSessionGuid = Guid.NewGuid(); |
| | } |
| |
|
| | return s_EventsRegistered; |
| | #else |
| | return false; |
| | #endif // MLA_UNITY_ANALYTICS_MODULE |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | [Conditional("MLA_UNITY_ANALYTICS_MODULE")] |
| | public static void SetTrainerInformation(string packageVersion, string communicationVersion) |
| | { |
| | s_TrainerPackageVersion = packageVersion; |
| | s_TrainerCommunicationVersion = communicationVersion; |
| | } |
| |
|
| | public static bool IsAnalyticsEnabled() |
| | { |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | return EditorAnalytics.enabled; |
| | #else |
| | return false; |
| | #endif |
| | } |
| |
|
| | [Conditional("MLA_UNITY_ANALYTICS_MODULE")] |
| | public static void TrainingEnvironmentInitialized(TrainingEnvironmentInitializedEvent tbiEvent) |
| | { |
| | if (!IsAnalyticsEnabled()) |
| | return; |
| |
|
| | if (!EnableAnalytics()) |
| | return; |
| |
|
| | if (s_SentEnvironmentInitialized) |
| | { |
| | |
| | return; |
| | } |
| |
|
| | s_SentEnvironmentInitialized = true; |
| | tbiEvent.TrainingSessionGuid = s_TrainingSessionGuid.ToString(); |
| |
|
| | |
| | |
| | |
| | |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | if (AnalyticsUtils.s_SendEditorAnalytics) |
| | { |
| | EditorAnalytics.SendEventWithLimit(k_TrainingEnvironmentInitializedEventName, tbiEvent); |
| | } |
| | #endif |
| | } |
| |
|
| | [Conditional("MLA_UNITY_ANALYTICS_MODULE")] |
| | public static void RemotePolicyInitialized( |
| | string fullyQualifiedBehaviorName, |
| | IList<ISensor> sensors, |
| | ActionSpec actionSpec, |
| | IList<IActuator> actuators |
| | ) |
| | { |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | if (!IsAnalyticsEnabled()) |
| | return; |
| |
|
| | if (!EnableAnalytics()) |
| | return; |
| |
|
| | |
| | var behaviorName = ParseBehaviorName(fullyQualifiedBehaviorName); |
| | var added = s_SentRemotePolicyInitialized.Add(behaviorName); |
| |
|
| | if (!added) |
| | { |
| | |
| | return; |
| | } |
| |
|
| | var data = GetEventForRemotePolicy(behaviorName, sensors, actionSpec, actuators); |
| | |
| | |
| | |
| | |
| | if (AnalyticsUtils.s_SendEditorAnalytics) |
| | { |
| | EditorAnalytics.SendEventWithLimit(k_RemotePolicyInitializedEventName, data); |
| | } |
| | #endif |
| | } |
| |
|
| | internal static string ParseBehaviorName(string fullyQualifiedBehaviorName) |
| | { |
| | var lastQuestionIndex = fullyQualifiedBehaviorName.LastIndexOf("?"); |
| | if (lastQuestionIndex < 0) |
| | { |
| | |
| | return fullyQualifiedBehaviorName; |
| | } |
| |
|
| | return fullyQualifiedBehaviorName.Substring(0, lastQuestionIndex); |
| | } |
| |
|
| | internal static TrainingBehaviorInitializedEvent SanitizeTrainingBehaviorInitializedEvent(TrainingBehaviorInitializedEvent tbiEvent) |
| | { |
| | |
| | |
| | |
| | if (tbiEvent.Config.Length == 0 || tbiEvent.BehaviorName.Length != 64) |
| | { |
| | tbiEvent.BehaviorName = AnalyticsUtils.Hash(k_VendorKey, tbiEvent.BehaviorName); |
| | } |
| |
|
| | return tbiEvent; |
| | } |
| |
|
| | [Conditional("MLA_UNITY_ANALYTICS_MODULE")] |
| | public static void TrainingBehaviorInitialized(TrainingBehaviorInitializedEvent rawTbiEvent) |
| | { |
| | #if UNITY_EDITOR && MLA_UNITY_ANALYTICS_MODULE && ENABLE_CLOUD_SERVICES_ANALYTICS |
| | if (!IsAnalyticsEnabled()) |
| | return; |
| |
|
| | if (!EnableAnalytics()) |
| | return; |
| |
|
| | var tbiEvent = SanitizeTrainingBehaviorInitializedEvent(rawTbiEvent); |
| | var behaviorName = tbiEvent.BehaviorName; |
| | var added = s_SentTrainingBehaviorInitialized.Add(behaviorName); |
| |
|
| | if (!added) |
| | { |
| | |
| | return; |
| | } |
| |
|
| | tbiEvent.TrainingSessionGuid = s_TrainingSessionGuid.ToString(); |
| |
|
| | |
| | |
| | |
| | |
| | if (AnalyticsUtils.s_SendEditorAnalytics) |
| | { |
| | EditorAnalytics.SendEventWithLimit(k_TrainingBehaviorInitializedEventName, tbiEvent); |
| | } |
| | #endif |
| | } |
| |
|
| | internal static RemotePolicyInitializedEvent GetEventForRemotePolicy( |
| | string behaviorName, |
| | IList<ISensor> sensors, |
| | ActionSpec actionSpec, |
| | IList<IActuator> actuators |
| | ) |
| | { |
| | var remotePolicyEvent = new RemotePolicyInitializedEvent(); |
| |
|
| | |
| | remotePolicyEvent.BehaviorName = AnalyticsUtils.Hash(k_VendorKey, behaviorName); |
| |
|
| | remotePolicyEvent.TrainingSessionGuid = s_TrainingSessionGuid.ToString(); |
| | remotePolicyEvent.ActionSpec = EventActionSpec.FromActionSpec(actionSpec); |
| | remotePolicyEvent.ObservationSpecs = new List<EventObservationSpec>(sensors.Count); |
| | foreach (var sensor in sensors) |
| | { |
| | remotePolicyEvent.ObservationSpecs.Add(EventObservationSpec.FromSensor(sensor)); |
| | } |
| |
|
| | remotePolicyEvent.ActuatorInfos = new List<EventActuatorInfo>(actuators.Count); |
| | foreach (var actuator in actuators) |
| | { |
| | remotePolicyEvent.ActuatorInfos.Add(EventActuatorInfo.FromActuator(actuator)); |
| | } |
| |
|
| | remotePolicyEvent.MLAgentsEnvsVersion = s_TrainerPackageVersion; |
| | remotePolicyEvent.TrainerCommunicationVersion = s_TrainerCommunicationVersion; |
| | return remotePolicyEvent; |
| | } |
| | } |
| | } |
| |
|