diff --git a/Neo.ConsoleService/ConsoleColorSet.cs b/Neo.ConsoleService/ConsoleColorSet.cs
new file mode 100644
index 000000000..c5cc9e4fb
--- /dev/null
+++ b/Neo.ConsoleService/ConsoleColorSet.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Neo.ConsoleService
+{
+ public class ConsoleColorSet
+ {
+ public ConsoleColor Foreground;
+ public ConsoleColor Background;
+
+ ///
+ /// Create a new color set with the current console colors
+ ///
+ public ConsoleColorSet() : this(Console.ForegroundColor, Console.BackgroundColor) { }
+
+ ///
+ /// Create a new color set
+ ///
+ /// Foreground color
+ public ConsoleColorSet(ConsoleColor foreground) : this(foreground, Console.BackgroundColor) { }
+
+ ///
+ /// Create a new color set
+ ///
+ /// Foreground color
+ /// Background color
+ public ConsoleColorSet(ConsoleColor foreground, ConsoleColor background)
+ {
+ Foreground = foreground;
+ Background = background;
+ }
+
+ ///
+ /// Apply the current set
+ ///
+ public void Apply()
+ {
+ Console.ForegroundColor = Foreground;
+ Console.BackgroundColor = Background;
+ }
+ }
+}
diff --git a/neo-cli/CLI/Logger.cs b/neo-cli/CLI/Logger.cs
new file mode 100644
index 000000000..43d178547
--- /dev/null
+++ b/neo-cli/CLI/Logger.cs
@@ -0,0 +1,96 @@
+using Neo.ConsoleService;
+using Neo.Plugins;
+using System;
+using System.IO;
+using System.Text;
+using static System.IO.Path;
+
+namespace Neo.CLI
+{
+ internal class Logger : Plugin, ILogPlugin
+ {
+ private static readonly ConsoleColorSet DebugColor = new ConsoleColorSet(ConsoleColor.Cyan);
+ private static readonly ConsoleColorSet InfoColor = new ConsoleColorSet(ConsoleColor.White);
+ private static readonly ConsoleColorSet WarningColor = new ConsoleColorSet(ConsoleColor.Yellow);
+ private static readonly ConsoleColorSet ErrorColor = new ConsoleColorSet(ConsoleColor.Red);
+ private static readonly ConsoleColorSet FatalColor = new ConsoleColorSet(ConsoleColor.Red);
+
+ public override string Name => "SystemLog";
+ public override string ConfigFile => Combine(GetDirectoryName(Path), "config.json");
+ public override string Path => GetType().Assembly.Location;
+
+ private static void GetErrorLogs(StringBuilder sb, Exception ex)
+ {
+ sb.AppendLine(ex.GetType().ToString());
+ sb.AppendLine(ex.Message);
+ sb.AppendLine(ex.StackTrace);
+ if (ex is AggregateException ex2)
+ {
+ foreach (Exception inner in ex2.InnerExceptions)
+ {
+ sb.AppendLine();
+ GetErrorLogs(sb, inner);
+ }
+ }
+ else if (ex.InnerException != null)
+ {
+ sb.AppendLine();
+ GetErrorLogs(sb, ex.InnerException);
+ }
+ }
+
+ void ILogPlugin.Log(string source, LogLevel level, object message)
+ {
+ if (!Settings.Default.Logger.Active)
+ return;
+
+ if (message is Exception ex)
+ {
+ var sb = new StringBuilder();
+ GetErrorLogs(sb, ex);
+ message = sb.ToString();
+ }
+
+ lock (typeof(Logger))
+ {
+ DateTime now = DateTime.Now;
+ var log = $"[{now.TimeOfDay:hh\\:mm\\:ss\\.fff}] {message}";
+
+ if (Settings.Default.Logger.ConsoleOutput)
+ {
+ var currentColor = new ConsoleColorSet();
+
+ switch (level)
+ {
+ case LogLevel.Debug: DebugColor.Apply(); break;
+ case LogLevel.Error: ErrorColor.Apply(); break;
+ case LogLevel.Fatal: FatalColor.Apply(); break;
+ case LogLevel.Info: InfoColor.Apply(); break;
+ case LogLevel.Warning: WarningColor.Apply(); break;
+ }
+
+ Console.WriteLine(log);
+ currentColor.Apply();
+ }
+
+ if (!string.IsNullOrEmpty(Settings.Default.Logger.Path))
+ {
+ StringBuilder sb = new StringBuilder(source);
+ foreach (char c in GetInvalidFileNameChars())
+ sb.Replace(c, '-');
+ var path = Combine(Settings.Default.Logger.Path, sb.ToString());
+ Directory.CreateDirectory(path);
+ path = Combine(path, $"{now:yyyy-MM-dd}.log");
+ try
+ {
+ File.AppendAllLines(path, new[] { $"[{level}]{log}" });
+ }
+ catch (IOException)
+ {
+ Console.WriteLine("Error writing the log file: " + path);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/neo-cli/CLI/MainService.cs b/neo-cli/CLI/MainService.cs
index 685b45cc4..85c78c41d 100644
--- a/neo-cli/CLI/MainService.cs
+++ b/neo-cli/CLI/MainService.cs
@@ -1,5 +1,4 @@
using Akka.Actor;
-using Microsoft.Extensions.Configuration;
using Neo.ConsoleService;
using Neo.Cryptography.ECC;
using Neo.IO;
@@ -356,19 +355,10 @@ public async void Start(string[] args)
case "--noverify":
verifyImport = false;
break;
- case "/testnet":
- case "--testnet":
- case "-t":
- ProtocolSettings.Initialize(new ConfigurationBuilder().AddJsonFile("protocol.testnet.json").Build());
- Settings.Initialize(new ConfigurationBuilder().AddJsonFile("config.testnet.json").Build());
- break;
- case "/mainnet":
- case "--mainnet":
- case "-m":
- ProtocolSettings.Initialize(new ConfigurationBuilder().AddJsonFile("protocol.mainnet.json").Build());
- Settings.Initialize(new ConfigurationBuilder().AddJsonFile("config.mainnet.json").Build());
- break;
}
+
+ _ = new Logger();
+
NeoSystem = new NeoSystem(Settings.Default.Storage.Engine);
foreach (var plugin in Plugin.Plugins)
diff --git a/neo-cli/Settings.cs b/neo-cli/Settings.cs
index 46c0dda3a..bbcb726b0 100644
--- a/neo-cli/Settings.cs
+++ b/neo-cli/Settings.cs
@@ -6,6 +6,7 @@ namespace Neo
{
public class Settings
{
+ public LoggerSettings Logger { get; }
public StorageSettings Storage { get; }
public P2PSettings P2P { get; }
public UnlockWalletSettings UnlockWallet { get; }
@@ -39,6 +40,7 @@ public static Settings Default
public Settings(IConfigurationSection section)
{
+ this.Logger = new LoggerSettings(section.GetSection("Logger"));
this.Storage = new StorageSettings(section.GetSection("Storage"));
this.P2P = new P2PSettings(section.GetSection("P2P"));
this.UnlockWallet = new UnlockWalletSettings(section.GetSection("UnlockWallet"));
@@ -46,6 +48,20 @@ public Settings(IConfigurationSection section)
}
}
+ public class LoggerSettings
+ {
+ public string Path { get; }
+ public bool ConsoleOutput { get; }
+ public bool Active { get; }
+
+ public LoggerSettings(IConfigurationSection section)
+ {
+ this.Path = string.Format(section.GetValue("Path", "Logs_{0}"), ProtocolSettings.Default.Magic.ToString("X8"));
+ this.ConsoleOutput = section.GetValue("ConsoleOutput", false);
+ this.Active = section.GetValue("Active", false);
+ }
+ }
+
public class StorageSettings
{
public string Engine { get; }
diff --git a/neo-cli/config.json b/neo-cli/config.json
index 239c1c70e..62df1df84 100644
--- a/neo-cli/config.json
+++ b/neo-cli/config.json
@@ -1,5 +1,10 @@
{
"ApplicationConfiguration": {
+ "Logger": {
+ "Path": "Logs_{0}",
+ "ConsoleOutput": false,
+ "Active": false
+ },
"Storage": {
"Engine": "LevelDBStore"
},
diff --git a/neo-cli/config.mainnet.json b/neo-cli/config.mainnet.json
index 239c1c70e..62df1df84 100644
--- a/neo-cli/config.mainnet.json
+++ b/neo-cli/config.mainnet.json
@@ -1,5 +1,10 @@
{
"ApplicationConfiguration": {
+ "Logger": {
+ "Path": "Logs_{0}",
+ "ConsoleOutput": false,
+ "Active": false
+ },
"Storage": {
"Engine": "LevelDBStore"
},
diff --git a/neo-cli/config.testnet.json b/neo-cli/config.testnet.json
index d310712ee..688dddac3 100644
--- a/neo-cli/config.testnet.json
+++ b/neo-cli/config.testnet.json
@@ -1,5 +1,10 @@
{
"ApplicationConfiguration": {
+ "Logger": {
+ "Path": "Logs_{0}",
+ "ConsoleOutput": false,
+ "Active": false
+ },
"Storage": {
"Engine": "LevelDBStore"
},
diff --git a/neo-cli/neo-cli.csproj b/neo-cli/neo-cli.csproj
index 1501d527e..2e51c0fad 100644
--- a/neo-cli/neo-cli.csproj
+++ b/neo-cli/neo-cli.csproj
@@ -28,7 +28,7 @@
-
+