< Summary

Class:GDX.Experimental.Logging.ManagedLog
Assembly:GDX
File(s):./Packages/com.dotbunny.gdx/GDX/Experimental/Logging/ManagedLog.cs
Covered lines:38
Uncovered lines:268
Coverable lines:306
Total lines:908
Line coverage:12.4% (38 of 306)
Covered branches:0
Total branches:0
Covered methods:6
Total methods:31
Method coverage:19.3% (6 of 31)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
ManagedLog()0%110100%
Clear()0%2100%
RegisterCategory(...)0%20400%
UnregisterCategory(...)0%6200%
GetCategoryLabel(...)0%49.513040%
GetEntriesByCategory(...)0%12300%
GetEntriesByParent(...)0%12300%
GetEntriesBySearch(...)0%20400%
GetLastEntry()0%110100%
SetBufferSizeByAllocation(...)0%2100%
SetBufferSizeByCount(...)0%2100%
SetConsoleOutput(...)0%2100%
SetUnityOutput(...)0%2100%
Debug(...)0%12300%
DebugWithContext(...)0%12300%
Info(...)0%12300%
InfoWithContext(...)0%12300%
Warning(...)0%330100%
WarningWithContext(...)0%12300%
Error(...)0%12300%
ErrorWithContext(...)0%12300%
Exception(...)0%12300%
ExceptionWithContext(...)0%12300%
Assertion(...)0%12300%
AssertionWithContext(...)0%12300%
Fatal(...)0%12300%
FatalWithContext(...)0%12300%
Trace(...)0%12300%
NewEntry(...)0%110100%
NewEntry(...)0%2100%
NextIdentifier()0%3.243070%

File(s)

./Packages/com.dotbunny.gdx/GDX/Experimental/Logging/ManagedLog.cs

