Last active
June 12, 2023 14:34
-
-
Save jbvrtx/f55040cfbf945cc456d4a1b0e00a836d to your computer and use it in GitHub Desktop.
Statically Create Logs of Completed Tasks in Unity Editor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Newtonsoft.Json; | |
using System; | |
using System.Linq; | |
using System.Collections.Generic; | |
using System.IO; | |
using UnityEngine; | |
namespace Logging | |
{ | |
public static class ProgressLogger | |
{ | |
// Constants | |
private const string FolderName = "/Logs/"; | |
private const string FileName = "taskLogs.json"; | |
private const string BackupPrefix = "backup_"; | |
// Variables | |
private static List<TaskLogEntry> _currentTaskLogEntries = new List<TaskLogEntry>(); | |
private static bool initialized = false; | |
private static bool dirty = false; | |
// Properties | |
public static string FolderPath { get => Application.persistentDataPath + FolderName; } | |
public static string FullPath { get => Application.persistentDataPath + FolderName + FileName; } | |
public static List<TaskLogEntry> CurrentTaskLogEntries | |
{ | |
get | |
{ | |
// Initialize to load logs before allowing access | |
if (!initialized) Initialize(); | |
return _currentTaskLogEntries; | |
} | |
private set | |
{ | |
if (value != null) _currentTaskLogEntries = value; | |
} | |
} | |
public static void Initialize() | |
{ | |
if (!initialized) | |
{ | |
initialized = true; | |
// Subscribe to event to save logs on exit | |
Application.quitting += SaveLogsToDisk; | |
// Load logs on first use | |
LoadLogs(); | |
} | |
} | |
public static void CreateLog(string taskName, int attempts, bool isSuccess, TimeSpan duration) | |
{ | |
// Create log entry and add it to the list | |
CurrentTaskLogEntries.Add(new TaskLogEntry(taskName, DateTime.Now, attempts, isSuccess, duration)); | |
dirty = true; | |
} | |
public static void SaveLogsToDisk() | |
{ | |
if (!dirty) return; | |
// Serialize to JSON | |
string jsonText = JsonConvert.SerializeObject(CurrentTaskLogEntries, Formatting.Indented); | |
try | |
{ | |
// Create folder & write to file | |
if (!Directory.Exists(FolderPath)) Directory.CreateDirectory(FolderPath); | |
using (TextWriter textWriter = new StreamWriter(FullPath, false)) | |
{ | |
textWriter.Write(jsonText); | |
dirty = false; | |
} | |
Debug.Log($"{nameof(ExerciseProgressLogger)}: Logs saved successfully at {FullPath}."); | |
} | |
catch (IOException exception) | |
{ | |
Debug.LogError($"{nameof(ExerciseProgressLogger)}: Logs could not be saved. Exception text: " + exception); | |
throw; | |
} | |
} | |
public static void LoadLogs() | |
{ | |
// Read file & Parse Json Data | |
try | |
{ | |
// Check if file exists | |
if (!File.Exists(FullPath)) | |
{ | |
DeleteLogHistory(); | |
} | |
// Read file and parse json content | |
string jsonText = File.ReadAllText(FullPath); | |
CurrentTaskLogEntries = JsonConvert.DeserializeObject<List<TaskLogEntry>>(jsonText); | |
Debug.Log($"{nameof(ExerciseProgressLogger)}: Successfully loaded {CurrentTaskLogEntries.Count} logs."); | |
} | |
// Catch errors in the Serialization Process | |
catch (JsonException) | |
{ | |
// Create backup of old log file | |
Debug.LogWarning($"{nameof(ExerciseProgressLogger)}: Log file corrupted, creating backup."); | |
CreateBackup(); | |
DeleteLogHistory(); | |
} | |
if (CurrentTaskLogEntries.Count > 0) | |
TaskLogEntry.CurrentExerciseRunID = CurrentTaskLogEntries.Max(entry => entry.ExerciseRunID); | |
else | |
TaskLogEntry.CurrentExerciseRunID = 0; | |
} | |
private static void CreateBackup() | |
{ | |
string backupPath = FolderPath + BackupPrefix + FileName; | |
if (File.Exists(backupPath)) File.Delete(backupPath); | |
File.Move(FullPath, backupPath); | |
Debug.LogWarning($"{nameof(ExerciseProgressLogger)}: Backup created at " + backupPath); | |
} | |
public static void DeleteLogHistory() | |
{ | |
// Saving new empty log file | |
dirty = true; | |
SaveLogsToDisk(); | |
TaskLogEntry.CurrentExerciseRunID = 0; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using UnityEngine; | |
namespace Logging | |
{ | |
[System.Serializable] | |
public class TaskLogEntry | |
{ | |
// Serialized fields | |
[SerializeField] private string _taskName; | |
[SerializeField] private DateTime _creationDate; | |
[SerializeField] private int _retryNumber; | |
[SerializeField] private bool _successfulCompletion; | |
[SerializeField] private TimeSpan _timeSpent; | |
[SerializeField] private ulong _exerciseRunID; // Used to identify tasks that belong to a consecutive run | |
// Properties | |
public string TaskName { get => _taskName; set => _taskName = value; } | |
public DateTime CreationDate { get => _creationDate; set => _creationDate = value; } | |
public int RetryNumber { get => _retryNumber; set => _retryNumber = value; } | |
public bool SuccessfulCompletion { get => _successfulCompletion; set => _successfulCompletion = value; } | |
public TimeSpan TimeSpent { get => _timeSpent; set => _timeSpent = value; } | |
public ulong ExerciseRunID { get => _exerciseRunID; set => _exerciseRunID = value; } | |
public static ulong CurrentExerciseRunID { get; set; } // Global value (current highest id) | |
// Auto-generated constructor | |
public TaskLogEntry(string taskName, DateTime creationDate, int retryNumber, bool finalResult, TimeSpan timeSpent) | |
{ | |
// Assign given values | |
TaskName = taskName; | |
CreationDate = creationDate; | |
RetryNumber = retryNumber; | |
SuccessfulCompletion = finalResult; | |
TimeSpent = timeSpent; | |
_exerciseRunID = CurrentExerciseRunID; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment