SEBWIN-226: Implemented global log severity threshold.

This commit is contained in:
dbuechel 2019-01-23 08:12:15 +01:00
parent 06c32ee359
commit 6436f98e3f
17 changed files with 87 additions and 61 deletions

View file

@ -117,8 +117,8 @@ namespace SafeExamBrowser.Browser
private CefSettings InitializeCefSettings()
{
var warning = appConfig.LogLevel == LogLevel.Warning;
var error = appConfig.LogLevel == LogLevel.Error;
var warning = logger.LogLevel == LogLevel.Warning;
var error = logger.LogLevel == LogLevel.Error;
var cefSettings = new CefSettings
{
CachePath = appConfig.BrowserCachePath,

View file

@ -49,6 +49,7 @@ namespace SafeExamBrowser.Client
internal class CompositionRoot
{
private string logFilePath;
private LogLevel logLevel;
private string runtimeHostUri;
private Guid startupToken;
@ -131,25 +132,27 @@ namespace SafeExamBrowser.Client
private void ValidateCommandLineArguments()
{
var args = Environment.GetCommandLineArgs();
var hasFour = args?.Length == 4;
var hasFive = args?.Length == 5;
if (hasFour)
if (hasFive)
{
var hasLogfilePath = Uri.TryCreate(args?[1], UriKind.Absolute, out Uri filePath) && filePath.IsFile;
var hasHostUri = Uri.TryCreate(args?[2], UriKind.Absolute, out Uri hostUri) && hostUri.IsWellFormedOriginalString();
var hasToken = Guid.TryParse(args?[3], out Guid token);
var hasLogfilePath = Uri.TryCreate(args[1], UriKind.Absolute, out Uri filePath) && filePath.IsFile;
var hasLogLevel = Enum.TryParse(args[2], out LogLevel level);
var hasHostUri = Uri.TryCreate(args[3], UriKind.Absolute, out Uri hostUri) && hostUri.IsWellFormedOriginalString();
var hasToken = Guid.TryParse(args[4], out Guid token);
if (hasLogfilePath && hasHostUri && hasToken)
if (hasLogfilePath && hasLogLevel && hasHostUri && hasToken)
{
logFilePath = args[1];
runtimeHostUri = args[2];
startupToken = Guid.Parse(args[3]);
logLevel = level;
runtimeHostUri = args[3];
startupToken = token;
return;
}
}
throw new ArgumentException("Invalid arguments! Required: SafeExamBrowser.Client.exe <logfile path> <host URI> <token>");
throw new ArgumentException("Invalid arguments! Required: SafeExamBrowser.Client.exe <logfile path> <log level> <host URI> <token>");
}
private void InitializeLogging()
@ -157,6 +160,7 @@ namespace SafeExamBrowser.Client
var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), logFilePath);
logFileWriter.Initialize();
logger.LogLevel = logLevel;
logger.Subscribe(logFileWriter);
}

View file

@ -7,6 +7,7 @@
*/
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Configuration.ConfigurationData
{
@ -20,6 +21,16 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
}
}
private void MapLogLevel(Settings settings, object value)
{
const int ERROR = 0, WARNING = 1, INFO = 2;
if (value is int level)
{
settings.LogLevel = level == ERROR ? LogLevel.Error : (level == WARNING ? LogLevel.Warning : (level == INFO ? LogLevel.Info : LogLevel.Debug));
}
}
private void MapQuitPasswordHash(Settings settings, object value)
{
if (value is string hash)

View file

@ -51,6 +51,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
case Keys.General.AdminPasswordHash:
MapAdminPasswordHash(settings, value);
break;
case Keys.General.LogLevel:
MapLogLevel(settings, value);
break;
case Keys.General.QuitPasswordHash:
MapQuitPasswordHash(settings, value);
break;

View file

@ -56,7 +56,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
appConfig.ConfigurationFileExtension = ".seb";
appConfig.DefaultSettingsFileName = "SebClientSettings.seb";
appConfig.DownloadDirectory = Path.Combine(appDataFolder, "Downloads");
appConfig.LogLevel = LogLevel.Debug;
appConfig.ProgramCopyright = programCopyright;
appConfig.ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), nameof(SafeExamBrowser));
appConfig.ProgramTitle = programTitle;
@ -122,6 +121,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
settings.KioskMode = KioskMode.CreateNewDesktop;
settings.LogLevel = LogLevel.Debug;
settings.Mouse.AllowMiddleButton = false;
settings.Mouse.AllowRightButton = true;

View file