#LineLine coverage
 1// Copyright (c) 2020-2023 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using System;
 6using System.Runtime.CompilerServices;
 7using System.Runtime.InteropServices;
 8using GDX.Collections;
 9using GDX.Collections.Generic;
 10using UnityEngine;
 11using UnityEngine.Diagnostics;
 12using Object = UnityEngine.Object;
 13
 14namespace GDX.Experimental.Logging
 15{
 16    /// <summary>
 17    ///     A managed-only categorized hierarchical logging solution.
 18    /// </summary>
 19    public static class ManagedLog
 20    {
 21        /// <summary>
 22        ///     A ring buffer structure of <see cref="LogEntry" />s.
 23        /// </summary>
 124        static ConcurrentCircularBuffer<LogEntry> s_Buffer = new ConcurrentCircularBuffer<LogEntry>(1000);
 25
 26        /// <summary>
 27        ///     An index of labels per category.
 28        /// </summary>
 129        static IntKeyDictionary<string> s_CustomCategories = new IntKeyDictionary<string>(10);
 30
 31        /// <summary>
 32        ///     A flag structure containing if a category should output to the system console.
 33        /// </summary>
 134        static BitArray64 s_EchoToConsole = new BitArray64(uint.MaxValue);
 35
 36        /// <summary>
 37        ///     A flag structure containing if a category should output to the Unity log handler.
 38        /// </summary>
 139        static BitArray64 s_EchoToUnity = new BitArray64(uint.MaxValue);
 40
 41        /// <summary>
 42        ///     The next identifier used when creating a new <see cref="LogEntry" />.
 43        /// </summary>
 44        static uint s_IdentifierHead;
 45
 46        /// <summary>
 47        ///     Thread-safety management object.
 48        /// </summary>
 149        static readonly object k_Lock = new object();
 50
 51        /// <summary>
 52        ///     Clears the internal buffer of <see cref="LogEntry" />s.
 53        /// </summary>
 54        public static void Clear()
 055        {
 056            s_Buffer.Clear();
 057        }
 58
 59        /// <summary>
 60        ///     Registers a category identifier for logging purposes.
 61        /// </summary>
 62        /// <param name="categoryIdentifier">
 63        ///     The designated identifier, must fall within a valid range. See
 64        ///     <see cref="LogCategory.MinimumIdentifier" /> and <see cref="LogCategory.MaximumIdentifier" />
 65        /// </param>
 66        /// <param name="name">The category's name.</param>
 67        /// <param name="outputToUnity">Should this category output to Unity's log handler?</param>
 68        /// <param name="outputToConsole">Should this category output to the Console.</param>
 69        public static void RegisterCategory(int categoryIdentifier, string name, bool outputToUnity = true,
 70            bool outputToConsole = false)
 071        {
 072            if (categoryIdentifier <= LogCategory.MinimumIdentifier)
 073            {
 074                Error(LogCategory.GDX,
 75                    $"Unable to register category {categoryIdentifier.ToString()}:{name} as identifier below threshold {
 076            }
 077            else if (categoryIdentifier > LogCategory.MaximumIdentifier)
 078            {
 079                Error(LogCategory.GDX,
 80                    $"Unable to register category {categoryIdentifier.ToString()}:{name} as identifier exceeds maximum a
 081            }
 82
 083            if (s_CustomCategories.ContainsKey(categoryIdentifier))
 084            {
 085                Error(LogCategory.GDX,
 86                    $"Unable to register category {categoryIdentifier.ToString()}:{name} as identifier already in use.")
 087            }
 88            else
 089            {
 090                s_CustomCategories.AddWithExpandCheck(categoryIdentifier, name);
 091                s_EchoToConsole[(byte)categoryIdentifier] = outputToConsole;
 092                s_EchoToUnity[(byte)categoryIdentifier] = outputToUnity;
 093            }
 094        }
 95
 96        /// <summary>
 97        ///     Unregisters a category identifier.
 98        /// </summary>
 99        /// <param name="categoryIdentifier"></param>
 100        public static void UnregisterCategory(int categoryIdentifier)
 0101        {
 0102            if (categoryIdentifier <= LogCategory.MinimumIdentifier)
 0103            {
 0104                return;
 105            }
 106
 0107            s_CustomCategories.TryRemove(categoryIdentifier);
 0108            s_EchoToConsole[(byte)categoryIdentifier] = true;
 0109            s_EchoToUnity[(byte)categoryIdentifier] = true;
 0110        }
 111
 112        /// <summary>
 113        ///     Gets the name of a category.
 114        /// </summary>
 115        /// <param name="categoryIdentifier">The category to evaluate.</param>
 116        /// <returns>The label for the category.</returns>
 117        public static string GetCategoryLabel(int categoryIdentifier)
 4118        {
 4119            if (categoryIdentifier <= LogCategory.MinimumIdentifier)
 4120            {
 4121                switch (categoryIdentifier)
 122                {
 123                    case LogCategory.GDX:
 4124                        return "GDX";
 125                    case LogCategory.Default:
 0126                        return "Default";
 127                    case LogCategory.Platform:
 0128                        return "Platform";
 129                    case LogCategory.Unity:
 0130                        return "Unity";
 131                    case LogCategory.Input:
 0132                        return "Input";
 133                    case LogCategory.Gameplay:
 0134                        return "Gameplay";
 135                    case LogCategory.UI:
 0136                        return "UI";
 137                    case LogCategory.Test:
 0138                        return "Test";
 139                    default:
 0140                        return LogCategory.UndefinedLabel;
 141                }
 142            }
 143
 0144            return s_CustomCategories.TryGetValue(categoryIdentifier, out string customCategory)
 145                ? customCategory
 146                : LogCategory.UndefinedLabel;
 4147        }
 148
 149        /// <summary>
 150        ///     Gets an array of <see cref="LogEntry" /> based on category.
 151        /// </summary>
 152        /// <param name="categoryIdentifier">The category identifier to filter by.</param>
 153        /// <returns>An array of filtered <see cref="LogEntry" />.</returns>
 154        public static LogEntry[] GetEntriesByCategory(int categoryIdentifier)
 0155        {
 0156            int count = s_Buffer.Count;
 0157            SimpleList<LogEntry> entries = new SimpleList<LogEntry>(count);
 0158            for (int i = 0; i < count; i++)
 0159            {
 0160                if (s_Buffer[i].Identifier == categoryIdentifier)
 0161                {
 0162                    entries.AddUnchecked(s_Buffer[i]);
 0163                }
 0164            }
 165
 0166            entries.Compact();
 0167            return entries.Array;
 0168        }
 169
 170        /// <summary>
 171        ///     Gets an array of <see cref="LogEntry" /> based on parent identifier.
 172        /// </summary>
 173        /// <param name="parentIdentifier">The parent identifier to filter by.</param>
 174        /// <returns>An array of filtered <see cref="LogEntry" />.</returns>
 175        public static LogEntry[] GetEntriesByParent(int parentIdentifier)
 0176        {
 0177            int count = s_Buffer.Count;
 0178            SimpleList<LogEntry> entries = new SimpleList<LogEntry>(count);
 0179            for (int i = 0; i < count; i++)
 0180            {
 0181                if (s_Buffer[i].ParentIdentifier == parentIdentifier)
 0182                {
 0183                    entries.AddUnchecked(s_Buffer[i]);
 0184                }
 0185            }
 186
 0187            entries.Compact();
 0188            return entries.Array;
 0189        }
 190
 191        /// <summary>
 192        ///     Gets an array of <see cref="LogEntry" /> based on contents.
 193        /// </summary>
 194        /// <param name="searchQuery">The text query to search for.</param>
 195        /// <returns>An array of filtered <see cref="LogEntry" />.</returns>
 196        public static LogEntry[] GetEntriesBySearch(string searchQuery)
 0197        {
 0198            int count = s_Buffer.Count;
 0199            SimpleList<LogEntry> entries = new SimpleList<LogEntry>(count);
 0200            for (int i = 0; i < count; i++)
 0201            {
 0202                if (s_Buffer[i].Message.IndexOf(searchQuery, StringComparison.OrdinalIgnoreCase) != -1 ||
 203                    s_Buffer[i].SourceFilePath.IndexOf(searchQuery, StringComparison.OrdinalIgnoreCase) != -1)
 0204                {
 0205                    entries.AddUnchecked(s_Buffer[i]);
 0206                }
 0207            }
 208
 0209            entries.Compact();
 0210            return entries.Array;
 0211        }
 212
 213        /// <summary>
 214        ///     Get the last <see cref="LogEntry" /> added to the backing buffer.
 215        /// </summary>
 216        /// <returns>The last log entry.</returns>
 217        public static LogEntry GetLastEntry()
 2218        {
 2219            return s_Buffer.GetBack();
 2220        }
 221
 222        /// <summary>
 223        ///     Sets the size of the internal <see cref="ConcurrentCircularBuffer{T}" /> based on a specific memory size
 224        ///     allocation.
 225        /// </summary>
 226        /// <param name="byteAllocation">The size in bytes to use for the internal buffer.</param>
 227        public static void SetBufferSizeByAllocation(long byteAllocation)
 0228        {
 0229            s_Buffer = new ConcurrentCircularBuffer<LogEntry>((int)(byteAllocation /
 230                                                                    Marshal.SizeOf(
 231                                                                        typeof(LogEntry))));
 0232        }
 233
 234        /// <summary>
 235        ///     Sets the size of the internal <see cref="ConcurrentCircularBuffer{T}" /> to be a specific number of entr
 236        /// </summary>
 237        /// <param name="numberOfLogEntries">The number of <see cref="LogEntry" /> to size the buffer too.</param>
 238        public static void SetBufferSizeByCount(int numberOfLogEntries)
 0239        {
 0240            s_Buffer = new ConcurrentCircularBuffer<LogEntry>(numberOfLogEntries);
 0241        }
 242
 243        /// <summary>
 244        ///     Set if a category should output to the system console.
 245        /// </summary>
 246        /// <param name="categoryIdentifier">The unique category identifier.</param>
 247        /// <param name="output">Should the log entry be outputted to the console?</param>
 248        public static void SetConsoleOutput(int categoryIdentifier, bool output)
 0249        {
 0250            s_EchoToConsole[(byte)categoryIdentifier] = output;
 0251        }
 252
 253        /// <summary>
 254        ///     Set if a category should output to the unity logger.
 255        /// </summary>
 256        /// <param name="categoryIdentifier">The unique category identifier.</param>
 257        /// <param name="output">Should the log entry be outputted to the unity logger?</param>
 258        public static void SetUnityOutput(int categoryIdentifier, bool output)
 0259        {
 0260            s_EchoToUnity[(byte)categoryIdentifier] = output;
 0261        }
 262
 263        /// <summary>
 264        ///     Log a debug message.
 265        /// </summary>
 266        /// <param name="category">The category identifier.</param>
 267        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 268        /// <param name="parentIdentifier">
 269        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 270        ///     associated with another.
 271        /// </param>
 272        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 273        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 274        public static uint Debug(int category, string message, uint parentIdentifier = 0,
 275                // ReSharper disable InvalidXmlDocComment
 276                [CallerMemberName] string memberName = "",
 277                [CallerFilePath] string sourceFilePath = "",
 278                [CallerLineNumber] int sourceLineNumber = 0)
 279            // ReSharper restore InvalidXmlDocComment
 0280        {
 0281            LogEntry newEntry = NewEntry(LogLevel.Debug, category, message,
 282                parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 283
 0284            if (s_EchoToConsole[(byte)category])
 0285            {
 0286                Console.WriteLine(newEntry.ToConsoleOutput());
 0287            }
 288
 0289            if (s_EchoToUnity[(byte)category])
 0290            {
 0291                UnityEngine.Debug.unityLogger.Log(LogType.Log,
 292                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 0293            }
 294
 0295            return newEntry.Identifier;
 0296        }
 297
 298        /// <summary>
 299        ///     Log a debug message with context.
 300        /// </summary>
 301        /// <remarks>The context-based versions of logging are slower.</remarks>
 302        /// <param name="category">The category identifier.</param>
 303        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 304        /// <param name="contextObject">A Unity-based context object.</param>
 305        /// <param name="parentIdentifier">
 306        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 307        ///     associated with another.
 308        /// </param>
 309        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 310        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 311        public static uint DebugWithContext(int category, string message, Object contextObject = null,
 312                uint parentIdentifier = 0,
 313                // ReSharper disable InvalidXmlDocComment
 314                [CallerMemberName] string memberName = "",
 315                [CallerFilePath] string sourceFilePath = "",
 316                [CallerLineNumber] int sourceLineNumber = 0)
 317            // ReSharper restore InvalidXmlDocComment
 0318        {
 0319            LogEntry newEntry = NewEntry(LogLevel.Debug, category, message,
 320                parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 321
 0322            if (s_EchoToConsole[(byte)category])
 0323            {
 0324                Console.WriteLine(newEntry.ToConsoleOutput());
 0325            }
 326
 0327            if (s_EchoToUnity[(byte)category])
 0328            {
 0329                UnityEngine.Debug.unityLogger.Log(LogType.Log,
 330                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput(), contextObject);
 0331            }
 332
 0333            return newEntry.Identifier;
 0334        }
 335
 336        /// <summary>
 337        ///     Log some information.
 338        /// </summary>
 339        /// <param name="category">The category identifier.</param>
 340        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 341        /// <param name="parentIdentifier">
 342        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 343        ///     associated with another.
 344        /// </param>
 345        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 346        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 347        public static uint Info(int category, string message, uint parentIdentifier = 0,
 348                // ReSharper disable InvalidXmlDocComment
 349                [CallerMemberName] string memberName = "",
 350                [CallerFilePath] string sourceFilePath = "",
 351                [CallerLineNumber] int sourceLineNumber = 0)
 352            // ReSharper restore InvalidXmlDocComment
 0353        {
 0354            LogEntry newEntry = NewEntry(LogLevel.Info, category, message,
 355                parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 356
 0357            if (s_EchoToConsole[(byte)category])
 0358            {
 0359                Console.WriteLine(newEntry.ToConsoleOutput());
 0360            }
 361
 0362            if (s_EchoToUnity[(byte)category])
 0363            {
 0364                UnityEngine.Debug.unityLogger.Log(
 365                    LogType.Log,
 366                    GetCategoryLabel(newEntry.CategoryIdentifier),
 367                    newEntry.ToUnityOutput());
 0368            }
 369
 0370            return newEntry.Identifier;
 0371        }
 372
 373        /// <summary>
 374        ///     Log some information with context.
 375        /// </summary>
 376        /// <remarks>The context-based versions of logging are slower.</remarks>
 377        /// <param name="category">The category identifier.</param>
 378        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 379        /// <param name="contextObject">A Unity-based context object.</param>
 380        /// <param name="parentIdentifier">
 381        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 382        ///     associated with another.
 383        /// </param>
 384        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 385        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 386        public static uint InfoWithContext(int category, string message, Object contextObject = null,
 387                uint parentIdentifier = 0,
 388                // ReSharper disable InvalidXmlDocComment
 389                [CallerMemberName] string memberName = "",
 390                [CallerFilePath] string sourceFilePath = "",
 391                [CallerLineNumber] int sourceLineNumber = 0)
 392            // ReSharper restore InvalidXmlDocComment
 0393        {
 0394            LogEntry newEntry = NewEntry(LogLevel.Info, category, message,
 395                parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 396
 0397            if (s_EchoToConsole[(byte)category])
 0398            {
 0399                Console.WriteLine(newEntry.ToConsoleOutput());
 0400            }
 401
 0402            if (s_EchoToUnity[(byte)category])
 0403            {
 0404                UnityEngine.Debug.unityLogger.Log(
 405                    LogType.Log,
 406                    GetCategoryLabel(newEntry.CategoryIdentifier),
 407                    newEntry.ToUnityOutput(), contextObject);
 0408            }
 409
 0410            return newEntry.Identifier;
 0411        }
 412
 413        /// <summary>
 414        ///     Log a warning.
 415        /// </summary>
 416        /// <param name="category">The category identifier.</param>
 417        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 418        /// <param name="parentIdentifier">
 419        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 420        ///     associated with another.
 421        /// </param>
 422        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 423        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 424        public static uint Warning(int category, string message, uint parentIdentifier = 0,
 425                // ReSharper disable InvalidXmlDocComment
 426                [CallerMemberName] string memberName = "",
 427                [CallerFilePath] string sourceFilePath = "",
 428                [CallerLineNumber] int sourceLineNumber = 0)
 429            // ReSharper restore InvalidXmlDocComment
 2430        {
 2431            LogEntry newEntry = NewEntry(LogLevel.Warning, category,
 432                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 433
 2434            if (s_EchoToConsole[(byte)category])
 2435            {
 2436                Console.WriteLine(newEntry.ToConsoleOutput());
 2437            }
 438
 2439            if (s_EchoToUnity[(byte)category])
 2440            {
 2441                UnityEngine.Debug.unityLogger.Log(LogType.Warning,
 442                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 2443            }
 444
 2445            return newEntry.Identifier;
 2446        }
 447
 448        /// <summary>
 449        ///     Log a warning with context.
 450        /// </summary>
 451        /// <remarks>The context-based versions of logging are slower.</remarks>
 452        /// <param name="category">The category identifier.</param>
 453        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 454        /// <param name="contextObject">A Unity-based context object.</param>
 455        /// <param name="parentIdentifier">
 456        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 457        ///     associated with another.
 458        /// </param>
 459        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 460        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 461        public static uint WarningWithContext(int category, string message, Object contextObject = null,
 462                uint parentIdentifier = 0,
 463                // ReSharper disable InvalidXmlDocComment
 464                [CallerMemberName] string memberName = "",
 465                [CallerFilePath] string sourceFilePath = "",
 466                [CallerLineNumber] int sourceLineNumber = 0)
 467            // ReSharper restore InvalidXmlDocComment
 0468        {
 0469            LogEntry newEntry = NewEntry(LogLevel.Warning, category,
 470                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 471
 0472            if (s_EchoToConsole[(byte)category])
 0473            {
 0474                Console.WriteLine(newEntry.ToConsoleOutput());
 0475            }
 476
 0477            if (s_EchoToUnity[(byte)category])
 0478            {
 0479                UnityEngine.Debug.unityLogger.Log(LogType.Warning,
 480                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput(), contextObject);
 0481            }
 482
 0483            return newEntry.Identifier;
 0484        }
 485
 486        /// <summary>
 487        ///     Log an error.
 488        /// </summary>
 489        /// <param name="category">The category identifier.</param>
 490        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 491        /// <param name="parentIdentifier">
 492        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 493        ///     associated with another.
 494        /// </param>
 495        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 496        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 497        public static uint Error(int category, string message, uint parentIdentifier = 0,
 498                // ReSharper disable InvalidXmlDocComment
 499                [CallerMemberName] string memberName = "",
 500                [CallerFilePath] string sourceFilePath = "",
 501                [CallerLineNumber] int sourceLineNumber = 0)
 502            // ReSharper restore InvalidXmlDocComment
 0503        {
 0504            LogEntry newEntry = NewEntry(LogLevel.Error, category,
 505                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 506
 0507            if (s_EchoToConsole[(byte)category])
 0508            {
 0509                Console.WriteLine(newEntry.ToConsoleOutput());
 0510            }
 511
 0512            if (s_EchoToUnity[(byte)category])
 0513            {
 0514                UnityEngine.Debug.unityLogger.Log(LogType.Error,
 515                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 0516            }
 517
 0518            return newEntry.Identifier;
 0519        }
 520
 521        /// <summary>
 522        ///     Log an error with context.
 523        /// </summary>
 524        /// <remarks>The context-based versions of logging are slower.</remarks>
 525        /// <param name="category">The category identifier.</param>
 526        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 527        /// <param name="contextObject">A Unity-based context object.</param>
 528        /// <param name="parentIdentifier">
 529        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 530        ///     associated with another.
 531        /// </param>
 532        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 533        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 534        public static uint ErrorWithContext(int category, string message, Object contextObject = null,
 535                uint parentIdentifier = 0,
 536                // ReSharper disable InvalidXmlDocComment
 537                [CallerMemberName] string memberName = "",
 538                [CallerFilePath] string sourceFilePath = "",
 539                [CallerLineNumber] int sourceLineNumber = 0)
 540            // ReSharper restore InvalidXmlDocComment
 0541        {
 0542            LogEntry newEntry = NewEntry(LogLevel.Error, category,
 543                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 544
 0545            if (s_EchoToConsole[(byte)category])
 0546            {
 0547                Console.WriteLine(newEntry.ToConsoleOutput());
 0548            }
 549
 0550            if (s_EchoToUnity[(byte)category])
 0551            {
 0552                UnityEngine.Debug.unityLogger.Log(LogType.Error,
 553                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput(), contextObject);
 0554            }
 555
 0556            return newEntry.Identifier;
 0557        }
 558
 559        /// <summary>
 560        ///     Log an exception.
 561        /// </summary>
 562        /// <param name="category">The category identifier.</param>
 563        /// <param name="exception">The exception object.</param>
 564        /// <param name="parentIdentifier">
 565        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 566        ///     associated with another.
 567        /// </param>
 568        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 569        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 570        public static uint Exception(int category, Exception exception, uint parentIdentifier = 0,
 571                // ReSharper disable InvalidXmlDocComment
 572                [CallerMemberName] string memberName = "",
 573                [CallerFilePath] string sourceFilePath = "",
 574                [CallerLineNumber] int sourceLineNumber = 0)
 575            // ReSharper restore InvalidXmlDocComment
 0576        {
 0577            LogEntry newEntry = NewEntry(LogLevel.Exception, category,
 578                exception, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 579
 0580            if (s_EchoToConsole[(byte)category])
 0581            {
 0582                Console.WriteLine(newEntry.ToConsoleOutput());
 0583            }
 584
 0585            if (s_EchoToUnity[(byte)category])
 0586            {
 0587                UnityEngine.Debug.unityLogger.Log(LogType.Exception,
 588                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 0589            }
 590
 0591            return newEntry.Identifier;
 0592        }
 593
 594        /// <summary>
 595        ///     Log an exception with context,
 596        /// </summary>
 597        /// <param name="category">The category identifier.</param>
 598        /// <param name="exception">The exception object.</param>
 599        /// <param name="contextObject">A Unity-based context object.</param>
 600        /// <param name="parentIdentifier">
 601        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 602        ///     associated with another.
 603        /// </param>
 604        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 605        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 606        public static uint ExceptionWithContext(int category,
 607                Exception exception,
 608                Object contextObject = null, uint parentIdentifier = 0,
 609                // ReSharper disable InvalidXmlDocComment
 610                [CallerMemberName] string memberName = "",
 611                [CallerFilePath] string sourceFilePath = "",
 612                [CallerLineNumber] int sourceLineNumber = 0)
 613            // ReSharper restore InvalidXmlDocComment
 0614        {
 0615            LogEntry newEntry = NewEntry(LogLevel.Exception, category,
 616                exception, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 617
 0618            if (s_EchoToConsole[(byte)category])
 0619            {
 0620                Console.WriteLine(newEntry.ToConsoleOutput());
 0621            }
 622
 0623            if (s_EchoToUnity[(byte)category])
 0624            {
 0625                UnityEngine.Debug.unityLogger.Log(LogType.Exception,
 626                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput(), contextObject);
 0627            }
 628
 0629            return newEntry.Identifier;
 0630        }
 631
 632        /// <summary>
 633        ///     Log an assertion failure.
 634        /// </summary>
 635        /// <param name="category">The category identifier.</param>
 636        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 637        /// <param name="parentIdentifier">
 638        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 639        ///     associated with another.
 640        /// </param>
 641        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 642        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 643        public static uint Assertion(int category, string message, uint parentIdentifier = 0,
 644                // ReSharper disable InvalidXmlDocComment
 645                [CallerMemberName] string memberName = "",
 646                [CallerFilePath] string sourceFilePath = "",
 647                [CallerLineNumber] int sourceLineNumber = 0)
 648            // ReSharper restore InvalidXmlDocComment
 0649        {
 0650            LogEntry newEntry = NewEntry(LogLevel.Assertion, category,
 651                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 652
 0653            if (s_EchoToConsole[(byte)category])
 0654            {
 0655                Console.WriteLine(newEntry.ToConsoleOutput());
 0656            }
 657
 0658            if (s_EchoToUnity[(byte)category])
 0659            {
 0660                UnityEngine.Debug.unityLogger.Log(LogType.Assert,
 661                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 0662            }
 663
 0664            return newEntry.Identifier;
 0665        }
 666
 667        /// <summary>
 668        ///     Log an assertion failure with context.
 669        /// </summary>
 670        /// <remarks>The context-based versions of logging are slower.</remarks>
 671        /// <param name="category">The category identifier.</param>
 672        /// <param name="message">The <see cref="LogEntry" /> message.</param>
 673        /// <param name="contextObject">A Unity-based context object.</param>
 674        /// <param name="parentIdentifier">
 675        ///     The optional parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 676        ///     associated with another.
 677        /// </param>
 678        /// <returns>The created <see cref="LogEntry" />'s Identifier.</returns>
 679        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 680        public static uint AssertionWithContext(int category, string message, Object contextObject = null,
 681                uint parentIdentifier = 0,
 682                // ReSharper disable InvalidXmlDocComment
 683                [CallerMemberName] string memberName = "",
 684                [CallerFilePath] string sourceFilePath = "",
 685                [CallerLineNumber] int sourceLineNumber = 0)
 686            // ReSharper restore InvalidXmlDocComment
 0687        {
 0688            LogEntry newEntry = NewEntry(LogLevel.Assertion, category,
 689                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 690
 0691            if (s_EchoToConsole[(byte)category])
 0692            {
 0693                Console.WriteLine(newEntry.ToConsoleOutput());
 0694            }
 695
 0696            if (s_EchoToUnity[(byte)category])
 0697            {
 0698                UnityEngine.Debug.unityLogger.Log(LogType.Assert,
 699                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput(), contextObject);
 0700            }
 701
 0702            return newEntry.Identifier;
 0703        }
 704
 705        /// <summary>
 706        ///     Logs a fatal event and forces Unity to crash.
 707        /// </summary>
 708        /// <remarks>
 709        ///     The crash ensures that we stop a cascade of problems, allowing for back tracing. The context object base
 710        ///     methods should no be the preferred method of logging as they require a main-thread lock internally insid
 711        /// </remarks>
 712        /// <param name="category">The category identifier to associate this event with.</param>
 713        /// <param name="message"></param>
 714        /// <param name="parentIdentifier">
 715        ///     The parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 716        ///     associated with another.
 717        /// </param>
 718        /// <returns>The newly created <see cref="LogEntry" />'s Identifier.</returns>
 719        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 720        public static uint Fatal(int category, string message, uint parentIdentifier = 0,
 721                // ReSharper disable InvalidXmlDocComment
 722                [CallerMemberName] string memberName = "",
 723                [CallerFilePath] string sourceFilePath = "",
 724                [CallerLineNumber] int sourceLineNumber = 0)
 725            // ReSharper restore InvalidXmlDocComment
 0726        {
 0727            LogEntry newEntry = NewEntry(LogLevel.Fatal, category,
 728                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 729
 0730            if (s_EchoToConsole[(byte)category])
 0731            {
 0732                Console.WriteLine(newEntry.ToConsoleOutput());
 0733            }
 734
 0735            if (s_EchoToUnity[(byte)category])
 0736            {
 0737                UnityEngine.Debug.unityLogger.Log(LogType.Error,
 738                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 0739            }
 740
 0741            Utils.ForceCrash(ForcedCrashCategory.FatalError);
 742
 0743            return newEntry.Identifier;
 0744        }
 745
 746        /// <summary>
 747        ///     Logs a fatal event and forces Unity to crash.
 748        /// </summary>
 749        /// <remarks>
 750        ///     The crash ensures that we stop a cascade of problems, allowing for back tracing. The context object base
 751        ///     methods should no be the preferred method of logging as they require a main-thread lock internally insid
 752        /// </remarks>
 753        /// <param name="category">The category identifier to associate this event with.</param>
 754        /// <param name="message"></param>
 755        /// <param name="contextObject">A unity-based context object.</param>
 756        /// <param name="parentIdentifier">
 757        ///     The parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 758        ///     associated with another.
 759        /// </param>
 760        /// <returns>The newly created <see cref="LogEntry" />'s Identifier.</returns>
 761        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 762        public static uint FatalWithContext(int category, string message, Object contextObject = null,
 763                uint parentIdentifier = 0,
 764                // ReSharper disable InvalidXmlDocComment
 765                [CallerMemberName] string memberName = "",
 766                [CallerFilePath] string sourceFilePath = "",
 767                [CallerLineNumber] int sourceLineNumber = 0)
 768            // ReSharper restore InvalidXmlDocComment
 0769        {
 0770            LogEntry newEntry = NewEntry(LogLevel.Fatal, category,
 771                message, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 772
 0773            if (s_EchoToConsole[(byte)category])
 0774            {
 0775                Console.WriteLine(newEntry.ToConsoleOutput());
 0776            }
 777
 0778            if (s_EchoToUnity[(byte)category])
 0779            {
 0780                UnityEngine.Debug.unityLogger.Log(LogType.Error,
 781                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput(), contextObject);
 0782            }
 783
 0784            Utils.ForceCrash(ForcedCrashCategory.FatalError);
 785
 0786            return newEntry.Identifier;
 0787        }
 788
 789        /// <summary>
 790        ///     Logs the current stack trace.
 791        /// </summary>
 792        /// <remarks>Pulled from <see cref="Environment.StackTrace " />.</remarks>
 793        /// <param name="category">The category identifier to associate this event with.</param>
 794        /// <param name="parentIdentifier">
 795        ///     The parent <see cref="LogEntry" />'s Identifier, if this event is meant to be
 796        ///     associated with another.
 797        /// </param>
 798        /// <returns>The newly created <see cref="LogEntry" />'s Identifier.</returns>
 799        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 800        public static uint Trace(int category = 0, uint parentIdentifier = 0,
 801                // ReSharper disable InvalidXmlDocComment
 802                [CallerMemberName] string memberName = "",
 803                [CallerFilePath] string sourceFilePath = "",
 804                [CallerLineNumber] int sourceLineNumber = 0)
 805            // ReSharper restore InvalidXmlDocComment
 0806        {
 0807            LogEntry newEntry = NewEntry(LogLevel.Trace, category,
 808                Environment.StackTrace, parentIdentifier, memberName, sourceFilePath, sourceLineNumber);
 809
 0810            if (s_EchoToConsole[(byte)category])
 0811            {
 0812                Console.WriteLine(newEntry.ToConsoleOutput());
 0813            }
 814
 0815            if (s_EchoToUnity[(byte)category])
 0816            {
 0817                UnityEngine.Debug.unityLogger.Log(LogType.Assert,
 818                    GetCategoryLabel(newEntry.CategoryIdentifier), newEntry.ToUnityOutput());
 0819            }
 820
 0821            return newEntry.Identifier;
 0822        }
 823
 824        /// <summary>
 825        ///     Creates and adds a new log entry to the <see cref="s_Buffer" />.
 826        /// </summary>
 827        /// <param name="level">The type/level of message being emitted.</param>
 828        /// <param name="category">The category of the message being emitted.</param>
 829        /// <param name="message">The content.</param>
 830        /// <param name="parentIdentifier">The parent <see cref="LogEntry" />'s Identifier.</param>
 831        /// <param name="memberName">The invoking member's name.</param>
 832        /// <param name="sourceFilePath">The source file where the member is found.</param>
 833        /// <param name="sourceLineNumber">The line number in the source file where the member is invoking the emit.</pa
 834        /// <returns>The newly created <see cref="LogEntry" />'s Identifier.</returns>
 835        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 836        static LogEntry NewEntry(LogLevel level, int category, string message, uint parentIdentifier = 0u,
 837            string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0)
 2838        {
 2839            LogEntry newEntry = new LogEntry
 840            {
 841                Timestamp = DateTime.UtcNow,
 842                Level = level,
 843                Identifier = NextIdentifier(),
 844                CategoryIdentifier = category,
 845                ParentIdentifier = parentIdentifier,
 846                Message = message,
 847                MemberName = memberName,
 848                SourceFilePath = sourceFilePath,
 849                SourceLineNumber = sourceLineNumber
 850            };
 2851            s_Buffer.Add(newEntry);
 2852            return newEntry;
 2853        }
 854
 855        /// <summary>
 856        ///     Creates and adds a new log entry to the <see cref="s_Buffer" /> from a <see cref="System.Exception" />.
 857        /// </summary>
 858        /// <param name="level">The type/level of message being emitted.</param>
 859        /// <param name="category">The category of the message being emitted.</param>
 860        /// <param name="exception">The emitted exception.</param>
 861        /// <param name="parentIdentifier">The parent <see cref="LogEntry" />'s Identifier.</param>
 862        /// <param name="memberName">The invoking member's name.</param>
 863        /// <param name="sourceFilePath">The source file where the member is found.</param>
 864        /// <param name="sourceLineNumber">The line number in the source file where the member is invoking the emit.</pa
 865        /// <returns>The newly created <see cref="LogEntry" />'s Identifier.</returns>
 866        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 867        static LogEntry NewEntry(LogLevel level, int category, Exception exception, uint parentIdentifier = 0u,
 868            string memberName = "", string sourceFilePath = "", int sourceLineNumber = 0)
 0869        {
 0870            LogEntry newEntry = new LogEntry
 871            {
 872                Timestamp = DateTime.UtcNow,
 873                Level = level,
 874                Identifier = NextIdentifier(),
 875                CategoryIdentifier = category,
 876                ParentIdentifier = parentIdentifier,
 877                Message = exception.Message,
 878                MemberName = memberName,
 879                SourceFilePath = sourceFilePath,
 880                SourceLineNumber = sourceLineNumber
 881            };
 0882            s_Buffer.Add(newEntry);
 883
 0884            return newEntry;
 0885        }
 886
 887        /// <summary>
 888        ///     Get the next identifier to use for a log entry
 889        /// </summary>
 890        /// <remarks>This will eventually roll over.</remarks>
 891        /// <returns>An unsigned integer representing a pseudo-unique log entry identifier.</returns>
 892        static uint NextIdentifier()
 2893        {
 2894            lock (k_Lock)
 2895            {
 2896                s_IdentifierHead++;
 897
 898                // We need to ensure this never hits it in rollover
 2899                if (s_IdentifierHead == 0)
 0900                {
 0901                    s_IdentifierHead++;
 0902                }
 903
 2904                return ++s_IdentifierHead;
 905            }
 2906        }
 907    }
 908}

Coverage by test methods



Methods/Properties

ManagedLog()
Clear()
RegisterCategory(System.Int32, System.String, System.Boolean, System.Boolean)
UnregisterCategory(System.Int32)
GetCategoryLabel(System.Int32)
GetEntriesByCategory(System.Int32)
GetEntriesByParent(System.Int32)
GetEntriesBySearch(System.String)
GetLastEntry()
SetBufferSizeByAllocation(System.Int64)
SetBufferSizeByCount(System.Int32)
SetConsoleOutput(System.Int32, System.Boolean)
SetUnityOutput(System.Int32, System.Boolean)
Debug(System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
DebugWithContext(System.Int32, System.String, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Info(System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
InfoWithContext(System.Int32, System.String, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Warning(System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
WarningWithContext(System.Int32, System.String, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Error(System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
ErrorWithContext(System.Int32, System.String, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Exception(System.Int32, System.Exception, System.UInt32, System.String, System.String, System.Int32)
ExceptionWithContext(System.Int32, System.Exception, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Assertion(System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
AssertionWithContext(System.Int32, System.String, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Fatal(System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
FatalWithContext(System.Int32, System.String, UnityEngine.Object, System.UInt32, System.String, System.String, System.Int32)
Trace(System.Int32, System.UInt32, System.String, System.String, System.Int32)
NewEntry(GDX.Experimental.Logging.LogLevel, System.Int32, System.String, System.UInt32, System.String, System.String, System.Int32)
NewEntry(GDX.Experimental.Logging.LogLevel, System.Int32, System.Exception, System.UInt32, System.String, System.String, System.Int32)
NextIdentifier()