Пример #1
0
        /// <summary>
        /// Gets a child printer with the given name, either constructing a new one or using one that was already made.
        /// </summary>
        /// <param name="name"></param>
        /// <returns>a child <see cref="StandardLogger"/> with the given sub-name</returns>
        internal StandardLogger GetChild(string name)
        {
            if (!children.TryGetValue(name, out var child))
            {
                child = new StandardLogger(this, name);
                children.Add(name, child);
            }

            return(child);
        }
        internal StandardLogger GetChild(string name)
        {
            if (!children.TryGetValue(name, out StandardLogger chld))
            {
                chld = new StandardLogger(logName, name, printers.ToArray());
                children.Add(name, chld);
            }

            return(chld);
        }
Пример #3
0
        private StandardLogger(StandardLogger parent, string subName)
        {
            logName     = $"{parent.logName}/{subName}";
            this.parent = parent;
            printers    = new List <LogPrinter>()
            {
                new PluginSubLogPrinter(parent.logName, subName)
            };

            if (logThread == null || !logThread.IsAlive)
            {
                logThread = new Thread(LogThread);
                logThread.Start();
            }
        }
Пример #4
0
        private StandardLogger(StandardLogger parent, string subName)
        {
            logName     = $"{parent.logName}/{subName}";
            this.parent = parent;
            printers    = new List <LogPrinter>();
            if (SelfConfig.Debug_.CondenseModLogs_)
            {
                printers.Add(new PluginSubLogPrinter(parent.logName, subName));
            }

            if (logThread == null || !logThread.IsAlive)
            {
                logThread = new Thread(LogThread);
                logThread.Start();
            }
        }
Пример #5
0
        /// <summary>
        /// The log printer thread for <see cref="StandardLogger"/>.
        /// </summary>
        private static void LogThread()
        {
            AppDomain.CurrentDomain.ProcessExit += (sender, args) =>
            {
                StopLogThread();
            };

            loggerLogger = new StandardLogger("Log Subsystem");
            loggerLogger.printers.Clear(); // don't need a log file for this one

            var timeout = TimeSpan.FromMilliseconds(LogCloseTimeout);

            var started = new HashSet <LogPrinter>();

            while (logQueue.TryTake(out var msg, Timeout.Infinite))
            {
                do
                {
                    var logger = msg.Logger;
                    IEnumerable <LogPrinter> printers = logger.printers;
                    do
                    { // aggregate all printers in the inheritance chain
                        logger = logger.parent;
                        if (logger != null)
                        {
                            printers = printers.Concat(logger.printers);
                        }
                    } while (logger != null);

                    foreach (var printer in printers.Concat(defaultPrinters))
                    {
                        try
                        { // print to them all
                            if (((byte)msg.Level & (byte)printer.Filter) != 0)
                            {
                                if (!started.Contains(printer))
                                { // start printer if not started
                                    printer.StartPrint();
                                    started.Add(printer);
                                }

                                // update last use time and print
                                printer.LastUse = DateTime.Now;
                                printer.Print(msg.Level, msg.Time, msg.Logger.logName, msg.Message);
                            }
                        }
                        catch (Exception e)
                        {
                            // do something sane in the face of an error
                            Console.WriteLine($"printer errored: {e}");
                        }
                    }

                    if (logQueue.Count > 512)
                    {                         // spam filtering (if queue has more tha 512 elements)
                        logWaitEvent.Reset(); // pause incoming log requests

                        // clear loggers for this instance, to print the message to all affected logs
                        loggerLogger.printers.Clear();
                        var prints = new HashSet <LogPrinter>();
                        // clear the queue
                        while (logQueue.TryTake(out var message))
                        { // aggregate loggers in the process
                            var messageLogger = message.Logger;
                            foreach (var print in messageLogger.printers)
                            {
                                prints.Add(print);
                            }
                            do
                            {
                                messageLogger = messageLogger.parent;
                                if (messageLogger != null)
                                {
                                    foreach (var print in messageLogger.printers)
                                    {
                                        prints.Add(print);
                                    }
                                }
                            } while (messageLogger != null);
                        }

                        // print using logging subsystem to all logger printers
                        loggerLogger.printers.AddRange(prints);
                        logQueue.Add(new LogMessage
                        { // manually adding to the queue instead of using Warn() because calls to the logger are suspended here
                            Level   = Level.Warning,
                            Logger  = loggerLogger,
                            Message = $"{loggerLogger.logName.ToUpper()}: Messages omitted to improve performance",
                            Time    = DateTime.Now
                        });

                        // resume log calls
                        logWaitEvent.Set();
                    }

                    var now  = DateTime.Now;
                    var copy = new List <LogPrinter>(started);
                    foreach (var printer in copy)
                    {
                        // close printer after 500ms from its last use
                        if (now - printer.LastUse > timeout)
                        {
                            try
                            {
                                printer.EndPrint();
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine($"printer errored: {e}");
                            }

                            started.Remove(printer);
                        }
                    }
                }
                // wait for messages for 500ms before ending the prints
                while (logQueue.TryTake(out msg, timeout));

                if (logQueue.Count == 0)
                { // when the queue has been empty for 500ms, end all prints
                    foreach (var printer in started)
                    {
                        try
                        {
                            printer.EndPrint();
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"printer errored: {e}");
                        }
                    }
                    started.Clear();
                }
            }
        }
Пример #6
0
 private StandardLogger(StandardLogger parent, string subName)
 {
     logName       = $"{parent.logName}/{subName}";
     BepInExLogger = BepInEx.Logging.Logger.CreateLogSource(logName);
     this.parent   = parent;
 }