| 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; |
| } |
| } |
| } |
|
|