summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/StardewModdingAPI/Framework/LogFileManager.cs46
-rw-r--r--src/StardewModdingAPI/Framework/Monitor.cs104
-rw-r--r--src/StardewModdingAPI/IMonitor.cs14
-rw-r--r--src/StardewModdingAPI/LogLevel.cs24
-rw-r--r--src/StardewModdingAPI/StardewModdingAPI.csproj4
5 files changed, 192 insertions, 0 deletions
diff --git a/src/StardewModdingAPI/Framework/LogFileManager.cs b/src/StardewModdingAPI/Framework/LogFileManager.cs
new file mode 100644
index 00000000..c2a2105b
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/LogFileManager.cs
@@ -0,0 +1,46 @@
+using System;
+using System.IO;
+
+namespace StardewModdingAPI.Framework
+{
+ /// <summary>Manages reading and writing to log file.</summary>
+ internal class LogFileManager : IDisposable
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>The underlying stream writer.</summary>
+ private readonly StreamWriter Stream;
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="path">The log file to write.</param>
+ public LogFileManager(string path)
+ {
+ // create log directory if needed
+ string logDir = Path.GetDirectoryName(path);
+ if (logDir == null)
+ throw new ArgumentException($"The log path '{path}' is not valid.");
+ Directory.CreateDirectory(logDir);
+
+ // open log file stream
+ this.Stream = new StreamWriter(path, append: false) { AutoFlush = true };
+ }
+
+ /// <summary>Write a message to the log.</summary>
+ /// <param name="message">The message to log.</param>
+ public void WriteLine(string message)
+ {
+ this.Stream.WriteLine(message);
+ }
+
+ /// <summary>Release all resources.</summary>
+ public void Dispose()
+ {
+ this.Stream.Dispose();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/Framework/Monitor.cs b/src/StardewModdingAPI/Framework/Monitor.cs
new file mode 100644
index 00000000..4fe1df04
--- /dev/null
+++ b/src/StardewModdingAPI/Framework/Monitor.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace StardewModdingAPI.Framework
+{
+ /// <summary>Encapsulates monitoring and logic for a given module.</summary>
+ internal class Monitor : IMonitor
+ {
+ /*********
+ ** Properties
+ *********/
+ /// <summary>The name of the module which logs messages using this instance.</summary>
+ private readonly string Source;
+
+ /// <summary>The log file to which to write messages.</summary>
+ private readonly LogFileManager LogFile;
+
+ /// <summary>The maximum length of the <see cref="LogLevel"/> values.</summary>
+ private static readonly int MaxLevelLength = (from level in Enumerable.Cast<LogLevel>(Enum.GetValues(typeof(LogLevel))) select level.ToString().Length).Max();
+
+ /// <summary>The console text color for each log level.</summary>
+ private static readonly Dictionary<LogLevel, ConsoleColor> Colors = new Dictionary<LogLevel, ConsoleColor>
+ {
+ [LogLevel.Trace] = ConsoleColor.DarkGray,
+ [LogLevel.Debug] = ConsoleColor.DarkGray,
+ [LogLevel.Info] = ConsoleColor.White,
+ [LogLevel.Warn] = ConsoleColor.Yellow,
+ [LogLevel.Error] = ConsoleColor.Red,
+ [LogLevel.Alert] = ConsoleColor.Magenta
+ };
+
+
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Whether to show trace messages in the console.</summary>
+ internal bool ShowTraceInConsole { get; set; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="source">The name of the module which logs messages using this instance.</param>
+ /// <param name="logFile">The log file to which to write messages.</param>
+ public Monitor(string source, LogFileManager logFile)
+ {
+ // validate
+ if (string.IsNullOrWhiteSpace(source))
+ throw new ArgumentException("The log source cannot be empty.");
+ if (logFile == null)
+ throw new ArgumentNullException(nameof(logFile), "The log file manager cannot be null.");
+
+ // initialise
+ this.Source = source;
+ this.LogFile = logFile;
+ }
+
+ /// <summary>Log a message for the player or developer.</summary>
+ /// <param name="message">The message to log.</param>
+ /// <param name="level">The log severity level.</param>
+ public void Log(string message, LogLevel level = LogLevel.Debug)
+ {
+ this.LogImpl(this.Source, message, Monitor.Colors[level], level);
+ }
+
+ /// <summary>Log a message for the player or developer, using the specified console color.</summary>
+ /// <param name="source">The name of the mod logging the message.</param>
+ /// <param name="message">The message to log.</param>
+ /// <param name="color">The console color.</param>
+ /// <param name="level">The log level.</param>
+ [Obsolete("This method is provided for backwards compatibility and otherwise should not be used. Use " + nameof(Monitor) + "." + nameof(Monitor.Log) + " instead.")]
+ internal void LegacyLog(string source, string message, ConsoleColor color, LogLevel level = LogLevel.Debug)
+ {
+ this.LogImpl(source, message, color, level);
+ }
+
+
+ /*********
+ ** Private methods
+ *********/
+ /// <summary>Write a message line to the log.</summary>
+ /// <param name="source">The name of the mod logging the message.</param>
+ /// <param name="message">The message to log.</param>
+ /// <param name="color">The console color.</param>
+ /// <param name="level">The log level.</param>
+ private void LogImpl(string source, string message, ConsoleColor color, LogLevel level)
+ {
+ // generate message
+ string levelStr = level.ToString().ToUpper().PadRight(Monitor.MaxLevelLength);
+ message = $"[{DateTime.Now:HH:mm:ss} {levelStr} {source}] {message}";
+
+ // log
+ if (this.ShowTraceInConsole || level != LogLevel.Trace)
+ {
+ Console.ForegroundColor = color;
+ Console.WriteLine(message);
+ Console.ResetColor();
+ }
+ this.LogFile.WriteLine(message);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/IMonitor.cs b/src/StardewModdingAPI/IMonitor.cs
new file mode 100644
index 00000000..8d20af01
--- /dev/null
+++ b/src/StardewModdingAPI/IMonitor.cs
@@ -0,0 +1,14 @@
+namespace StardewModdingAPI
+{
+ /// <summary>Encapsulates monitoring and logging for a given module.</summary>
+ public interface IMonitor
+ {
+ /*********
+ ** Methods
+ *********/
+ /// <summary>Log a message for the player or developer.</summary>
+ /// <param name="message">The message to log.</param>
+ /// <param name="level">The log severity level.</param>
+ void Log(string message, LogLevel level = LogLevel.Debug);
+ }
+}
diff --git a/src/StardewModdingAPI/LogLevel.cs b/src/StardewModdingAPI/LogLevel.cs
new file mode 100644
index 00000000..89647876
--- /dev/null
+++ b/src/StardewModdingAPI/LogLevel.cs
@@ -0,0 +1,24 @@
+namespace StardewModdingAPI
+{
+ /// <summary>The log severity levels.</summary>
+ public enum LogLevel
+ {
+ /// <summary>Tracing info intended for developers.</summary>
+ Trace,
+
+ /// <summary>Troubleshooting info that may be relevant to the player.</summary>
+ Debug,
+
+ /// <summary>Info relevant to the player. This should be used judiciously.</summary>
+ Info,
+
+ /// <summary>An issue the player should be aware of. This should be used rarely.</summary>
+ Warn,
+
+ /// <summary>A message indicating something went wrong.</summary>
+ Error,
+
+ /// <summary>Important information to highlight for the player when player action is needed (e.g. new version available). This should be used rarely to avoid alert fatigue.</summary>
+ Alert
+ }
+} \ No newline at end of file
diff --git a/src/StardewModdingAPI/StardewModdingAPI.csproj b/src/StardewModdingAPI/StardewModdingAPI.csproj
index ce302b95..2d6a7c7f 100644
--- a/src/StardewModdingAPI/StardewModdingAPI.csproj
+++ b/src/StardewModdingAPI/StardewModdingAPI.csproj
@@ -195,14 +195,18 @@
<Compile Include="Extensions.cs" />
<Compile Include="Framework\DeprecationLevel.cs" />
<Compile Include="Framework\DeprecationManager.cs" />
+ <Compile Include="Framework\LogFileManager.cs" />
+ <Compile Include="LogLevel.cs" />
<Compile Include="Framework\ModRegistry.cs" />
<Compile Include="Framework\UpdateHelper.cs" />
<Compile Include="Framework\GitRelease.cs" />
<Compile Include="Framework\UserSettings.cs" />
+ <Compile Include="IMonitor.cs" />
<Compile Include="Inheritance\ChangeType.cs" />
<Compile Include="Inheritance\ItemStackChange.cs" />
<Compile Include="Inheritance\SObject.cs" />
<Compile Include="Log.cs" />
+ <Compile Include="Framework\Monitor.cs" />
<Compile Include="LogInfo.cs" />
<Compile Include="LogWriter.cs" />
<Compile Include="Manifest.cs" />