Skip to content

Commit 1d0aa58

Browse files
committed
Working NLog with config file and "verbose log" option
1 parent c93e1d5 commit 1d0aa58

10 files changed

+188
-28
lines changed

shadowsocks-csharp/Controller/ShadowsocksController.cs

+4
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ public void ToggleVerboseLogging(bool enabled)
254254
{
255255
_config.isVerboseLogging = enabled;
256256
SaveConfig(_config);
257+
NLogConfig.LoadConfiguration(); // reload nlog
257258

258259
VerboseLoggingStatusChanged?.Invoke(this, new EventArgs());
259260
}
@@ -477,6 +478,9 @@ protected void Reload()
477478
Encryption.RNG.Reload();
478479
// some logic in configuration updated the config when saving, we need to read it again
479480
_config = Configuration.Load();
481+
482+
NLogConfig.LoadConfiguration();
483+
480484
StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
481485

482486
privoxyRunner = privoxyRunner ?? new PrivoxyRunner();

shadowsocks-csharp/Data/NLog.config

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<?xml version="1.0" encoding="utf-8" ?>
2-
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2+
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
autoReload="true">
35
<targets>
46
<target name="file" xsi:type="File" fileName="shadowsocks.log"/>
5-
<target name="richText" xsi:type="RichTextBox" allowAccessoryFormCreation="false" messageRetention="All" maxLines="5120" autoScroll="true" controlName="" formName=""/>
67
</targets>
78
<rules>
8-
<logger name="*" minlevel="Info" writeTo="file, richText" />
9+
<logger name="*" minlevel="Info" writeTo="file"/>
910
</rules>
1011
</nlog>

shadowsocks-csharp/Model/Configuration.cs

+37-1
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ public class Configuration
3636
public bool autoCheckUpdate;
3737
public bool checkPreRelease;
3838
public bool isVerboseLogging;
39+
//public NLogConfig.LogLevel logLevel;
3940
public LogViewerConfig logViewer;
4041
public ProxyConfig proxy;
4142
public HotkeyConfig hotkey;
4243

44+
[JsonIgnore]
45+
NLogConfig nLogConfig;
46+
4347
private static readonly string CONFIG_FILE = "gui-config.json";
4448
[JsonIgnore]
4549
public string localHost => GetLocalHost();
@@ -104,6 +108,28 @@ public static Configuration Load()
104108

105109
config.proxy.CheckConfig();
106110

