123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- /// <summary>
- /// This is a simple logger override, that will catch any AVDebug.LogXXX calls. It also exposes some simple wrappers
- /// for logging events in Flurry.
- /// To use it simply drag the Logger prefa into your first scene, and will continue to exist across scenes.
- ///
- /// It keeps track of the logs in a StringBuilder, which can then be viewed through Show Log button in
- /// the Debug Menu, through DebugViewManager and build must have DEBUG set in Scripting Define Symbols.
- /// The player can also Copy Log (in Web Build only, since we don't have access to clipboard in iOS or Android)
- ///
- /// It also keeps track of the last exception, which can be emailed through Email Last Exception button in
- /// the Debug Menu, through DebugViewManager and build must have DEBUG set in Scripting Define Symbols
- ///
- /// You can also halt the application on the first exception that occurs and show the Crash scene where they
- /// have access to the Debug Menu. DEBUG;HALT_ON_EXCEPTION must be set in Scripting Define Symbols.
- /// On iOS, Script Call Optimization must be set to Slow and Safe (otherwise it will crash the application)
- /// We only should use this when we have an issue with some client and want to get the stack trace of their
- /// crash
- ///
- /// ALWAYS MAKE SURE THAT ON RELEASE, TO HAVE Scripting Define Symbols EMPTY AND ON iOS TO HAVE Script Call Optimization
- /// SET TO FAST & FURIOUS.
- /// </summary>
- public class Logger : MonoBehaviour
- {
- #region Unity Singleton
- private static Logger _instance;
- public static Logger Instance
- {
- get
- {
- if (_instance == null)
- {
- _instance = FindObjectOfType(typeof(Logger)) as Logger;
- if (_instance == null)
- {
- AVDebug.LogError(string.Format("No gameObject with {0} component exists. Make sure to create a gameObject with {0} component", new System.Diagnostics.StackFrame().GetMethod().DeclaringType));
- }
- }
- return _instance;
- }
- }
- void Awake()
- {
- if (_instance != null && _instance != this)
- {
- AVDebug.LogWarning(string.Format("{0} Instance already exists on another gameObject. Destroying this gameObject {1}", this.GetType().Name, gameObject.name));
- Destroy(gameObject);
- return;
- }
- _instance = this;
- DontDestroyOnLoad(gameObject);
- }
- #endregion
- static StringBuilder log = new StringBuilder();
- Vector2 _logScrollPosition;
- bool _isShowingLog;
- public GUIStyle logBackgroundStyle;
- string _lastException;
- const int MAX_URL_SIZE = 2083; //According to http://stackoverflow.com/questions/4067391/getting-around-mailto-href-url-character-limit
- #region Unity Callbacks
- void OnEnable()
- {
- Application.logMessageReceived+=(LogCallbackHandler);
- DebugViewManager.OnDebugView += OnDebugView;
- }
- void OnDisable()
- {
- Application.logMessageReceived += (null);
- DebugViewManager.OnDebugView -= OnDebugView;
- }
- #endregion
- void LogCallbackHandler(string logString, string stackTrace, LogType type)
- {
- StackTrace s = new StackTrace(true);
- string logMessage = type + ": " + logString + "\n" + s.ToString();
- Log(logMessage);
- //Crash reporting based on this http://entitycrisis.blogspot.com/2011/01/error-reporting-from-your-unity3d-game.html
- if (type == LogType.Exception &&
- !logString.Contains("SocketException")) // Don't make it stop cause of a socket exception (as this would not allow to play offline)
- {
- _lastException = logMessage;
- #if HALT_ON_EXCEPTION
- Application.LoadLevel("Crash");
- #endif
- }
- }
- [System.Diagnostics.Conditional("DEBUG")]
- private static void Log(string message)
- {
- log.AppendLine(message);
- log.AppendLine();
- #if UNITY_WEBPLAYER
- Application.ExternalCall("LogMessage",message);
- #endif
- }
- public static void LogFlurryEvent(string eventName, params string[] keyValues)
- {
- #if UNITY_IPHONE || UNITY_ANDROID
- AVDebug.Assert(keyValues.Length % 2 == 0, "Make sure to pass key value pairs");
- var parameters = new Dictionary<string, string>();
- for (int i = 0; i < keyValues.Length; i += 2)
- {
- parameters[keyValues[i]] = keyValues[i + 1];
- }
- #if UNITY_IPHONE
- FlurryLogger.Instance.LogFlurryEvent(eventName, keyValues);
- #elif UNITY_ANDROID && !UNITY_EDITOR
- FlurryLogger.Instance.LogFlurryEvent(eventName, keyValues);
- //FlurryAndroid.logEvent(eventName, parameters, false);
- #endif
- #elif UNITY_WEBPLAYER
- Application.ExternalCall("LogFlurryEventWithParameters", eventName, keyValues);
- #endif
- //#if UNITY_IPHONE
- // FlurryBinding.logEvent(eventName, false);
- //#elif UNITY_ANDROID
- // FlurryLogger.Instance.LogFlurryEvent(eventName);
- // #elif UNITY_WEBPLAYER
- // Application.ExternalCall("LogFlurryEvent", eventName);
- // #endif
- }
- /*public static void LogFlurryEvent(string eventName, params string[] keyValues)
- {
- #if UNITY_IPHONE || UNITY_ANDROID
- AVDebug.Assert(keyValues.Length % 2 == 0, "Make sure to pass key value pairs");
- var parameters = new Dictionary<string, string>();
- for (int i = 0; i < keyValues.Length; i += 2)
- {
- parameters[keyValues[i]] = keyValues[i+1];
- }
- #if UNITY_IPHONE
- FlurryBinding.logEventWithParameters(eventName, parameters, false);
- #elif UNITY_ANDROID
- FlurryAndroid.logEvent(eventName, parameters, false);
- #endif
- #elif UNITY_WEBPLAYER
- Application.ExternalCall("LogFlurryEventWithParameters", eventName, keyValues);
- #endif
- }*/
- void OnDebugView()
- {
- if (_isShowingLog)
- {
- if (GUILayout.Button("Hide Log"))
- {
- _isShowingLog = false;
- }
- _logScrollPosition = GUILayout.BeginScrollView(_logScrollPosition, logBackgroundStyle, GUILayout.Width(Screen.width), GUILayout.Height(400));
- GUILayout.Label(log.ToString(), GUILayout.Width(2048));
- GUILayout.EndScrollView();
- }
- else
- {
- if (GUILayout.Button("Show Log"))
- {
- _isShowingLog = true;
- }
- }
- GUILayout.BeginHorizontal();
- if (GUILayout.Button("Clear Log"))
- {
- log = new StringBuilder();
- }
- #if UNITY_WEBPLAYER
- if (GUILayout.Button("Copy Log"))
- {
- //from http://forum.unity3d.com/threads/24101-Copy-TextField-or-TextArea-text-to-Clipboard
- TextEditor te = new TextEditor();
- te.content = new GUIContent(log.ToString());
- te.SelectAll();
- te.Copy();
- }
- #endif
- if (_lastException != null &&
- GUILayout.Button("Email Last Exception"))
- {
- string emailURL = "mailto:"+GameConstants.SUPPORT_EMAIL_FOR_IOS_CRASH_LOG+"?subject="+WWW.EscapeURL(GameConstants.GAME_NAME)+"%20log&body="+WWW.EscapeURL(_lastException);
- if (emailURL.Length > MAX_URL_SIZE) //which seems to be the limit of IE
- {
- emailURL.Substring(0, MAX_URL_SIZE);
- }
- Application.OpenURL(emailURL);
- }
- GUILayout.EndHorizontal();
- }
- }
|