144 lines
5.0 KiB
C#
144 lines
5.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Runtime.CompilerServices;
|
|
using UnityEngine;
|
|
|
|
namespace Core
|
|
{
|
|
/// <summary>
|
|
/// Centralized logging system with automatic class/method tagging and editor integration.
|
|
/// Broadcasts log entries to custom editor windows for filtering and analysis.
|
|
/// </summary>
|
|
public static class Logging
|
|
{
|
|
/// <summary>
|
|
/// Event fired when a new log entry is added. Subscribe to this in editor windows.
|
|
/// </summary>
|
|
public static event Action<LogEntry> OnLogEntryAdded;
|
|
|
|
// Store recent logs for late-subscriber editor windows (e.g., windows opened after play mode started)
|
|
private static readonly List<LogEntry> RecentLogs = new List<LogEntry>();
|
|
private const int MaxStoredLogs = 5000; // Prevent memory bloat
|
|
|
|
/// <summary>
|
|
/// Get all recent logs. Used by editor windows when they first open.
|
|
/// </summary>
|
|
public static IReadOnlyList<LogEntry> GetRecentLogs() => RecentLogs;
|
|
|
|
/// <summary>
|
|
/// Clear all stored logs. Useful for editor windows "Clear" button.
|
|
/// </summary>
|
|
public static void ClearLogs()
|
|
{
|
|
RecentLogs.Clear();
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
|
public static void Debug(string message,
|
|
[CallerFilePath] string filePath = "",
|
|
[CallerMemberName] string memberName = "")
|
|
{
|
|
LogInternal(LogLevel.Debug, message, filePath, memberName);
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
|
public static void Info(string message,
|
|
[CallerFilePath] string filePath = "",
|
|
[CallerMemberName] string memberName = "")
|
|
{
|
|
LogInternal(LogLevel.Info, message, filePath, memberName);
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("ENABLE_LOG")]
|
|
public static void Warning(string message,
|
|
[CallerFilePath] string filePath = "",
|
|
[CallerMemberName] string memberName = "")
|
|
{
|
|
LogInternal(LogLevel.Warning, message, filePath, memberName);
|
|
}
|
|
|
|
public static void Error(string message,
|
|
[CallerFilePath] string filePath = "",
|
|
[CallerMemberName] string memberName = "")
|
|
{
|
|
LogInternal(LogLevel.Error, message, filePath, memberName);
|
|
}
|
|
|
|
private static void LogInternal(LogLevel level, string message, string filePath, string memberName)
|
|
{
|
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
|
string formattedMessage = $"[{className}][{memberName}] {message}";
|
|
|
|
// Create log entry
|
|
var entry = new LogEntry(className, memberName, message, level, Time.realtimeSinceStartup);
|
|
|
|
// Store for late subscribers
|
|
RecentLogs.Add(entry);
|
|
if (RecentLogs.Count > MaxStoredLogs)
|
|
RecentLogs.RemoveAt(0);
|
|
|
|
// Broadcast to editor windows (editor-only, won't fire in builds)
|
|
OnLogEntryAdded?.Invoke(entry);
|
|
|
|
// Also log to Unity console
|
|
switch (level)
|
|
{
|
|
case LogLevel.Debug:
|
|
case LogLevel.Info:
|
|
UnityEngine.Debug.Log(formattedMessage);
|
|
break;
|
|
case LogLevel.Warning:
|
|
UnityEngine.Debug.LogWarning(formattedMessage);
|
|
break;
|
|
case LogLevel.Error:
|
|
UnityEngine.Debug.LogError(formattedMessage);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a single log entry with class, method, message, level, and timestamp.
|
|
/// </summary>
|
|
public class LogEntry
|
|
{
|
|
public string ClassName { get; }
|
|
public string MethodName { get; }
|
|
public string Message { get; }
|
|
public LogLevel Level { get; }
|
|
public float Timestamp { get; }
|
|
|
|
public LogEntry(string className, string methodName, string message, LogLevel level, float timestamp)
|
|
{
|
|
ClassName = className;
|
|
MethodName = methodName;
|
|
Message = message;
|
|
Level = level;
|
|
Timestamp = timestamp;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Formatted message with class and method tags.
|
|
/// Format: [ClassName][MethodName] Message
|
|
/// </summary>
|
|
public string FormattedMessage => $"[{ClassName}][{MethodName}] {Message}";
|
|
|
|
/// <summary>
|
|
/// Full formatted message with timestamp and level.
|
|
/// Format: [12.34s][Debug][ClassName][MethodName] Message
|
|
/// </summary>
|
|
public string FullFormattedMessage => $"[{Timestamp:F2}s][{Level}]{FormattedMessage}";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Log severity levels.
|
|
/// </summary>
|
|
public enum LogLevel
|
|
{
|
|
Debug,
|
|
Info,
|
|
Warning,
|
|
Error
|
|
}
|
|
} |