/// <summary> /// Reads the log configuration from a file with the specified <paramref name="fileName"/>. /// If <paramref name="watch"/> is set, the configuration is updated /// every time the file is modified. /// </summary> /// <exception cref="ArgumentException">If the specified <paramref name="fileName"/> does not point to valid file.</exception> public static LogConfiguration ReadFile(string fileName, bool watch) { string fullPath = Path.GetFullPath(fileName); if (!File.Exists(fullPath)) { throw new ArgumentException($"There is no file located at '{fullPath}'."); } string fileContent = File.ReadAllText(fileName); LogConfiguration logConfig = ReadText(fileContent); if (!watch) { return(logConfig); } string fileDir = Path.GetDirectoryName(fullPath); if (fileDir == null) { throw new ArgumentException($"Cannot resolve containing folder of file '{fullPath}'."); } string simpleFileName = Path.GetFileName(fullPath); // ReSharper disable once InconsistentNaming void updateLogConfiguration(object sender, FileSystemEventArgs e) { OnFileChanged(logConfig, e); } if (_fileSystemWatcher != null) { _fileSystemWatcher.Changed -= updateLogConfiguration; // Does this really work? _fileSystemWatcher.Dispose(); _fileSystemWatcher = null; } _fileSystemWatcher = new FileSystemWatcher(fileDir, simpleFileName); _fileSystemWatcher.Changed += updateLogConfiguration; return(logConfig); }
/// <summary> /// Reads the log configuration from the given <paramref name="fileContent"/>. /// If the <paramref name="fileContent"/> is NULL or empty, a default configuration /// is returned. /// </summary> public static LogConfiguration ReadText(string fileContent) { LogConfiguration fileConfig = new LogConfiguration(); // No content, no configuration if (string.IsNullOrEmpty(fileContent)) { return(fileConfig); } Dictionary <string, ILogStream> streamSet = new Dictionary <string, ILogStream>(10); // Parse lines string[] lines = fileContent.Split('\n'); for (int i = -1; ++i != lines.Length;) { string line = lines[i]; if (string.IsNullOrEmpty(line)) { continue; // Empty line } if (line[0] == '#') { continue; // Comment line } string[] linePair = line.Split('='); if (linePair.Length != 2) { continue; // Invalid format } char[] bias = { ' ', '\t', '\r' }; string key = linePair[0].Trim(bias).ToLower(); string value = linePair[1].Trim(bias); if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) { continue; } // Reserved word if (key == "level") { ELogLevel.TryParse(value, out ELogLevel level); fileConfig.SetLevel(level); continue; } if (key == "pattern") { fileConfig.SetPattern(value); continue; } if (key == "streams") { string[] streamNames = value.Split(','); for (int j = -1; ++j != streamNames.Length;) { string streamName = streamNames[j].Trim(); if (string.IsNullOrEmpty(streamName)) { continue; } streamSet[streamName] = null; } continue; } // Dynamic content int psIdx = key.IndexOf('.'); string streamId; string streamProp; ILogStream logStream; // No dot, no stream property. But the stream kind. if (psIdx == -1) { streamId = key; logStream = StreamStore.GetStreamInstance(value); streamSet[streamId] = logStream; fileConfig.AddStream(logStream); continue; } streamId = key.Substring(0, psIdx); streamProp = key.Substring(psIdx + 1); if (!streamSet.TryGetValue(streamId, out logStream)) { continue; } SetStreamProperty(logStream, streamProp, value); } return(fileConfig); }
/// <summary> Is invoked when the watched log file has been changed. </summary> private static void OnFileChanged(LogConfiguration logConfig, FileSystemEventArgs e) { // Currently not implemented }