111+
try
112+
{
113+
config.nLogConfig = NLogConfig.LoadXML();
114+
switch (config.nLogConfig.GetLogLevel())
115+
{
116+
case NLogConfig.LogLevel.Fatal:
117+
case NLogConfig.LogLevel.Error:
118+
case NLogConfig.LogLevel.Warn:
119+
case NLogConfig.LogLevel.Info:
120+
config.isVerboseLogging = false;
121+
break;
122+
case NLogConfig.LogLevel.Debug:
123+
case NLogConfig.LogLevel.Trace:
124+
config.isVerboseLogging = true;
125+
break;
126+
}
127+
}
128+
catch (Exception e)
129+
{
130+
logger.Error(e, "Cannot get the log level from NLog config file.");
131+
}
132+
107133
return config;
108134
}
109135
catch (Exception e)
@@ -122,7 +148,7 @@ public static Configuration Load()
122148
},
123149
logViewer = new LogViewerConfig(),
124150
proxy = new ProxyConfig(),
125-
hotkey = new HotkeyConfig()
151+
hotkey = new HotkeyConfig(),
126152
};
127153
}
128154
}
@@ -145,6 +171,16 @@ public static void Save(Configuration config)
145171
sw.Write(jsonString);
146172
sw.Flush();
147173
}
174+
try
175+
{
176+
// apply changs to NLog.config
177+
config.nLogConfig.SetLogLevel(config.isVerboseLogging? NLogConfig.LogLevel.Trace: NLogConfig.LogLevel.Info);
178+
NLogConfig.SaveXML(config.nLogConfig);
179+
}
180+
catch(Exception e)
181+
{
182+
logger.Error(e, "Cannot set the log level");
183+
}
148184
}
149185
catch (IOException e)
150186
{
+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using NLog;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using System.Xml;
9+
10+
namespace Shadowsocks.Model
11+
{
12+
public class NLogConfig
13+
{
14+
public enum LogLevel
15+
{
16+
Fatal,
17+
Error,
18+
Warn,
19+
Info,
20+
Debug,
21+
Trace,
22+
}
23+
24+
const string NLOG_CONFIG_FILE_NAME = "NLog.config";
25+
const string MIN_LEVEL_ATTRIBUTE = "minlevel";
26+
const string FILE_NAME_ATTRIBUTE = "fileName";
27+
28+
XmlDocument doc = new XmlDocument();
29+
XmlElement logLevelElement;
30+
XmlElement logFileNameElement;
31+
32+
/// <summary>
33+
/// Load the NLog config xml file content
34+
/// </summary>
35+
public static NLogConfig LoadXML()
36+
{
37+
NLogConfig config = new NLogConfig();
38+
config.doc.Load(NLOG_CONFIG_FILE_NAME);
39+
config.logLevelElement = (XmlElement)SelectSingleNode(config.doc, "//nlog:logger[@name='*']");
40+
config.logFileNameElement = (XmlElement)SelectSingleNode(config.doc, "//nlog:target[@name='file']");
41+
return config;
42+
}
43+
44+
/// <summary>
45+
/// Save the content to NLog config xml file
46+
/// </summary>
47+
public static void SaveXML(NLogConfig nLogConfig)
48+
{
49+
nLogConfig.doc.Save(NLOG_CONFIG_FILE_NAME);
50+
}
51+
52+
53+
/// <summary>
54+
/// Get the current minLogLevel from xml file
55+
/// </summary>
56+
/// <returns></returns>
57+
public LogLevel GetLogLevel()
58+
{
59+
LogLevel level = LogLevel.Warn;
60+
string levelStr = logLevelElement.GetAttribute(MIN_LEVEL_ATTRIBUTE);
61+
Enum.TryParse(levelStr, out level);
62+
return level;
63+
}
64+
65+
/// <summary>
66+
/// Get the target fileName from xml file
67+
/// </summary>
68+
/// <returns></returns>
69+
public string GetLogFileName()
70+
{
71+
return logFileNameElement.GetAttribute(FILE_NAME_ATTRIBUTE);
72+
}
73+
74+
/// <summary>
75+
/// Set the minLogLevel to xml file
76+
/// </summary>
77+
/// <param name="logLevel"></param>
78+
public void SetLogLevel(LogLevel logLevel)
79+
{
80+
logLevelElement.SetAttribute(MIN_LEVEL_ATTRIBUTE, logLevel.ToString("G"));
81+
}
82+
83+
/// <summary>
84+
/// Set the target fileName to xml file
85+
/// </summary>
86+
/// <param name="fileName"></param>
87+
public void SetLogFileName(string fileName)
88+
{
89+
logFileNameElement.SetAttribute(FILE_NAME_ATTRIBUTE, fileName);
90+
}
91+
92+
private static XmlNode SelectSingleNode(XmlDocument doc, string xpath)
93+
{
94+
XmlNamespaceManager manager = new XmlNamespaceManager(doc.NameTable);
95+
manager.AddNamespace("nlog", "http://www.nlog-project.org/schemas/NLog.xsd");
96+
//return doc.SelectSingleNode("//nlog:logger[(@shadowsocks='managed') and (@name='*')]", manager);
97+
return doc.SelectSingleNode(xpath, manager);
98+
}
99+
100+
/// <summary>
101+
/// Extract the pre-defined NLog configuration file is does not exist. Then reload the Nlog configuration.
102+
/// </summary>
103+
public static void TouchAndApplyNLogConfig()
104+
{
105+
if (!File.Exists(NLOG_CONFIG_FILE_NAME))
106+
{
107+
File.WriteAllText(NLOG_CONFIG_FILE_NAME, Properties.Resources.NLog_config);
108+
LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME);
109+
}
110+
}
111+
112+
public static void LoadConfiguration()
113+
{
114+
LogManager.LoadConfiguration(NLOG_CONFIG_FILE_NAME);
115+
}
116+
}
117+
}

shadowsocks-csharp/Program.cs

+1-11
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ static class Program
2727
static void Main(string[] args)
2828
{
2929
// todo: initialize the NLog configuartion
30-
TouchAndApplyNLogConfig();
30+
Model.NLogConfig.TouchAndApplyNLogConfig();
3131

3232
// .NET Framework 4.7.2 on Win7 compatibility
3333
System.Net.ServicePointManager.SecurityProtocol |=
@@ -97,16 +97,6 @@ static void Main(string[] args)
9797
}
9898
}
9999

100-
private static void TouchAndApplyNLogConfig()
101-
{
102-
string NLogConfigFileName = "NLog.config";
103-
if (!File.Exists(NLogConfigFileName))
104-
{
105-
File.WriteAllText(NLogConfigFileName, Properties.Resources.NLog_config);
106-
LogManager.LoadConfiguration(NLogConfigFileName);
107-
}
108-
}
109-
110100
private static int exited = 0;
111101
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
112102
{

shadowsocks-csharp/Util/Util.cs

+5-6
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static string GetTempPath()
6161
public enum WindowsThemeMode { Dark, Light }
6262

6363
// Support on Windows 10 1903+
64-
public static WindowsThemeMode GetWindows10SystemThemeSetting(bool isVerbose)
64+
public static WindowsThemeMode GetWindows10SystemThemeSetting()
6565
{
6666
WindowsThemeMode themeMode = WindowsThemeMode.Dark;
6767
try
@@ -81,11 +81,10 @@ public static WindowsThemeMode GetWindows10SystemThemeSetting(bool isVerbose)
8181
}
8282
catch
8383
{
84-
if (isVerbose)
85-
{
86-
logger.Info(
87-
$"Cannot get Windows 10 system theme mode, return default value 0 (dark mode).");
88-
}
84+
85+
logger.Info(
86+
$"Cannot get Windows 10 system theme mode, return default value 0 (dark mode).");
87+
8988
}
9089
return themeMode;
9190
}

