Forráskód Böngészése

Added LogSearcher function to PRS Server Grid

frankvandenbos 5 napja
szülő
commit
2f3ea1ac2e

+ 50 - 0
prs.server/Forms/LogSearcher/LogSearcher.xaml

@@ -0,0 +1,50 @@
+<Window x:Class="PRSServer.LogSearcher"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:local="clr-namespace:PRSServer"
+        mc:Ignorable="d"
+        Title="Log Searcher" Height="800" Width="1200">
+     <Window.DataContext><local:logsearcherViewModel x:Name="ViewModel"/></Window.DataContext>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition Height="*"/>
+        </Grid.RowDefinitions>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="3*"/>
+            <ColumnDefinition Width="4*"/>
+            <ColumnDefinition Width="Auto"/>
+            <ColumnDefinition Width="Auto"/>
+        </Grid.ColumnDefinitions>
+        
+        <TextBox Grid.Row="0" Grid.Column="0" Padding="2" Text="Keyword" BorderThickness="0" />
+        <TextBox Grid.Row="0" Grid.Column="5" Padding="2" Text="Lines Before/After" BorderThickness="0" />
+        
+        <TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" x:Name="keywordBox" Text="{Binding SearchString}" Padding="2" TextBox.Margin="2" Background="LightYellow"/>
+        <Button Grid.Row="1" Grid.Column="2" Content="Search" x:Name="searchButton" Command="{Binding SearchCommand}" Padding="2" Button.Margin="2"/>
+        <TextBox Grid.Row="1" Grid.Column="3" Text="{Binding LineBuffer}" x:Name="LineBuffer" Padding="2" TextBox.Margin="2" Background="LightYellow"/>
+        
+        <ListBox ItemsSource="{Binding Output}" x:Name="outputBox" Grid.Row="2" Padding="2" ListBox.Margin="2" >
+            <ListBox.ItemTemplate>
+                <DataTemplate>
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="Auto"/>
+                            <ColumnDefinition Width="*"/>
+                        </Grid.ColumnDefinitions>
+                        <TextBlock Text="{Binding LineData}" Grid.Column="0" />
+                        <TextBlock Text="{Binding Path=DisplayData}" Grid.Column="1">
+                            <TextBlock.InputBindings>
+                                <MouseBinding Command="{Binding OpenFileCommand}" MouseAction="LeftClick" />
+                            </TextBlock.InputBindings>
+                        </TextBlock>
+                    </Grid>
+                </DataTemplate>
+            </ListBox.ItemTemplate>
+        </ListBox>   
+        <ListBox ItemsSource="{Binding FileInfo}" x:Name="ViewerList" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" Padding="2" ListBox.Margin="2" />
+    </Grid>
+</Window>

+ 11 - 0
prs.server/Forms/LogSearcher/LogSearcher.xaml.cs

@@ -0,0 +1,11 @@
+using System.Windows;
+
+namespace PRSServer;
+
+public partial class LogSearcher : Window
+{
+    public LogSearcher()
+    {
+        InitializeComponent();
+    }
+}

+ 202 - 0
prs.server/Forms/LogSearcher/logsearcherViewModel.cs

