From 63e1e964630026c73b8e04585bc71e162127b5f8 Mon Sep 17 00:00:00 2001 From: qinyouzeng Date: Fri, 15 Nov 2024 14:13:58 +0800 Subject: [PATCH] feat: add trace detail latency changed --- .../Services/ApmService.cs | 2 +- .../Cliclhouse/ClickhouseApmService.cs | 32 +++- .../Interfaces/IApmService.cs | 2 +- .../Request/ApmTraceLatencyRequestDto.cs | 2 +- .../Services/ApmService.cs | 2 +- .../Apm/ApmSearchComponent.razor.cs | 13 +- .../Data/Apm/SearchData.cs | 5 + .../Extentions/ObjectExtensions.cs | 15 ++ .../Pages/Apm/EndpointDetail.razor.cs | 2 +- .../Pages/Apm/Endpoints/OverView.razor | 2 +- .../Pages/Apm/Endpoints/OverView.razor.cs | 162 +++++++++++++++--- .../Pages/Apm/Endpoints/OverView.razor.js | 39 +++++ .../Pages/Apm/Errors.razor.cs | 2 +- .../Pages/Apm/Logs.razor.cs | 2 +- .../Pages/Apm/Service.razor.cs | 4 +- .../Pages/Apm/Services/OverView.razor.cs | 2 + .../Apm/Services/ServiceEndpoints.razor.cs | 2 +- .../Pages/App/Index.razor | 6 +- .../Pages/App/Index.razor.cs | 25 +-- 19 files changed, 254 insertions(+), 67 deletions(-) create mode 100644 src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.js diff --git a/src/ApiGateways/Masa.Tsc.ApiGateways.Caller/Services/ApmService.cs b/src/ApiGateways/Masa.Tsc.ApiGateways.Caller/Services/ApmService.cs index a88adc18..89b20708 100644 --- a/src/ApiGateways/Masa.Tsc.ApiGateways.Caller/Services/ApmService.cs +++ b/src/ApiGateways/Masa.Tsc.ApiGateways.Caller/Services/ApmService.cs @@ -39,5 +39,5 @@ internal ApmService(ICaller caller) : base(caller, "/api/apm") { } public Task> GetExceptionTypesAsync(BaseRequestDto query) => Caller.GetByBodyAsync>($"{RootPath}/errorTypes", query)!; - public Task> GetSimpleTraceListAsync(ApmEndpointRequestDto query) => Caller.GetByBodyAsync>($"{RootPath}/simpleTraceList", body: query)!; + public Task> GetSimpleTraceListAsync(ApmTraceLatencyRequestDto query) => Caller.GetByBodyAsync>($"{RootPath}/simpleTraceList", body: query)!; } \ No newline at end of file diff --git a/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Cliclhouse/ClickhouseApmService.cs b/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Cliclhouse/ClickhouseApmService.cs index 2a58a28f..a1de307e 100644 --- a/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Cliclhouse/ClickhouseApmService.cs +++ b/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Cliclhouse/ClickhouseApmService.cs @@ -313,7 +313,7 @@ public async Task> TraceLatencyDetailAsync(A return await _traceService.ListAsync(queryDto); } - public async Task> GetSimpleTraceListAsync(ApmEndpointRequestDto query) + public async Task> GetSimpleTraceListAsync(ApmTraceLatencyRequestDto query) { var orderBy = GetOrderBy(query, new() { { StorageConst.Current.Timestimap, StorageConst.Current.Timestimap } }); var (where, ors, parameters) = AppendWhere(query); @@ -323,16 +323,18 @@ public async Task> GetSimpleTraceListAsync string sql1; if (query.IsInstrument) { - sql1 = $"select count(1) as Total from {MasaStackClickhouseConnection.TraceHttpServerTable} where {where}"; + sql1 = $"select 1 as Total from {MasaStackClickhouseConnection.TraceHttpServerTable} where {where}"; } else { - sql1 = $@"select countMerge(Total) as Total from {Constants.DurationCountTable} where {where}"; + sql1 = $@"select 1 as Total from {Constants.DurationCountTable} where {where}"; } sql1 = CombineOrs(sql1, ors); var countSql = $"select sum(Total) from({sql1})"; + SetMinDurationUnit(parameters); result.Total = Convert.ToInt64(await Scalar(countSql, parameters)); + ResetMinDurationUnit(parameters); } var sql = CombineOrs($@"select TraceId,Duration,Timestamp from {(query.IsInstrument ? MasaStackClickhouseConnection.TraceHttpServerTable : Constants.DurationTable)} where {where}", ors); @@ -342,6 +344,30 @@ public async Task> GetSimpleTraceListAsync return result; } + private void SetMinDurationUnit(List parameters) + { + if (parameters == null || !parameters.Any()) + return; + var param = parameters.Find(p => p.ParameterName == "minDuration"); + if (param != null) + param.Value = (long)(((long)param.Value) / MILLSECOND); + param = parameters.Find(p => p.ParameterName == "maxDuration"); + if (param != null) + param.Value = (long)(((long)param.Value) / MILLSECOND); + } + + private void ResetMinDurationUnit(List parameters) + { + if (parameters == null || !parameters.Any()) + return; + var param = parameters.Find(p => p.ParameterName == "minDuration"); + if (param != null) + param.Value = (long)(((long)param.Value) * MILLSECOND); + param = parameters.Find(p => p.ParameterName == "maxDuration"); + if (param != null) + param.Value = (long)(((long)param.Value) * MILLSECOND); + } + private static SimpleTraceListDto ToSampleTraceListDto(IDataReader reader) { var startTime = Convert.ToDateTime(reader[StorageConst.Current.Timestimap]); diff --git a/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Interfaces/IApmService.cs b/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Interfaces/IApmService.cs index 3def7a07..090cc4f5 100644 --- a/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Interfaces/IApmService.cs +++ b/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Interfaces/IApmService.cs @@ -69,7 +69,7 @@ public interface IApmService : IDisposable /// /// /// - Task> GetSimpleTraceListAsync(ApmEndpointRequestDto query); + Task> GetSimpleTraceListAsync(ApmTraceLatencyRequestDto query); Task> GetErrorTypesAsync(BaseApmRequestDto query); diff --git a/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Models/Request/ApmTraceLatencyRequestDto.cs b/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Models/Request/ApmTraceLatencyRequestDto.cs index ed926c5c..63dd606a 100644 --- a/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Models/Request/ApmTraceLatencyRequestDto.cs +++ b/src/Infrastructure/Masa.Tsc.Storage.Clickhouse.Apm/Models/Request/ApmTraceLatencyRequestDto.cs @@ -15,5 +15,5 @@ public class ApmTraceLatencyRequestDto : ApmEndpointRequestDto /// public long? LatMax { get; set; } - public new int PageSize { get; } = 1; + public new int PageSize { get; } = 500; } diff --git a/src/Services/Masa.Tsc.Service.Admin/Services/ApmService.cs b/src/Services/Masa.Tsc.Service.Admin/Services/ApmService.cs index 0382025a..b950ef23 100644 --- a/src/Services/Masa.Tsc.Service.Admin/Services/ApmService.cs +++ b/src/Services/Masa.Tsc.Service.Admin/Services/ApmService.cs @@ -308,7 +308,7 @@ private async Task>> GetTeamAllEnvApps return result; } - public Task> GetSimpleTraceList([FromServices] IApmService apmService, [FromBody] ApmEndpointRequestDto query) + public Task> GetSimpleTraceList([FromServices] IApmService apmService, [FromBody] ApmTraceLatencyRequestDto query) => apmService.GetSimpleTraceListAsync(query); public Task> GetEndpointList([FromServices] IApmService apmService, [FromBody] BaseApmRequestDto query) diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Components/Apm/ApmSearchComponent.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Components/Apm/ApmSearchComponent.razor.cs index 20409ef0..fa213fbb 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Components/Apm/ApmSearchComponent.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Components/Apm/ApmSearchComponent.razor.cs @@ -45,8 +45,7 @@ public partial class ApmSearchComponent AppTypes.Service.ToString(), AppTypes.Job.ToString() }; - - private bool Isloaded = false; + private QuickRangeKey quickRangeKey = QuickRangeKey.Last15Minutes; private List textFileds = new(); @@ -60,7 +59,7 @@ protected override async Task OnInitializedAsync() { await InitAsync(); } - Isloaded = true; + Search.Loaded = true; await OnValueChanged(); StateHasChanged(); } @@ -198,7 +197,7 @@ private void SetQueryList() private void TeamChanged(Guid teamId) { GlobalConfig.CurrentTeamId = teamId; - if (Isloaded && CheckUrl()) + if (Search.Loaded && CheckUrl()) { NavigationManager.NavigateTo(NavigationManager.Uri, true); return; @@ -379,12 +378,12 @@ private async Task LoadErrorAsync() private async Task OnTimeUpdate((DateTimeOffset? start, DateTimeOffset? end) times) { - if (Isloaded || Search.Start == DateTime.MinValue) + if (Search.Loaded || Search.Start == DateTime.MinValue) { Search.Start = times.start!.Value.UtcDateTime; Search.End = times.end!.Value.UtcDateTime; } - if (Isloaded) + if (Search.Loaded) { await InitAsync(); await OnValueChanged(); @@ -473,7 +472,7 @@ private async Task OnMessageEnter() private async Task OnValueChanged() { - if (!Isloaded || string.IsNullOrEmpty(Value.Environment)) + if (!Search.Loaded || string.IsNullOrEmpty(Value.Environment)) return; if (ValueChanged.HasDelegate) await ValueChanged.InvokeAsync(Value); diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Data/Apm/SearchData.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Data/Apm/SearchData.cs index 2e7c1af9..e85e4fab 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Data/Apm/SearchData.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Data/Apm/SearchData.cs @@ -41,6 +41,11 @@ public SearchData() public string TraceId { get; set; } public string SpanId { get; set; } + + /// + /// search com + /// + public bool Loaded { get; set; } } public enum ApmComparisonTypes diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Extentions/ObjectExtensions.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Extentions/ObjectExtensions.cs index 26d43e0b..d4107a33 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Extentions/ObjectExtensions.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Extentions/ObjectExtensions.cs @@ -60,6 +60,21 @@ public static string FormatTime(this double millionSeconds) return $"{minis} min{(seconds > 0 ? $"{seconds} s" : "")}"; } + public static int FormatTimeToNumber(this string s) + { + if (string.IsNullOrEmpty(s)) + return 0; + if (s == "<1ms") + return 0; + if (s.EndsWith("ms")) + return Convert.ToInt32(s.Substring(0, s.Length - 2)); + if (s.EndsWith(" s")) + return Convert.ToInt32(s.Substring(0, s.Length - 2)) * 60; + if (s.EndsWith(" min")) + return Convert.ToInt32(s.Substring(0, s.Length - 4)) * 360; + return default; + } + public static string FormatHistory(this DateTime time) { var now = DateTime.UtcNow; diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/EndpointDetail.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/EndpointDetail.razor.cs index 22366173..beb65aa0 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/EndpointDetail.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/EndpointDetail.razor.cs @@ -11,7 +11,7 @@ public partial class EndpointDetail private string spanId = default!; [Parameter] - public string Name { get; set; } + public string Name { get; set; } private void OnSearchValueChanged(SearchData data) { diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor index c1a6fb9a..699cb988 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor @@ -79,7 +79,7 @@ @if (!timeTypeCount.ChartLoading && timeTypeCount.HasChart) { - + } diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.cs index 154b5bd2..78d5bbc6 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.cs @@ -1,10 +1,18 @@ // Copyright (c) MASA Stack All rights reserved. // Licensed under the Apache License. See LICENSE.txt in the project root for license information. +using Masa.Blazor.JSInterop; +using System.Reflection; + namespace Masa.Tsc.Web.Admin.Rcl.Pages.Apm.Endpoints; public partial class OverView { + [Inject] + IJSRuntime JSRuntime { get; set; } + IJSObjectReference? echartEventModule = null; + DotNetObjectReference objRef; + [CascadingParameter] public SearchData SearchData { get; set; } @@ -30,10 +38,92 @@ private async Task SpanIdChange(string spanId) double percentile = 0; private List traceIds = new(); private List traceTails = new(); + MECharts? mechart; + + protected override void OnInitialized() + { + base.OnInitialized(); + objRef = DotNetObjectReference.Create(this); + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + await base.OnAfterRenderAsync(firstRender); + + if (mechart != null) + { + await Task.Delay(1200); + var echart = typeof(MECharts).GetField("_echarts", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField)!.GetValue(mechart)!; + if (echart != null) + { + var reference = echart.GetType().GetField("_selfReference", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField)!.GetValue(echart); + var echartJs = (IJSObjectReference)typeof(JSObjectReferenceProxy).GetField("_jsObjectReference", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField)!.GetValue(echart)!; + + if (reference != null && echartJs != null && echartEventModule == null) + { + //重新注册 + echartEventModule = await JSRuntime.InvokeAsync("import", "/_content/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.js"); + await echartEventModule.InvokeVoidAsync("setChartEvent", echartJs, objRef); + + } + } + else + { + if (echartEventModule != null) + { + await echartEventModule.DisposeAsync(); + echartEventModule = null; + } + } + } + } + + CancellationTokenSource source = null; + private EChartBrushEventArg lastSelect = new() { IsClear = true }; + [JSInvokable("OnBrushEnd")] + public async Task BrushEnd(EChartBrushEventArg args) + { + bool isRefresh = false; + if (args.IsClear && !lastSelect.IsClear) + { + lastSelect.IsClear = false; + isRefresh = true; + } + else if (!args.IsClear && (lastSelect.IsClear || !lastSelect.IsClear && (lastSelect.Start - args.Start != 0 || lastSelect.End - args.Start != 0))) + { + lastSelect.IsClear = false; + lastSelect.Start = args.Start; + lastSelect.End = args.End; + isRefresh = true; + } + + if (isRefresh) + { + source?.Cancel(); + source = new CancellationTokenSource(); + await RefreshDurationListAsync(source.Token); + await InvokeAsync(StateHasChanged); + source?.Dispose(); + source = null; + } + } + + private async Task RefreshDurationListAsync(CancellationToken token) + { + Console.WriteLine("1"); + await Task.Delay(400); + total = 0; + if (token.IsCancellationRequested) + return; + Console.WriteLine("2"); + await LoadTraceDetailAsync(1); + } protected override async Task OnParametersSetAsync() { await base.OnParametersSetAsync(); + if (!SearchData.Loaded) + return; var text = JsonSerializer.Serialize(SearchData); var key = MD5Utils.Encrypt(text); if (lastKey != key) @@ -54,7 +144,9 @@ private async Task LoadTraceDetailAsync(int page = 1) //首次 if (total == 0 && page == 1) { - var result1 = await ApiCaller.ApmService.GetSimpleTraceListAsync(new ApmEndpointRequestDto + traceIds.Clear(); + traceTails.Clear(); + var query = new ApmTraceLatencyRequestDto { Start = SearchData.Start, End = SearchData.End, @@ -62,7 +154,6 @@ private async Task LoadTraceDetailAsync(int page = 1) Service = SearchData.Service!, Env = SearchData.Environment!, Page = 1, - PageSize = 500, Method = SearchData.Method, TextField = SearchData.TextField, TextValue = SearchData.TextValue, @@ -70,7 +161,20 @@ private async Task LoadTraceDetailAsync(int page = 1) //Queries = SearchData.Text, OrderField = "Timestamp", IsDesc = true - }); + }; + if (lastSelect != null && !lastSelect.IsClear) + { + var isEqal = lastSelect.Start == lastSelect.End; + int start = chartData[lastSelect.Start][0].FormatTimeToNumber(), end = chartData[lastSelect.End][0].FormatTimeToNumber(); + query.LatMin = start; + if (isEqal) + query.LatMax = start + 1; + else + query.LatMax = end; + Console.WriteLine($"start:{query.LatMin},end:{query.LatMax}"); + } + + var result1 = await ApiCaller.ApmService.GetSimpleTraceListAsync(query); if (result1 != null && result1.Result != null) { traceIds.AddRange(result1.Result); @@ -112,7 +216,7 @@ private void CaculatePercentil() { if (traceDetails == null || !traceDetails.Any()) return; - var current = traceDetails.FirstOrDefault(item => item.Kind == "SPAN_KIND_SERVER" + var current = traceDetails.Find(item => item.Kind == "SPAN_KIND_SERVER" && item.Attributes.TryGetValue("http.target", out var url) && string.Equals(SearchData.Endpoint, ((JsonElement)url).GetString()) && item.Resource.TryGetValue("service.name", out var service) && string.Equals(SearchData.Service, ((JsonElement)service).GetString()) )?.Duration; @@ -129,7 +233,6 @@ private void CaculatePercentil() percentile = lessTotal * 1.0 / sum; } - //需要优化,不是自己关注的条件不刷新数据 private async Task LoadDataAsync() { var query = new ApmEndpointRequestDto @@ -146,7 +249,7 @@ private async Task LoadDataAsync() var data = await ApiCaller.ApmService.GetChartsAsync(query); if (data != null && data.Any()) { - var chartData = data[0]; + var chartData1 = data[0]; { metricTypeChartData.Avg = new(); metricTypeChartData.P95 = new(); @@ -154,11 +257,11 @@ private async Task LoadDataAsync() throughput = new(); failed = new(); - metricTypeChartData.Avg.Data = ConvertLatencyChartData(chartData, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.Latency, unit: "ms", lineName: "Average").Json; - metricTypeChartData.P95.Data = ConvertLatencyChartData(chartData, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.P95, unit: "ms", lineName: "95th percentile").Json; - metricTypeChartData.P99.Data = ConvertLatencyChartData(chartData, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.P99, unit: "ms", lineName: "99th percentile").Json; - throughput.Data = ConvertLatencyChartData(chartData, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.Throughput, unit: "tpm").Json; - failed.Data = ConvertLatencyChartData(chartData, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.Failed, unit: "%").Json; + metricTypeChartData.Avg.Data = ConvertLatencyChartData(chartData1, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.Latency, unit: "ms", lineName: "Average").Json; + metricTypeChartData.P95.Data = ConvertLatencyChartData(chartData1, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.P95, unit: "ms", lineName: "95th percentile").Json; + metricTypeChartData.P99.Data = ConvertLatencyChartData(chartData1, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.P99, unit: "ms", lineName: "99th percentile").Json; + throughput.Data = ConvertLatencyChartData(chartData1, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.Throughput, unit: "tpm").Json; + failed.Data = ConvertLatencyChartData(chartData1, item => item.Time.ToDateTime(CurrentTimeZone).ToString("yyyy/MM/dd HH:mm:ss"), item => item.Failed, unit: "%").Json; metricTypeChartData.Avg.ChartLoading = false; metricTypeChartData.P95.ChartLoading = false; @@ -209,8 +312,6 @@ private static EChartType ConvertLatencyChartData(ChartLineDto data, Func data) } return findIndex; } - - private static EChartType ConvertDistributionChartData(IEnumerable data, int current, int p95) + private List chartData = new(); + private EChartType ConvertDistributionChartData(IEnumerable data, int current, int p95) { var chart = EChartConst.Line; var list = data.Select(item => new[] { Convert.ToDouble(item.X).FormatTime(), item.Y }).ToList(); string currentItem = list[current][0], p95Item = list[p95][0]; - var array = list.GroupBy(item => item[0]).Select(item => new[] { item.Key, item.Sum(values => Convert.ToInt32(values[1])).ToString() }).ToList(); + chartData = list.GroupBy(item => item[0]).Select(item => new[] { item.Key, item.Sum(values => Convert.ToInt32(values[1])).ToString() }).ToList(); bool isFoundCurrent = false, isFoundP95 = false; - var index = array.Count - 1; + var index = chartData.Count - 1; do { - if (!isFoundCurrent && array[index][0] == currentItem) + if (!isFoundCurrent && chartData[index][0] == currentItem) { current = index; isFoundCurrent = true; } - if (!isFoundP95 && array[index][0] == p95Item) + if (!isFoundP95 && chartData[index][0] == p95Item) { p95 = index; isFoundP95 = true; @@ -297,14 +398,33 @@ private static EChartType ConvertDistributionChartData(IEnumerable= 0); - chart.SetValue("tooltip", new { trigger = "axis" }); + chart.SetValue("tooltip", new { trigger = "axis", feature = new { dataZoom = new { yAxisIndex = false }, brush = new { type = new string[] { "lineX", "clear" } } } }); + chart.SetValue("toolbox", new { top = -6, show = true }); + chart.SetValue("grid.top", 40); chart.SetValue("xAxis", new { type = "category", boundaryGap = false }); chart.SetValue("yAxis", new { type = "value", boundaryGap = false }); chart.SetValue("series[0]", new { type = "line", step = "end", symbol = "none", areaStyle = new { } }); chart.SetValue("series[0].markLine", new { symbol = new string[] { "none", "none" }, lineStyle = new { type = "solid", width = 2 }, label = new { show = true } }); chart.SetValue("series[0].markLine.data[1]", new { xAxis = p95, lineStyle = new { color = "" }, label = new { formatter = "P95" } }); chart.SetValue("series[0].markLine.data[0]", new { xAxis = current, lineStyle = new { color = "gray" }, label = new { formatter = "Current" } }); - chart.SetValue("series[0].data", array); + chart.SetValue("series[0].data", chartData); + chart.SetValue("brush", new { xAxisIndex = "all", brushLink = "all", outOfBrush = new { colorAlpha = 0.1 }, toolbox = new string[] { "lineX", "clear" }, throttleType = "debounce", throttleDelay = 200, brushStyle = new { color = "#FFA726", borderColor = "#FFA726" } }); return chart; } + + protected override async ValueTask DisposeAsyncCore() + { + if (echartEventModule != null) + await echartEventModule.DisposeAsync(); + await base.DisposeAsyncCore(); + } +} + +public class EChartBrushEventArg +{ + public bool IsClear { get; set; } + + public int Start { get; set; } + + public int End { get; set; } } \ No newline at end of file diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.js b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.js new file mode 100644 index 00000000..00b1038f --- /dev/null +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Endpoints/OverView.razor.js @@ -0,0 +1,39 @@ +let $this = {}; +let _dotnetHelper = false; +function setChartEvent(module, donetHelper) { + _dotnetHelper = donetHelper; + let mychart = module.getOriginInstance(); + console.log("mychart") + console.log(mychart) + mychart.on("brushselected", function (e) { + var areas = e.batch[0].areas; + if (areas.length == 0) { + //清除选择 + callBack(true); + } else { + let startIndex = areas[0].coordRange[0], endIndex = areas[0].coordRange[1]; + callBack(false, startIndex, endIndex); + } + }); +} + +function callBack(clear, start = 0, end = 0) { + clearTimter($this) + $this.clear = clear; + $this.start = start; + $this.end = end; + $this.timerId = setTimeout(() => { + if (!_dotnetHelper) + return; + _dotnetHelper.invokeMethodAsync("OnBrushEnd", { isClear: $this.clear, start: $this.start, end: $this.end }).then(() => { clearTimter($this); }) + }, 500); +} + +function clearTimter(obj) { + try { + if (obj && !obj.timerId) + clearTimeout(obj.timerId); + } catch { } +} + +export { setChartEvent } \ No newline at end of file diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Errors.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Errors.razor.cs index 6715644c..feed249b 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Errors.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Errors.razor.cs @@ -52,7 +52,7 @@ private async Task LoadASync(SearchData data = null!) total = 0; Search = data; } - if (Search.Start == DateTime.MinValue || Search.End == DateTime.MinValue) + if (!Search.Loaded) return; isTableLoading = true; StateHasChanged(); diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Logs.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Logs.razor.cs index 02c966ee..4764800e 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Logs.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Logs.razor.cs @@ -78,7 +78,7 @@ private async Task LoadASync(SearchData data = null!) page = 1; Search = data; } - if (Search.Start == DateTime.MinValue || Search.End == DateTime.MinValue) + if (!Search.Loaded) return; isTableLoading = true; StateHasChanged(); diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Service.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Service.razor.cs index 0a4ecd15..69ceb9c8 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Service.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Service.razor.cs @@ -15,7 +15,7 @@ public partial class Service new() { Text = I18n.Apm("Service.List.Throughput"), Value = nameof(ListChartData.Throughput)}, new() { Text = I18n.Apm("Service.List.Failed"), Value = nameof(ListChartData.Failed)} }; - + private int defaultSize = 20; private int total = 0; private int page = 1; @@ -52,7 +52,7 @@ private async Task LoadASync(SearchData data = null!) Search = data; page = 1; } - if (Search.Start == DateTime.MinValue || Search.End == DateTime.MinValue) + if (!Search.Loaded) return; isTableLoading = true; StateHasChanged(); diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/OverView.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/OverView.razor.cs index 0a327109..01f0dcf2 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/OverView.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/OverView.razor.cs @@ -32,6 +32,8 @@ protected override async Task OnInitializedAsync() private async Task LoadDataAsync() { + if (!SearchData.Loaded) + return; var query = new ApmEndpointRequestDto { Start = SearchData.Start, diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/ServiceEndpoints.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/ServiceEndpoints.razor.cs index 92e6306c..53c3890a 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/ServiceEndpoints.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/Apm/Services/ServiceEndpoints.razor.cs @@ -70,7 +70,7 @@ private async Task LoadASync(SearchData data = null) total = 0; SearchData = data; } - if (SearchData.Start == DateTime.MinValue || SearchData.End == DateTime.MinValue) + if (!SearchData.Loaded) return; if (isTableLoading) { diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor index f39a56fc..d180d5ee 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor @@ -56,10 +56,12 @@
-
+
顶部 前一分钟 - @btnText +
@if (dataLoading) { diff --git a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor.cs b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor.cs index 8fc9f3dd..87749191 100644 --- a/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor.cs +++ b/src/Web/Masa.Tsc.Web.Admin.Rcl/Pages/App/Index.razor.cs @@ -466,27 +466,6 @@ private async Task LoadLog(List traceIds) SetLogData(logs.Result); } - //private void SetLogData(List logs) - //{ - // do - // { - // var first = logs[0]; - // var trace = data.Find(trace => trace.Data.TraceId == first.TraceId); - // if (trace == null) - // { - // //该页面报错了,先不处理 - // logs.Remove(first); - // } - // else - // { - // var childLogs = logs.Where(log => log.TraceId == first.TraceId).ToList(); - // SetChild(trace, childLogs); - // //logs.RemoveAll(childLogs); - // } - // } - // while (logs.Count > 0); - //} - private void SetLogData(List logs) { foreach (var trace in data) @@ -526,12 +505,12 @@ private async Task Share() await PopupService.EnqueueSnackbarAsync("分享连接复制成功", AlertTypes.Success, true); } - string btnText = "不显示正常HTTP"; + //string btnText = "不显示正常HTTP"; bool showNormalClient = false; private void ShowHideHttpTrace() { showNormalClient = !showNormalClient; - btnText = showNormalClient ? "显示所有HTTP" : "不显示正常HTTP"; + //btnText = showNormalClient ? "显示所有HTTP" : "不显示正常HTTP"; StateHasChanged(); }