mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Logging improvements.
1. Logging is now thread safe. 2. Slight optimizations.
This commit is contained in:
@@ -73,17 +73,20 @@ namespace SS14.Client.UserInterface.CustomControls
|
||||
|
||||
public void AddLine(string text, ChatChannel channel, Color color)
|
||||
{
|
||||
if (!firstLine)
|
||||
lock (Contents)
|
||||
{
|
||||
Contents.NewLine();
|
||||
if (!firstLine)
|
||||
{
|
||||
Contents.NewLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
firstLine = false;
|
||||
}
|
||||
Contents.PushColor(color);
|
||||
Contents.AddText(text);
|
||||
Contents.Pop(); // Pop the color off.
|
||||
}
|
||||
else
|
||||
{
|
||||
firstLine = false;
|
||||
}
|
||||
Contents.PushColor(color);
|
||||
Contents.AddText(text);
|
||||
Contents.Pop(); // Pop the color off.
|
||||
}
|
||||
|
||||
public void AddLine(string text, Color color)
|
||||
@@ -98,48 +101,55 @@ namespace SS14.Client.UserInterface.CustomControls
|
||||
|
||||
public void AddFormattedLine(FormattedMessage message)
|
||||
{
|
||||
if (!firstLine)
|
||||
lock (Contents)
|
||||
{
|
||||
Contents.NewLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
firstLine = false;
|
||||
}
|
||||
|
||||
var pushCount = 0;
|
||||
foreach (var tag in message.Tags)
|
||||
{
|
||||
switch (tag)
|
||||
if (!firstLine)
|
||||
{
|
||||
case FormattedMessage.TagText text:
|
||||
Contents.AddText(text.Text);
|
||||
break;
|
||||
case FormattedMessage.TagColor color:
|
||||
Contents.PushColor(color.Color);
|
||||
pushCount++;
|
||||
break;
|
||||
case FormattedMessage.TagPop _:
|
||||
if (pushCount <= 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
Contents.Pop();
|
||||
pushCount--;
|
||||
break;
|
||||
Contents.NewLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
firstLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (; pushCount > 0; pushCount--)
|
||||
{
|
||||
Contents.Pop();
|
||||
var pushCount = 0;
|
||||
foreach (var tag in message.Tags)
|
||||
{
|
||||
switch (tag)
|
||||
{
|
||||
case FormattedMessage.TagText text:
|
||||
Contents.AddText(text.Text);
|
||||
break;
|
||||
case FormattedMessage.TagColor color:
|
||||
Contents.PushColor(color.Color);
|
||||
pushCount++;
|
||||
break;
|
||||
case FormattedMessage.TagPop _:
|
||||
if (pushCount <= 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
Contents.Pop();
|
||||
pushCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (; pushCount > 0; pushCount--)
|
||||
{
|
||||
Contents.Pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Contents.Clear();
|
||||
firstLine = true;
|
||||
lock (Contents)
|
||||
{
|
||||
Contents.Clear();
|
||||
firstLine = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Newtonsoft.Json;
|
||||
@@ -10,6 +11,7 @@ using SS14.Server.Interfaces.ServerStatus;
|
||||
using SS14.Shared.Configuration;
|
||||
using SS14.Shared.Interfaces.Configuration;
|
||||
using SS14.Shared.IoC;
|
||||
using SS14.Shared.Log;
|
||||
|
||||
// This entire file is NIHing a REST server because pulling in libraries is effort.
|
||||
// Also it was fun to write.
|
||||
@@ -58,6 +60,7 @@ namespace SS14.Server.ServerStatus
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_stop.Set();
|
||||
_listenerThread.Join(1000);
|
||||
_listener.Stop();
|
||||
@@ -81,6 +84,15 @@ namespace SS14.Server.ServerStatus
|
||||
}
|
||||
|
||||
private void _processRequest(HttpListenerContext context)
|
||||
{
|
||||
_processRequestInternal(context);
|
||||
Logger.DebugS("statushost", "{0} -> {1} {2}",
|
||||
context.Request.Url.AbsolutePath,
|
||||
context.Response.StatusCode,
|
||||
context.Response.StatusDescription);
|
||||
}
|
||||
|
||||
private void _processRequestInternal(HttpListenerContext context)
|
||||
{
|
||||
var response = context.Response;
|
||||
var request = context.Request;
|
||||
@@ -112,6 +124,7 @@ namespace SS14.Server.ServerStatus
|
||||
response.StatusDescription = "Not Implemented";
|
||||
response.ContentType = "text/plain";
|
||||
_respondText(response, "501 Not Implemented", head);
|
||||
Logger.WarningS("statushost", "OnStatusRequest is not set, responding with a 501.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -146,15 +159,13 @@ namespace SS14.Server.ServerStatus
|
||||
_respondText(response, "404 Not Found", head);
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
response.StatusCode = (int) HttpStatusCode.InternalServerError;
|
||||
response.StatusDescription = "Internal Server Error";
|
||||
response.ContentType = "text/plain";
|
||||
_respondText(response, "500 Internal Server Error", head);
|
||||
// TODO: Logging.
|
||||
// Logger is not thread safe atm.
|
||||
// This is a problem.
|
||||
Logger.ErrorS("statushost", "Exception in StatusHost: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,21 @@ namespace SS14.Shared.Log
|
||||
/// </summary>
|
||||
public sealed class ConsoleLogHandler : ILogHandler
|
||||
{
|
||||
public void Log(LogMessage message)
|
||||
{
|
||||
string name = LogMessage.LogLevelToName(message.Level);
|
||||
ConsoleColor color = LogLevelToConsoleColor(message.Level);
|
||||
private readonly object locker = new object();
|
||||
|
||||
System.Console.Write('[');
|
||||
System.Console.ForegroundColor = color;
|
||||
System.Console.Write(name);
|
||||
System.Console.ResetColor();
|
||||
System.Console.WriteLine("] {0}: {1}", message.SawmillName, message.Message);
|
||||
public void Log(in LogMessage message)
|
||||
{
|
||||
var name = LogMessage.LogLevelToName(message.Level);
|
||||
var color = LogLevelToConsoleColor(message.Level);
|
||||
|
||||
lock (locker)
|
||||
{
|
||||
System.Console.Write('[');
|
||||
System.Console.ForegroundColor = color;
|
||||
System.Console.Write(name);
|
||||
System.Console.ResetColor();
|
||||
System.Console.WriteLine("] {0}: {1}", message.SawmillName, message.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static ConsoleColor LogLevelToConsoleColor(LogLevel level)
|
||||
|
||||
@@ -7,12 +7,12 @@ namespace SS14.Shared.Log
|
||||
{
|
||||
public sealed class FileLogHandler : ILogHandler, IDisposable
|
||||
{
|
||||
private readonly StreamWriter writer;
|
||||
private readonly TextWriter writer;
|
||||
|
||||
public FileLogHandler(string path)
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
writer = new StreamWriter(path, true, Encoding.UTF8);
|
||||
writer = TextWriter.Synchronized(new StreamWriter(path, true, Encoding.UTF8));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -20,10 +20,10 @@ namespace SS14.Shared.Log
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
public void Log(LogMessage message)
|
||||
public void Log(in LogMessage message)
|
||||
{
|
||||
var name = message.LogLevelToName();
|
||||
writer.WriteLine("{0} [{1}] {2}: {3}", DateTime.Now.ToString("o"), name, message.SawmillName, message.Message);
|
||||
writer.WriteLine("{0:o} [{1}] {2}: {3}", DateTime.Now, name, message.SawmillName, message.Message);
|
||||
|
||||
// This probably isn't the best idea.
|
||||
// Remove this flush if it becomes a problem (say performance).
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using SS14.Shared.Interfaces.Log;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace SS14.Shared.Log
|
||||
{
|
||||
@@ -26,7 +27,8 @@ namespace SS14.Shared.Log
|
||||
}
|
||||
private LogLevel? _level = null;
|
||||
|
||||
private List<ILogHandler> handlers = new List<ILogHandler>();
|
||||
private readonly List<ILogHandler> _handlers = new List<ILogHandler>();
|
||||
private readonly ReaderWriterLockSlim _handlerLock = new ReaderWriterLockSlim();
|
||||
|
||||
public Sawmill(Sawmill parent, string name)
|
||||
{
|
||||
@@ -36,12 +38,28 @@ namespace SS14.Shared.Log
|
||||
|
||||
public void AddHandler(ILogHandler handler)
|
||||
{
|
||||
handlers.Add(handler);
|
||||
_handlerLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_handlers.Add(handler);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_handlerLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveHandler(ILogHandler handler)
|
||||
{
|
||||
handlers.Remove(handler);
|
||||
_handlerLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_handlers.Remove(handler);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_handlerLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void Log(LogLevel level, string message, params object[] args)
|
||||
@@ -52,22 +70,30 @@ namespace SS14.Shared.Log
|
||||
public void Log(LogLevel level, string message)
|
||||
{
|
||||
var msg = new LogMessage(message, level, Name);
|
||||
LogInternal(ref msg);
|
||||
LogInternal(msg);
|
||||
}
|
||||
|
||||
private void LogInternal(ref LogMessage message)
|
||||
private void LogInternal(in LogMessage message)
|
||||
{
|
||||
if (message.Level < GetPracticalLevel())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
_handlerLock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
handler.Log(message);
|
||||
foreach (var handler in _handlers)
|
||||
{
|
||||
handler.Log(message);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_handlerLock.ExitReadLock();
|
||||
}
|
||||
|
||||
Parent?.LogInternal(ref message);
|
||||
Parent?.LogInternal(message);
|
||||
}
|
||||
|
||||
private LogLevel GetPracticalLevel()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using SS14.Shared.Interfaces.Log;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Threading;
|
||||
|
||||
namespace SS14.Shared.Log
|
||||
{
|
||||
@@ -11,8 +11,36 @@ namespace SS14.Shared.Log
|
||||
private readonly Sawmill rootSawmill;
|
||||
public ISawmill RootSawmill => rootSawmill;
|
||||
|
||||
[Pure]
|
||||
private readonly Dictionary<string, Sawmill> sawmills = new Dictionary<string, Sawmill>();
|
||||
private readonly ReaderWriterLockSlim _sawmillsLock = new ReaderWriterLockSlim();
|
||||
|
||||
public ISawmill GetSawmill(string name)
|
||||
{
|
||||
_sawmillsLock.EnterReadLock();
|
||||
try
|
||||
{
|
||||
if (sawmills.TryGetValue(name, out var sawmill))
|
||||
{
|
||||
return sawmill;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_sawmillsLock.ExitReadLock();
|
||||
}
|
||||
|
||||
_sawmillsLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
return _getSawmillUnlocked(name);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_sawmillsLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
private Sawmill _getSawmillUnlocked(string name)
|
||||
{
|
||||
if (sawmills.TryGetValue(name, out var sawmill))
|
||||
{
|
||||
@@ -20,24 +48,22 @@ namespace SS14.Shared.Log
|
||||
}
|
||||
|
||||
var index = name.LastIndexOf('.');
|
||||
string parentname;
|
||||
string parentName;
|
||||
if (index == -1)
|
||||
{
|
||||
parentname = ROOT;
|
||||
parentName = ROOT;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentname = name.Substring(0, index);
|
||||
parentName = name.Substring(0, index);
|
||||
}
|
||||
|
||||
var parent = (Sawmill)GetSawmill(parentname);
|
||||
var parent = _getSawmillUnlocked(parentName);
|
||||
sawmill = new Sawmill(parent, name);
|
||||
sawmills[name] = sawmill;
|
||||
sawmills.Add(name, sawmill);
|
||||
return sawmill;
|
||||
}
|
||||
|
||||
private Dictionary<string, Sawmill> sawmills = new Dictionary<string, Sawmill>();
|
||||
|
||||
public LogManager()
|
||||
{
|
||||
rootSawmill = new Sawmill(null, ROOT)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace SS14.Shared.Log
|
||||
{
|
||||
public struct LogMessage
|
||||
public readonly struct LogMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// The actual log message given.
|
||||
|
||||
@@ -20,12 +20,18 @@ namespace SS14.UnitTesting
|
||||
/// </summary>
|
||||
public void Flush()
|
||||
{
|
||||
_logs.Clear();
|
||||
lock (_logs)
|
||||
{
|
||||
_logs.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void ILogHandler.Log(LogMessage message)
|
||||
void ILogHandler.Log(in LogMessage message)
|
||||
{
|
||||
_logs.Add(message);
|
||||
lock (_logs)
|
||||
{
|
||||
_logs.Add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user