@@ -0,0 +1,202 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Security.AccessControl;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using com.sun.java.swing.plaf.windows;
+using Microsoft.Win32;
+using Microsoft.Xaml.Behaviors.Core;
+using NPOI.XSSF.UserModel.Charts;
+
+
+namespace PRSServer;
+
+public class OutputData
+{
+    public string Directory { get; set; }
+    public string DisplayData { get; set; }
+    public string LineData { get; set; }
+    public int LineNumber { get; set; }
+    
+    public ICommand OpenFileCommand { get; set; }
+
+    public OutputData()
+    {
+        OpenFileCommand = new ActionCommand(OpenFile);
+    }
+
+    public void OpenFile()
+    {
+        logsearcherViewModel.LoadFile(LineNumber, Directory);
+    }
+}
+
+public class logsearcherViewModel : INotifyPropertyChanged
+{
+
+    public string SearchString { get; set; }
+    
+    public static int LineBuffer { get; set; }
+
+    public static string Folder { get; set; }
+
+    public ObservableCollection<OutputData> Output { get; set; }
+    
+    public ICommand SearchCommand { get; set; }
+
+    public static String FileName  { get; set; }
+    
+    public static int Line { get; set; }
+    
+    public static ObservableCollection<String> FileInfo { get; set; }
+
+    public logsearcherViewModel()
+    {
+        SearchCommand = new ActionCommand(Search);
+
+        Output = new ObservableCollection<OutputData>();
+        
+        FileInfo = new ObservableCollection<String>();
+
+        LineBuffer = 10;
+    }
+    
+    public static void LoadFile(int LineNumber, string FileLocation)
+    {
+        if (FileLocation == "")
+        {
+            FileInfo.Clear();
+        }
+        else
+        {
+            Line = LineNumber;
+            FileName = FileLocation;
+
+            String[] TempFile = System.IO.File.ReadAllLines(FileName);
+
+            FileInfo.Clear();
+
+            if (LineBuffer < 0)
+            {
+                FileInfo.Add("Please Provide a positive line buffer");
+            }
+            else
+            {
+
+                for (int i = LineNumber - LineBuffer; i < LineNumber + LineBuffer + 1; i++)
+                {
+                    if (i > 0 && i < TempFile.Length)
+                    {
+                        FileInfo.Add(TempFile[i]);
+                    }
+                }
+            }
+        }
+    }
+
+    private void Search()
+    {
+        Output.Clear();
+        Task.Run(() => { SearchDir(SearchString, Folder, SendOutput); });
+
+    }
+
+    private void SendOutput(string text, string fileDirectory, int LineNumber, bool Succeed)
+    {
+        App.Current.Dispatcher.Invoke(() =>
+        {
+            OutputData data = new OutputData();
+            data.Directory = fileDirectory;
+            data.DisplayData = Convert.ToString(LineNumber) + text;
+            data.LineNumber = LineNumber;
+
+            if (Succeed) data.LineData = "O";
+            else data.LineData = "X";
+            if (fileDirectory != "") data.LineData = "   ";
+            data.LineData += "  ";
+            
+            Output.Add(data);
+        });
+    }
+
+    public void SearchDir(string keyword, string folderDirectory, Action<String, String, int, bool> report)
+    {
+        if (keyword == "")
+        {
+            report("No keyword specified", "", 0, false);
+        }
+        else if (keyword == " ")
+        {
+            report("Invalid keyword specified", "", 0, false);
+        }
+        else
+        {
+            if (!Directory.Exists(@folderDirectory))
+            {
+                report("Directory does not exist: " + folderDirectory, "", 0, false);
+            }
+            else
+            {
+                string path = @folderDirectory;
+
+                string[] logFiles = Directory.GetFiles(path, "*.log");
+
+                for (int i = logFiles.Length - 1; i >= 0; i--)
+                {
+                    string newPath = logFiles[i];
+                    string fileName = Path.GetFileName(newPath);
+                    List<(string, int)> results = new List<(string, int)>();
+
+                    string[] CurrentFile = File.ReadAllLines(newPath);
+                    for (int j = 0; j < CurrentFile.Length; j++)
+                    {
+                        string line = CurrentFile[j];
+                        
+                        if (Regex.IsMatch(line, keyword))
+                        {
+                            results.Add((line, j));
+                        }
+                    }
+
+                    if (results.Count > 0)
+                    {
+                        report($"{fileName}: found {results.Count} matches", "", 0, true);
+
+                        for (int j = 0; j < results.Count; j++)
+                        {
+                            (string, int) result = results[j];
+                            report("    " + result.Item1, newPath, result.Item2, false);
+
+                        }
+                    }
+                    else
+                    {
+                        report($"{fileName}: found no matches", "", 0, false);
+                    }
+                }
+            }
+
+            ;
+        }
+    }
+
+    public event PropertyChangedEventHandler? PropertyChanged;
+
+    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
+    {
+        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+    }
+
+    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
+    {
+        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
+        field = value;
+        OnPropertyChanged(propertyName);
+        return true;
+    }
+}

+ 25 - 0
prs.server/Forms/ServerGrid.cs

