Files
DDUtility/DDUtilityApp/LOGPARSER/FrmMessageReplyTime1.cs
2025-02-03 11:02:48 +09:00

580 lines
20 KiB
C#

#define XDateTimeAxis
using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using DDUtilityApp.LOGPARSER.DATA;
using JWH;
using JWH.DATA;
using Telerik.Charting;
using Telerik.WinControls.UI;
namespace DDUtilityApp.LOGPARSER
{
public partial class FrmMessageReplyTime1 : Form
{
#region [ Deleage ] ===================================================
#endregion
#region [ Events ] ====================================================
#endregion
#region [ Variables ] =================================================
private Dictionary<string, StandardDataAnalysis> AnalysisCollection = new Dictionary<string, StandardDataAnalysis>();
private CartesianAxis HorizontalAxis { get; set; } = null;
private LinearAxis VerticalAxis { get; set; } = null;
#endregion
#region [ Properties ] ================================================
public StandardCollection StandardCollection { get; set; } = null;
public Dictionary<string, List<StandardDataPair>> MessageCollection { get; set; } = new Dictionary<string, List<StandardDataPair>>();
public RadGridView GridView { get; set; } = null;
#endregion
#region [ Constructor ] ===============================================
public FrmMessageReplyTime1()
{
InitializeComponent();
this.SetLayout();
this.SetEventHandler();
}
public FrmMessageReplyTime1(StandardCollection standardCollection) : this()
{
this.StandardCollection = standardCollection;
}
private void SetLayout()
{
Font font = new Font("돋움체", 9);
this.cboxMessageName.Font = font;
this.Grid_Setting();
this.GridAnalysis_Setting();
this.Chart_Setting();
}
private void SetEventHandler()
{
this.btnGenerate.Click += this.BtnGenerate_Click;
this.chkTrimmed.CheckedChanged += this.ChkTrimmed_CheckedChanged;
this.button1.Click += this.Button1_Click;
this.cboxMessageName.SelectedIndexChanged += this.CboxMessageName_SelectedIndexChanged;
this.chkShowLabel.CheckedChanged += this.ChkShowLabel_CheckedChanged;
ChartTrackballController controller = new ChartTrackballController();
controller.TextNeeded += this.ChartTrackball_TextNeeded;
this.chart.Controllers.Add(controller);
this.grid.RowFormatting += this.Grid_RowFormatting;
this.grid.CellDoubleClick += this.Grid_CellDoubleClick;
this.gridAnalysis.RowFormatting += this.GridAnalysis_RowFormatting;
this.gridAnalysis.CellFormatting += this.GridAnalysis_CellFormatting;
}
#endregion
#region [ Control Events ] ============================================
private void BtnGenerate_Click(object sender, EventArgs e)
{
this.Generate();
}
private void ChkTrimmed_CheckedChanged(object sender, EventArgs e)
{
}
private void CboxMessageName_SelectedIndexChanged(object sender, EventArgs e)
{
this.chart.Series.Clear();
try
{
#region Grid Display
List<StandardDataPair> lst = new List<StandardDataPair>();
if (string.IsNullOrEmpty(this.cboxMessageName.Text))
{
foreach (KeyValuePair<string, List<StandardDataPair>> pair in this.MessageCollection)
{
lst.AddRange(pair.Value.ToArray());
this.Chart_AddSeries(pair.Key, pair.Value.ToArray());
}
}
else
{
string key = this.cboxMessageName.Text;
if (this.MessageCollection.ContainsKey(key) == false) return;
lst.AddRange(this.MessageCollection[key].ToArray());
this.Chart_AddSeries(key, this.MessageCollection[key].ToArray());
}
this.grid.AutoBinding(lst.ToArray());
#endregion
#region Chart Display
if (lst.Count < 1) return;
if (this.chart.Series.Count < 1) return;
StandardDataPair min = lst[0];
StandardDataPair max = lst[0];
foreach (StandardDataPair pair in lst)
{
if (pair.RequestTime < min.RequestTime) min = pair;
if (pair.RequestTime > max.RequestTime) max = pair;
}
foreach (CartesianAxis item in this.chart.Axes)
{
if (item.GetType() == typeof(DateTimeContinuousAxis))
{
DateTimeContinuousAxis axis = item as DateTimeContinuousAxis;
//datetimeAxis.PlotMode = AxisPlotMode.BetweenTicks;
//datetimeAxis.LabelFormat = "{0:d}";
axis.MajorStepUnit = TimeInterval.Hour;
axis.LabelFormatProvider = new DateTimeFormatProvider();
}
else if (item.GetType() == typeof(CategoricalAxis))
{
CategoricalAxis axis = item as CategoricalAxis;
if (lst.Count < 10) axis.MajorTickInterval = 1;
else axis.MajorTickInterval = (int)Math.Round(lst.Count / 10.0);
}
else if (item.GetType() == typeof(LinearAxis))
{
LinearAxis axis = item as LinearAxis;
}
}
#endregion
}
catch (Exception ex)
{
XLogger.Instance.Fatal(ex);
}
}
private void Button1_Click(object sender, EventArgs e)
{
}
private void ChkShowLabel_CheckedChanged(object sender, EventArgs e)
{
foreach (ChartSeries series in this.chart.Series)
series.ShowLabels = this.chkShowLabel.Checked;
}
private void ChartTrackball_TextNeeded(object sender, TextNeededEventArgs e)
{
StandardDataPair data = e.Points[0].DataPoint.DataItem as StandardDataPair;
if (data != null)
{
e.Text = $"{data.RequestTime}{Environment.NewLine}{data.MessageName} : {data.Interval}";
}
}
private void Grid_RowFormatting(object sender, RowFormattingEventArgs e)
{
StandardDataPair stdPair = e.RowElement.RowInfo.DataBoundItem as StandardDataPair;
if (stdPair == null) return;
if (this.AnalysisCollection.ContainsKey(stdPair.MessageName) == false) return;
StandardDataAnalysis stdAnalysis = this.AnalysisCollection[stdPair.MessageName];
if (stdAnalysis.CheckOver(stdPair)) e.RowElement.ForeColor = Color.Red;
else e.RowElement.ForeColor = SystemColors.ControlText;
}
private void Grid_CellDoubleClick(object sender, GridViewCellEventArgs e)
{
StandardDataPair pair = e.Row.DataBoundItem as StandardDataPair;
if (pair == null) return;
if (this.GridView == null) return;
RadGridView grid = this.GridView;
try
{
this.Cursor = Cursors.WaitCursor;
StandardData data = pair.Request;
if (e.Column.FieldName.ToUpper() == "RESPONSETIME") data = pair.Response;
int lineNumber = data.LineNumber;
foreach (GridViewRowInfo row in grid.Rows)
{
try
{
StandardData standardData = row.DataBoundItem as StandardData;
if (standardData == null) continue;
if (lineNumber <= standardData.LineNumber)
{
this.grid.Focus();
row.IsSelected = false;
row.IsCurrent = false;
row.IsSelected = true;
row.IsCurrent = true;
break;
}
}
catch (Exception ex)
{
XLogger.Instance.Debug(ex);
}
}
}
catch (Exception ex)
{
XLogger.Instance.Fatal(ex);
}
finally
{
this.Cursor = Cursors.Default;
}
}
private void GridAnalysis_RowFormatting(object sender, RowFormattingEventArgs e)
{
}
private void GridAnalysis_CellFormatting(object sender, CellFormattingEventArgs e)
{
string[] arrTrimmed = new string[] { "TrimmedMean", "TrimmedStdDeviation" };
string[] arrArithmetic = new string[] { "ArithmeticMean", "ArithmeticStdDeviation" };
if (this.chkTrimmed.Checked)
{
if (arrArithmetic.Contains(e.Column.FieldName)) e.CellElement.ForeColor = Color.LightGray;
else e.CellElement.ForeColor = SystemColors.ControlText;
}
else
{
if (arrTrimmed.Contains(e.Column.FieldName)) e.CellElement.ForeColor = Color.LightGray;
else e.CellElement.ForeColor = SystemColors.ControlText;
}
}
#endregion
#region [ Public Method ] =============================================
public void Generate()
{
this.DataGenerate();
this.DataAnalysis();
List<string> lstMessage = new List<string>();
lstMessage.Add("");
lstMessage.AddRange(this.MessageCollection.Keys.ToArray());
lstMessage.Sort();
this.cboxMessageName.DataSource = lstMessage.ToArray();
this.cboxMessageName.SelectedIndex = 0;
}
#endregion
#region [ Method ] ====================================================
private void DataGenerate()
{
Dictionary<string, List<StandardDataPair>> dicSrc = new Dictionary<string, List<StandardDataPair>>();
try
{
this.MessageCollection.Clear();
string[] arrServer = new string[] { "MES", "FDC", "RMS", "RTD" };
foreach (StandardData data in this.StandardCollection)
{
if (arrServer.Contains(data.Server) == false) continue;
if (string.IsNullOrWhiteSpace(data.TID)) continue;
string key = data.MessageName.Replace("Reply", "");
if (dicSrc.ContainsKey(key) == false)
{
dicSrc.Add(key, new List<StandardDataPair>());
StandardDataPair pair = dicSrc[key].Where(x => x.TID == data.TID).FirstOrDefault();
if (pair == null) dicSrc[key].Add(new StandardDataPair(data));
else pair.Add(data);
}
else
{
StandardDataPair pair = dicSrc[key].Where(x => x.TID == data.TID).FirstOrDefault();
if (pair == null) dicSrc[key].Add(new StandardDataPair(data));
else pair.Add(data);
}
}
foreach (KeyValuePair<string, List<StandardDataPair>> srcPair in dicSrc)
{
string key = srcPair.Key;
foreach (StandardDataPair pair in srcPair.Value)
{
if (pair.Request == null || pair.Response == null) continue;
if (this.MessageCollection.ContainsKey(key) == false) MessageCollection.Add(key, new List<StandardDataPair>());
this.MessageCollection[key].Add(pair);
}
}
}
catch (Exception ex)
{
XLogger.Instance.Fatal(ex);
}
}
private void DataAnalysis()
{
this.AnalysisCollection.Clear();
foreach (KeyValuePair<string, List<StandardDataPair>> item in this.MessageCollection)
{
if (this.AnalysisCollection.ContainsKey(item.Key) == false)
{
StandardDataAnalysis analysis = new StandardDataAnalysis(item.Key);
analysis.UseTrimmed = this.chkTrimmed.Checked;
analysis.TrimmedBegin = (double)this.numTrimmedBegin.Value;
analysis.TrimmedEnd = (double)this.numTrimmedEnd.Value;
this.AnalysisCollection.Add(item.Key, analysis);
}
this.AnalysisCollection[item.Key].AddRange(item.Value.ToArray());
}
this.gridAnalysis.AutoBinding(this.AnalysisCollection.Values.ToArray());
}
private void Grid_Setting()
{
this.grid.MultiSelect = true;
this.grid.Columns.Clear();
this.grid.TableElement.RowHeight = 20;
this.grid.AddColumn("MessageName");
this.grid.AddColumn("RequestTime");
this.grid.AddColumn("ResponseTime");
this.grid.AddColumn("Interval", "", true, "{0:#,##0.000}");
}
private void GridAnalysis_Setting()
{
this.gridAnalysis.MultiSelect = true;
this.gridAnalysis.Columns.Clear();
this.gridAnalysis.TableElement.RowHeight = 20;
this.gridAnalysis.AddColumn("MessageName");
this.gridAnalysis.AddColumn("Count");
this.gridAnalysis.AddColumn("Min", "", true, "{0:#,##0.000}");
this.gridAnalysis.AddColumn("Max", "", true, "{0:#,##0.000}");
this.gridAnalysis.AddColumn("TrimmedMean", "절사평균", true, "{0:#,##0.000}");
this.gridAnalysis.AddColumn("TrimmedStdDeviation", "절사편차", true, "{0:#,##0.000}");
this.gridAnalysis.AddColumn("ArithmeticMean", "산술평균", true, "{0:#,##0.000}");
this.gridAnalysis.AddColumn("ArithmeticStdDeviation", "산술편차", true, "{0:#,##0.000}");
}
private void Chart_Setting()
{
this.chart.ShowGrid = true;
this.chart.ShowLegend = true;
#if DateTimeAxis
this.HorizontalAxis = new DateTimeContinuousAxis()
{
MajorStepUnit = TimeInterval.Hour,
LabelFormatProvider = new DateTimeFormatProvider()
};
this.VerticalAxis = new LinearAxis()
{
};
#else
this.HorizontalAxis = new CategoricalAxis()
{
};
this.VerticalAxis = new LinearAxis()
{
};
#endif
}
private ChartSeries Chart_AddSeries(string name, StandardDataPair[] values)
{
LineSeries series = new LineSeries();
series.Name = name;
//series.HorizontalAxis = this.HorizontalAxis;
//series.VerticalAxis = this.VerticalAxis;
series.PointSize = new SizeF(3, 3);
series.BorderWidth = 2;
series.CategoryMember = "RequestTime";
series.ValueMember = "Interval";
series.ShowLabels = this.chkShowLabel.Checked;
series.Spline = true;
series.CombineMode = ChartSeriesCombineMode.Stack;
series.DataSource = values;
this.chart.Series.Add(series);
return series;
}
#endregion
}
public class DateTimeFormatProvider : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
return this;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
DateTime val = (DateTime)arg;
return val.ToString("HH:mm:ss");
}
}
public class StandardDataAnalysis : DataTableBase
{
/// <summary>MessageName</summary>
public string MessageName { get; set; } = string.Empty;
public int Count { get { return this.Collection.Count; } }
public bool UseTrimmed { get; set; } = false;
public double Min { get; set; } = -1;
public double Max { get; set; } = -1;
/// <summary>산술평균</summary>
public double ArithmeticMean { get; set; } = 0;
/// <summary>산술평균>표준편차</summary>
public double ArithmeticStdDeviation { get; set; } = 0;
/// <summary>절사평균</summary>
public double TrimmedMean { get; set; } = 0;
/// <summary>절사평균>표준편차</summary>
public double TrimmedStdDeviation { get; set; } = 0;
/// <summary>절사평균 범위</summary>
public double TrimmedBegin { get; set; } = 0;
/// <summary>절사평균 범위</summary>
public double TrimmedEnd { get; set; } = 80;
private List<StandardDataPair> Collection { get; set; } = new List<StandardDataPair>();
public StandardDataAnalysis() { }
public StandardDataAnalysis(string name, params StandardDataPair[] value)
{
this.MessageName = name;
this.Collection.AddRange(value);
if (value.Length > 0) this.Calculation();
}
public void AddRange(params StandardDataPair[] values)
{
this.Collection.AddRange(values);
this.Calculation();
}
private void Calculation()
{
double sum = 0;
double average = 0;
#region
sum = 0;
int trimStartIndex = (int)(this.Collection.Count * (this.TrimmedBegin / 100));
int trimEndIndex = (int)(this.Collection.Count * (this.TrimmedEnd / 100));
int trimCount = 0;
int trimIndex = -1;
foreach (StandardDataPair item in this.Collection.OrderBy(item => item.Interval))
{
trimIndex++;
if (trimIndex < trimStartIndex) continue;
if (trimIndex > trimEndIndex) break;
sum += item.Interval;
trimCount++;
}
average = sum / trimCount;
this.TrimmedMean = average;
#endregion
#region
sum = 0;
double min = -1;
double max = -1;
foreach (StandardDataPair item in this.Collection)
{
sum += item.Interval;
if (item.Interval < min || min == -1) min = item.Interval;
if (item.Interval > max || max == -1) max = item.Interval;
}
average = sum / this.Collection.Count;
this.Min = min; this.Max = max;
this.ArithmeticMean = average;
#endregion
double deviation = 0;
double sumTrimVariance = 0;
double sumArithmeticVariance = 0;
double variance = 0;
foreach (StandardDataPair item in this.Collection)
{
deviation = item.Interval - this.TrimmedMean; // 절사평균 편차
sumTrimVariance += Math.Pow(deviation, 2);
deviation = item.Interval - this.ArithmeticMean; // 산술평균 편차
sumArithmeticVariance += Math.Pow(deviation, 2);
}
variance = sumTrimVariance / this.Collection.Count; // 절사평균 분산
this.TrimmedStdDeviation = Math.Sqrt(variance); // 절사평균 표준편차
variance = sumArithmeticVariance / this.Collection.Count; // 산술평균 분산
this.ArithmeticStdDeviation = Math.Sqrt(variance); // 산술평균 표준편차
}
public bool CheckOver(StandardDataPair pair)
{
double average = 0;
if (this.UseTrimmed) average = this.ArithmeticMean; else average = this.TrimmedMean;
double min = average - (this.ArithmeticStdDeviation / 2);
double max = average + (this.ArithmeticStdDeviation / 2);
if (pair.Interval > max) return true;
return false;
}
}
}