private static void TailFiles(int lines, List<string> files, Action<LogEntry> showentry) { foreach (var fileName in files) { using (var file = FileUtil.OpenReadOnly(fileName)) { var items = new LogEntryParser().Parse(file) .ToArray(); foreach (var logEntry in items.Skip(items.Count() - lines)) { showentry(logEntry); } } } }
static void Main(string[] args) { var files = new List<string>(); int monitor = 0; int? lines = null; var watch = false; PatternLayout layout=null; var help = false; var p = new OptionSet() { { "f|file=", v => { files.Add(v); } }, { "m|monitor=", v => { monitor=Int32.Parse(v);}}, { "w|watch", v => { watch = true;}}, { "l|lines=", v => { lines=Int32.Parse(v);}}, { "h|?|help", v => { help = true;}}, { "y|layout=",v=> { layout=new PatternLayout(v);}} }; var detectedFiles = args .Where(a=>!(a.StartsWith("-") || a.StartsWith("/"))) .Where(a=> Uri.IsWellFormedUriString(a, UriKind.RelativeOrAbsolute)) .Where(a=> File.Exists(a)); // does not seem to work. add tests files.AddRange(detectedFiles); p.Parse(args); Action<LogEntry> showentry; if (null != layout) { showentry = l => layout.Format(Console.Out, new LoggingEvent(l.Data)); } else { showentry = l => Console.WriteLine(l.Data.Message); } if (help) { Console.WriteLine(@"Usage: -f|file={a filename} The file to watch, monitor or -l|lines={tail x lines} Display the last x lines. Defaults to 10 lines. -y|layout={pattern layout syntax as defined in log4net.Layout.PatternLayout} -h|?|help Display help For instance to : LogTail.exe -f=logfile.xml LogTail.exe -file=logfile.xml "); return; } if (watch) { Do(new Watcher(new FileWithPosition(files.Single())) { logentry = showentry }); return; } if (monitor > 0) { Do(new Poller(new FileWithPosition(files.Single()), monitor) { logentry = showentry }); return; } if (files.Any()){ TailFiles(lines ?? 10, files, showentry); return; } else { Console.WriteLine("No files, listening to standard input."); using (Stream stdin = Console.OpenStandardInput()) using (Stream stdout = Console.OpenStandardOutput()) using (StreamWriter writer = new StreamWriter(stdout)) { var items = new LogEntryParser().Parse(stdin).ToArray(); foreach (var logEntry in items.Skip(items.Count() - (lines??10))) { writer.WriteLine(logEntry.Data.Message); } } return; } }
static void Main(string[] args) { var files = new List<string>(); int monitor = 0; int? lines = null; var watch = false; LayoutSkeleton layout = null; var help = false; var p = new OptionSet() { { "i|file=", v => { files.Add(v); } }, { "m|monitor=", v => { monitor=ParseInterval(v);}}, { "w|watch", v => { watch = true;}}, { "l|lines=", v => { lines=Int32.Parse(v);}}, { "h|?|help", v => { help = true;}}, { "y|layout=",v=> { layout=new PatternLayout(v);}}, { "f|format=", v=> { layout = GetFormatLayout(v); }} }; var detectedFiles = args .Where(a => !(a.StartsWith("-") || a.StartsWith("/"))) .Where(a => File.Exists(a)); files.AddRange(detectedFiles); p.Parse(args); if (layout == null) { layout = new SimpleLayout(); } Action<TextWriter,LogEntry> showentry = (writer, l) => layout.Format(writer, new LoggingEvent(l.Data)); if (help) { Console.WriteLine(@"Usage: -i|file={a filename} The (input) file to watch, monitor or -l|lines={tail x lines} Display the last x lines. Defaults to 10 lines. -y|layout={pattern layout syntax as defined in log4net.Layout.PatternLayout} -f|format={a named layout format} The available formats are: -f=minusminus Information delimited by newline and ---------------------- -h|?|help Display help -w|watch Use file system watcher to watch file -m|monitor=seconds Use polling to check for changes of the file. For instance to : LogTail.exe -f=logfile.xml LogTail.exe -file=logfile.xml If you are in powershell (or cygwin) you can do the following: cat yourlogfile.xml | LogTail.exe "); return; } if (watch) { var w = new Watcher<LogEntry>(new FileWithPosition(files.Single()), new LogEntryParser()); w.LogEntry += (entry) => showentry(Console.Out, entry); Do(w); return; } if (monitor > 0) { var w = new Poller<LogEntry>(new FileWithPosition(files.Single()), monitor, new LogEntryParser()); w.LogEntry += (entry) => showentry(Console.Out, entry); Do(w); return; } if (files.Any()) { TailFiles(lines ?? 10, files, (entry) => showentry(Console.Out, entry)); return; } else { Console.WriteLine("No files, listening to standard input."); using (Stream stdin = Console.OpenStandardInput()) using (Stream stdout = Console.OpenStandardOutput()) using (StreamWriter writer = new StreamWriter(stdout)) { var items = new LogEntryParser().Parse(stdin).ToArray(); foreach (var logEntry in items.Skip(items.Count() - (lines ?? 10))) { showentry(writer, logEntry); } } return; } }