diff --git a/.gitignore b/.gitignore index ef6f314e..23f300f8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,7 @@ x86/ bld/ [Bb]in/ [Oo]bj/ -[Ll]og/ +#[Ll]og/ # Visual Studio 2015 cache/options directory .vs/ @@ -249,4 +249,4 @@ paket-files/ # VS Code files .browse.VC.db .browse.VC.db-shm -.browse.VC.db-wal \ No newline at end of file +.browse.VC.db-wal diff --git a/Ntp.Common/Log/ActivityLog.cs b/Ntp.Common/Log/ActivityLog.cs new file mode 100644 index 00000000..06c7bdf4 --- /dev/null +++ b/Ntp.Common/Log/ActivityLog.cs @@ -0,0 +1,128 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Ntp.Common.Log +{ + public sealed class ActivityLog : LogBase, IEnumerable + { + internal ActivityLog() + : base(Severity.Debug) + { + activity = new List(2001); + } + + private readonly List activity; + private readonly object locker = new object(); + + public IEnumerator GetEnumerator() + { + return activity.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return activity.GetEnumerator(); + } + + public override void Close() + { + activity.Clear(); + } + + public override void Initialize() + { + activity.Clear(); + } + + public override void Resume() + { + } + + public override void Suspend() + { + } + + public override void WriteLine(string text, Severity severity) + { + string severityText; + + if (severity == Severity.Trace) + return; + + switch (severity) + { + case Severity.Error: + severityText = "E"; + break; + case Severity.Warn: + severityText = "W"; + break; + case Severity.Notice: + severityText = "N"; + break; + case Severity.Info: + severityText = "I"; + break; + case Severity.Debug: + severityText = "D"; + break; + case Severity.Trace: + severityText = "T"; + break; + default: + throw new ArgumentOutOfRangeException(nameof(severity)); + } + + var now = DateTime.Now; + string entry = string.Concat( + now.ToString("HH:mm:ss"), + " ", severityText, " ", + text); + + lock (locker) + { + if (activity.Count == 1000) + activity.RemoveAt(0); + + activity.Add(entry); + } + } + + public override void WriteLine(Exception exception) + { + WriteLine(exception.Message, Severity.Error); + WriteLine(exception.StackTrace, Severity.Debug); + } + + public override void WriteLine(Exception exception, Severity severity) + { + if (severity == Severity.Trace) + return; + + WriteLine(exception.Message, severity); + WriteLine(exception.StackTrace, severity); + } + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/ConsoleLog.cs b/Ntp.Common/Log/ConsoleLog.cs new file mode 100644 index 00000000..26a90043 --- /dev/null +++ b/Ntp.Common/Log/ConsoleLog.cs @@ -0,0 +1,49 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.IO; + +namespace Ntp.Common.Log +{ + public sealed class ConsoleLog : TextLog + { + internal ConsoleLog(Severity treshold, string timeFormat) + : base(treshold, timeFormat) + { + } + + internal ConsoleLog(Severity treshold) + : base(treshold, null) + { + } + + public override void Close() + { + // Dont close standard out stream + } + + protected override TextWriter CreateWriter() + { + return Console.Out; + } + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/EventLog.cs b/Ntp.Common/Log/EventLog.cs new file mode 100644 index 00000000..42d89efb --- /dev/null +++ b/Ntp.Common/Log/EventLog.cs @@ -0,0 +1,127 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if !__MonoCS__ +using System; +using System.Diagnostics; +using System.Security; + +namespace Ntp.Common.Log +{ + public sealed class EventLog : LogBase + { + public EventLog(string name, Severity treshold) + : base(treshold, true) + { + this.name = name; + } + + private const string Log = "Application"; + private static bool initialized; + private readonly string name; + + public override void Close() + { + } + + public override void Initialize() + { + if (initialized) + return; + try + { + if (!global::System.Diagnostics.EventLog.SourceExists(name)) + global::System.Diagnostics.EventLog.CreateEventSource(name, Log); + } + catch (SecurityException) + { + } + + initialized = true; + } + + public override void Resume() + { + // EventLog does not support resume + } + + public override void Suspend() + { + // EventLog does not support suspend + } + + public override void WriteLine(string text, Severity severity) + { + if (!initialized) + Initialize(); + + if (severity < Treshold) + return; + + global::System.Diagnostics.EventLog.WriteEntry(name, text, + GetEventLogEntryType(severity), 0); + } + + public override void WriteLine(Exception exception, Severity severity) + { + if (!initialized) + Initialize(); + + if (severity < Treshold) + return; + + if (!initialized) + Initialize(); + + if (severity < Treshold) + return; + + global::System.Diagnostics.EventLog.WriteEntry(name, exception.ToString(), + GetEventLogEntryType(severity), 0); + } + + public override void WriteLine(Exception exception) + { + global::System.Diagnostics.EventLog.WriteEntry(name, exception.ToString(), + EventLogEntryType.Error, 1); + } + + private static EventLogEntryType GetEventLogEntryType(Severity severity) + { + switch (severity) + { + case Severity.Trace: + case Severity.Debug: + case Severity.Info: + case Severity.Notice: + return EventLogEntryType.Information; + case Severity.Warn: + return EventLogEntryType.Warning; + case Severity.Error: + return EventLogEntryType.Error; + default: + throw new ArgumentOutOfRangeException(nameof(severity), severity, null); + } + } + } +} + +#endif \ No newline at end of file diff --git a/Ntp.Common/Log/FileLog.cs b/Ntp.Common/Log/FileLog.cs new file mode 100644 index 00000000..19ad1917 --- /dev/null +++ b/Ntp.Common/Log/FileLog.cs @@ -0,0 +1,89 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.IO; +using System.Text; + +namespace Ntp.Common.Log +{ + public sealed class FileLog : TextLog, IDisposable + { + internal FileLog(string file, Severity treshold, string timeFormat) + : base(treshold, timeFormat) + { + this.file = file; + } + + private readonly string file; + private TextWriter writer; + + public override void Close() + { + lock (Locker) + { + if (writer != null) + { + writer.Close(); + writer.Dispose(); + writer = null; + } + Initialized = false; + } + } + + protected override TextWriter CreateWriter() + { + writer = new StreamWriter(file, true, Encoding.ASCII); + return writer; + } + + #region IDisposable Support + + private bool disposedValue; + + private void Dispose(bool disposing) + { + if (disposedValue) + return; + + if (disposing) + { + writer.Dispose(); + } + + disposedValue = true; + } + + ~FileLog() + { + Dispose(false); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/ILogConfiguration.cs b/Ntp.Common/Log/ILogConfiguration.cs new file mode 100644 index 00000000..1a45a3d5 --- /dev/null +++ b/Ntp.Common/Log/ILogConfiguration.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace Ntp.Common.Log +{ + public interface ILogConfiguration + { + string File { get; } + Severity Treshold { get; } + LogType LogType { get; } + bool ShowTimestamp { get; } + bool ShowSeverity { get; } + string TimeFormat { get; } + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/LogBase.cs b/Ntp.Common/Log/LogBase.cs new file mode 100644 index 00000000..ca96d9be --- /dev/null +++ b/Ntp.Common/Log/LogBase.cs @@ -0,0 +1,52 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; + +namespace Ntp.Common.Log +{ + public abstract class LogBase + { + protected LogBase(Severity treshold, bool isSysLog = false) + { + Treshold = treshold; + IsSysLog = isSysLog; + } + + public Severity Treshold { get; } + + public bool IsSysLog { get; } + + public abstract void Close(); + + public abstract void Initialize(); + + public abstract void Resume(); + + public abstract void Suspend(); + + public abstract void WriteLine(string text, Severity severity); + + public abstract void WriteLine(Exception exception, Severity severity); + + public abstract void WriteLine(Exception exception); + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/LogFactory.cs b/Ntp.Common/Log/LogFactory.cs new file mode 100644 index 00000000..c5c85fea --- /dev/null +++ b/Ntp.Common/Log/LogFactory.cs @@ -0,0 +1,142 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace Ntp.Common.Log +{ + public static class LogFactory + { + public static string ApplicationName; + private static readonly List Logs = new List(); + + public static void Cleanup() + { + Close(); + Logs.Clear(); + } + + public static void Close() + { + foreach (var log in Logs) + log.Close(); + } + + public static ActivityLog CreateActivityLog() + { + return new ActivityLog(); + } + + public static LogGroup CreateErrorLog(string name) + { + var log = new LogGroup + { + new ConsoleLog(Severity.Error) + { + ShowSeverity = false, + ShowTimeStamp = false + } + }; + return log; + } + + public static LogGroup CreateGroupLog() + { + return new LogGroup(); + } + + public static LogBase CreateLog(ILogConfiguration config) + { + var log = CreateLogInternal(config); + Logs.Add(log); + return log; + } + + public static LogBase CreateLog(IEnumerable configs) + { + var group = new LogGroup(); + + foreach (var config in configs) + { + var log = CreateLogInternal(config); + group.Add(log); + Logs.Add(log); + } + + return group; + } + + public static LogBase CreateSysLog(string name) + { +#if __MonoCS__ + LogBase log = new SysLog(name, Severity.Notice); + Logs.Add(log); + return log; +#else + LogBase log = new EventLog(name, Severity.Notice); + Logs.Add(log); + return log; +#endif + } + + public static void Resume() + { + foreach (var log in Logs) + log.Resume(); + } + + public static void Suspend() + { + foreach (var log in Logs) + log.Suspend(); + } + + private static LogBase CreateLogInternal(ILogConfiguration config) + { + switch (config.LogType) + { + case LogType.Unknown: + case LogType.Console: + return new ConsoleLog(config.Treshold, config.TimeFormat) + { + ShowSeverity = config.ShowSeverity, + ShowTimeStamp = config.ShowTimestamp + }; + case LogType.Syslog: + case LogType.EventLog: +#if __MonoCS__ + return new SysLog(ApplicationName, config.Treshold); +#else + return new EventLog(ApplicationName, config.Treshold); +#endif + case LogType.File: + return new FileLog(config.File, config.Treshold, config.TimeFormat) + { + ShowSeverity = config.ShowSeverity, + ShowTimeStamp = config.ShowTimestamp + }; + default: + throw new ArgumentOutOfRangeException(nameof(config)); + } + } + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/LogGroup.cs b/Ntp.Common/Log/LogGroup.cs new file mode 100644 index 00000000..a5f67242 --- /dev/null +++ b/Ntp.Common/Log/LogGroup.cs @@ -0,0 +1,135 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Ntp.Common.Log +{ + public sealed class LogGroup : LogBase, IEnumerable + { + internal LogGroup() + : base(Severity.Trace) + { + logs = new List(); + } + + private readonly List logs; + + private LogBase SysLog + { + get + { + return logs. + Where(l => l.IsSysLog). + OrderBy(l => l.Treshold). + FirstOrDefault(); + } + } + + private LogBase ConsoleLog + { + get + { + return logs. + Where(l => l is ConsoleLog). + OrderBy(l => l.Treshold). + FirstOrDefault(); + } + } + + public IEnumerator GetEnumerator() + { + return logs.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(LogBase log) + { + var logGroup = log as LogGroup; + if (logGroup != null) + { + logs.AddRange(logGroup); + } + else + { + logs.Add(log); + } + } + + public override void Close() + { + foreach (var log in logs) + log.Close(); + } + + public override void Initialize() + { + foreach (var log in logs) + log.Initialize(); + } + + public override void Resume() + { + foreach (var log in logs) + log.Resume(); + } + + public override void Suspend() + { + foreach (var log in logs) + log.Suspend(); + } + + public override void WriteLine(string text, Severity severity) + { + SysLog?.WriteLine(text, severity); + ConsoleLog?.WriteLine(text, severity); + + foreach (var log in logs.Where(l => l is FileLog)) + log.WriteLine(text, severity); + } + + public override void WriteLine(Exception exception) + { + SysLog?.WriteLine(exception); + ConsoleLog?.WriteLine(exception); + + foreach (var log in logs.Where(l => l is FileLog)) + log.WriteLine(exception); + } + + public override void WriteLine(Exception exception, Severity severity) + { + SysLog?.WriteLine(exception, severity); + ConsoleLog?.WriteLine(exception, severity); + + foreach (var log in logs.Where(l => l is FileLog)) + log.WriteLine(exception, severity); + } + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/LogMessage.cs b/Ntp.Common/Log/LogMessage.cs new file mode 100644 index 00000000..a17daea0 --- /dev/null +++ b/Ntp.Common/Log/LogMessage.cs @@ -0,0 +1,100 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace Ntp.Common.Log +{ + public static class LogMessage + { + public const string HostNotFound = "Host with ID {0} does not exists in database."; + public const string PeerIpNotFound = "Peer with IP {0} does not exists in database."; + public const string PeerIpAmbiguous = "Ambiguous peer IP {0}. Multiple occurrences found in database."; + public const string OpenNtpConfigError = "Traffic data collection is not supported for OpenNTP."; + + public const string DatabaseOpenError = "Failed to connect to database: {0}"; + public const string DatabaseCreateError = "Failed to create database."; + public const string DatabaseCacheError = "Mapper does not implement caching."; + public const string DatabaseCreateTableError = "Could not create database table."; + public const string DatabaseCreateTable = "Creating new table '{0}'."; + public const string DatabaseTableError = "Error while {0} table {1}: {2}"; + public const string DatabaseRead = "reading from"; + public const string DatabaseInsert = "inserting into"; + public const string DatabaseUpdate = "updating"; + public const string DatabaseDelete = "deleting from"; + public const string DatabaseNoUpdate = "Updating rows in {0} table is not supported."; + + public const string HostImportError = "Could not import host data {0}"; + public const string PeerImportError = "Could not import peer data {0}"; + + public const string ClusterStart = "Starting cluster module."; + public const string ClusterNodeAlive = "Cluster node {0} is alive."; + public const string ClusterNodeActive = "Cluster node {0} is active."; + public const string ClusterNodeDead = "Cluster node {0} is dead."; + public const string ClusterNodeError = "Error while contacting cluster node {0}."; + public const string ClusterError = "Error in scheduler module. Aborting."; + + public const string SchedulerStart = "Starting scheduler with {0} jobs."; + public const string SchedulerBehind = "Behind schedule. Trying to catch up."; + public const string SchedulerWaiting = "Waiting for {0} threads to finish."; + public const string SchedulerAbort = "Aborting thread {0}."; + public const string SchedulerFinished = "All threads finished."; + public const string SchedulerError = "Unexpected error in thread {0}."; + + public const string SchedulerJobAdded = + "{0} job{1} added to scheduler with {2}{3} minutes run interval."; + + public const string SchedulerFixedInterval = "fixed "; + public const string SchedulerJobExecuting = "{0} is executing."; + + public const string ScheduledJobText = "{0} scheduled to run {1}"; + + public const string JobRunning = "running"; + public const string JobPostponed = "postponed"; + public const string JobQueued = "queued"; + public const string JobStopped = "stopped"; + + public const string JobError = "Error while executing {0}."; + public const string JobException = "Error in {0}: {1}"; + public const string JobFailed = "{0} failed."; + public const string JobDone = "{0} is done."; + public const string JobText = "{0} job{1}"; + + public const string DestinationNewDirectory = "Created new directory {0}"; + public const string DestinationFileError = "Could not write file {0}"; + public const string DestinationPathError = "Could not create path for file {0}"; + public const string DestinationOwnerError = "Could not change ownership of file {0}"; + public const string DestinationPermissonError = "Could not change permission on file {0}"; + + public const string ImportHostError = "Error while reading host statistics."; + public const string ImportPeerError = "Error while reading peer statistics."; + public const string ImportIoError = "Error while reading I/O statistics."; + + public const string ImportPeerNotFound = + "Could not import host stats from {0}. Peer with IP {1} was not found in database."; + + public const string ImportMultiplePeersNot = + "Could not import host stats from {0}. Found more than one peer with IP {1} in database."; + + public const string ImportNoSyncing = "{0} is not syncing. Adjust clock to start sync."; + public const string ImportNtpValueError = "Received an unknown value from NTP Daemon: {0}"; + public const string ImportOpenNtpUnsynced = "OpenNTP clock is unsynced."; + public const string ImportSyncing = "{0} is syncing to {1}."; + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/LogType.cs b/Ntp.Common/Log/LogType.cs new file mode 100644 index 00000000..19516ef0 --- /dev/null +++ b/Ntp.Common/Log/LogType.cs @@ -0,0 +1,32 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace Ntp.Common.Log +{ + public enum LogType + { + Unknown, + Console, + Syslog, + EventLog, + File + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/Severity.cs b/Ntp.Common/Log/Severity.cs new file mode 100644 index 00000000..2a8c84e4 --- /dev/null +++ b/Ntp.Common/Log/Severity.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +namespace Ntp.Common.Log +{ + public enum Severity + { + Trace = 0, + Debug, + Info, + Notice, + Warn, + Error + } +} \ No newline at end of file diff --git a/Ntp.Common/Log/SysLog.cs b/Ntp.Common/Log/SysLog.cs new file mode 100644 index 00000000..53da6033 --- /dev/null +++ b/Ntp.Common/Log/SysLog.cs @@ -0,0 +1,115 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + + +#if __MonoCS__ +using System; +using Mono.Unix; +using Mono.Unix.Native; + +namespace Ntp.Common.Log +{ + public sealed class SysLog : LogBase + { + public SysLog(string name, Severity treshold) + : base(treshold, true) + { + this.name = name; + } + + private readonly string name; + private static bool initialized = false; + + private const SyslogFacility Facility = SyslogFacility.LOG_DAEMON; + private const SyslogOptions Options = SyslogOptions.LOG_PID; + + public override void Initialize() + { + if (initialized) + return; + + string ident = name; + Syscall.openlog(UnixMarshal.StringToHeap(ident), Options, Facility); + initialized = true; + } + + public override void Suspend() + { + // SysLog cannot suspend + } + + public override void Resume() + { + // SysLog cannot resume + } + + public override void Close() + { + if (initialized) + return; + + Syscall.closelog(); + initialized = false; + } + + public override void WriteLine(Exception exception) + { + WriteLine(exception, Severity.Error); + } + + public override void WriteLine(Exception exception, Severity severity) + { + WriteLine(exception.Message, Severity.Error); + } + + public override void WriteLine(string text, Severity severity) + { + if (initialized) + Initialize(); + + if (severity < Treshold) + return; + + Syscall.syslog(Facility, GetSyslogLevel(severity), text); + } + + private SyslogLevel GetSyslogLevel(Severity severity) + { + switch (severity) + { + case Severity.Error: + return SyslogLevel.LOG_ERR; + case Severity.Warn: + return SyslogLevel.LOG_WARNING; + case Severity.Notice: + return SyslogLevel.LOG_NOTICE; + case Severity.Info: + return SyslogLevel.LOG_INFO; + case Severity.Debug: + return SyslogLevel.LOG_DEBUG; + default: + return SyslogLevel.LOG_DEBUG; + } + } + } +} + +#endif \ No newline at end of file diff --git a/Ntp.Common/Log/TextLog.cs b/Ntp.Common/Log/TextLog.cs new file mode 100644 index 00000000..cf0e400c --- /dev/null +++ b/Ntp.Common/Log/TextLog.cs @@ -0,0 +1,181 @@ +// +// Copyright (c) 2013-2016 Carsten Sonne Larsen +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Ntp.Common.Log +{ + public abstract class TextLog : LogBase + { + protected TextLog(Severity treshold, string timeFormat) + : base(treshold) + { + this.timeFormat = timeFormat; + Initialized = false; + suspended = false; + } + + private readonly List cache = new List(); + + protected readonly object Locker = new object(); + private readonly string timeFormat; + protected bool Initialized; + private bool suspended; + private TextWriter writer; + + public bool ShowTimeStamp { get; set; } + + public bool ShowSeverity { get; set; } + + public override void Initialize() + { + lock (Locker) + { + if (!Initialized && !suspended) + { + writer = CreateWriter(); + Initialized = true; + } + } + } + + public override void Resume() + { + lock (Locker) + { + suspended = false; + } + } + + public override void Suspend() + { + lock (Locker) + { + if (writer != null) + { + writer.Close(); + writer.Dispose(); + writer = null; + } + Initialized = false; + suspended = true; + } + } + + public override void WriteLine(string text, Severity severity) + { + if (!Initialized) + Initialize(); + + lock (Locker) + { + if (Initialized && !suspended && cache.Count != 0) + { + foreach (string line in cache) + { + writer.WriteLine(line); + } + writer.Flush(); + cache.Clear(); + } + } + + if (severity < Treshold) + return; + + string severityText = string.Empty; + + if (ShowSeverity) + { + string pad = string.Empty; + + switch (severity) + { + case Severity.Error: + severityText = "ERROR"; + break; + case Severity.Warn: + severityText = "WARN"; + pad = " "; + break; + case Severity.Notice: + severityText = "NOTICE"; + break; + case Severity.Info: + severityText = "INFO"; + pad = " "; + break; + case Severity.Debug: + severityText = "DEBUG"; + break; + case Severity.Trace: + severityText = "TRACE"; + break; + default: + throw new ApplicationException("Unknown severity level."); + } + + severityText = string.Concat(" [", severityText, "] ", pad); + } + + DateTime now = DateTime.Now; + + string stamp = + ShowTimeStamp && timeFormat != null + ? now.ToString(timeFormat) + : string.Empty; + + string entry = string.Concat(stamp, severityText, text); + + lock (Locker) + { + if (Initialized) + { + writer.WriteLine(entry); + writer.Flush(); + } + else + { + cache.Add(entry); + } + } + } + + public override void WriteLine(Exception exception) + { + WriteLine(exception.Message, Severity.Error); + WriteLine(exception.StackTrace, Severity.Debug); + } + + public override void WriteLine(Exception exception, Severity severity) + { + if (severity < Treshold) + return; + + WriteLine(exception.Message, severity); + WriteLine(exception.StackTrace, severity); + } + + protected abstract TextWriter CreateWriter(); + } +} \ No newline at end of file