@ -45,6 +45,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
internal static class General
{
internal const string AdminPasswordHash = "hashedAdminPassword";
internal const string LogLevel = "logLevel";
internal const string QuitPasswordHash = "hashedQuitPassword";
internal const string StartUrl = "startURL";
}

View file

@ -7,7 +7,6 @@
*/
using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Contracts.Configuration
{
@ -72,11 +71,6 @@ namespace SafeExamBrowser.Contracts.Configuration
/// </summary>
public string DownloadDirectory { get; set; }
/// <summary>
/// The currently active, global log severity threshold.
/// </summary>
public LogLevel LogLevel { get; set; }
/// <summary>
/// The copyright information for the application (i.e. the executing assembly).
/// </summary>

View file

@ -7,6 +7,7 @@
*/
using System;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.Contracts.Configuration.Settings
{
@ -41,6 +42,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
/// </summary>
public KioskMode KioskMode { get; set; }
/// <summary>
/// The global log severity to be used.
/// </summary>
public LogLevel LogLevel { get; set; }
/// <summary>
/// All mouse-related settings.
/// </summary>

View file

@ -16,6 +16,11 @@ namespace SafeExamBrowser.Contracts.Logging
/// </summary>
public interface ILogger
{
/// <summary>
/// The currently active severity threshold. All messages with a lower severity won't be logged!
/// </summary>
LogLevel LogLevel { get; set; }
/// <summary>
/// Logs the given message with severity <see cref="LogLevel.Debug"/>.
/// </summary>
@ -53,12 +58,6 @@ namespace SafeExamBrowser.Contracts.Logging
/// <exception cref="ArgumentNullException" />
void Log(string message);
/// <summary>
/// Appends the given content to the log.
/// </summary>
/// <exception cref="ArgumentNullException" />
void Log(ILogContent content);
/// <summary>
/// Subscribes an observer to the application log.
/// </summary>

View file

@ -13,9 +13,9 @@ namespace SafeExamBrowser.Contracts.Logging
/// </summary>
public enum LogLevel
{
Debug = 1,
Info = 2,
Warning = 3,
Error = 4
Debug,
Info,
Warning,
Error
}
}

View file

@ -11,7 +11,6 @@ using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Logging;
namespace SafeExamBrowser.Logging.UnitTests
{
@ -29,7 +28,6 @@ namespace SafeExamBrowser.Logging.UnitTests
var exceptionMessage = "I'm an exception message";
var exception = new Exception(exceptionMessage);
var message = "I'm a simple text message";
var content = new LogText("I'm some raw log text...");
sut.Debug(debug);
sut.Info(info);
@ -37,11 +35,10 @@ namespace SafeExamBrowser.Logging.UnitTests
sut.Error(error);
sut.Error(error, exception);
sut.Log(message);
sut.Log(content);
var log = sut.GetLog();
Assert.IsTrue(log.Count == 8);
Assert.IsTrue(log.Count == 7);
Assert.IsTrue(debug.Equals((log[0] as ILogMessage).Message));
Assert.IsTrue((log[0] as ILogMessage).Severity == LogLevel.Debug);
@ -60,8 +57,6 @@ namespace SafeExamBrowser.Logging.UnitTests
Assert.IsTrue((log[5] as ILogText).Text.Contains(exceptionMessage));
Assert.IsTrue(message.Equals((log[6] as ILogText).Text));
Assert.IsTrue(content.Text.Equals((log[7] as ILogText).Text));
}
[TestMethod]
@ -122,7 +117,6 @@ namespace SafeExamBrowser.Logging.UnitTests
Assert.ThrowsException<ArgumentNullException>(() => sut.Error("Hello world!", null));
Assert.ThrowsException<ArgumentNullException>(() => sut.Error(null, new Exception()));
Assert.ThrowsException<ArgumentNullException>(() => sut.Log((string) null));
Assert.ThrowsException<ArgumentNullException>(() => sut.Log((ILogContent) null));
}
[TestMethod]

View file

@ -45,7 +45,6 @@ namespace SafeExamBrowser.Logging.UnitTests
sut.Error("Error");
sut.Error("Error", exception);
sut.Log("Raw text");
sut.Log(logText);
sut.Subscribe(logObserverMock.Object);
sut.Unsubscribe(logObserverMock.Object);
sut.GetLog();
@ -56,7 +55,6 @@ namespace SafeExamBrowser.Logging.UnitTests
loggerMock.Verify(l => l.Error($"[{nameof(ModuleLoggerTests)}] Error"), Times.Once);
loggerMock.Verify(l => l.Error($"[{nameof(ModuleLoggerTests)}] Error", exception), Times.Once);
loggerMock.Verify(l => l.Log("Raw text"), Times.Once);
loggerMock.Verify(l => l.Log(logText), Times.Once);
loggerMock.Verify(l => l.Subscribe(logObserverMock.Object), Times.Once);
loggerMock.Verify(l => l.Unsubscribe(logObserverMock.Object), Times.Once);
loggerMock.Verify(l => l.GetLog(), Times.Once);

View file

@ -24,6 +24,8 @@ namespace SafeExamBrowser.Logging
private readonly IList<ILogContent> log = new List<ILogContent>();
private readonly IList<ILogObserver> observers = new List<ILogObserver>();
public LogLevel LogLevel { get; set; }
public void Debug(string message)
{
if (message == null)
@ -31,8 +33,11 @@ namespace SafeExamBrowser.Logging
throw new ArgumentNullException(nameof(message));
}
if (LogLevel <= LogLevel.Debug)
{
Add(LogLevel.Debug, message);
}
}
public void Info(string message)
{
@ -41,8 +46,11 @@ namespace SafeExamBrowser.Logging
throw new ArgumentNullException(nameof(message));
}
if (LogLevel <= LogLevel.Info)
{
Add(LogLevel.Info, message);
}
}
public void Warn(string message)
{
@ -51,8 +59,11 @@ namespace SafeExamBrowser.Logging
throw new ArgumentNullException(nameof(message));
}
if (LogLevel <= LogLevel.Warning)
{
Add(LogLevel.Warning, message);
}
}
public void Error(string message)
{
@ -61,8 +72,11 @@ namespace SafeExamBrowser.Logging
throw new ArgumentNullException(nameof(message));
}
if (LogLevel <= LogLevel.Error)
{
Add(LogLevel.Error, message);
}
}
public void Error(string message, Exception exception)
{
@ -101,9 +115,12 @@ namespace SafeExamBrowser.Logging
}
}
if (LogLevel <= LogLevel.Error)
{
Add(LogLevel.Error, message);
Add(new LogText(details.ToString()));
}
}
public void Log(string text)
{
@ -115,16 +132,6 @@ namespace SafeExamBrowser.Logging
Add(new LogText(text));
}
public void Log(ILogContent content)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
Add(content.Clone() as ILogContent);
}
public IList<ILogContent> GetLog()
{
lock (@lock)

View file

@ -17,6 +17,12 @@ namespace SafeExamBrowser.Logging
private ILogger logger;
private string moduleInfo;
public LogLevel LogLevel
{
get { return logger.LogLevel; }
set { logger.LogLevel = value; }
}
public ModuleLogger(ILogger logger, string moduleInfo)
{
this.logger = logger;
@ -58,11 +64,6 @@ namespace SafeExamBrowser.Logging
logger.Log(message);
}
public void Log(ILogContent content)
{
logger.Log(content);
}
public void Subscribe(ILogObserver observer)
{
logger.Subscribe(observer);

View file

@ -134,6 +134,7 @@ namespace SafeExamBrowser.Runtime
var logFileWriter = new LogFileWriter(new DefaultLogFormatter(), appConfig.RuntimeLogFile);
logFileWriter.Initialize();
logger.LogLevel = LogLevel.Debug;
logger.Subscribe(logFileWriter);
}

View file

@ -102,13 +102,14 @@ namespace SafeExamBrowser.Runtime.Operations
var clientExecutable = Context.Next.AppConfig.ClientExecutablePath;
var clientLogFile = $"{'"' + Context.Next.AppConfig.ClientLogFile + '"'}";
var hostUri = Context.Next.AppConfig.RuntimeAddress;
var token = Context.Next.StartupToken.ToString("D");
var clientLogLevel = logger.LogLevel.ToString();
var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress;
var startupToken = Context.Next.StartupToken.ToString("D");
logger.Info("Starting new client process...");
runtimeHost.AllowConnection = true;
runtimeHost.ClientReady += clientReadyEventHandler;
ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, hostUri, token);
ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, clientLogLevel, runtimeHostUri, startupToken);
logger.Info("Waiting for client to complete initialization...");
clientReady = clientReadyEvent.WaitOne(timeout_ms);

View file

@ -142,6 +142,11 @@ namespace SafeExamBrowser.Runtime.Operations
Context.Next.Settings = settings;
if (settings != null)
{
logger.LogLevel = settings.LogLevel;
}
return HandleLoadResult(uri, settings, status, passwordParams);
}