shadowsocks-csharp/View/LogForm.cs

+7-4
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@ public partial class LogForm : Form
4141
TextAnnotation outboundAnnotation = new TextAnnotation();
4242
#endregion
4343

44-
public LogForm(ShadowsocksController controller, string filename=null)
44+
public LogForm(ShadowsocksController controller)
4545
{
4646
this.controller = controller;
47-
this.filename = filename;
47+
4848
InitializeComponent();
4949
Icon = Icon.FromHandle(Resources.ssw128.GetHicon());
5050

51+
var nLogConfig = NLogConfig.LoadXML();
52+
this.filename = nLogConfig.GetLogFileName();
53+
5154
LogViewerConfig config = controller.GetConfigurationCopy().logViewer;
5255

5356
topMostTrigger = config.topMost;
@@ -173,7 +176,7 @@ private void InitContent()
173176
string line = "";
174177
StringBuilder appendText = new StringBuilder(1024);
175178
while ((line = reader.ReadLine()) != null)
176-
appendText.Append(line + Environment.NewLine);
179+
appendText.AppendLine(line);
177180

178181
LogMessageTextBox.AppendText(appendText.ToString());
179182
LogMessageTextBox.ScrollToCaret();
@@ -197,7 +200,7 @@ private void UpdateContent()
197200
while ((line = reader.ReadLine()) != null)
198201
{
199202
changed = true;
200-
appendText.Append(line + Environment.NewLine);
203+
appendText.AppendLine(line);
201204
}
202205

203206
if (changed)

shadowsocks-csharp/View/MenuViewController.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ private Color SelectColorMask(bool isProxyEnabled, bool isGlobalProxy)
222222
{
223223
Color colorMask = Color.White;
224224

225-
Utils.WindowsThemeMode currentWindowsThemeMode = Utils.GetWindows10SystemThemeSetting(controller.GetCurrentConfiguration().isVerboseLogging);
225+
Utils.WindowsThemeMode currentWindowsThemeMode = Utils.GetWindows10SystemThemeSetting();
226226

227227
if (isProxyEnabled)
228228
{

shadowsocks-csharp/shadowsocks-csharp.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
<Compile Include="Encryption\Stream\StreamOpenSSLEncryptor.cs" />
133133
<Compile Include="Encryption\Stream\StreamSodiumEncryptor.cs" />
134134
<Compile Include="Model\HotKeyConfig.cs" />
135+
<Compile Include="Model\NLogConfig.cs" />
135136
<Compile Include="Model\ProxyConfig.cs" />
136137
<Compile Include="Model\SysproxyConfig.cs" />
137138
<Compile Include="Properties\Resources.Designer.cs">

shadowsocks-windows.sln

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
3-
# Visual Studio 15
4-
VisualStudioVersion = 15.0.26228.10
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.29709.97
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shadowsocks-csharp", "shadowsocks-csharp\shadowsocks-csharp.csproj", "{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}"
77
EndProject
@@ -12,21 +12,30 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShadowsocksTest", "test\Sha
1212
EndProject
1313
Global
1414
GlobalSection(SolutionConfigurationPlatforms) = preSolution
15+
Debug|Any CPU = Debug|Any CPU
1516
Debug|x86 = Debug|x86
17+
Release|Any CPU = Release|Any CPU
1618
Release|x86 = Release|x86
1719
EndGlobalSection
1820
GlobalSection(ProjectConfigurationPlatforms) = postSolution
21+
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|Any CPU.ActiveCfg = Debug|x86
1922
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.ActiveCfg = Debug|x86
2023
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Build.0 = Debug|x86
2124
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Debug|x86.Deploy.0 = Debug|x86
25+
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|Any CPU.ActiveCfg = Release|x86
2226
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.ActiveCfg = Release|x86
2327
{8C02D2F7-7CDB-4D55-9F25-CD03EF4AA062}.Release|x86.Build.0 = Release|x86
28+
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|Any CPU.ActiveCfg = Debug|x86
2429
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.ActiveCfg = Debug|x86
2530
{45913187-0685-4903-B250-DCEF0479CD86}.Debug|x86.Build.0 = Debug|x86
31+
{45913187-0685-4903-B250-DCEF0479CD86}.Release|Any CPU.ActiveCfg = Release|x86
2632
{45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.ActiveCfg = Release|x86
2733
{45913187-0685-4903-B250-DCEF0479CD86}.Release|x86.Build.0 = Release|x86
2834
EndGlobalSection
2935
GlobalSection(SolutionProperties) = preSolution
3036
HideSolutionNode = FALSE
3137
EndGlobalSection
38+
GlobalSection(ExtensibilityGlobals) = postSolution
39+
SolutionGuid = {F7E7D35B-4FDA-4385-95CF-09DADED042EA}
40+
EndGlobalSection
3241
EndGlobal

0 commit comments

Comments
 (0)