private void DrawChart(GrpcChannelx channel, DataRatePoints history) { // Draw Chart var prevHandlesColor = Handles.color; { var rect = EditorGUI.IndentedRect(GUILayoutUtility.GetRect(GUILayoutUtility.GetLastRect().width, 100)); Handles.DrawSolidRectangleWithOutline(rect, Color.black, Color.gray); var drawableRect = new Rect(rect.x + 2, rect.y + 2, rect.width - 4, rect.height - 4); var maxCount = 60; var maxY = DataUnit.GetScaleMaxValue(Math.Max(history.ReceivedValues.DefaultIfEmpty().Max(), history.SentValues.DefaultIfEmpty().Max())); var dx = drawableRect.width / (float)(maxCount - 1); var dy = drawableRect.height / (float)maxY; // Grid (9 lines) Handles.color = new Color(0.05f, 0.25f, 0.05f); for (var i = 1; i < 10; i++) { var yTop = drawableRect.y + (drawableRect.height / 10) * i; Handles.DrawLine(new Vector3(drawableRect.x, yTop), new Vector3(drawableRect.xMax, yTop)); } // Label Handles.Label(new Vector3(drawableRect.x, drawableRect.y), DataUnit.Humanize(maxY) + " bytes/sec"); // Values Span <int> buffer = stackalloc int[60]; var points = new List <Vector3>(); { var values = history.ReceivedValues.ToSpan(buffer); for (var i = 0; i < Math.Min(maxCount, values.Length); i++) { var p = new Vector3(drawableRect.x + (drawableRect.width - (dx * i)), drawableRect.yMax - (dy * values[values.Length - i - 1])); points.Add(p); } Handles.color = new Color(0.33f, 0.55f, 0.33f); Handles.DrawAAPolyLine(4f, points.ToArray()); } points.Clear(); { var values = history.SentValues.ToSpan(buffer); for (var i = 0; i < Math.Min(maxCount, values.Length); i++) { var p = new Vector3(drawableRect.x + (drawableRect.width - (dx * i)), drawableRect.yMax - (dy * values[values.Length - i - 1])); points.Add(p); } Handles.color = new Color(0.2f, 0.33f, 0.2f); Handles.DrawAAPolyLine(2f, points.ToArray()); } } Handles.color = prevHandlesColor; }
public bool TryUpdate() { if ((DateTime.Now - _lastUpdatedAt).TotalSeconds >= 1) { foreach (var channel in _provider.GetAllChannels()) { if (!_historyByChannel.TryGetValue(channel, out var history)) { _historyByChannel[channel] = history = new DataRatePoints(); } var diagInfo = ((IGrpcChannelxDiagnosticsInfo)channel); history.AddValues(diagInfo.Stats.ReceiveBytesPerSecond, diagInfo.Stats.SentBytesPerSecond); } _lastUpdatedAt = DateTime.Now; return(true); } return(false); }
public void DrawChannels() { var channels = _provider.GetAllChannels(); if (!channels.Any()) { EditorGUILayout.HelpBox("The application has no gRPC channel yet.", MessageType.Info); return; } foreach (var channel in channels) { var diagInfo = ((IGrpcChannelxDiagnosticsInfo)channel); if (!_historyByChannel.TryGetValue(channel, out var history)) { _historyByChannel[channel] = history = new DataRatePoints(); } using (new Section(() => { using (new EditorGUILayout.HorizontalScope()) { #if !USE_GRPC_NET_CLIENT_ONLY if (diagInfo.UnderlyingChannel is Channel grpcCCoreChannel) { EditorGUILayout.LabelField($"Channel: {channel.Id} ({channel.Target}; State={grpcCCoreChannel.State})", EditorStyles.boldLabel); } else #endif { EditorGUILayout.LabelField($"Channel: {channel.Id} ({channel.Target})", EditorStyles.boldLabel); } if (GUILayout.Button("...", GUILayout.ExpandWidth(false))) { var menu = new GenericMenu(); menu.AddItem(new GUIContent("Disconnect"), false, x => { ((GrpcChannelx)x).Dispose(); }, channel); menu.ShowAsContext(); } } })) { using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Total Received Bytes", diagInfo.Stats.ReceivedBytes.ToString("#,0") + " bytes"); EditorGUILayout.LabelField("Total Sent Bytes", diagInfo.Stats.SentBytes.ToString("#,0") + " bytes"); } using (new EditorGUILayout.HorizontalScope()) { EditorGUILayout.LabelField("Received Bytes/Sec", diagInfo.Stats.ReceiveBytesPerSecond.ToString("#,0") + " bytes/s"); EditorGUILayout.LabelField("Sent Bytes/Sec", diagInfo.Stats.SentBytesPerSecond.ToString("#,0") + " bytes/s"); } DrawChart(channel, history); var streamingHubs = ((IMagicOnionAwareGrpcChannel)channel).GetAllManagedStreamingHubs(); if (streamingHubs.Any()) { using (new Section("StreamingHubs")) { foreach (var streamingHub in streamingHubs) { EditorGUILayout.LabelField(streamingHub.StreamingHubType.FullName); EditorGUI.indentLevel++; EditorGUILayout.LabelField(streamingHub.Client.GetType().FullName); EditorGUI.indentLevel--; } } } if (_stackTraceFoldout[channel.Id] = EditorGUILayout.Foldout(_stackTraceFoldout.TryGetValue(channel.Id, out var foldout) ? foldout : false, "StackTrace")) { var reducedStackTrace = string.Join("\n", diagInfo.StackTrace .Split('\n') .SkipWhile(x => x.StartsWith($" at {typeof(GrpcChannelx).FullName}")) .Where(x => !x.StartsWith(" at System.Runtime.CompilerServices.")) .Where(x => !x.StartsWith(" at System.Threading.ExecutionContext.")) .Where(x => !x.StartsWith(" at Cysharp.Threading.Tasks.CompilerServices.")) .Where(x => !x.StartsWith(" at Cysharp.Threading.Tasks.AwaiterActions.")) .Where(x => !x.StartsWith(" at Cysharp.Threading.Tasks.UniTask")) .Where(x => !x.StartsWith(" at MagicOnion.Unity.GrpcChannelProviderExtensions.")) ); EditorGUILayout.TextArea(reducedStackTrace, GUILayout.MaxWidth(EditorGUIUtility.currentViewWidth - 40)); } if (_channelOptionsFoldout[channel.Id] = EditorGUILayout.Foldout(_channelOptionsFoldout.TryGetValue(channel.Id, out var channelOptionsFoldout) ? channelOptionsFoldout : false, "ChannelOptions")) { using (new EditorGUI.DisabledGroupScope(true)) { var prevLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 350; foreach (var keyValue in diagInfo.ChannelOptions.GetValues()) { if (keyValue.Value is int intValue) { EditorGUILayout.IntField(keyValue.Key, intValue); } else if (keyValue.Value is long longValue) { EditorGUILayout.LongField(keyValue.Key, longValue); } else { EditorGUILayout.TextField(keyValue.Key, keyValue.Value?.ToString() ?? ""); } } EditorGUIUtility.labelWidth = prevLabelWidth; } } } } }