@@ -170,6 +170,13 @@ public class ServerGrid : DynamicGrid<Server>
         if (type.Equals(ServerType.Database))
         {
             column.AddSeparator();
+            column.AddItem(
+                "Search Log Files",
+                Properties.Resources.service,
+                (row) => SearchLogFiles(row!), 
+                null, 
+                status == DynamicMenuStatus.Enabled
+            );
             column.AddItem(
                 "Custom Fields",
                 Properties.Resources.service,
@@ -1199,6 +1206,24 @@ public class ServerGrid : DynamicGrid<Server>
         return false;
     }
 
+    private bool SearchLogFiles(CoreRow selectedrow)
+    {
+        string Folder = "";
+        
+        if (selectedrow != null)
+        {
+            var Key = selectedrow.Get<Server, string>(x => x.Key);
+            var manager = new RpcClientPipeTransport($"{Key}M");
+            var result = manager.Send<LogFolderCommand, LogFolderParameters, LogFolderResult>(new LogFolderParameters());
+            Folder = result.Folder;
+        }
+
+        var window = new LogSearcher();
+        logsearcherViewModel.Folder = Folder;
+        window.ShowDialog();
+        return false;
+    }
+
     private bool ManageDeletions(CoreRow row)
     {
         ConfigureLocalDatabase(row, () =>

+ 10 - 1
prs.services/Engine.cs

@@ -14,6 +14,7 @@ namespace PRSServices;
 public interface IEngine
 {
     string ServiceName { get; set; }
+    string AppDataFolder { get; set; }
 
     string Version { get; set; }
     void Run();
@@ -22,6 +23,8 @@ public interface IEngine
     void Configure(Server settings);
 
     PortStatus[] PortStatusList();
+    
+    string LogFolder();
 }
 
 public abstract class Engine<TProperties> : IEngine where TProperties : ServerProperties
@@ -40,11 +43,16 @@ public abstract class Engine<TProperties> : IEngine where TProperties : ServerPr
         return new PortStatus[] { };
     }
 
+    public string LogFolder()
+    {
+        throw new NotImplementedException();
+    }
+
     public string ServiceName { get; set; }
 
     public string Version { get; set; }
 
-    protected string AppDataFolder { get; set; }
+    public string AppDataFolder { get; set; }
 
     public virtual void Configure(Server server)
     {
@@ -56,6 +64,7 @@ public abstract class Engine<TProperties> : IEngine where TProperties : ServerPr
         
         _enginemanager = new RpcServerPipeTransport($"{ServiceName}M");
         _enginemanager.AddHandler<IEngine, PortStatusCommand, PortStatusParameters, PortStatusResult>(new PortStatusHandler(this));
+        _enginemanager.AddHandler<IEngine,LogFolderCommand,LogFolderParameters,LogFolderResult>(new LogFolderHandler(this));
         _enginemanager.AfterMessage += (transport, args) => MainLogger.Send(LogType.Information,"",$"Engine Manager Message: {args.Message?.Command}", Guid.Empty);
         _enginemanager.Start();
     }

+ 55 - 0
prs.services/LogFolder.cs

@@ -0,0 +1,55 @@
+using InABox.Core;
+using InABox.Rpc;
+
+namespace PRSServices;
+
+public class LogFolderResult : IRpcCommandResult
+{
+    public string Folder { get; set; }
+
+    public LogFolderResult()
+    {
+        Folder = "";
+    }
+    public void SerializeBinary(CoreBinaryWriter writer)
+    {
+        writer.WriteBinaryValue(Folder);
+    }
+
+    public void DeserializeBinary(CoreBinaryReader reader)
+    {
+        Folder = reader.ReadBinaryValue<string>();
+    }
+
+    public string? FullDescription() => null;
+}
+
+public class LogFolderCommand : IRpcCommand<LogFolderParameters, LogFolderResult>
+{
+
+}
+
+public class LogFolderParameters : IRpcCommandParameters
+{
+    public void SerializeBinary(CoreBinaryWriter writer)
+    {
+    }
+
+    public void DeserializeBinary(CoreBinaryReader reader)
+    {
+    }
+
+    public string? FullDescription() => null;
+
+    public string? ShortDescription() => null;
+}
+
+public class LogFolderHandler : RpcCommandHandler<IEngine, LogFolderCommand, LogFolderParameters, LogFolderResult> 
+{
+    protected override LogFolderResult Execute(IRpcSession session, LogFolderParameters? parameters, Logger logger) 
+        => new() { Folder = Sender.AppDataFolder };
+
+    public LogFolderHandler(IEngine sender) : base(sender)
+    {
+    }
+}