Logger.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. using UnityEngine;
  2. using System.IO;
  3. using System.Text;
  4. #if UNITY_EDITOR
  5. using UnityEditor;
  6. #endif
  7. namespace SchoenLogger
  8. {
  9. public class Logger<TLogEntry, TCondition> : MonoBehaviour, ILogger where TLogEntry : LogEntry, new() where TCondition : Condition , new()
  10. {
  11. [Header("General Settings")]
  12. public StudyManager<TCondition> studyManager;
  13. [Tooltip("Keep empty to autofill to PersistentDataPath")]
  14. public string LogPathOverride= "";
  15. [Tooltip("Buffersize (in bytes) for the LogFileWriter. Larger means less writing cycles")]
  16. public int BufferSize = 65536;
  17. private string LogPath = "";
  18. private string LogFilePath = "";
  19. private string LogFileName = "";
  20. private FileStream LogFileStream;
  21. private StreamWriter LogFileWriter;
  22. private string CurrentConditionString = "";
  23. private int CurrentParticipantId = -1;
  24. // Start is called before the first frame update
  25. void Start()
  26. {
  27. StartLogFileStream();
  28. if (studyManager == null)
  29. {
  30. studyManager.GetComponent<StudyManager<TCondition>>();
  31. if (studyManager == null)
  32. {
  33. Debug.LogErrorFormat("{0} has not set studyManager", this.gameObject.name);
  34. return;
  35. }
  36. }
  37. studyManager.ChangeCondition.AddListener(OnConditionChanged);
  38. }
  39. private void OnConditionChanged(TCondition cond, int partId)
  40. {
  41. CurrentConditionString = cond.ToCsv();
  42. CurrentParticipantId = partId;
  43. }
  44. private void OnApplicationQuit()
  45. {
  46. LogFileStream.Flush();
  47. LogFileWriter?.Dispose();
  48. LogFileStream?.Dispose();
  49. Debug.Log("Closed Logger FileStreams!");
  50. }
  51. protected void StartLogFileStream()
  52. {
  53. if(LogPathOverride == "")
  54. LogPath = Application.persistentDataPath;
  55. else
  56. LogPath = LogPathOverride;
  57. LogFileName = "log_" + typeof(TLogEntry).Name + ".csv";
  58. LogFilePath = Path.Combine(LogPath, LogFileName);
  59. if (!File.Exists(LogFilePath))
  60. {
  61. using (FileStream stream = File.Open(LogFilePath, FileMode.Create))
  62. {
  63. using (StreamWriter writer = new StreamWriter(stream))
  64. {
  65. writer.WriteLine(GetLogFileHeader());
  66. writer.Flush();
  67. }
  68. }
  69. Debug.LogFormat("Created new Logfile {0}", LogFileName);
  70. }
  71. LogFileStream = File.Open(LogFilePath, FileMode.Append);
  72. LogFileWriter = new StreamWriter(LogFileStream, Encoding.UTF8, BufferSize);
  73. LogFileWriter.AutoFlush = true;
  74. }
  75. protected string GetLogFileHeader()
  76. {
  77. StringBuilder header = new StringBuilder("ParticipantID");
  78. header.Append(Condition.GetCsvHeader<TCondition>());
  79. header.Append(LogEntry.GetCsvHeader<TLogEntry>());
  80. return header.ToString();
  81. }
  82. public void Log(TLogEntry entry)
  83. {
  84. string logEntry = CreateLogEntryCsvLine(entry);
  85. LogFileWriter.WriteLine(CreateLogEntryCsvLine(entry));
  86. Debug.Log(logEntry);
  87. }
  88. private string CreateLogEntryCsvLine(TLogEntry entry)
  89. {
  90. StringBuilder stringBuilder = new StringBuilder();
  91. stringBuilder.Append(CurrentParticipantId);
  92. stringBuilder.Append(CurrentConditionString);
  93. stringBuilder.Append(entry.ToCsv());
  94. return stringBuilder.ToString();
  95. }
  96. public string GetLogPath()
  97. {
  98. if (LogPath == "")
  99. return Application.persistentDataPath;
  100. return LogPath;
  101. }
  102. }
  103. public interface ILogger
  104. {
  105. string GetLogPath();
  106. }
  107. #if UNITY_EDITOR
  108. [CustomEditor(typeof(Logger<,>), true)]
  109. public class LoggerEditor : Editor
  110. {
  111. public override void OnInspectorGUI()
  112. {
  113. DrawDefaultInspector();
  114. ILogger Target = (ILogger)target;
  115. EditorGUILayout.Space(10);
  116. EditorGUILayout.LabelField("Info", EditorStyles.boldLabel);
  117. EditorGUILayout.LabelField("Log Path: ", Target.GetLogPath());
  118. if (GUILayout.Button("Show in Explorer"))
  119. {
  120. string itemPath = Target.GetLogPath().Replace(@"/", @"\");
  121. System.Diagnostics.Process.Start("explorer.exe", "/select,"+itemPath);
  122. }
  123. }
  124. }
  125. #endif
  126. }