├── .github
└── FUNDING.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── images
├── button.png
├── limits-modal.png
├── memory-modal.png
├── trace-list-modal.png
├── trace-modal-methods.png
├── trace-modal-muted.png
├── trace-modal-signals.png
└── trace-modal-snapshots.png
├── site
└── WebVella.BlazorTrace.Site
│ ├── App.razor
│ ├── Components
│ ├── Test1.razor
│ └── Test2.razor
│ ├── Layout
│ ├── MainLayout.razor
│ └── MainLayout.razor.css
│ ├── Pages
│ ├── Home.razor
│ └── Page.razor
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── WebVella.BlazorTrace.Site.csproj
│ ├── _Imports.razor
│ └── wwwroot
│ ├── favicon.png
│ ├── icon-192.png
│ ├── icon-512.png
│ ├── index.html
│ ├── manifest.webmanifest
│ ├── service-worker.js
│ └── service-worker.published.js
├── src
└── WebVella.BlazorTrace
│ ├── Components
│ ├── General
│ │ └── WvBlazorTraceModalOverlay.razor
│ ├── WvBlazorTrace
│ │ ├── WvBlazorTrace.razor
│ │ ├── WvBlazorTraceBody.razor
│ │ ├── WvBlazorTraceBody.razor.cs
│ │ ├── WvBlazorTraceMethodMenu.razor
│ │ ├── WvBlazorTraceMuteMenu.razor
│ │ ├── WvBlazorTraceRow.razor
│ │ ├── WvBlazorTraceSignalMenu.razor
│ │ ├── WvBlazorTraceSignalRow.razor
│ │ └── WvBlazorTraceSnapshotMenu.razor
│ ├── WvBlazorTraceLimitInfoModal.razor
│ ├── WvBlazorTraceLimitInfoModal.razor.cs
│ ├── WvBlazorTraceLimitInfoSignalModal.razor
│ ├── WvBlazorTraceLimitInfoSignalModal.razor.cs
│ ├── WvBlazorTraceLimitModal.razor
│ ├── WvBlazorTraceLimitModal.razor.cs
│ ├── WvBlazorTraceListModal.razor
│ ├── WvBlazorTraceListModal.razor.cs
│ ├── WvBlazorTraceMemoryModal.razor
│ ├── WvBlazorTraceMemoryModal.razor.cs
│ ├── WvBlazorTraceMuteLimitModal.razor
│ ├── WvBlazorTraceMuteLimitModal.razor.cs
│ ├── WvBlazorTraceMuteMemoryModal.razor
│ ├── WvBlazorTraceMuteMemoryModal.razor.cs
│ ├── WvBlazorTraceMuteMethodModal.razor
│ ├── WvBlazorTraceMuteMethodModal.razor.cs
│ ├── WvBlazorTraceMuteSignalModal.razor
│ ├── WvBlazorTraceMuteSignalModal.razor.cs
│ ├── WvBlazorTraceMuteSignalTraceModal.razor
│ ├── WvBlazorTraceMuteSignalTraceModal.razor.cs
│ ├── WvBlazorTraceMuteTraceModal.razor
│ ├── WvBlazorTraceMuteTraceModal.razor.cs
│ ├── WvBlazorTraceSignalLimitModal.razor
│ ├── WvBlazorTraceSignalLimitModal.razor.cs
│ ├── WvBlazorTraceSignalTraceListModal.razor
│ ├── WvBlazorTraceSignalTraceListModal.razor.cs
│ └── _Imports.razor
│ ├── Models
│ ├── WvBlazorTraceComponentBase.cs
│ ├── WvBlazorTraceConfiguration.cs
│ ├── WvButtonPosition.cs
│ ├── WvCall.cs
│ ├── WvLocalStore.cs
│ ├── WvMethodTraceRow.cs
│ ├── WvSignalTraceRow.cs
│ ├── WvSnapshot.cs
│ ├── WvSnapshotListItem.cs
│ ├── WvSnapshotMemoryComparison.cs
│ ├── WvSnapshotMethodComparison.cs
│ ├── WvSnapshotSavingState.cs
│ ├── WvSnapshotSignalComparison.cs
│ ├── WvTraceInfo.cs
│ ├── WvTraceMemoryInfo.cs
│ ├── WvTraceMethodOptions.cs
│ ├── WvTraceModalData.cs
│ ├── WvTraceModalMenuItem.cs
│ ├── WvTraceMute.cs
│ ├── WvTraceMuteType.cs
│ ├── WvTraceQueueAction.cs
│ ├── WvTraceSession.cs
│ ├── WvTraceSignalOptions.cs
│ └── WvUnionData.cs
│ ├── Services
│ ├── JsService.cs
│ ├── WvBlazorTraceConfigurationService.cs
│ ├── WvBlazorTraceInjection.cs
│ ├── WvBlazorTraceService.MethodCalls.cs
│ ├── WvBlazorTraceService.Modal.cs
│ ├── WvBlazorTraceService.Queue.cs
│ ├── WvBlazorTraceService.Signals.cs
│ ├── WvBlazorTraceService.Store.cs
│ ├── WvBlazorTraceService.Utils.cs
│ └── WvBlazorTraceService.cs
│ ├── Styles
│ ├── index.less
│ ├── wv-trace-button.less
│ ├── wv-trace-modal.less
│ └── wv-trace-nav.less
│ ├── TraceView.razor
│ ├── Utility
│ ├── CompressionUtility.cs
│ ├── EnumExtensions.cs
│ ├── MemorySizeCalculator.cs
│ ├── WvModalUtility.cs
│ ├── WvTraceUtility.Converters.cs
│ ├── WvTraceUtility.Info.cs
│ ├── WvTraceUtility.Memory.cs
│ ├── WvTraceUtility.ModelHelpers.cs
│ ├── WvTraceUtility.Mute.cs
│ └── WvTraceUtility.cs
│ ├── WebVella.BlazorTrace.csproj
│ ├── WebVella.BlazorTrace.sln
│ ├── WvConstants.cs
│ ├── compilerconfig.json
│ ├── compilerconfig.json.defaults
│ ├── scripts.js
│ ├── styles.css
│ └── styles.min.css
└── tests
└── WebVella.BlazorTrace.Tests
├── Models
├── BaseTest.cs
└── TestComponent.cs
├── WebVella.BlazorTrace.Tests.csproj
└── WvBlazorTraceService
├── WvBlazorTraceServiceTests.Limits.cs
├── WvBlazorTraceServiceTests.MethodCalls.cs
├── WvBlazorTraceServiceTests.Modal.cs
└── WvBlazorTraceServiceTests.Mute.cs
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: webvella
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # v1.0.6
2 | - OPTIMIZATION: memory size calculation optimization for large repeatable objects.
3 | - OPTIMIZATION: adding compression for snapshots in local storage.
4 | - OPTIMIZATION: changing documents to instruct SignalR Hub Message Size increase to 10 MB from the current 1MB, which is needed for bigger projects with large snapshots.
5 |
6 | # v1.0.5
7 | - FIX: adding missing JsonIgnores (delete localstorage if problems occur)
8 |
9 | # v1.0.4
10 |
11 | - FEATURE: Create "Mute" trace functionality to mute tracers based on module, component, component instance, method or custom data
12 | - OPTIMIZATION: Virtualize the result rows for scalable interface
13 | - FEATURE: Create "Clear Current" session functionality to quickly flush all the current tracers.
14 |
15 | # v1.0.3
16 | - FEATURE: Support .net8 and .net9 by @jhsheets in #6
17 |
18 | # v1.0.0
19 | - FEATURE: Initial Releat
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 WebVella
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/images/button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/button.png
--------------------------------------------------------------------------------
/images/limits-modal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/limits-modal.png
--------------------------------------------------------------------------------
/images/memory-modal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/memory-modal.png
--------------------------------------------------------------------------------
/images/trace-list-modal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/trace-list-modal.png
--------------------------------------------------------------------------------
/images/trace-modal-methods.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/trace-modal-methods.png
--------------------------------------------------------------------------------
/images/trace-modal-muted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/trace-modal-muted.png
--------------------------------------------------------------------------------
/images/trace-modal-signals.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/trace-modal-signals.png
--------------------------------------------------------------------------------
/images/trace-modal-snapshots.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/images/trace-modal-snapshots.png
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/App.razor:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Not found
8 |
9 | Sorry, there's nothing at this address.
10 |
11 |
12 |
13 | @* <-- INSERT HERE *@
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Components/Test1.razor:
--------------------------------------------------------------------------------
1 | @inject IWvBlazorTraceService WvBlazorTraceService
2 |
3 |
4 | Test 1 Counter: @_counter
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | @code {
20 | [Parameter] public string? InstanceTag { get; set; }
21 | private bool _enableTrace = true;
22 | private int _counter = 0;
23 |
24 | protected override void OnInitialized()
25 | {
26 | if (_enableTrace)
27 | WvBlazorTraceService.OnEnter(component: this, instanceTag: InstanceTag, customData: $"counter");
28 |
29 | base.OnInitialized();
30 | if (_enableTrace)
31 | WvBlazorTraceService.OnExit(component: this, instanceTag: InstanceTag, customData: $"counter");
32 | }
33 |
34 | protected override void OnAfterRender(bool firstRender)
35 | {
36 |
37 | if (_enableTrace)
38 | WvBlazorTraceService.OnEnter(component: this, firstRender: firstRender, instanceTag: InstanceTag);
39 |
40 | base.OnAfterRender(firstRender);
41 |
42 | if (_enableTrace)
43 | WvBlazorTraceService.OnExit(component: this, firstRender: firstRender, instanceTag: InstanceTag);
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | if (_enableTrace)
49 | WvBlazorTraceService.OnEnter(component: this, instanceTag: InstanceTag);
50 |
51 | base.OnParametersSet();
52 |
53 | if (_enableTrace)
54 | WvBlazorTraceService.OnExit(component: this, instanceTag: InstanceTag);
55 | }
56 |
57 | protected override bool ShouldRender()
58 | {
59 | if (_enableTrace)
60 | WvBlazorTraceService.OnEnter(component: this, instanceTag: InstanceTag);
61 |
62 | if (_enableTrace)
63 | WvBlazorTraceService.OnExit(component: this, instanceTag: InstanceTag);
64 | return base.ShouldRender();
65 | }
66 |
67 |
68 |
69 | private void _countTest1()
70 | {
71 | if (_enableTrace)
72 | WvBlazorTraceService.OnEnter(component: this, instanceTag: InstanceTag);
73 |
74 | _counter++;
75 | if(_enableTrace)
76 | WvBlazorTraceService.OnSignal(caller: this, signalName: "counter", instanceTag: InstanceTag,
77 | customData: $"counter:{_counter}",
78 | options: new Models.WvTraceSignalOptions
79 | {
80 | CallLimit = 0
81 | });
82 |
83 | if (_enableTrace)
84 | WvBlazorTraceService.OnExit(component: this, instanceTag: InstanceTag);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Components/Test2.razor:
--------------------------------------------------------------------------------
1 | @using System.Diagnostics
2 | @using WebVella.BlazorTrace.Models
3 | @inject IWvBlazorTraceService WvBlazorTraceService
4 |
5 |
6 | Test 1 Parent: @ParentCounter
7 |
8 |
9 | Test 2 Instance 1 Counter: @_counter
10 |
11 |
12 |
13 |
14 |
15 |
16 | @code {
17 | [Parameter] public int ParentCounter { get; set; } = 0;
18 | [Parameter] public string? InstanceTag { get; set; }
19 | private bool _enableTrace = true;
20 | private int _counter = 0;
21 | private List _list = new();
22 | private static string _staticTest = Guid.NewGuid().ToString();
23 |
24 | protected override void OnInitialized()
25 | {
26 | if (_enableTrace)
27 | WvBlazorTraceService.OnEnter(this, instanceTag: InstanceTag);
28 |
29 | base.OnInitialized();
30 | for (int i = 0; i < 5; i++)
31 | {
32 | _list.Add(Guid.NewGuid());
33 | if (_enableTrace)
34 | WvBlazorTraceService.OnSignal(this, signalName: "test-signal", instanceTag: InstanceTag,
35 | customData:$"index={i}",
36 | options: new WvTraceSignalOptions
37 | {
38 | CallLimit = 5 - i
39 | });
40 | }
41 |
42 | if (_enableTrace)
43 | WvBlazorTraceService.OnExit(this, instanceTag: InstanceTag, options: new WvTraceMethodOptions
44 | {
45 | MemoryLimitTotalBytes = 1,
46 | MemoryLimitDeltaBytes = 1,
47 | CallLimit = 1,
48 | DurationLimitMS = 1
49 | });
50 | }
51 |
52 | protected override async Task OnAfterRenderAsync(bool firstRender)
53 | {
54 | if (_enableTrace)
55 | WvBlazorTraceService.OnEnter(this, firstRender: firstRender, instanceTag: InstanceTag);
56 |
57 | base.OnAfterRender(firstRender);
58 | await Task.Delay(50);
59 |
60 | if (_enableTrace)
61 | WvBlazorTraceService.OnExit(this, firstRender: firstRender, instanceTag: InstanceTag);
62 | }
63 |
64 | protected override void OnParametersSet()
65 | {
66 | if (_enableTrace)
67 | WvBlazorTraceService.OnEnter(this, instanceTag: InstanceTag);
68 |
69 | base.OnParametersSet();
70 |
71 | if (_enableTrace)
72 | WvBlazorTraceService.OnExit(this, instanceTag: InstanceTag);
73 | }
74 |
75 | protected override bool ShouldRender()
76 | {
77 | if (_enableTrace)
78 | WvBlazorTraceService.OnEnter(this, instanceTag: InstanceTag);
79 |
80 | if (_enableTrace)
81 | WvBlazorTraceService.OnExit(this, instanceTag: InstanceTag);
82 | return base.ShouldRender();
83 | }
84 |
85 | private void _countTest2()
86 | {
87 | if (_enableTrace)
88 | WvBlazorTraceService.OnEnter(component: this, instanceTag: InstanceTag);
89 |
90 | _counter++;
91 |
92 | if (_enableTrace)
93 | WvBlazorTraceService.OnExit(component: this, instanceTag: InstanceTag);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Layout/MainLayout.razor:
--------------------------------------------------------------------------------
1 | @inherits LayoutComponentBase
2 |
7 |
8 | @Body
9 |
10 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Layout/MainLayout.razor.css:
--------------------------------------------------------------------------------
1 | .page {
2 | position: relative;
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | main {
8 | flex: 1;
9 | }
10 |
11 | .sidebar {
12 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
13 | }
14 |
15 | .top-row {
16 | background-color: #f7f7f7;
17 | border-bottom: 1px solid #d6d5d5;
18 | justify-content: flex-end;
19 | height: 3.5rem;
20 | display: flex;
21 | align-items: center;
22 | }
23 |
24 | .top-row ::deep a, .top-row ::deep .btn-link {
25 | white-space: nowrap;
26 | margin-left: 1.5rem;
27 | text-decoration: none;
28 | }
29 |
30 | .top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
31 | text-decoration: underline;
32 | }
33 |
34 | .top-row ::deep a:first-child {
35 | overflow: hidden;
36 | text-overflow: ellipsis;
37 | }
38 |
39 | @media (max-width: 640.98px) {
40 | .top-row {
41 | justify-content: space-between;
42 | }
43 |
44 | .top-row ::deep a, .top-row ::deep .btn-link {
45 | margin-left: 0;
46 | }
47 | }
48 |
49 | @media (min-width: 641px) {
50 | .page {
51 | flex-direction: row;
52 | }
53 |
54 | .sidebar {
55 | width: 250px;
56 | height: 100vh;
57 | position: sticky;
58 | top: 0;
59 | }
60 |
61 | .top-row {
62 | position: sticky;
63 | top: 0;
64 | z-index: 1;
65 | }
66 |
67 | .top-row.auth ::deep a:first-child {
68 | flex: 1;
69 | text-align: right;
70 | width: 0;
71 | }
72 |
73 | .top-row, article {
74 | padding-left: 2rem !important;
75 | padding-right: 1.5rem !important;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Pages/Home.razor:
--------------------------------------------------------------------------------
1 | @page "/"
2 | Home
3 | Home Page
4 |
5 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Pages/Page.razor:
--------------------------------------------------------------------------------
1 | @page "/page"
2 | Page
3 | Addon Page
4 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components.Web;
2 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
3 |
4 | namespace WebVella.BlazorTrace.Site;
5 | public class Program
6 | {
7 | public static async Task Main(string[] args)
8 | {
9 | var builder = WebAssemblyHostBuilder.CreateDefault(args);
10 | builder.RootComponents.Add("#app");
11 | builder.RootComponents.Add("head::after");
12 |
13 | builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
14 | builder.Services.AddBlazorTrace(new WvBlazorTraceConfiguration()
15 | {
16 | #if DEBUG
17 | EnableTracing = true,
18 | AutoShowModal = true,
19 | #else
20 | EnableTracing = false,
21 | #endif
22 | EnableF1Shortcut = true,
23 | MemoryIncludeAssemblyList = new(){
24 | "WebVella.BlazorTrace.Site"
25 | }
26 | });
27 |
28 | await builder.Build().RunAsync();
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "profiles": {
4 | "http": {
5 | "commandName": "Project",
6 | "dotnetRunMessages": true,
7 | "launchBrowser": true,
8 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
9 | "applicationUrl": "http://localhost:5066",
10 | "environmentVariables": {
11 | "ASPNETCORE_ENVIRONMENT": "Development"
12 | }
13 | },
14 | "https": {
15 | "commandName": "Project",
16 | "dotnetRunMessages": true,
17 | "launchBrowser": true,
18 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
19 | "applicationUrl": "https://localhost:7291;http://localhost:5066",
20 | "environmentVariables": {
21 | "ASPNETCORE_ENVIRONMENT": "Development"
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/WebVella.BlazorTrace.Site.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | service-worker-assets.js
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using System.Net.Http.Json
3 | @using Microsoft.AspNetCore.Components.Forms
4 | @using Microsoft.AspNetCore.Components.Routing
5 | @using Microsoft.AspNetCore.Components.Web
6 | @using Microsoft.AspNetCore.Components.Web.Virtualization
7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http
8 | @using Microsoft.JSInterop
9 | @using WebVella.BlazorTrace.Site
10 | @using WebVella.BlazorTrace.Site.Layout
11 | @using WebVella.BlazorTrace.Site.Components
12 | @using WebVella.BlazorTrace.Components
13 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/site/WebVella.BlazorTrace.Site/wwwroot/favicon.png
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/site/WebVella.BlazorTrace.Site/wwwroot/icon-192.png
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WebVella/WebVella.BlazorTrace/b37b9015e83780b7a96f94e4cbe5e2ac721690aa/site/WebVella.BlazorTrace.Site/wwwroot/icon-512.png
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | WebVella.BlazorTrace.Site
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/manifest.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "WebVella.BlazorTrace.Site",
3 | "short_name": "WebVella.BlazorTrace.Site",
4 | "id": "./",
5 | "start_url": "./",
6 | "display": "standalone",
7 | "background_color": "#ffffff",
8 | "theme_color": "#03173d",
9 | "prefer_related_applications": false,
10 | "icons": [
11 | {
12 | "src": "icon-512.png",
13 | "type": "image/png",
14 | "sizes": "512x512"
15 | },
16 | {
17 | "src": "icon-192.png",
18 | "type": "image/png",
19 | "sizes": "192x192"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/service-worker.js:
--------------------------------------------------------------------------------
1 | // In development, always fetch from the network and do not enable offline support.
2 | // This is because caching would make development more difficult (changes would not
3 | // be reflected on the first load after each change).
4 | self.addEventListener('fetch', () => { });
5 |
--------------------------------------------------------------------------------
/site/WebVella.BlazorTrace.Site/wwwroot/service-worker.published.js:
--------------------------------------------------------------------------------
1 | // Caution! Be sure you understand the caveats before publishing an application with
2 | // offline support. See https://aka.ms/blazor-offline-considerations
3 |
4 | self.importScripts('./service-worker-assets.js');
5 | self.addEventListener('install', event => event.waitUntil(onInstall(event)));
6 | self.addEventListener('activate', event => event.waitUntil(onActivate(event)));
7 | self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
8 |
9 | const cacheNamePrefix = 'offline-cache-';
10 | const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
11 | const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ];
12 | const offlineAssetsExclude = [ /^service-worker\.js$/ ];
13 |
14 | // Replace with your base path if you are hosting on a subfolder. Ensure there is a trailing '/'.
15 | const base = "/";
16 | const baseUrl = new URL(base, self.origin);
17 | const manifestUrlList = self.assetsManifest.assets.map(asset => new URL(asset.url, baseUrl).href);
18 |
19 | async function onInstall(event) {
20 | console.info('Service worker: Install');
21 |
22 | // Fetch and cache all matching items from the assets manifest
23 | const assetsRequests = self.assetsManifest.assets
24 | .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
25 | .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
26 | .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }));
27 | await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
28 | }
29 |
30 | async function onActivate(event) {
31 | console.info('Service worker: Activate');
32 |
33 | // Delete unused caches
34 | const cacheKeys = await caches.keys();
35 | await Promise.all(cacheKeys
36 | .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
37 | .map(key => caches.delete(key)));
38 | }
39 |
40 | async function onFetch(event) {
41 | let cachedResponse = null;
42 | if (event.request.method === 'GET') {
43 | // For all navigation requests, try to serve index.html from cache,
44 | // unless that request is for an offline resource.
45 | // If you need some URLs to be server-rendered, edit the following check to exclude those URLs
46 | const shouldServeIndexHtml = event.request.mode === 'navigate'
47 | && !manifestUrlList.some(url => url === event.request.url);
48 |
49 | const request = shouldServeIndexHtml ? 'index.html' : event.request;
50 | const cache = await caches.open(cacheName);
51 | cachedResponse = await cache.match(request);
52 | }
53 |
54 | return cachedResponse || fetch(event.request);
55 | }
56 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/General/WvBlazorTraceModalOverlay.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 |
4 |
8 | @code {
9 | [Parameter] public EventCallback OnHide { get; set; }
10 | [Parameter] public int NestLevel { get; set; } = 0;
11 | private string _style { get => $"z-index:{(20000 + (2*NestLevel))}"; }
12 | private async Task _hideClick()
13 | => await OnHide.InvokeAsync();
14 |
15 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTrace/WvBlazorTrace.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @if (WvBlazorTraceConfigurationService.GetConfiguraion().EnableTracing)
4 | {
5 |
6 | }
7 |
8 | @code {
9 | [Inject] public IWvBlazorTraceConfigurationService WvBlazorTraceConfigurationService { get; set; } = default!;
10 | // PARAMS
11 | //////////////////////////////////////////////////
12 | ///
13 | /// the 'heart button' position on the screen
14 | ///
15 | [Parameter] public WvButtonPosition Position { get; set; } = WvButtonPosition.RightTop;
16 | ///
17 | /// the background color of the 'heart button'
18 | ///
19 | [Parameter] public string ButtonColor { get; set; } = "#be123c";
20 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTrace/WvBlazorTraceMethodMenu.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 |
4 | @if (Data is not null && Data.Request is not null && Data.Request!.IsMethodMenu)
5 | {
6 |
7 |
8 |
9 |
10 | @if (Data?.Request is not null && Data.Request.MethodsFilter.HasFilter)
11 | {
12 |
18 | }
19 | |
20 |
21 | await SubmitFilter.InvokeAsync())" />
24 | |
25 |
26 | await SubmitFilter.InvokeAsync())" />
29 | |
30 |
31 | await SubmitFilter.InvokeAsync())" />
34 | |
35 |
36 | await SubmitFilter.InvokeAsync())">
37 |
38 | @foreach (var option in Enum.GetValues())
39 | {
40 |
41 | }
42 |
43 | |
44 |
45 | await SubmitFilter.InvokeAsync())">
47 |
48 | @foreach (var option in Enum.GetValues())
49 | {
50 |
51 | }
52 |
53 | |
54 |
55 | await SubmitFilter.InvokeAsync())">
56 |
57 | @foreach (var option in Enum.GetValues())
58 | {
59 |
60 | }
61 |
62 | |
63 |
64 | await SubmitFilter.InvokeAsync())">
65 |
66 | @foreach (var option in Enum.GetValues())
67 | {
68 |
69 | }
70 |
71 | |
72 |
73 | @foreach (var item in Data.MethodTraceRows.Where(x => x.IsPinned))
74 | {
75 |
81 | }
82 |
83 |
84 | @if (Loading)
85 | {
86 |
87 | Loading .... |
88 |
89 | }
90 | else
91 | {
92 |
93 |
99 |
100 | @if (Data.MethodTraceRows.Count == 0)
101 | {
102 |
103 | No tracers are logged yet |
104 |
105 | }
106 | }
107 |
108 |
109 | }
110 | @code {
111 | [Parameter] public WvTraceModalData? Data { get; set; } = null;
112 | [Parameter] public bool Loading { get; set; } = false;
113 | [Parameter] public EventCallback ClearFilter { get; set; }
114 | [Parameter] public EventCallback SubmitFilter { get; set; } = default!;
115 | [Parameter] public EventCallback ShowTraceListModal { get; set; }
116 | [Parameter] public EventCallback ShowMemoryModal { get; set; }
117 | [Parameter] public EventCallback PinClicked { get; set; }
118 | [Parameter] public EventCallback ShowLimitModal { get; set; }
119 | [Parameter] public EventCallback ShowTraceMuteModal { get; set; }
120 |
121 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTrace/WvBlazorTraceMuteMenu.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 |
4 | @if (Data is not null && Data.Request is not null && Data.Request!.IsTraceMuteMenu)
5 | {
6 |
7 |
8 |
9 |
10 | @if (Data?.Request is not null && Data.Request.MutedFilter.HasFilter)
11 | {
12 |
18 | }
19 | |
20 |
21 | await SubmitFilter.InvokeAsync())" />
24 | |
25 |
26 | await SubmitFilter.InvokeAsync())" />
29 | |
30 |
31 | await SubmitFilter.InvokeAsync())" />
34 | |
35 |
36 | await SubmitFilter.InvokeAsync())" />
39 | |
40 |
41 | await SubmitFilter.InvokeAsync())" />
44 | |
45 |
46 | await SubmitFilter.InvokeAsync())" />
49 | |
50 |
51 | await SubmitFilter.InvokeAsync())" />
54 | |
55 |
56 | await SubmitFilter.InvokeAsync())" />
59 | |
60 |
61 | await SubmitFilter.InvokeAsync())" />
64 | |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
78 | |
79 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
80 | @((MarkupString)(String.IsNullOrWhiteSpace(item.Module) ? "undefined" : item.Module)) |
81 | @((MarkupString)(String.IsNullOrWhiteSpace(item.ComponentName) ? "undefined" : item.ComponentName)) |
82 | @((MarkupString)(String.IsNullOrWhiteSpace(item.InstanceTag) ? "undefined" : item.InstanceTag)) |
83 | @((MarkupString)(String.IsNullOrWhiteSpace(item.Method) ? "undefined" : item.Method)) |
84 | @((MarkupString)(String.IsNullOrWhiteSpace(item.Signal) ? "undefined" : item.Signal)) |
85 | @((MarkupString)(String.IsNullOrWhiteSpace(item.Field) ? "undefined" : item.Field)) |
86 | @((MarkupString)(String.IsNullOrWhiteSpace(item.OnEnterCustomData) ? "undefined" : item.OnEnterCustomData)) |
87 |
88 | @if (item.IsPinned is not null)
89 | {
90 | @item.IsPinned.Value.ToString()
91 | }
92 | else
93 | {
94 | undefined
95 | }
96 | |
97 |
98 |
99 | @if (Data.MutedTraceRows.Count == 0)
100 | {
101 |
102 | No traces are muted yet |
103 |
104 | }
105 |
106 |
107 | }
108 | @code {
109 | [Parameter] public WvTraceModalData? Data { get; set; } = null;
110 | [Parameter] public EventCallback ClearFilter { get; set; }
111 | [Parameter] public EventCallback SubmitFilter { get; set; } = default!;
112 | [Parameter] public EventCallback MuteTraceChange { get; set; }
113 |
114 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTrace/WvBlazorTraceSignalMenu.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 |
4 | @if (Data is not null && Data.Request is not null && Data.Request!.IsSignalMenu)
5 | {
6 |
7 |
8 |
9 |
10 | @if (Data?.Request is not null && Data.Request.SignalsFilter.HasFilter)
11 | {
12 |
18 | }
19 | |
20 |
21 | await SubmitFilter.InvokeAsync())" />
24 | |
25 |
26 | await SubmitFilter.InvokeAsync())">
27 |
28 | @foreach (var option in Enum.GetValues())
29 | {
30 |
31 | }
32 |
33 | |
34 |
35 | await SubmitFilter.InvokeAsync())">
36 |
37 | @foreach (var option in new List {
38 | WvTraceModalLimitsFilter.HasLimitHits,
39 | WvTraceModalLimitsFilter.ZeroLimitHits
40 | })
41 | {
42 |
43 | }
44 |
45 | |
46 |
47 | @foreach (var item in Data.SignalTraceRows.Where(x => x.IsPinned))
48 | {
49 |
54 | }
55 |
56 |
57 | @if (Loading)
58 | {
59 |
60 | Loading .... |
61 |
62 | }
63 | else
64 | {
65 |
66 |
71 |
72 | @if (Data.SignalTraceRows.Count == 0)
73 | {
74 |
75 | No tracers are logged yet |
76 |
77 | }
78 | }
79 |
80 |
81 | }
82 | @code {
83 | [Parameter] public WvTraceModalData? Data { get; set; } = null;
84 | [Parameter] public bool Loading { get; set; } = false;
85 | [Parameter] public EventCallback ClearFilter { get; set; }
86 | [Parameter] public EventCallback SubmitFilter { get; set; } = default!;
87 | [Parameter] public EventCallback ShowTraceListModal { get; set; }
88 | [Parameter] public EventCallback PinClicked { get; set; }
89 | [Parameter] public EventCallback ShowLimitModal { get; set; }
90 | [Parameter] public EventCallback ShowTraceMuteModal { get; set; }
91 |
92 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTrace/WvBlazorTraceSignalRow.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 |
3 | @if (Item is not null)
4 | {
5 |
6 |
7 | @if (Item.IsPinned)
8 | {
9 |
14 | }
15 | else
16 | {
17 |
22 | }
23 |
28 | |
29 |
30 | @Item.SignalName
31 | |
32 |
33 |
39 |
40 | @Item.TraceList.Count
41 | @((MarkupString)Item.SignalComparison.TraceListChangeHtml)
42 |
43 | |
44 |
45 |
51 | @((MarkupString)Item.LimitsHtml)
52 | |
53 |
54 |
55 | }
56 | @code {
57 | [Parameter] public string? Class { get; set; }
58 | [Parameter] public WvSignalTraceRow? Item { get; set; }
59 | [Parameter] public EventCallback OnTraceListView { get; set; }
60 | [Parameter] public EventCallback OnPin { get; set; }
61 | [Parameter] public EventCallback OnMute { get; set; }
62 | [Parameter] public EventCallback OnLimitView { get; set; }
63 |
64 | private async Task _onTraceListView() => await OnTraceListView.InvokeAsync(Item);
65 | private async Task _onPin() => await OnPin.InvokeAsync(Item);
66 | private async Task _onMute() => await OnMute.InvokeAsync(Item);
67 | private async Task _onLimitView() => await OnLimitView.InvokeAsync(Item);
68 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTrace/WvBlazorTraceSnapshotMenu.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 |
4 | @if (Data is not null && Data.Request is not null && Data.Request!.IsSnapshotMenu)
5 | {
6 |
7 |
8 |
9 | |
10 | created on |
11 | name |
12 |
13 |
14 |
15 | @foreach (var item in Data.SnapshotList.OrderBy(x => x.CreatedOn))
16 | {
17 |
18 |
19 |
20 | |
21 | @item.CreatedOn.ToString("yyyy-MM-dd HH:mm:ss") |
22 |
23 |
26 | |
27 |
28 |
29 | }
30 | @if (Data.SnapshotList.Count == 0)
31 | {
32 |
33 | No snapshots saved yet |
34 |
35 | }
36 |
37 |
38 | }
39 | @code {
40 | [Parameter] public WvTraceModalData? Data { get; set; } = null;
41 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceLimitInfoModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _options is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | option |
20 | value |
21 |
22 |
23 |
24 |
25 | call limit |
26 | @_options.CallLimit |
27 |
28 |
29 | total memory limit |
30 | @_options.MemoryLimitTotalBytes.WvBTToKilobytesString() |
31 |
32 |
33 | new/delta memory limit |
34 | @_options.MemoryLimitDeltaBytes.WvBTToKilobytesString() |
35 |
36 |
37 | duration limit |
38 | @_options.DurationLimitMS.WvBTToDurationMSString() |
39 |
40 |
41 |
42 |
43 |
46 |
47 | }
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceLimitInfoModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 | using WebVella.BlazorTrace.Utility;
6 |
7 | namespace WebVella.BlazorTrace;
8 | public partial class WvBlazorTraceLimitInfoModal : WvBlazorTraceComponentBase
9 | {
10 | // INJECTS
11 | //////////////////////////////////////////////////
12 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
13 |
14 | // PARAMETERS
15 | //////////////////////////////////////////////////
16 | [Parameter] public int NestLevel { get; set; } = 1;
17 |
18 | // LOCAL VARIABLES
19 | //////////////////////////////////////////////////
20 | private Guid _componentId = Guid.NewGuid();
21 | private DotNetObjectReference _objectRef = default!;
22 | private bool _escapeListenerEnabled = false;
23 | private bool _modalVisible = false;
24 | private WvTraceMethodOptions? _options = null;
25 | private bool _isEnterOptions = true;
26 |
27 | // LIFECYCLE
28 | /// //////////////////////////////////////////////
29 | public async ValueTask DisposeAsync()
30 | {
31 | if (_escapeListenerEnabled)
32 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
33 | _objectRef?.Dispose();
34 | }
35 | protected override void OnInitialized()
36 | {
37 | base.OnInitialized();
38 | _objectRef = DotNetObjectReference.Create(this);
39 | EnableRenderLock();
40 | }
41 |
42 | protected override void OnParametersSet()
43 | {
44 | base.OnParametersSet();
45 | RegenRenderLock();
46 | }
47 |
48 | // PUBLIC
49 | //////////////////////////////////////////////////
50 | public async Task Show(WvTraceMethodOptions options, bool isEnterOptions = true)
51 | {
52 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
53 | _escapeListenerEnabled = true;
54 | _options = options;
55 | _isEnterOptions = isEnterOptions;
56 | _modalVisible = true;
57 | RegenRenderLock();
58 | await InvokeAsync(StateHasChanged);
59 | }
60 | public async Task Hide(bool invokeStateChanged = true)
61 | {
62 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
63 | _escapeListenerEnabled = false;
64 | _options = null;
65 | _isEnterOptions = true;
66 | _modalVisible = false;
67 | RegenRenderLock();
68 | if (invokeStateChanged)
69 | {
70 | await InvokeAsync(StateHasChanged);
71 | }
72 | }
73 |
74 | [JSInvokable("OnShortcutKey")]
75 | public async Task OnShortcutKey(string code)
76 | {
77 | await Hide();
78 | }
79 |
80 | //PRIVATE
81 | /////////////////////////////////////////////////
82 | private string _getTitle()
83 | {
84 | if (_options is null) return String.Empty;
85 |
86 | var sb = new StringBuilder();
87 | sb.Append($"{(_isEnterOptions ? "OnEnter" : "OnExit")} Limit Options");
88 |
89 | return sb.ToString();
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceLimitInfoSignalModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _options is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | option |
20 | value |
21 |
22 |
23 |
24 |
25 | call limit |
26 | @_options.CallLimit |
27 |
28 |
29 |
30 |
31 |
34 |
35 | }
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceLimitInfoSignalModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceLimitInfoSignalModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [Parameter] public int NestLevel { get; set; } = 1;
16 |
17 | // LOCAL VARIABLES
18 | //////////////////////////////////////////////////
19 | private Guid _componentId = Guid.NewGuid();
20 | private DotNetObjectReference _objectRef = default!;
21 | private bool _escapeListenerEnabled = false;
22 | private bool _modalVisible = false;
23 | private WvTraceSignalOptions? _options = null;
24 |
25 | // LIFECYCLE
26 | /// //////////////////////////////////////////////
27 | public async ValueTask DisposeAsync()
28 | {
29 | if (_escapeListenerEnabled)
30 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
31 | _objectRef?.Dispose();
32 | }
33 | protected override void OnInitialized()
34 | {
35 | base.OnInitialized();
36 | _objectRef = DotNetObjectReference.Create(this);
37 | EnableRenderLock();
38 | }
39 |
40 | protected override void OnParametersSet()
41 | {
42 | base.OnParametersSet();
43 | RegenRenderLock();
44 | }
45 |
46 | // PUBLIC
47 | //////////////////////////////////////////////////
48 | public async Task Show(WvTraceSignalOptions options)
49 | {
50 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
51 | _escapeListenerEnabled = true;
52 | _options = options;
53 | _modalVisible = true;
54 | RegenRenderLock();
55 | await InvokeAsync(StateHasChanged);
56 | }
57 | public async Task Hide(bool invokeStateChanged = true)
58 | {
59 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
60 | _escapeListenerEnabled = false;
61 | _options = null;
62 | _modalVisible = false;
63 | RegenRenderLock();
64 | if (invokeStateChanged)
65 | {
66 | await InvokeAsync(StateHasChanged);
67 | }
68 | }
69 |
70 | [JSInvokable("OnShortcutKey")]
71 | public async Task OnShortcutKey(string code)
72 | {
73 | await Hide();
74 | }
75 |
76 | //PRIVATE
77 | /////////////////////////////////////////////////
78 | private string _getTitle()
79 | {
80 | if (_options is null) return String.Empty;
81 |
82 | var sb = new StringBuilder();
83 | sb.Append($"Limit Options");
84 |
85 | return sb.ToString();
86 | }
87 |
88 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceLimitModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | limit type |
21 | stage |
22 | limit |
23 | actual |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
35 | |
36 | @item.Type.WvBTToDescriptionString() |
37 | @(item.IsOnEnter ? "onEnter" : "OnExit") |
38 | @item.Limit.GetLimitValueAsString(item.Type) |
39 | @item.Actual.GetLimitValueAsString(item.Type) |
40 |
41 |
42 | @if (_row.LimitHits.Count == 0)
43 | {
44 |
45 | No tracers are logged yet for this method |
46 |
47 | }
48 |
49 |
50 |
51 |
54 |
55 |
56 | }
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceLimitModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceLimitModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [CascadingParameter(Name = "WvBlazorTraceBody")]
12 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
13 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
14 |
15 | // PARAMETERS
16 | //////////////////////////////////////////////////
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 |
19 | // LOCAL VARIABLES
20 | //////////////////////////////////////////////////
21 | private Guid _componentId = Guid.NewGuid();
22 | private DotNetObjectReference _objectRef = default!;
23 | private bool _escapeListenerEnabled = false;
24 | private bool _modalVisible = false;
25 | private WvMethodTraceRow? _row = null;
26 | private WvBlazorTraceMuteLimitModal? _limitMuteModal = null;
27 |
28 | // LIFECYCLE
29 | /// //////////////////////////////////////////////
30 | public async ValueTask DisposeAsync()
31 | {
32 | if (_escapeListenerEnabled)
33 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
34 | _objectRef?.Dispose();
35 | }
36 | protected override void OnInitialized()
37 | {
38 | base.OnInitialized();
39 | _objectRef = DotNetObjectReference.Create(this);
40 | EnableRenderLock();
41 | }
42 |
43 | // PUBLIC
44 | //////////////////////////////////////////////////
45 | public async Task Show(WvMethodTraceRow row)
46 | {
47 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
48 | _escapeListenerEnabled = true;
49 | _row = row;
50 | _modalVisible = true;
51 | RegenRenderLock();
52 | await InvokeAsync(StateHasChanged);
53 | }
54 | public async Task Hide(bool invokeStateChanged = true)
55 | {
56 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
57 | _escapeListenerEnabled = false;
58 | _row = null;
59 | _modalVisible = false;
60 | RegenRenderLock();
61 | if (invokeStateChanged)
62 | {
63 | await InvokeAsync(StateHasChanged);
64 | }
65 | }
66 |
67 | [JSInvokable("OnShortcutKey")]
68 | public async Task OnShortcutKey(string code)
69 | {
70 | await Hide();
71 | }
72 |
73 | //PRIVATE
74 | /////////////////////////////////////////////////
75 | private string _getTitle()
76 | {
77 | if (_row is null) return String.Empty;
78 |
79 | var sb = new StringBuilder();
80 | sb.Append($"{_row.Component}");
81 | if (!String.IsNullOrWhiteSpace(_row.InstanceTag))
82 | {
83 | sb.Append($" {_row.InstanceTag}");
84 | }
85 | sb.Append("");
86 | sb.Append($"{_row.Method}");
87 |
88 | return sb.ToString();
89 | }
90 |
91 | private async Task _onMute(WvTraceSessionLimitHit dataField)
92 | {
93 | if (dataField is null || _row is null) return;
94 | if (_limitMuteModal is null) return;
95 | await _limitMuteModal.Show(_row, dataField);
96 | }
97 |
98 | private async Task _muteChanged()
99 | {
100 | var data = WvBlazorTraceBody.GetData();
101 | if (data is null || _row is null) return;
102 |
103 | var row = data.MethodTraceRows.FirstOrDefault(x => x.Id == _row.Id);
104 | if (row is null)
105 | {
106 | _row.LimitHits = new();
107 | }
108 | else
109 | _row = row;
110 | RegenRenderLock();
111 | await InvokeAsync(StateHasChanged);
112 | }
113 |
114 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceListModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_row is not null && _modalVisible)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | duration |
21 | enter |
22 | exit |
23 |
24 |
25 | timestamp |
26 | memory |
27 | custom data |
28 | first render |
29 | limits |
30 | timestamp |
31 | memory |
32 | custom data |
33 | first render |
34 | limits |
35 |
36 |
37 |
38 |
40 |
41 |
42 |
47 | |
48 | @item.DurationMs.WvBTToDurationMSString() |
49 | @item.EnteredOn?.WvBTToTimeString() |
50 | _showMemoryModal(item.TraceId,true))>
51 |
57 |
58 | @item.OnEnterMemoryBytes.WvBTToKilobytesString()
59 |
60 | |
61 | @item.OnEnterCustomData |
62 | @item.OnEnterFirstRender.WvBTGetFirstRenderString() |
63 |
64 |
65 | |
66 | @item.ExitedOn?.WvBTToTimeString() |
67 | _showMemoryModal(item.TraceId,false))>
68 |
74 |
75 | @item.OnExitMemoryBytes.WvBTToKilobytesString()
76 |
77 | |
78 | @item.OnExitCustomData |
79 | @item.OnExitFirstRender.WvBTGetFirstRenderString() |
80 |
81 |
82 | |
83 |
84 |
85 | @if (_row.TraceList.Count == 0)
86 | {
87 |
88 | No tracers are logged yet for this method |
89 |
90 | }
91 |
92 |
93 |
94 |
97 |
98 |
99 |
100 |
101 | }
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceListModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceListModal : WvBlazorTraceComponentBase, IAsyncDisposable
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 |
19 | // LOCAL VARIABLES
20 | //////////////////////////////////////////////////
21 | private Guid _componentId = Guid.NewGuid();
22 | private DotNetObjectReference _objectRef = default!;
23 | private bool _escapeListenerEnabled = false;
24 | private bool _modalVisible = false;
25 | private WvMethodTraceRow? _row = null;
26 | private WvBlazorTraceMemoryModal? _memoryModal = null;
27 | private WvBlazorTraceLimitInfoModal? _limitInfoModal = null;
28 | private WvBlazorTraceMuteTraceModal? _traceMuteModal = null;
29 | // LIFECYCLE
30 | /// //////////////////////////////////////////////
31 | public async ValueTask DisposeAsync()
32 | {
33 | if (_escapeListenerEnabled)
34 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
35 | _objectRef?.Dispose();
36 | }
37 | protected override void OnInitialized()
38 | {
39 | base.OnInitialized();
40 | _objectRef = DotNetObjectReference.Create(this);
41 | EnableRenderLock();
42 | }
43 |
44 | // PUBLIC
45 | //////////////////////////////////////////////////
46 | public async Task Show(WvMethodTraceRow row)
47 | {
48 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
49 | _escapeListenerEnabled = true;
50 | _row = row;
51 | _modalVisible = true;
52 | RegenRenderLock();
53 | await InvokeAsync(StateHasChanged);
54 | }
55 | public async Task Hide(bool invokeStateChanged = true)
56 | {
57 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
58 | _escapeListenerEnabled = false;
59 | _row = null;
60 | _modalVisible = false;
61 | RegenRenderLock();
62 | if (invokeStateChanged)
63 | {
64 | await InvokeAsync(StateHasChanged);
65 | }
66 | }
67 |
68 | [JSInvokable("OnShortcutKey")]
69 | public async Task OnShortcutKey(string code)
70 | {
71 | await Hide();
72 | }
73 |
74 | //PRIVATE
75 | /////////////////////////////////////////////////
76 | private string _getTitle()
77 | {
78 | if (_row is null) return String.Empty;
79 |
80 | var sb = new StringBuilder();
81 | sb.Append($"{_row.Component}");
82 | if (!String.IsNullOrWhiteSpace(_row.InstanceTag))
83 | {
84 | sb.Append($" {_row.InstanceTag}");
85 | }
86 | sb.Append("");
87 | sb.Append($"{_row.Method}");
88 |
89 | return sb.ToString();
90 | }
91 |
92 | private async Task _showMemoryModal(Guid traceId, bool isOnEnter = true)
93 | {
94 | if (_memoryModal is null || _row is null) return;
95 | await _memoryModal.Show(_row, traceId, isOnEnter);
96 | }
97 | private async Task _showLimitInfoModal(WvTraceSessionMethodTrace trace, bool isOnEnter = true)
98 | {
99 | if (_limitInfoModal is null) return;
100 | await _limitInfoModal.Show(isOnEnter ? trace.OnEnterOptions : trace.OnExitOptions, isOnEnter);
101 | }
102 | private async Task _onMute(WvTraceSessionMethodTrace dataField)
103 | {
104 | if (dataField is null || _row is null) return;
105 | if (_traceMuteModal is null) return;
106 | await _traceMuteModal.Show(_row, dataField);
107 | }
108 |
109 | private async Task _muteChanged()
110 | {
111 | var data = WvBlazorTraceBody.GetData();
112 | if (data is null || _row is null) return;
113 |
114 | var row = data.MethodTraceRows.FirstOrDefault(x => x.Id == _row.Id);
115 | if (row is null)
116 | _row.TraceList = new();
117 | else
118 | _row = row;
119 | RegenRenderLock();
120 | await InvokeAsync(StateHasChanged);
121 | }
122 |
123 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMemoryModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | field |
21 | type |
22 | assembly |
23 | memory |
24 | change |
25 |
26 |
27 |
28 |
30 |
31 |
32 |
37 | |
38 | @item.FieldName |
39 | @item.TypeName |
40 | @item.AssemblyName |
41 | @item.SecondarySnapshotBytes.WvBTToKilobytesString() |
42 | @((MarkupString)item.ChangeKBHtml) |
43 |
44 |
45 | @if (_items.Count == 0)
46 | {
47 |
48 | Memory info is presented only if the current snapshot is selected as secondary |
49 |
50 | }
51 |
52 |
53 |
54 |
57 |
58 |
59 | }
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMemoryModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 | using WebVella.BlazorTrace.Utility;
6 |
7 | namespace WebVella.BlazorTrace;
8 | public partial class WvBlazorTraceMemoryModal : WvBlazorTraceComponentBase
9 | {
10 | // INJECTS
11 | //////////////////////////////////////////////////
12 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
13 | [Inject] public IWvBlazorTraceService WvBlazorTraceService { get; set; } = default!;
14 |
15 | // PARAMETERS
16 | //////////////////////////////////////////////////
17 | [CascadingParameter(Name = "WvBlazorTraceBody")]
18 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
19 | [Parameter] public int NestLevel { get; set; } = 1;
20 | [Parameter] public EventCallback OnChange { get; set; }
21 |
22 | // LOCAL VARIABLES
23 | //////////////////////////////////////////////////
24 | private Guid _componentId = Guid.NewGuid();
25 | private DotNetObjectReference _objectRef = default!;
26 | private bool _escapeListenerEnabled = false;
27 | private bool _modalVisible = false;
28 | private WvMethodTraceRow? _row = null;
29 | private Guid? _traceId = null;
30 | private bool _isOnEnter = true;
31 | private List _items = new();
32 | private WvBlazorTraceMuteMemoryModal? _memoryMuteModal = null;
33 |
34 | // LIFECYCLE
35 | /// //////////////////////////////////////////////
36 | public async ValueTask DisposeAsync()
37 | {
38 | if (_escapeListenerEnabled)
39 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
40 | _objectRef?.Dispose();
41 | }
42 | protected override void OnInitialized()
43 | {
44 | base.OnInitialized();
45 | _objectRef = DotNetObjectReference.Create(this);
46 | EnableRenderLock();
47 | }
48 |
49 | // PUBLIC
50 | //////////////////////////////////////////////////
51 | public async Task Show(WvMethodTraceRow row, Guid? traceId = null, bool isOnEnter = true)
52 | {
53 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
54 | _escapeListenerEnabled = true;
55 | _initData(row, traceId, isOnEnter);
56 | _modalVisible = true;
57 | RegenRenderLock();
58 | await InvokeAsync(StateHasChanged);
59 | }
60 | public async Task Hide(bool invokeStateChanged = true)
61 | {
62 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
63 | _escapeListenerEnabled = false;
64 | _row = null;
65 | _items = new();
66 | _modalVisible = false;
67 | RegenRenderLock();
68 | if (invokeStateChanged)
69 | {
70 | await InvokeAsync(StateHasChanged);
71 | }
72 | }
73 |
74 | [JSInvokable("OnShortcutKey")]
75 | public async Task OnShortcutKey(string code)
76 | {
77 | await Hide();
78 | }
79 |
80 |
81 | //PRIVATE
82 | /////////////////////////////////////////////////
83 | private string _getTitle()
84 | {
85 | if (_row is null) return String.Empty;
86 |
87 | var sb = new StringBuilder();
88 | sb.Append($"{_row.Component}");
89 | if (!String.IsNullOrWhiteSpace(_row.InstanceTag))
90 | {
91 | sb.Append($" {_row.InstanceTag}");
92 | }
93 | sb.Append("");
94 | sb.Append($"{_row.Method}");
95 |
96 | return sb.ToString();
97 | }
98 |
99 | private async Task _onMute(WvSnapshotMemoryComparisonDataField dataField)
100 | {
101 | if (dataField is null || _row is null) return;
102 | if (_memoryMuteModal is null) return;
103 | await _memoryMuteModal.Show(_row, dataField);
104 | }
105 |
106 | private async Task _muteChanged()
107 | {
108 | var data = WvBlazorTraceBody.GetData();
109 | if (data is null || _row is null) return;
110 |
111 | var row = data.MethodTraceRows.FirstOrDefault(x => x.Id == _row.Id);
112 | _initData(row, _traceId, _isOnEnter);
113 | await OnChange.InvokeAsync();
114 | RegenRenderLock();
115 | await InvokeAsync(StateHasChanged);
116 | }
117 |
118 | private void _initData(WvMethodTraceRow? row, Guid? traceId, bool isOnEnter = true)
119 | {
120 | _items = new();
121 | _traceId = null;
122 | _isOnEnter = true;
123 | if (row is null) return;
124 |
125 | _row = row;
126 | if (traceId is not null)
127 | {
128 | var trace = _row.TraceList.FirstOrDefault(x => x.TraceId == traceId);
129 | if (trace is not null && isOnEnter)
130 | {
131 | _traceId = traceId;
132 | _isOnEnter = isOnEnter;
133 | _items = trace.OnEnterMemoryInfo.ToMemoryDataFields();
134 | }
135 | else if (trace is not null && !isOnEnter)
136 | {
137 | _traceId = traceId;
138 | _isOnEnter = isOnEnter;
139 | _items = trace.OnExitMemoryInfo.ToMemoryDataFields();
140 | }
141 | }
142 | else
143 | _items = _row.MemoryComparison.Fields;
144 | }
145 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteLimitModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null && _limitHit is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | scope |
21 | muted traces description |
22 |
23 |
24 |
25 | @foreach (var item in _applicableTypes)
26 | {
27 | var selected = _selectedTypes.Any(x => x.Id == item.Id);
28 |
29 |
30 | @if (selected)
31 | {
32 |
33 | }
34 | else
35 | {
36 |
37 |
38 | }
39 | |
40 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
41 | @((MarkupString)item.Type.GenerateMuteDescriptionHtml(
42 | module: _row.Module,
43 | component: _row.Component,
44 | instanceTag: _row.InstanceTag,
45 | limitType: _limitHit.Type
46 | ))
47 | |
48 |
49 | }
50 | @if (_applicableTypes.Count == 0)
51 | {
52 |
53 | No Custom Data found OnEnter or OnExit in this trace. You need one in order to limit by it. |
54 |
55 | }
56 |
57 |
58 |
59 |
60 |
63 |
64 | }
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteLimitModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceMuteLimitModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 | [Parameter] public EventCallback OnChange { get; set; }
19 |
20 | // LOCAL VARIABLES
21 | //////////////////////////////////////////////////
22 | private Guid _componentId = Guid.NewGuid();
23 | private DotNetObjectReference _objectRef = default!;
24 | private bool _escapeListenerEnabled = false;
25 | private bool _modalVisible = false;
26 | private WvMethodTraceRow? _row = null;
27 | private WvTraceSessionLimitHit? _limitHit = null;
28 | private List _applicableTypes = new();
29 | private List _selectedTypes = new();
30 |
31 | // LIFECYCLE
32 | /// //////////////////////////////////////////////
33 | public async ValueTask DisposeAsync()
34 | {
35 | if (_escapeListenerEnabled)
36 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
37 | _objectRef?.Dispose();
38 | }
39 | protected override void OnInitialized()
40 | {
41 | base.OnInitialized();
42 | _objectRef = DotNetObjectReference.Create(this);
43 | EnableRenderLock();
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | base.OnParametersSet();
49 | RegenRenderLock();
50 | }
51 |
52 | // PUBLIC
53 | //////////////////////////////////////////////////
54 | public async Task Show(WvMethodTraceRow row, WvTraceSessionLimitHit dataField)
55 | {
56 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
57 | _escapeListenerEnabled = true;
58 | _row = row;
59 | _limitHit = dataField;
60 | _initMuteOptions();
61 | _modalVisible = true;
62 | RegenRenderLock();
63 | await InvokeAsync(StateHasChanged);
64 | }
65 | public async Task Hide(bool invokeStateChanged = true)
66 | {
67 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
68 | _escapeListenerEnabled = false;
69 | _row = null;
70 | _limitHit = null;
71 | _modalVisible = false;
72 | RegenRenderLock();
73 | if (invokeStateChanged)
74 | {
75 | await InvokeAsync(StateHasChanged);
76 | }
77 | }
78 |
79 | [JSInvokable("OnShortcutKey")]
80 | public async Task OnShortcutKey(string code)
81 | {
82 | await Hide();
83 | }
84 |
85 | //PRIVATE
86 | /////////////////////////////////////////////////
87 | private string _getTitle()
88 | {
89 | if (_limitHit is null) return String.Empty;
90 |
91 | var sb = new StringBuilder();
92 | sb.Append($"Mute method trace");
93 |
94 | return sb.ToString();
95 | }
96 |
97 | private async Task _typeClick(WvTraceMute item)
98 | {
99 | await WvBlazorTraceBody.MuteTraceChange(item);
100 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
101 | await OnChange.InvokeAsync();
102 | RegenRenderLock();
103 | }
104 |
105 | private void _initMuteOptions()
106 | {
107 | _applicableTypes = new();
108 | if (_limitHit is not null && _row is not null)
109 | {
110 | _applicableTypes = new(){
111 | new WvTraceMute(WvTraceMuteType.Limit, _row, _limitHit),
112 | new WvTraceMute(WvTraceMuteType.LimitInModule, _row, _limitHit),
113 | new WvTraceMute(WvTraceMuteType.LimitInComponent, _row, _limitHit),
114 | new WvTraceMute(WvTraceMuteType.LimitInComponentInstance, _row, _limitHit),
115 | };
116 | }
117 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
118 | }
119 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteMemoryModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null && _dataField is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | scope |
21 | muted traces description |
22 |
23 |
24 |
25 | @foreach (var item in _applicableTypes)
26 | {
27 | var selected = _selectedTypes.Any(x => x.Id == item.Id);
28 |
29 |
30 | @if (selected)
31 | {
32 |
33 | }
34 | else
35 | {
36 |
37 | }
38 | |
39 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
40 | @((MarkupString)item.Type.GenerateMuteDescriptionHtml(
41 | module: _row.Module,
42 | component: _row.Component,
43 | instanceTag: _row.InstanceTag,
44 | field: _dataField.FieldName,
45 | assembly:_dataField.AssemblyName
46 | )) |
47 |
48 | }
49 |
50 |
51 |
52 |
53 |
56 |
57 | }
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteMemoryModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceMuteMemoryModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 | [Parameter] public EventCallback OnChange { get; set; }
19 |
20 | // LOCAL VARIABLES
21 | //////////////////////////////////////////////////
22 | private Guid _componentId = Guid.NewGuid();
23 | private DotNetObjectReference _objectRef = default!;
24 | private bool _escapeListenerEnabled = false;
25 | private bool _modalVisible = false;
26 | private WvMethodTraceRow? _row = null;
27 | private WvSnapshotMemoryComparisonDataField? _dataField = null;
28 | private List _applicableTypes = new();
29 | private List _selectedTypes = new();
30 |
31 | // LIFECYCLE
32 | /// //////////////////////////////////////////////
33 | public async ValueTask DisposeAsync()
34 | {
35 | if (_escapeListenerEnabled)
36 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
37 | _objectRef?.Dispose();
38 | }
39 | protected override void OnInitialized()
40 | {
41 | base.OnInitialized();
42 | _objectRef = DotNetObjectReference.Create(this);
43 | EnableRenderLock();
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | base.OnParametersSet();
49 | RegenRenderLock();
50 | }
51 |
52 | // PUBLIC
53 | //////////////////////////////////////////////////
54 | public async Task Show(WvMethodTraceRow row, WvSnapshotMemoryComparisonDataField dataField)
55 | {
56 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
57 | _escapeListenerEnabled = true;
58 | _row = row;
59 | _dataField = dataField;
60 | _initMuteOptions();
61 | _modalVisible = true;
62 | RegenRenderLock();
63 | await InvokeAsync(StateHasChanged);
64 | }
65 | public async Task Hide(bool invokeStateChanged = true)
66 | {
67 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
68 | _escapeListenerEnabled = false;
69 | _row = null;
70 | _dataField = null;
71 | _modalVisible = false;
72 | RegenRenderLock();
73 | if (invokeStateChanged)
74 | {
75 | await InvokeAsync(StateHasChanged);
76 | }
77 | }
78 |
79 | [JSInvokable("OnShortcutKey")]
80 | public async Task OnShortcutKey(string code)
81 | {
82 | await Hide();
83 | }
84 |
85 | //PRIVATE
86 | /////////////////////////////////////////////////
87 | private string _getTitle()
88 | {
89 | if (_dataField is null) return String.Empty;
90 |
91 | var sb = new StringBuilder();
92 | sb.Append($"Mute method trace");
93 |
94 | return sb.ToString();
95 | }
96 |
97 | private async Task _typeClick(WvTraceMute item)
98 | {
99 | await WvBlazorTraceBody.MuteTraceChange(item);
100 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
101 | await OnChange.InvokeAsync();
102 | RegenRenderLock();
103 | }
104 |
105 | private void _initMuteOptions()
106 | {
107 | _applicableTypes = new();
108 | if (_dataField is not null && _row is not null)
109 | {
110 | _applicableTypes = new()
111 | {
112 | new WvTraceMute(WvTraceMuteType.Assembly,_row, _dataField),
113 | new WvTraceMute(WvTraceMuteType.Field,_row, _dataField),
114 | new WvTraceMute(WvTraceMuteType.FieldInAssembly,_row, _dataField),
115 | new WvTraceMute(WvTraceMuteType.FieldInModule,_row, _dataField),
116 | new WvTraceMute(WvTraceMuteType.FieldInComponent,_row, _dataField),
117 | new WvTraceMute(WvTraceMuteType.FieldInComponentInstance,_row, _dataField),
118 | };
119 | }
120 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
121 | }
122 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteMethodModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | scope |
21 | muted traces description |
22 |
23 |
24 |
25 | @foreach (var item in _applicableTypes)
26 | {
27 | var selected = _selectedTypes.Any(x => x.Id == item.Id);
28 |
29 |
30 | @if (selected)
31 | {
32 |
33 | }
34 | else
35 | {
36 |
37 |
38 | }
39 | |
40 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
41 | @((MarkupString)item.Type.GenerateMuteDescriptionHtml(
42 | module:_row.Module,
43 | component:_row.Component,
44 | instanceTag:_row.InstanceTag,
45 | method:_row.Method
46 | )) |
47 |
48 | }
49 |
50 |
51 |
52 |
53 |
56 |
57 | }
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteMethodModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceMuteMethodModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 | [Parameter] public EventCallback OnChange { get; set; }
19 |
20 |
21 | // LOCAL VARIABLES
22 | //////////////////////////////////////////////////
23 | private Guid _componentId = Guid.NewGuid();
24 | private DotNetObjectReference _objectRef = default!;
25 | private bool _escapeListenerEnabled = false;
26 | private bool _modalVisible = false;
27 | private WvMethodTraceRow? _row = null;
28 | private List _applicableTypes = new();
29 | private List _selectedTypes = new();
30 |
31 | // LIFECYCLE
32 | /// //////////////////////////////////////////////
33 | public async ValueTask DisposeAsync()
34 | {
35 | if (_escapeListenerEnabled)
36 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
37 | _objectRef?.Dispose();
38 | }
39 | protected override void OnInitialized()
40 | {
41 | base.OnInitialized();
42 | _objectRef = DotNetObjectReference.Create(this);
43 | EnableRenderLock();
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | base.OnParametersSet();
49 | RegenRenderLock();
50 | }
51 |
52 | // PUBLIC
53 | //////////////////////////////////////////////////
54 | public async Task Show(WvMethodTraceRow row)
55 | {
56 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
57 | _escapeListenerEnabled = true;
58 | _row = row;
59 | _initMuteOptions();
60 | _modalVisible = true;
61 | RegenRenderLock();
62 | await InvokeAsync(StateHasChanged);
63 | }
64 | public async Task Hide(bool invokeStateChanged = true)
65 | {
66 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
67 | _escapeListenerEnabled = false;
68 | _row = null;
69 | _modalVisible = false;
70 | RegenRenderLock();
71 | if (invokeStateChanged)
72 | {
73 | await InvokeAsync(StateHasChanged);
74 | }
75 | }
76 |
77 | [JSInvokable("OnShortcutKey")]
78 | public async Task OnShortcutKey(string code)
79 | {
80 | await Hide();
81 | }
82 |
83 | //PRIVATE
84 | /////////////////////////////////////////////////
85 | private string _getTitle()
86 | {
87 | if (_row is null) return String.Empty;
88 |
89 | var sb = new StringBuilder();
90 | sb.Append($"Mute method trace");
91 |
92 | return sb.ToString();
93 | }
94 |
95 | private async Task _typeClick(WvTraceMute item)
96 | {
97 | await WvBlazorTraceBody.MuteTraceChange(item);
98 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
99 | await OnChange.InvokeAsync();
100 | RegenRenderLock();
101 | }
102 |
103 | private void _initMuteOptions()
104 | {
105 | _applicableTypes = new();
106 | if (_row is not null)
107 | {
108 | _applicableTypes = new(){
109 | new WvTraceMute(WvTraceMuteType.MethodInComponentInstance,_row),
110 | new WvTraceMute(WvTraceMuteType.MethodInComponent,_row),
111 | new WvTraceMute(WvTraceMuteType.MethodInModule,_row),
112 | new WvTraceMute(WvTraceMuteType.Method,_row),
113 | new WvTraceMute(WvTraceMuteType.ComponentInstance,_row),
114 | new WvTraceMute(WvTraceMuteType.Component,_row),
115 | new WvTraceMute(WvTraceMuteType.Module,_row),
116 | };
117 | if (_row!.IsPinned)
118 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.PinnedMethods, _row));
119 | else
120 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.NotPinnedMethods, _row));
121 | }
122 |
123 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
124 | }
125 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteSignalModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | scope |
21 | muted traces description |
22 |
23 |
24 |
25 | @foreach (var item in _applicableTypes)
26 | {
27 | var selected = _selectedTypes.Any(x => x.Id == item.Id);
28 |
29 |
30 | @if (selected)
31 | {
32 |
33 | }
34 | else
35 | {
36 |
37 |
38 | }
39 | |
40 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
41 | @((MarkupString)item.Type.GenerateMuteDescriptionHtml(signalName:_row.SignalName)) |
42 |
43 | }
44 |
45 |
46 |
47 |
50 |
51 | }
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteSignalModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceMuteSignalModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 |
19 | [Parameter] public EventCallback OnChange { get; set; }
20 |
21 | // LOCAL VARIABLES
22 | //////////////////////////////////////////////////
23 | private Guid _componentId = Guid.NewGuid();
24 | private DotNetObjectReference _objectRef = default!;
25 | private bool _escapeListenerEnabled = false;
26 | private bool _modalVisible = false;
27 | private WvSignalTraceRow? _row = null;
28 | private List _applicableTypes = new();
29 | private List _selectedTypes = new();
30 |
31 | // LIFECYCLE
32 | /// //////////////////////////////////////////////
33 | public async ValueTask DisposeAsync()
34 | {
35 | if (_escapeListenerEnabled)
36 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
37 | _objectRef?.Dispose();
38 | }
39 | protected override void OnInitialized()
40 | {
41 | base.OnInitialized();
42 | _objectRef = DotNetObjectReference.Create(this);
43 | EnableRenderLock();
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | base.OnParametersSet();
49 | RegenRenderLock();
50 | }
51 |
52 | // PUBLIC
53 | //////////////////////////////////////////////////
54 | public async Task Show(WvSignalTraceRow row)
55 | {
56 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
57 | _escapeListenerEnabled = true;
58 | _row = row;
59 | _initMuteOptions();
60 | _modalVisible = true;
61 | RegenRenderLock();
62 | await InvokeAsync(StateHasChanged);
63 | }
64 | public async Task Hide(bool invokeStateChanged = true)
65 | {
66 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
67 | _escapeListenerEnabled = false;
68 | _row = null;
69 | _modalVisible = false;
70 | RegenRenderLock();
71 | if (invokeStateChanged)
72 | {
73 | await InvokeAsync(StateHasChanged);
74 | }
75 | }
76 |
77 | [JSInvokable("OnShortcutKey")]
78 | public async Task OnShortcutKey(string code)
79 | {
80 | await Hide();
81 | }
82 |
83 | //PRIVATE
84 | /////////////////////////////////////////////////
85 | private string _getTitle()
86 | {
87 | if (_row is null) return String.Empty;
88 |
89 | var sb = new StringBuilder();
90 | sb.Append($"Mute signal");
91 |
92 | return sb.ToString();
93 | }
94 |
95 | private async Task _typeClick(WvTraceMute item)
96 | {
97 | await WvBlazorTraceBody.MuteTraceChange(item);
98 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
99 | await OnChange.InvokeAsync();
100 | RegenRenderLock();
101 | }
102 |
103 | private void _initMuteOptions()
104 | {
105 | _applicableTypes = new();
106 | if (_row is not null)
107 | {
108 | _applicableTypes = new(){
109 | new WvTraceMute(WvTraceMuteType.Signal,_row),
110 | };
111 | if (_row!.IsPinned)
112 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.PinnedSignals, _row));
113 | else
114 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.NotPinnedSignals, _row));
115 | }
116 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
117 | }
118 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteSignalTraceModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null && _signalTrace is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | scope |
21 | muted traces description |
22 |
23 |
24 |
25 | @foreach (var item in _applicableTypes)
26 | {
27 | var selected = _selectedTypes.Any(x => x.Id == item.Id);
28 |
29 |
30 | @if (selected)
31 | {
32 |
33 | }
34 | else
35 | {
36 |
37 |
38 | }
39 | |
40 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
41 |
42 | @((MarkupString)item.Type.GenerateMuteDescriptionHtml(
43 | module: _signalTrace.ModuleName,
44 | component: _signalTrace.ComponentName,
45 | instanceTag: _signalTrace.InstanceTag,
46 | signalName: _row.SignalName
47 | ))
48 | |
49 |
50 | }
51 |
52 |
53 |
54 |
55 |
58 |
59 | }
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteSignalTraceModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceMuteSignalTraceModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 | [Parameter] public EventCallback OnChange { get; set; }
19 |
20 | // LOCAL VARIABLES
21 | //////////////////////////////////////////////////
22 | private Guid _componentId = Guid.NewGuid();
23 | private DotNetObjectReference _objectRef = default!;
24 | private bool _escapeListenerEnabled = false;
25 | private bool _modalVisible = false;
26 | private WvSignalTraceRow? _row = null;
27 | private WvTraceSessionSignalTrace? _signalTrace = null;
28 | private List _applicableTypes = new();
29 | private List _selectedTypes = new();
30 |
31 | // LIFECYCLE
32 | /// //////////////////////////////////////////////
33 | public async ValueTask DisposeAsync()
34 | {
35 | if (_escapeListenerEnabled)
36 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
37 | _objectRef?.Dispose();
38 | }
39 | protected override void OnInitialized()
40 | {
41 | base.OnInitialized();
42 | _objectRef = DotNetObjectReference.Create(this);
43 | EnableRenderLock();
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | base.OnParametersSet();
49 | RegenRenderLock();
50 | }
51 |
52 | // PUBLIC
53 | //////////////////////////////////////////////////
54 | public async Task Show(WvSignalTraceRow row, WvTraceSessionSignalTrace dataField)
55 | {
56 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
57 | _escapeListenerEnabled = true;
58 | _row = row;
59 | _signalTrace = dataField;
60 | _initMuteOptions();
61 | _modalVisible = true;
62 | RegenRenderLock();
63 | await InvokeAsync(StateHasChanged);
64 | }
65 | public async Task Hide(bool invokeStateChanged = true)
66 | {
67 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
68 | _escapeListenerEnabled = false;
69 | _row = null;
70 | _signalTrace = null;
71 | _modalVisible = false;
72 | RegenRenderLock();
73 | if (invokeStateChanged)
74 | {
75 | await InvokeAsync(StateHasChanged);
76 | }
77 | }
78 |
79 | [JSInvokable("OnShortcutKey")]
80 | public async Task OnShortcutKey(string code)
81 | {
82 | await Hide();
83 | }
84 |
85 | //PRIVATE
86 | /////////////////////////////////////////////////
87 | private string _getTitle()
88 | {
89 | if (_signalTrace is null) return String.Empty;
90 |
91 | var sb = new StringBuilder();
92 | sb.Append($"Mute method trace");
93 |
94 | return sb.ToString();
95 | }
96 |
97 | private async Task _typeClick(WvTraceMute item)
98 | {
99 | await WvBlazorTraceBody.MuteTraceChange(item);
100 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
101 | await OnChange.InvokeAsync();
102 | RegenRenderLock();
103 | }
104 |
105 | private void _initMuteOptions()
106 | {
107 | _applicableTypes = new();
108 | if (_signalTrace is not null && _row is not null)
109 | {
110 | _applicableTypes = new(){
111 | new WvTraceMute(WvTraceMuteType.SignalInModule,_row,_signalTrace),
112 | new WvTraceMute(WvTraceMuteType.SignalInComponent,_row,_signalTrace),
113 | new WvTraceMute(WvTraceMuteType.SignalInComponentInstance,_row,_signalTrace),
114 | };
115 |
116 | }
117 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
118 | }
119 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteTraceModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null && _methodTrace is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | scope |
21 | muted traces description |
22 |
23 |
24 |
25 | @foreach (var item in _applicableTypes)
26 | {
27 | var selected = _selectedTypes.Any(x => x.Id == item.Id);
28 |
29 |
30 | @if (selected)
31 | {
32 |
33 | }
34 | else
35 | {
36 |
37 |
38 | }
39 | |
40 | @((MarkupString)item.Type.WvBTToDescriptionString()) |
41 | @((MarkupString)item.Type.GenerateMuteDescriptionHtml(
42 | module: _row.Module,
43 | component: _row.Component,
44 | instanceTag: _row.InstanceTag,
45 | onEnterCustomData: _methodTrace.OnEnterCustomData,
46 | onExitCustomData: _methodTrace.OnExitCustomData
47 | ))
48 | |
49 |
50 | }
51 | @if (_applicableTypes.Count == 0)
52 | {
53 |
54 | No Custom Data found OnEnter or OnExit in this trace. You need one in order to limit by it. |
55 |
56 | }
57 |
58 |
59 |
60 |
61 |
64 |
65 | }
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceMuteTraceModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceMuteTraceModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [CascadingParameter(Name = "WvBlazorTraceBody")]
16 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
17 | [Parameter] public int NestLevel { get; set; } = 1;
18 | [Parameter] public EventCallback OnChange { get; set; }
19 |
20 | // LOCAL VARIABLES
21 | //////////////////////////////////////////////////
22 | private Guid _componentId = Guid.NewGuid();
23 | private DotNetObjectReference _objectRef = default!;
24 | private bool _escapeListenerEnabled = false;
25 | private bool _modalVisible = false;
26 | private WvMethodTraceRow? _row = null;
27 | private WvTraceSessionMethodTrace? _methodTrace = null;
28 | private List _applicableTypes = new();
29 | private List _selectedTypes = new();
30 |
31 | // LIFECYCLE
32 | /// //////////////////////////////////////////////
33 | public async ValueTask DisposeAsync()
34 | {
35 | if (_escapeListenerEnabled)
36 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
37 | _objectRef?.Dispose();
38 | }
39 | protected override void OnInitialized()
40 | {
41 | base.OnInitialized();
42 | _objectRef = DotNetObjectReference.Create(this);
43 | EnableRenderLock();
44 | }
45 |
46 | protected override void OnParametersSet()
47 | {
48 | base.OnParametersSet();
49 | RegenRenderLock();
50 | }
51 |
52 | // PUBLIC
53 | //////////////////////////////////////////////////
54 | public async Task Show(WvMethodTraceRow row, WvTraceSessionMethodTrace dataField)
55 | {
56 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
57 | _escapeListenerEnabled = true;
58 | _row = row;
59 | _methodTrace = dataField;
60 | _initMuteOptions();
61 | _modalVisible = true;
62 | RegenRenderLock();
63 | await InvokeAsync(StateHasChanged);
64 | }
65 | public async Task Hide(bool invokeStateChanged = true)
66 | {
67 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
68 | _escapeListenerEnabled = false;
69 | _row = null;
70 | _methodTrace = null;
71 | _modalVisible = false;
72 | RegenRenderLock();
73 | if (invokeStateChanged)
74 | {
75 | await InvokeAsync(StateHasChanged);
76 | }
77 | }
78 |
79 | [JSInvokable("OnShortcutKey")]
80 | public async Task OnShortcutKey(string code)
81 | {
82 | await Hide();
83 | }
84 |
85 | //PRIVATE
86 | /////////////////////////////////////////////////
87 | private string _getTitle()
88 | {
89 | if (_methodTrace is null) return String.Empty;
90 |
91 | var sb = new StringBuilder();
92 | sb.Append($"Mute method trace");
93 |
94 | return sb.ToString();
95 | }
96 |
97 | private async Task _typeClick(WvTraceMute item)
98 | {
99 | await WvBlazorTraceBody.MuteTraceChange(item);
100 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
101 | await OnChange.InvokeAsync();
102 | RegenRenderLock();
103 | }
104 |
105 | private void _initMuteOptions()
106 | {
107 | _applicableTypes = new();
108 | if (_methodTrace is not null && _row is not null)
109 | {
110 | _applicableTypes = new();
111 | if (!String.IsNullOrWhiteSpace(_methodTrace.OnEnterCustomData))
112 | {
113 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnEnterCustomData, _row, _methodTrace.OnEnterCustomData));
114 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnEnterCustomDataInModule, _row, _methodTrace.OnEnterCustomData));
115 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnEnterCustomDataInComponent, _row, _methodTrace.OnEnterCustomData));
116 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnEnterCustomDataInComponentInstance, _row, _methodTrace.OnEnterCustomData));
117 | }
118 | if (!String.IsNullOrWhiteSpace(_methodTrace.OnExitCustomData))
119 | {
120 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnExitCustomData, _row, _methodTrace.OnExitCustomData));
121 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnExitCustomDataInModule, _row, _methodTrace.OnExitCustomData));
122 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnExitCustomDataInComponent, _row, _methodTrace.OnExitCustomData));
123 | _applicableTypes.Add(new WvTraceMute(WvTraceMuteType.OnExitCustomDataInComponentInstance, _row, _methodTrace.OnExitCustomData));
124 | }
125 |
126 | }
127 | _selectedTypes = WvBlazorTraceBody.GetTraceMutes();
128 | }
129 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceSignalLimitModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_modalVisible && _row is not null)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | limit type |
20 | limit |
21 | actual |
22 |
23 |
24 |
25 |
27 |
28 | @item.Type.WvBTToDescriptionString() |
29 | @item.Limit.GetLimitValueAsString(item.Type) |
30 | @item.Actual.GetLimitValueAsString(item.Type) |
31 |
32 |
33 | @if (_row.LimitHits.Count == 0)
34 | {
35 |
36 | No tracers are logged yet for this method |
37 |
38 | }
39 |
40 |
41 |
42 |
45 |
46 | }
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceSignalLimitModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceSignalLimitModal : WvBlazorTraceComponentBase
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 | [Parameter] public int NestLevel { get; set; } = 1;
16 |
17 | // LOCAL VARIABLES
18 | //////////////////////////////////////////////////
19 | private Guid _componentId = Guid.NewGuid();
20 | private DotNetObjectReference _objectRef = default!;
21 | private bool _escapeListenerEnabled = false;
22 | private bool _modalVisible = false;
23 | private WvSignalTraceRow? _row = null;
24 |
25 | // LIFECYCLE
26 | /// //////////////////////////////////////////////
27 | public async ValueTask DisposeAsync()
28 | {
29 | if (_escapeListenerEnabled)
30 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
31 | _objectRef?.Dispose();
32 | }
33 | protected override void OnInitialized()
34 | {
35 | base.OnInitialized();
36 | _objectRef = DotNetObjectReference.Create(this);
37 | EnableRenderLock();
38 | }
39 |
40 | // PUBLIC
41 | //////////////////////////////////////////////////
42 | public async Task Show(WvSignalTraceRow row)
43 | {
44 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
45 | _escapeListenerEnabled = true;
46 | _row = row;
47 | _modalVisible = true;
48 | RegenRenderLock();
49 | await InvokeAsync(StateHasChanged);
50 | }
51 | public async Task Hide(bool invokeStateChanged = true)
52 | {
53 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
54 | _escapeListenerEnabled = false;
55 | _row = null;
56 | _modalVisible = false;
57 | RegenRenderLock();
58 | if (invokeStateChanged)
59 | {
60 | await InvokeAsync(StateHasChanged);
61 | }
62 | }
63 |
64 | [JSInvokable("OnShortcutKey")]
65 | public async Task OnShortcutKey(string code)
66 | {
67 | await Hide();
68 | }
69 |
70 | //PRIVATE
71 | /////////////////////////////////////////////////
72 | private string _getTitle()
73 | {
74 | if (_row is null) return String.Empty;
75 |
76 | var sb = new StringBuilder();
77 | sb.Append($"{_row.SignalName}");
78 |
79 | return sb.ToString();
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceSignalTraceListModal.razor:
--------------------------------------------------------------------------------
1 | @namespace WebVella.BlazorTrace
2 | @using WebVella.BlazorTrace.Utility
3 | @inherits WvBlazorTraceComponentBase
4 | @if (_row is not null && _modalVisible)
5 | {
6 | var style = $"z-index:{(20000 + (2 * NestLevel))}";
7 |
8 |
9 |
15 |
16 |
17 |
18 |
19 | |
20 | send on |
21 | module |
22 | component |
23 | method |
24 | custom data |
25 | limits |
26 |
27 |
28 |
29 |
31 |
32 |
33 |
38 | |
39 | @item.SendOn.ToString("yyyy-MMM-dd HH:mm:ss") |
40 | @item.ModuleName |
41 |
42 | @item.ComponentName
43 | @if (!String.IsNullOrWhiteSpace(item.InstanceTag))
44 | {
45 |
46 | @item.InstanceTag
47 | }
48 | |
49 | @item.MethodName |
50 | @item.CustomData |
51 |
52 |
53 | |
54 |
55 |
56 | @if (_row.TraceList.Count == 0)
57 | {
58 |
59 | No tracers are logged yet for this method |
60 |
61 | }
62 |
63 |
64 |
65 |
68 |
69 |
70 |
71 | }
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/WvBlazorTraceSignalTraceListModal.razor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System.Text;
4 | using WebVella.BlazorTrace.Models;
5 |
6 | namespace WebVella.BlazorTrace;
7 | public partial class WvBlazorTraceSignalTraceListModal : WvBlazorTraceComponentBase, IAsyncDisposable
8 | {
9 | // INJECTS
10 | //////////////////////////////////////////////////
11 | [Inject] protected IJSRuntime JSRuntimeSrv { get; set; } = default!;
12 |
13 | // PARAMETERS
14 | //////////////////////////////////////////////////
15 |
16 | [CascadingParameter(Name = "WvBlazorTraceBody")]
17 | public WvBlazorTraceBody WvBlazorTraceBody { get; set; } = default!;
18 | [Parameter] public int NestLevel { get; set; } = 1;
19 |
20 | // LOCAL VARIABLES
21 | //////////////////////////////////////////////////
22 | private Guid _componentId = Guid.NewGuid();
23 | private DotNetObjectReference _objectRef = default!;
24 | private bool _escapeListenerEnabled = false;
25 | private bool _modalVisible = false;
26 | private WvSignalTraceRow? _row = null;
27 | private WvBlazorTraceLimitInfoSignalModal? _limitInfoModal = null;
28 | private WvBlazorTraceMuteSignalTraceModal? _traceMuteModal = null;
29 | // LIFECYCLE
30 | /// //////////////////////////////////////////////
31 | public async ValueTask DisposeAsync()
32 | {
33 | if (_escapeListenerEnabled)
34 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
35 | _objectRef?.Dispose();
36 | }
37 | protected override void OnInitialized()
38 | {
39 | base.OnInitialized();
40 | _objectRef = DotNetObjectReference.Create(this);
41 | EnableRenderLock();
42 | }
43 |
44 | // PUBLIC
45 | //////////////////////////////////////////////////
46 | public async Task Show(WvSignalTraceRow row)
47 | {
48 | await new JsService(JSRuntimeSrv).AddKeyEventListener(_objectRef, "OnShortcutKey", "Escape", _componentId.ToString());
49 | _escapeListenerEnabled = true;
50 | _row = row;
51 | _modalVisible = true;
52 | RegenRenderLock();
53 | await InvokeAsync(StateHasChanged);
54 | }
55 | public async Task Hide(bool invokeStateChanged = true)
56 | {
57 | await new JsService(JSRuntimeSrv).RemoveKeyEventListener("Escape", _componentId.ToString());
58 | _escapeListenerEnabled = false;
59 | _row = null;
60 | _modalVisible = false;
61 | RegenRenderLock();
62 | if (invokeStateChanged)
63 | {
64 | await InvokeAsync(StateHasChanged);
65 | }
66 | }
67 |
68 | [JSInvokable("OnShortcutKey")]
69 | public async Task OnShortcutKey(string code)
70 | {
71 | await Hide();
72 | }
73 |
74 | //PRIVATE
75 | /////////////////////////////////////////////////
76 | private string _getTitle()
77 | {
78 | if (_row is null) return String.Empty;
79 |
80 | var sb = new StringBuilder();
81 | sb.Append($"{_row.SignalName}");
82 |
83 | return sb.ToString();
84 | }
85 | private async Task _showLimitInfoModal(WvTraceSessionSignalTrace trace, bool isOnEnter = true)
86 | {
87 | if (_limitInfoModal is null) return;
88 | await _limitInfoModal.Show(trace.Options);
89 | }
90 |
91 | private async Task _onMute(WvTraceSessionSignalTrace dataField)
92 | {
93 | if (dataField is null || _row is null) return;
94 | if (_traceMuteModal is null) return;
95 | await _traceMuteModal.Show(_row, dataField);
96 | }
97 |
98 | private async Task _muteChanged()
99 | {
100 | var data = WvBlazorTraceBody.GetData();
101 | if (data is null || _row is null) return;
102 |
103 | var row = data.SignalTraceRows.FirstOrDefault(x => x.Id == _row.Id);
104 | if (row is null)
105 | _row.TraceList = new();
106 | else
107 | _row = row;
108 | RegenRenderLock();
109 | await InvokeAsync(StateHasChanged);
110 | }
111 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Components/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using System.Net.Http.Json
3 | @using Microsoft.AspNetCore.Components.Forms
4 | @using Microsoft.AspNetCore.Components.Routing
5 | @using Microsoft.AspNetCore.Components.Web
6 | @using Microsoft.AspNetCore.Components.Web.Virtualization
7 | @using Microsoft.JSInterop
8 | @using WebVella.BlazorTrace.Components
9 | @using WebVella.BlazorTrace.Models
10 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvBlazorTraceComponentBase.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public class WvBlazorTraceComponentBase : ComponentBase
10 | {
11 | public bool IsRenderLockEnabled { get; private set; } = false;
12 | public Guid CurrentRenderLock { get; private set; } = Guid.Empty;
13 | public Guid OldRenderLock { get; private set; } = Guid.Empty;
14 |
15 | protected void EnableRenderLock() => IsRenderLockEnabled = true;
16 | protected void DisableRenderLock() => IsRenderLockEnabled = false;
17 | protected void RegenRenderLock() => CurrentRenderLock = Guid.NewGuid();
18 | protected override void OnParametersSet()
19 | {
20 | if (IsRenderLockEnabled) RegenRenderLock();
21 | }
22 |
23 | protected override bool ShouldRender()
24 | {
25 | if (!IsRenderLockEnabled) return true;
26 | if (CurrentRenderLock == OldRenderLock) return false;
27 | OldRenderLock = CurrentRenderLock;
28 | return true;
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvBlazorTraceConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using WebVella.BlazorTrace.Models;
3 |
4 | namespace WebVella.BlazorTrace;
5 | public class WvBlazorTraceConfiguration
6 | {
7 | ///
8 | /// By default the tracing is enabled, but from this property you can stop the tracing globally
9 | ///
10 | public bool EnableTracing { get; set; } = true;
11 |
12 | ///
13 | /// For easier tool development
14 | ///
15 | public bool AutoShowModal { get; set; } = false;
16 |
17 | ///
18 | /// By default F1 will open the trace modal
19 | ///
20 | public bool EnableF1Shortcut { get; set; } = true;
21 |
22 | ///
23 | /// Assemblies name start strings that you want to always include in memory trace.
24 | ///
25 | public List MemoryIncludeAssemblyList { get; set; } = new();
26 |
27 | ///
28 | /// Assemblies name start strings that you want to exclude from memory trace.
29 | /// Some framework assemblies are excluded by default. Set the to false if you need them
30 | ///
31 | public List MemoryExcludeAssemblyList { get; set; } = new();
32 |
33 | ///
34 | /// By default some framework assemblies are excluded for convenience.
35 | ///
36 | public bool ExcludeDefaultAssemblies { get; set; } = true;
37 |
38 | ///
39 | /// Field Names that are containing one of the strings in this list will be always included in the trace
40 | ///
41 | public List MemoryIncludeFieldNameList { get; set; } = new();
42 |
43 | ///
44 | /// Field Names that are containing one of the strings in this list will be excluded from the trace
45 | /// Some field names are excluded by default. Set the to false if you need them
46 | ///
47 | public List MemoryExcludeFieldNameList { get; set; } = new();
48 |
49 | ///
50 | /// By default some field names that are excluded for convenience.
51 | ///
52 | public bool ExcludeDefaultFieldNames { get; set; } = true;
53 |
54 | ///
55 | /// Override the default Trace method options
56 | ///
57 | public WvTraceMethodOptions? DefaultTraceMethodOptions { get; set; } = null;
58 |
59 | ///
60 | /// Override the default Trace signal options
61 | ///
62 | public WvTraceSignalOptions? DefaultTraceSignalOptions { get; set; } = null;
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvButtonPosition.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public enum WvButtonPosition
10 | {
11 | [Description("wv-trace-hidden")]
12 | Hidden = 0,
13 | [Description("wv-trace-right-top")]
14 | RightTop = 1,
15 | [Description("wv-trace-right-center")]
16 | RightCenter = 2,
17 | [Description("wv-trace-right-bottom")]
18 | RightBottom = 3,
19 | [Description("wv-trace-bottom-right")]
20 | BottomRight = 4,
21 | [Description("wv-trace-bottom-center")]
22 | BottomCenter = 5,
23 | [Description("wv-trace-bottom-left")]
24 | BottomLeft = 6,
25 | [Description("wv-trace-left-top")]
26 | LeftTop = 7,
27 | [Description("wv-trace-left-center")]
28 | LeftCenter = 8,
29 | [Description("wv-trace-left-bottom")]
30 | LeftBottom = 9,
31 | [Description("wv-trace-top-left")]
32 | TopLeft = 10,
33 | [Description("wv-trace-top-center")]
34 | TopCenter = 11,
35 | [Description("wv-trace-top-right")]
36 | TopRight = 12
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvCall.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public class WvCall
10 | {
11 | public DateTimeOffset? EnteredOn { get; set; }
12 | public DateTimeOffset? ExitedOn { get; set; }
13 | [JsonIgnore]
14 | public long DurationMs
15 | {
16 | get
17 | {
18 | if (EnteredOn is null || ExitedOn is null) return 0;
19 | if(EnteredOn.Value > ExitedOn.Value) return 0;
20 | return (ExitedOn.Value - EnteredOn.Value).Milliseconds;
21 | }
22 | }
23 | }
24 |
25 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvLocalStore.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public class WvLocalStore
10 | {
11 | public List Pins { get; set; } = new();
12 | public List MutedTraces { get; set; } = new();
13 | public WvTraceModalRequest? LastModalRequest { get; set; } = null;
14 | public List Snapshots { get; set; } = new();
15 | }
16 |
17 | public class WvSnapshotStore
18 | {
19 | public Guid Id { get; set; } = Guid.NewGuid();
20 | public DateTimeOffset CreatedOn { get; set; } = default!;
21 | public string Name { get; set; } = string.Empty;
22 | public string? CompressedModuleDict { get; set; } = null;
23 | public string? CompressedSignalDict { get; set; } = null;
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSignalTraceRow.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 | using WebVella.BlazorTrace.Utility;
8 |
9 | namespace WebVella.BlazorTrace.Models;
10 | public class WvSignalTraceRow
11 | {
12 | [JsonIgnore]
13 | public string Id { get => WvModalUtility.GenerateSignalHash(SignalName); }
14 | public string? SignalName { get; set; }
15 | public bool IsPinned { get; set; } = false;
16 | public List TraceList { get; set; } = new();
17 | public List LimitHits { get; set; } = new();
18 | [JsonIgnore]
19 | public string LimitsHint
20 | {
21 | get
22 | {
23 | var hints = new List();
24 | if (LimitHits.Count > 0) hints.Add($"{LimitHits.Count} calls");
25 |
26 | if (hints.Count == 0) return "no limits are hit";
27 |
28 | return String.Join("; ", hints);
29 | }
30 | }
31 | [JsonIgnore]
32 | public string LimitsHtml
33 | {
34 | get
35 | {
36 | var html = new List();
37 | if (LimitHits.Count > 0)
38 | html.Add($"{LimitHits.Count}");
39 | else
40 | html.Add($"0");
41 |
42 | return String.Join(" / ", html);
43 | }
44 | }
45 | public WvSnapshotSignalComparisonData SignalComparison { get; set; } = new();
46 | public bool SignalNameMatches(string? search)
47 | {
48 |
49 | if (string.IsNullOrWhiteSpace(search)) return true;
50 |
51 | if ((SignalName ?? String.Empty).ToLowerInvariant().Contains(search.Trim().ToLowerInvariant()))
52 | return true;
53 |
54 | return false;
55 | }
56 |
57 | public bool CallsMatches(WvTraceModalCallsFilter? filter)
58 | {
59 | if (filter is null) return true;
60 | if (TraceList is null) return false;
61 |
62 | if (filter == WvTraceModalCallsFilter.LessThan25 && TraceList.Count <= 25) return true;
63 | if (filter == WvTraceModalCallsFilter.TwentyFiveTo50 && TraceList.Count > 25 && TraceList.Count <= 50) return true;
64 | if (filter == WvTraceModalCallsFilter.MoreThan50 && TraceList.Count > 50) return true;
65 | if (filter == WvTraceModalCallsFilter.PositiveDelta && SignalComparison.TraceListChange > 0) return true;
66 | if (filter == WvTraceModalCallsFilter.NegativeDelta && SignalComparison.TraceListChange < 0) return true;
67 | if (filter == WvTraceModalCallsFilter.NoDelta && SignalComparison.TraceListChange == 0) return true;
68 |
69 | return false;
70 | }
71 |
72 |
73 | public bool LimitMatches(WvTraceModalLimitsFilter? filter)
74 | {
75 | if (filter is null) return true;
76 | if (LimitHits is null) return false;
77 | if (filter == WvTraceModalLimitsFilter.HasLimitHits && LimitHits.Count > 0) return true;
78 | if (filter == WvTraceModalLimitsFilter.ZeroLimitHits && LimitHits.Count == 0) return true;
79 | if (filter == WvTraceModalLimitsFilter.ExceedCallLimit && LimitHits.Count > 0) return true;
80 |
81 | return false;
82 | }
83 | }
84 |
85 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSnapshot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public class WvSnapshot
10 | {
11 | public Guid Id { get; set; } = Guid.NewGuid();
12 | public DateTimeOffset CreatedOn { get; set; } = default!;
13 | public string Name { get; set; } = string.Empty;
14 | public Dictionary ModuleDict { get; set; } = new();
15 | public Dictionary SignalDict { get; set; } = new();
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSnapshotListItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebVella.BlazorTrace.Models;
8 | public class WvSnapshotListItem
9 | {
10 | public Guid Id { get; set; }
11 | public string Name { get; set; } = default!;
12 | public DateTimeOffset CreatedOn { get; set; } = default!;
13 | public Action OnRemove { get; set; } = default!;
14 | public Action OnRename { get; set; } = default!;
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSnapshotMemoryComparison.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 | using WebVella.BlazorTrace.Utility;
8 |
9 | namespace WebVella.BlazorTrace.Models;
10 | public class WvSnapshotMemoryComparison
11 | {
12 | public WvTraceSessionMethod PrimarySnapshotMethod { get; set; } = default!;
13 | public WvTraceSessionMethod SecondarySnapshotMethod { get; set; } = default!;
14 | public WvSnapshotMemoryComparisonData ComparisonData { get; set; } = new();
15 | }
16 |
17 | public class WvSnapshotMemoryComparisonData
18 | {
19 | public long LastMemoryChangeBytes { get; set; }
20 | [JsonIgnore]
21 | public string LastMemoryChangeKBHtml
22 | {
23 | get
24 | {
25 | if (LastMemoryChangeBytes == 0) return $"=";
26 | else if (LastMemoryChangeBytes < 0)
27 | {
28 | return $"{LastMemoryChangeBytes.WvBTToKilobytesString()}";
29 | }
30 | return $"+{LastMemoryChangeBytes.WvBTToKilobytesString()}";
31 | }
32 | }
33 | public List Fields { get; set; } = new();
34 | }
35 |
36 |
37 | public class WvSnapshotMemoryComparisonDataField
38 | {
39 | [JsonIgnore]
40 | public string Id { get => WvTraceUtility.WvBTGetMemoryInfoId(AssemblyName, FieldName); }
41 | public string FieldName { get; set; } = String.Empty;
42 | public string TypeName { get; set; } = String.Empty;
43 | public string AssemblyName { get; set; } = String.Empty;
44 | public long? PrimarySnapshotBytes { get; set; }
45 | public long? SecondarySnapshotBytes { get; set; }
46 | [JsonIgnore]
47 | public long ChangeBytes => (SecondarySnapshotBytes ?? 0) - (PrimarySnapshotBytes ?? 0);
48 | [JsonIgnore]
49 | public string ChangeKBHtml
50 | {
51 | get
52 | {
53 | if (ChangeBytes == 0) return $"=";
54 | else if (ChangeBytes < 0)
55 | {
56 | return $"{ChangeBytes.WvBTToKilobytesString()}";
57 | }
58 | return $"+{ChangeBytes.WvBTToKilobytesString()}";
59 | }
60 | }
61 |
62 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSnapshotMethodComparison.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 | using WebVella.BlazorTrace.Utility;
8 |
9 | namespace WebVella.BlazorTrace.Models;
10 | public class WvSnapshotMethodComparison
11 | {
12 | public WvTraceSessionMethod PrimarySnapshotMethod { get; set; } = default!;
13 | public WvTraceSessionMethod SecondarySnapshotMethod { get; set; } = default!;
14 | public WvSnapshotMethodComparisonData ComparisonData { get; set; } = new();
15 | }
16 |
17 | public class WvSnapshotMethodComparisonData
18 | {
19 | public int TraceListChange { get; set; }
20 | [JsonIgnore]
21 | public string TraceListChangeHtml
22 | {
23 | get
24 | {
25 | if (TraceListChange == 0) return $"=";
26 | else if (TraceListChange < 0)
27 | {
28 | return $"{TraceListChange}";
29 | }
30 | return $"+{TraceListChange}";
31 | }
32 | }
33 | public long LastDurationChangeMS { get; set; }
34 | [JsonIgnore]
35 | public string LastDurationChangeMSHtml
36 | {
37 | get
38 | {
39 | if (LastDurationChangeMS == 0) return $"=";
40 | else if (LastDurationChangeMS < 0)
41 | {
42 | return $"{LastDurationChangeMS}";
43 | }
44 | return $"+{LastDurationChangeMS}";
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSnapshotSavingState.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebVella.BlazorTrace.Models;
8 | public enum WvSnapshotSavingState
9 | {
10 | NotSaving = 0,
11 | Saving = 1,
12 | Saved = 2
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvSnapshotSignalComparison.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 | using WebVella.BlazorTrace.Utility;
8 |
9 | namespace WebVella.BlazorTrace.Models;
10 | public class WvSnapshotSignalComparison
11 | {
12 | public WvTraceSessionSignal PrimarySnapshotSignal { get; set; } = default!;
13 | public WvTraceSessionSignal SecondarySnapshotSignal { get; set; } = default!;
14 | public WvSnapshotSignalComparisonData ComparisonData { get; set; } = new();
15 | }
16 |
17 | public class WvSnapshotSignalComparisonData
18 | {
19 | public int TraceListChange { get; set; }
20 | [JsonIgnore]
21 | public string TraceListChangeHtml
22 | {
23 | get
24 | {
25 | if (TraceListChange == 0) return $"=";
26 | else if (TraceListChange < 0)
27 | {
28 | return $"{TraceListChange}";
29 | }
30 | return $"+{TraceListChange}";
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public class WvTraceInfo
10 | {
11 | public Guid? TraceId { get; set; }
12 | public string? MethodName { get; set; }
13 | public string? ComponentFullName { get; set; }
14 | public string? ComponentName { get; set; }
15 | public string? InstanceTag { get; set; }
16 | public string? ModuleName { get; set; }
17 | [JsonIgnore]
18 | public bool CanGetMemory { get => IsOnAfterRender; }
19 | [JsonIgnore]
20 | public bool IsOnInitialized { get => new List {"OnInitialized","OnInitializedAsync"}.Contains(MethodName ?? string.Empty); }
21 | [JsonIgnore]
22 | public bool IsOnParameterSet { get => new List {"OnParametersSet","OnParametersSetAsync"}.Contains(MethodName ?? string.Empty); }
23 | [JsonIgnore]
24 | public bool IsOnAfterRender { get => new List {"OnAfterRender","OnAfterRenderAsync"}.Contains(MethodName ?? string.Empty); }
25 | [JsonIgnore]
26 | public bool IsShouldRender { get => new List {"ShouldRender"}.Contains(MethodName ?? string.Empty); }
27 | [JsonIgnore]
28 | public bool IsDispose { get => new List {"Dispose","DisposeAsync"}.Contains(MethodName ?? string.Empty); }
29 | [JsonIgnore]
30 | public bool IsOther { get => !IsOnInitialized && !IsOnParameterSet && !IsOnAfterRender && !IsShouldRender && !IsDispose; }
31 | }
32 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceMemoryInfo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 | using WebVella.BlazorTrace.Utility;
8 |
9 | namespace WebVella.BlazorTrace.Models;
10 | public class WvTraceMemoryInfo
11 | {
12 | [JsonIgnore]
13 | public string Id { get => WvTraceUtility.WvBTGetMemoryInfoId(AssemblyName,FieldName); }
14 | public string FieldName { get; set; } = String.Empty;
15 | public string TypeName { get; set; } = String.Empty;
16 | public string AssemblyName { get; set; } = String.Empty;
17 | public long Size { get; set; } = 0;
18 | }
19 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceMethodOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebVella.BlazorTrace.Models;
8 | public class WvTraceMethodOptions
9 | {
10 | ///
11 | /// How many milliseconds is an OK for executing this method. Default is 1000.
12 | ///
13 | public long DurationLimitMS { get; set; } = 1000;
14 |
15 | ///
16 | /// How many calls is OK for this method. Default is 10.
17 | ///
18 | public long CallLimit { get; set; } = 10;
19 |
20 | ///
21 | /// What is the total maximum memory limit. Default is 2048.
22 | ///
23 | public long MemoryLimitTotalBytes { get; set; } = 2048;
24 |
25 | ///
26 | /// What is the maximum memory delta limit between enter and exit. Default is 2048.
27 | ///
28 | public long MemoryLimitDeltaBytes { get; set; } = 2048;
29 | }
30 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceModalMenuItem.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Text.Json.Serialization;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public class WvTraceModalMenuItem
10 | {
11 | public WvTraceModalMenu Id { get; set; } = WvTraceModalMenu.MethodName;
12 | public bool IsActive { get; set; } = false;
13 | public int Counter { get; set; } = 0;
14 | [JsonIgnore]
15 | public string CounterHtml
16 | {
17 | get
18 | {
19 | if (Counter <= 0) return String.Empty;
20 | return $"{(Counter > 99 ? "99+" : Counter)}";
21 | }
22 | }
23 | [JsonIgnore]
24 | public Action OnClick { get; set; } = default!;
25 | }
26 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceMuteType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace WebVella.BlazorTrace.Models;
9 | public enum WvTraceMuteType
10 | {
11 | [Description("Module")]
12 | Module = 0,
13 | [Description("Component")]
14 | Component = 1,
15 | [Description("Component Instance")]
16 | ComponentInstance = 2,
17 | [Description("Method")]
18 | Method = 10,
19 | [Description("Method in Module")]
20 | MethodInModule = 11,
21 | [Description("Method in Component")]
22 | MethodInComponent = 12,
23 | [Description("Method in Component Instance")]
24 | MethodInComponentInstance = 13,
25 | [Description("Signal")]
26 | Signal = 20,
27 | [Description("Signal in Module")]
28 | SignalInModule = 21,
29 | [Description("Signal in Component")]
30 | SignalInComponent = 22,
31 | [Description("Signal in Component Instance")]
32 | SignalInComponentInstance = 23,
33 | [Description("Field")]
34 | Field = 30,
35 | [Description("Field in Module")]
36 | FieldInModule = 31,
37 | [Description("Field in Component")]
38 | FieldInComponent = 32,
39 | [Description("Field in Component Instance")]
40 | FieldInComponentInstance = 33,
41 | [Description("Field in Assembly")]
42 | FieldInAssembly = 34,
43 | [Description("Assembly")]
44 | Assembly = 35,
45 | [Description("Limit")]
46 | Limit = 40,
47 | [Description("Limit in Module")]
48 | LimitInModule = 41,
49 | [Description("Limit in Component")]
50 | LimitInComponent = 42,
51 | [Description("Limit in Component Instance")]
52 | LimitInComponentInstance = 43,
53 | [Description("OnEnter Custom Data")]
54 | OnEnterCustomData = 50,
55 | [Description("OnEnter Custom Data in Module")]
56 | OnEnterCustomDataInModule = 51,
57 | [Description("OnEnter Custom Data in Component")]
58 | OnEnterCustomDataInComponent = 52,
59 | [Description("OnEnter Custom Data in Component Instance")]
60 | OnEnterCustomDataInComponentInstance = 53,
61 | [Description("OnExit Custom Data")]
62 | OnExitCustomData = 54,
63 | [Description("OnExit Custom Data in Module")]
64 | OnExitCustomDataInModule = 55,
65 | [Description("OnExit Custom Data in Component")]
66 | OnExitCustomDataInComponent = 56,
67 | [Description("OnExit Custom Data in Component Instance")]
68 | OnExitCustomDataInComponentInstance = 57,
69 | [Description("Not Pinned methods")]
70 | NotPinnedMethods = 60,
71 | [Description("Pinned methods")]
72 | PinnedMethods = 61,
73 | [Description("Not Pinned signals")]
74 | NotPinnedSignals = 62,
75 | [Description("Pinned signals")]
76 | PinnedSignals = 63,
77 | }
78 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceQueueAction.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Text.Json.Serialization;
7 | using System.Threading.Tasks;
8 | using WebVella.BlazorTrace.Utility;
9 |
10 | namespace WebVella.BlazorTrace.Models;
11 | public class WvTraceQueueAction
12 | {
13 | public WvTraceQueueItemMethod MethodCalled { get; set; } = WvTraceQueueItemMethod.OnEnter;
14 | [JsonIgnore]
15 | public object Caller { get; set; } = default!;
16 | public Guid? TraceId { get; set; } = null;
17 | public WvTraceMethodOptions MethodOptions { get; set; } = default!;
18 | public WvTraceSignalOptions SignalOptions { get; set; } = default!;
19 | public bool? FirstRender { get; set; } = null;
20 | public string SignalName { get; set; } = default!;
21 | public string? InstanceTag { get; set; } = null;
22 | public string? CustomData { get; set; } = null;
23 | public string MethodName { get; set; } = default!;
24 | public DateTimeOffset Timestamp { get; set; } = default!;
25 | }
26 |
27 | public enum WvTraceQueueItemMethod
28 | {
29 | OnEnter = 0,
30 | OnExit = 1,
31 | Signal = 2
32 | }
33 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceSession.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Text.Json.Serialization;
8 | using System.Threading.Tasks;
9 | using WebVella.BlazorTrace.Utility;
10 |
11 | namespace WebVella.BlazorTrace.Models;
12 | public class WvTraceSessionModule
13 | {
14 | public Dictionary ComponentDict { get; set; } = new();
15 | }
16 |
17 | public class WvTraceSessionComponent
18 | {
19 | public string? Name { get; set; }
20 | public List TaggedInstances { get; set; } = new();
21 | }
22 |
23 | public class WvTraceSessionComponentTaggedInstance
24 | {
25 | public string? Tag { get; set; }
26 | public WvTraceSessionMethod OnInitialized { get; set; } = new();
27 | public WvTraceSessionMethod OnParameterSet { get; set; } = new();
28 | public WvTraceSessionMethod OnAfterRender { get; set; } = new();
29 | public WvTraceSessionMethod ShouldRender { get; set; } = new();
30 | public WvTraceSessionMethod Dispose { get; set; } = new();
31 | public List OtherMethods { get; set; } = new();
32 |
33 | public List MethodsTotal()
34 | {
35 | var methods = new List();
36 | methods.Add(OnInitialized);
37 | methods.Add(OnParameterSet);
38 | methods.Add(OnAfterRender);
39 | methods.Add(ShouldRender);
40 | methods.Add(Dispose);
41 | methods.AddRange(OtherMethods);
42 | var calledMethods = new List();
43 | foreach (var method in methods)
44 | {
45 | if (method.MaxCallsCount > 0)
46 | calledMethods.Add(method);
47 | }
48 | return calledMethods;
49 | }
50 | }
51 |
52 | public class WvTraceSessionMethod
53 | {
54 | public string? Name { get; set; } = null;
55 | public List TraceList { get; set; } = new();
56 | //Generated props
57 | [JsonIgnore]
58 | public long? MinDurationMs { get => this.GetMinDuration(); }
59 | [JsonIgnore]
60 | public long? MaxDurationMs { get => this.GetMaxDuration(); }
61 | [JsonIgnore]
62 | public long? LastDurationMS { get => this.GetLastDuration(); }
63 | [JsonIgnore]
64 | public long? OnEnterMinMemoryBytes { get => this.GetMinMemory(isOnEnter: true); }
65 | [JsonIgnore]
66 | public long? OnEnterMaxMemoryBytes { get => this.GetMaxMemory(isOnEnter: true); }
67 | [JsonIgnore]
68 | public long? OnExitMinMemoryBytes { get => this.GetMinMemory(isOnEnter: false); }
69 | [JsonIgnore]
70 | public long? OnExitMaxMemoryBytes { get => this.GetMaxMemory(isOnEnter: false); }
71 | [JsonIgnore]
72 | public long? LastMemoryBytes { get => this.GetLastMemory().Item1; }
73 | [JsonIgnore]
74 | public List? LastMemoryInfo { get => this.GetLastMemory().Item2; }
75 | [JsonIgnore]
76 | public long? MinMemoryDeltaBytes { get => this.GetMinMemoryDelta(); }
77 | [JsonIgnore]
78 | public long? MaxMemoryDeltaBytes { get => this.GetMaxMemoryDelta(); }
79 | [JsonIgnore]
80 | public long OnEnterCallsCount { get => this.GetOnEnterCallCount(); }
81 | [JsonIgnore]
82 | public long OnExitCallsCount { get => this.GetOnExitCallsCount(); }
83 | [JsonIgnore]
84 | public long MaxCallsCount { get => this.GetMaxCallsCount(); }
85 | [JsonIgnore]
86 | public long CompletedCallsCount { get => this.CompletedCallsCount(); }
87 | [JsonIgnore]
88 | public WvTraceSessionMethodTrace? LastExitedTrace
89 | {
90 | get => TraceList.Where(x => x.ExitedOn is not null).OrderByDescending(x => x.ExitedOn).FirstOrDefault();
91 | }
92 | [JsonIgnore]
93 | public List LimitHits { get => this.CalculateLimitsInfo(); }
94 | public string GenerateHash(string moduleName, string componentFullname, string? tag)
95 | {
96 | return WvModalUtility.GenerateMethodHash(moduleName, componentFullname, tag, Name);
97 | }
98 | }
99 |
100 |
101 | public class WvTraceSessionMethodTrace
102 | {
103 | public Guid TraceId { get; set; } = default!;
104 | public DateTimeOffset? EnteredOn { get; set; } = null;
105 | public DateTimeOffset? ExitedOn { get; set; } = null;
106 | public long? OnEnterMemoryBytes { get; set; } = null;
107 | public long? OnExitMemoryBytes { get; set; } = null;
108 | public bool? OnEnterFirstRender { get; set; } = null;
109 | public bool? OnExitFirstRender { get; set; } = null;
110 | public string? OnEnterCustomData { get; set; } = null;
111 | public string? OnExitCustomData { get; set; } = null;
112 | public WvTraceMethodOptions OnEnterOptions { get; set; } = new();
113 | public WvTraceMethodOptions OnExitOptions { get; set; } = new();
114 |
115 | //Non Serializable - to much info to be stored in the store JSON
116 | [JsonIgnore]
117 | public List? OnEnterMemoryInfo { get; set; } = null;
118 |
119 | [JsonIgnore]
120 | public List? OnExitMemoryInfo { get; set; } = null;
121 |
122 | //Generated props
123 | [JsonIgnore]
124 | public long? DurationMs { get => this.GetDurationMS(); }
125 | [JsonIgnore]
126 | public string OnEnterLimitsHTML { get => this.CalculateLimitsHTML(true); }
127 | [JsonIgnore]
128 | public string OnExitLimitsHTML { get => this.CalculateLimitsHTML(false); }
129 | }
130 |
131 | public class WvTraceSessionSignal
132 | {
133 | public List TraceList { get; set; } = new();
134 |
135 | [JsonIgnore]
136 | public List LimitHits { get => this.CalculateLimitsInfo(); }
137 | }
138 |
139 | public class WvTraceSessionSignalTrace
140 | {
141 | public DateTimeOffset SendOn { get; set; } = default!;
142 | public string? ModuleName { get; set; } = null;
143 | public string? ComponentName { get; set; } = null;
144 | public string? ComponentFullName { get; set; } = null;
145 | public string? InstanceTag { get; set; } = null;
146 | public string? MethodName { get; set; } = null;
147 | public string? CustomData { get; set; } = null;
148 | public WvTraceSignalOptions Options { get; set; } = default!;
149 | }
150 |
151 |
152 | public class WvTraceSessionLimitHit
153 | {
154 | public bool IsOnEnter { get; set; } = true;
155 | public WvTraceSessionLimitType Type { get; set; }
156 | public long Limit { get; set; } = 0;
157 | public long Actual { get; set; } = 0;
158 | }
159 |
160 | public enum WvTraceSessionLimitType
161 | {
162 | [Description("calls count")]
163 | CallCount = 0,
164 | [Description("duration")]
165 | Duration = 1,
166 | [Description("total memory")]
167 | MemoryTotal = 2,
168 | [Description("memory delta")]
169 | MemoryDelta = 3
170 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvTraceSignalOptions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebVella.BlazorTrace.Models;
8 | public class WvTraceSignalOptions
9 | {
10 | ///
11 | /// How many calls is OK for this method. Default is 10.
12 | ///
13 | public long CallLimit { get; set; } = 10;
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Models/WvUnionData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebVella.BlazorTrace.Models;
8 | public class WvModuleUnionData
9 | {
10 | public WvTraceSessionModule? Primary { get; set; }
11 | public WvTraceSessionModule? Secondary { get; set; }
12 | public Dictionary ComponentDict { get; set; } = new();
13 | public Dictionary SignalDict { get; set; } = new();
14 | }
15 |
16 |
17 | public class WvComponentUnionData
18 | {
19 | public string? Name { get; set; }
20 | public WvTraceSessionComponent? Primary { get; set; }
21 | public WvTraceSessionComponent? Secondary { get; set; }
22 | public List TaggedInstances { get; set; } = new();
23 | }
24 |
25 | public class WvSignalUnionData
26 | {
27 | public WvTraceSessionSignal? Primary { get; set; }
28 | public WvTraceSessionSignal? Secondary { get; set; }
29 | }
30 |
31 | public class WvTaggedInstanceUnionData
32 | {
33 | public string? Tag { get; set; }
34 | public WvTraceSessionComponentTaggedInstance? Primary { get; set; }
35 | public WvTraceSessionComponentTaggedInstance? Secondary { get; set; }
36 | public Dictionary MethodDict { get; set; } = new();
37 | }
38 |
39 | public class WvMethodUnionData
40 | {
41 | public WvTraceSessionMethod? Primary { get; set; }
42 | public WvTraceSessionMethod? Secondary { get; set; }
43 |
44 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Services/JsService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.JSInterop;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using WebVella.BlazorTrace.Models;
8 |
9 | namespace WebVella.BlazorTrace;
10 | public class JsService
11 | {
12 | protected IJSRuntime JSRuntime { get; }
13 | public JsService(IJSRuntime jsRuntime)
14 | {
15 | JSRuntime = jsRuntime;
16 | }
17 | public async ValueTask AddKeyEventListener(object objectRef, string methodName, string keyCode, string? listenerId = null)
18 | {
19 | try
20 | {
21 | if (keyCode == "Escape")
22 | return await JSRuntime.InvokeAsync(
23 | "WebVellaBlazorTrace.addEscapeKeyEventListener",
24 | objectRef, listenerId, methodName);
25 | else if (keyCode == "F1")
26 | return await JSRuntime.InvokeAsync(
27 | "WebVellaBlazorTrace.addF1KeyEventListener",
28 | objectRef, methodName);
29 | }
30 | catch
31 | {
32 | }
33 | return false;
34 | }
35 |
36 | public async ValueTask RemoveKeyEventListener(string keyCode, string? listenerId = null)
37 | {
38 | try
39 | {
40 | if (keyCode == "Escape")
41 | return await JSRuntime.InvokeAsync(
42 | "WebVellaBlazorTrace.removeEscapeKeyEventListener", listenerId);
43 | else if (keyCode == "F1")
44 | return await JSRuntime.InvokeAsync(
45 | "WebVellaBlazorTrace.removeF1KeyEventListener");
46 | }
47 | catch
48 | {
49 | }
50 | return false;
51 | }
52 |
53 | public async Task SetUnprotectedLocalStorageAsync(string key, string value)
54 | {
55 | await JSRuntime.InvokeVoidAsync("localStorage.setItem", key, value);
56 | }
57 |
58 | public async Task RemoveUnprotectedLocalStorageAsync(string key)
59 | {
60 | await JSRuntime.InvokeVoidAsync("localStorage.removeItem", key);
61 | }
62 |
63 | public async Task GetUnprotectedLocalStorageAsync(string key)
64 | {
65 | return await JSRuntime.InvokeAsync("localStorage.getItem", key);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Services/WvBlazorTraceConfigurationService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Net.WebSockets;
8 | using System.Reflection;
9 | using System.Runtime.CompilerServices;
10 | using System.Runtime.InteropServices;
11 | using System.Text;
12 | using System.Text.Json;
13 | using System.Text.Json.Serialization;
14 | using System.Threading.Tasks;
15 | using WebVella.BlazorTrace.Models;
16 | using WebVella.BlazorTrace.Utility;
17 |
18 | namespace WebVella.BlazorTrace;
19 | public partial interface IWvBlazorTraceConfigurationService
20 | {
21 | WvBlazorTraceConfiguration GetConfiguraion();
22 | }
23 | public partial class WvBlazorTraceConfigurationService : IWvBlazorTraceConfigurationService
24 | {
25 | private readonly WvBlazorTraceConfiguration _configuration = default!;
26 | public WvBlazorTraceConfigurationService(WvBlazorTraceConfiguration? config)
27 | {
28 | this._configuration = config is not null ? config : new();
29 | if (_configuration.ExcludeDefaultAssemblies)
30 | {
31 | if (_configuration.MemoryExcludeAssemblyList is null)
32 | _configuration.MemoryExcludeAssemblyList = new();
33 |
34 | _configuration.MemoryExcludeAssemblyList.AddRange(
35 | new[]{
36 | "Microsoft.AspNetCore"
37 | }
38 | );
39 | }
40 | if (_configuration.ExcludeDefaultFieldNames)
41 | {
42 | if (_configuration.MemoryExcludeFieldNameList is null)
43 | _configuration.MemoryExcludeFieldNameList = new();
44 |
45 | _configuration.MemoryExcludeFieldNameList.AddRange(
46 | new[]{
47 | "k__BackingField"
48 | }
49 | );
50 | }
51 | if(_configuration.DefaultTraceMethodOptions is null)
52 | _configuration.DefaultTraceMethodOptions = new();
53 |
54 | if(_configuration.DefaultTraceSignalOptions is null)
55 | _configuration.DefaultTraceSignalOptions = new();
56 | }
57 | public WvBlazorTraceConfiguration GetConfiguraion()
58 | {
59 | return _configuration;
60 | }
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Services/WvBlazorTraceInjection.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.JSInterop;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using WebVella.BlazorTrace.Models;
9 |
10 | namespace WebVella.BlazorTrace;
11 | public static class WvBlazorTraceInjection
12 | {
13 | public static IServiceCollection AddBlazorTrace(this IServiceCollection services,
14 | WvBlazorTraceConfiguration? configuration = null)
15 | {
16 | services.AddSingleton(provider => new WvBlazorTraceConfigurationService(configuration));
17 | services.AddScoped();
18 | return services;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Services/WvBlazorTraceService.Queue.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System;
4 | using System.Collections.Concurrent;
5 | using System.Collections.Generic;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.Net.WebSockets;
9 | using System.Reflection;
10 | using System.Runtime.CompilerServices;
11 | using System.Runtime.InteropServices;
12 | using System.Text;
13 | using System.Text.Json;
14 | using System.Text.Json.Serialization;
15 | using System.Threading.Tasks;
16 | using WebVella.BlazorTrace.Models;
17 | using WebVella.BlazorTrace.Utility;
18 |
19 | namespace WebVella.BlazorTrace;
20 | public partial interface IWvBlazorTraceService
21 | {
22 | ConcurrentQueue GetQueue();
23 | void ForceProcessQueue();
24 | }
25 | public partial class WvBlazorTraceService : IWvBlazorTraceService
26 | {
27 | public ConcurrentQueue GetQueue() => _traceQueue;
28 | // Because of the force process the queue process could be triggered from two methods
29 | public Lock _queueProcessLock = LockFactory.Create();
30 | private void _addToQueue(WvTraceQueueAction trace)
31 | {
32 | _traceQueue.Enqueue(trace);
33 | }
34 | private void _processQueue()
35 | {
36 | _infiniteLoopCancellationTokenSource = new CancellationTokenSource();
37 | _infiniteLoop = Task.Run(async () =>
38 | {
39 | //Just to be sure that local trace mutes are loaded
40 | _ = await GetTraceMutes();
41 | while (!_infiniteLoopCancellationTokenSource.IsCancellationRequested)
42 | {
43 | await Task.Delay(_infiniteLoopDelaySeconds * 1000);
44 | lock (_queueProcessLock)
45 | {
46 | while (!_traceQueue.IsEmpty)
47 | {
48 | try
49 | {
50 | if (_traceQueue.TryDequeue(out var trace))
51 | {
52 | _processQueueTrace(trace);
53 | }
54 | }
55 | catch (Exception ex)
56 | {
57 | Console.Error.WriteLine(ex.Message.ToString() + Environment.NewLine + ex.StackTrace);
58 | break;
59 | }
60 | }
61 | }
62 |
63 | }
64 | }, _infiniteLoopCancellationTokenSource.Token);
65 | }
66 | private void _processQueueTrace(WvTraceQueueAction action)
67 | {
68 | if (action is null) return;
69 | if (action.Caller is null) return;
70 | var traceInfo = action.Caller.GetInfo(action.TraceId, action.InstanceTag, action.MethodName);
71 | if (traceInfo is null)
72 | throw new Exception("callerInfo cannot be evaluated");
73 | _saveSessionTrace(traceInfo, action);
74 | }
75 |
76 | public void ForceProcessQueue()
77 | {
78 | lock (_queueProcessLock)
79 | {
80 | while (!_traceQueue.IsEmpty)
81 | {
82 | try
83 | {
84 | if (_traceQueue.TryDequeue(out var trace))
85 | {
86 | _processQueueTrace(trace);
87 | }
88 | }
89 | catch (Exception ex)
90 | {
91 | Console.Error.WriteLine(ex.Message.ToString() + Environment.NewLine + ex.StackTrace);
92 | break;
93 | }
94 | }
95 | }
96 | }
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Services/WvBlazorTraceService.Signals.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Net.WebSockets;
8 | using System.Reflection;
9 | using System.Runtime.CompilerServices;
10 | using System.Runtime.InteropServices;
11 | using System.Text;
12 | using System.Text.Json;
13 | using System.Text.Json.Serialization;
14 | using System.Threading.Tasks;
15 | using WebVella.BlazorTrace.Models;
16 | using WebVella.BlazorTrace.Utility;
17 |
18 | namespace WebVella.BlazorTrace;
19 | public partial interface IWvBlazorTraceService
20 | {
21 |
22 | }
23 | public partial class WvBlazorTraceService : IWvBlazorTraceService
24 | {
25 |
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Services/WvBlazorTraceService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System;
4 | using System.Collections.Concurrent;
5 | using System.Collections.Generic;
6 | using System.Diagnostics;
7 | using System.Linq;
8 | using System.Net.WebSockets;
9 | using System.Reflection;
10 | using System.Runtime.CompilerServices;
11 | using System.Runtime.InteropServices;
12 | using System.Text;
13 | using System.Text.Json;
14 | using System.Text.Json.Serialization;
15 | using System.Threading.Tasks;
16 | using WebVella.BlazorTrace.Models;
17 | using WebVella.BlazorTrace.Utility;
18 |
19 | namespace WebVella.BlazorTrace;
20 | public partial interface IWvBlazorTraceService
21 | {
22 | Dictionary GetModuleDict();
23 | Dictionary GetSignalDict();
24 | void ClearCurrentSession();
25 | Task> GetTraceMutes();
26 | }
27 | public partial class WvBlazorTraceService : IWvBlazorTraceService, IDisposable
28 | {
29 | private IJSRuntime _jSRuntime;
30 | private const string _snapshotStoreKey = "wvbtstore";
31 | private Dictionary _moduleDictInternal = new();
32 | private Dictionary _signalDictInternal = new();
33 | private List? _traceMutesInternal = null;
34 | private WvBlazorTraceConfiguration _configuration = new();
35 | private readonly ConcurrentQueue _traceQueue = new();
36 | private int _infiniteLoopDelaySeconds = 1;
37 | private Task? _infiniteLoop;
38 | private CancellationTokenSource? _infiniteLoopCancellationTokenSource;
39 |
40 | ///
41 | /// Needs to be implemented to destroy the infinite loop
42 | ///
43 | ///
44 | public void Dispose()
45 | {
46 | if (_infiniteLoopCancellationTokenSource is not null)
47 | _infiniteLoopCancellationTokenSource.Cancel();
48 | }
49 |
50 | public WvBlazorTraceService(IJSRuntime jSRuntime,
51 | IWvBlazorTraceConfigurationService configurationService,
52 | bool triggerQueueProcessing = true)
53 | {
54 | this._jSRuntime = jSRuntime;
55 | this._configuration = configurationService.GetConfiguraion();
56 | if (triggerQueueProcessing)
57 | _processQueue();
58 | }
59 | public Dictionary GetModuleDict()
60 | {
61 | return _moduleDictInternal.Clone();
62 | }
63 | public Dictionary GetSignalDict()
64 | {
65 | return _signalDictInternal.Clone();
66 | }
67 |
68 | public async Task> GetTraceMutes()
69 | {
70 | if (_traceMutesInternal is null)
71 | {
72 | var store = await GetLocalStoreAsync();
73 | _traceMutesInternal = store.MutedTraces ?? new();
74 | }
75 | return _traceMutesInternal.Clone();
76 | }
77 | public void ClearCurrentSession()
78 | {
79 | _moduleDictInternal = new();
80 | _signalDictInternal = new();
81 | }
82 | }
83 |
84 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Styles/index.less:
--------------------------------------------------------------------------------
1 | @import 'wv-trace-button.less';
2 | @import 'wv-trace-modal.less';
3 | @import 'wv-trace-nav.less';
4 |
5 | .animation-keyframes(@name, @from, @to, @anim-selector) {
6 | @keyf: ~"@keyframes @{name} { `'\n'`from ";
7 | @anim: ~"} `'\n'`.@{anim-selector}";
8 |
9 | @{keyf} {
10 | .from(@name,@from);
11 | }
12 |
13 | to {
14 | .to(@name,@to);
15 | }
16 |
17 | @{anim} {
18 | animation-name: @name;
19 | }
20 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Styles/wv-trace-button.less:
--------------------------------------------------------------------------------
1 | .wv-trace-button {
2 | position: fixed;
3 | z-index: 19000;
4 | @button-offset: 50px;
5 | @button-size: 36px;
6 | @button-center-offset: calc(@button-size / -2);
7 |
8 | button {
9 | display: flex;
10 | justify-content: center;
11 | align-items: center;
12 | width: @button-size;
13 | height: @button-size;
14 | /*background: #e11d48;*/
15 | color: white;
16 | border: 1px solid transparent;
17 | box-shadow: 0 0 10px rgba(0,0,0,0.25);
18 |
19 | &:hover {
20 | cursor: pointer;
21 | box-shadow: 0 0 10px rgba(0,0,0,0.5);
22 | }
23 |
24 | svg {
25 | width: 20px;
26 | height: 20px;
27 | position: relative;
28 | }
29 | }
30 |
31 | &.wv-trace-right-top {
32 | right: 0;
33 | top: @button-offset;
34 | }
35 |
36 | &.wv-trace-right-center {
37 | right: 0;
38 | top: 50%;
39 | margin-top: @button-center-offset;
40 | }
41 |
42 | &.wv-trace-right-bottom {
43 | right: 0;
44 | bottom: @button-offset;
45 | }
46 |
47 | &.wv-trace-right-top,
48 | &.wv-trace-right-center,
49 | &.wv-trace-right-bottom {
50 | button {
51 | border-radius: 50% 0 0 50%;
52 |
53 | svg {
54 | top: 1px;
55 | }
56 | }
57 | }
58 |
59 | &.wv-trace-bottom-right {
60 | bottom: 0;
61 | right: @button-offset;
62 | }
63 |
64 | &.wv-trace-bottom-center {
65 | bottom: 0;
66 | left: 50%;
67 | margin-left: @button-center-offset;
68 | }
69 |
70 | &.wv-trace-bottom-left {
71 | bottom: 0;
72 | left: @button-offset;
73 | }
74 |
75 | &.wv-trace-bottom-right,
76 | &.wv-trace-bottom-center,
77 | &.wv-trace-bottom-left {
78 | button {
79 | border-radius: 50% 50% 0 0;
80 |
81 | svg {
82 | top: 1px;
83 | }
84 | }
85 | }
86 |
87 |
88 | &.wv-trace-left-bottom {
89 | left: 0;
90 | bottom: @button-offset;
91 | }
92 |
93 | &.wv-trace-left-center {
94 | left: 0;
95 | top: 50%;
96 | margin-top: @button-center-offset;
97 | }
98 |
99 | &.wv-trace-left-top {
100 | left: 0;
101 | top: @button-offset;
102 | }
103 |
104 | &.wv-trace-left-bottom,
105 | &.wv-trace-left-center,
106 | &.wv-trace-left-top {
107 | button {
108 | border-radius: 0 50% 50% 0;
109 |
110 | svg {
111 | top: 1px;
112 | }
113 | }
114 | }
115 |
116 |
117 | &.wv-trace-top-left {
118 | top: 0;
119 | left: @button-offset;
120 | }
121 |
122 | &.wv-trace-top-center {
123 | top: 0;
124 | left: 50%;
125 | margin-left: @button-center-offset;
126 | }
127 |
128 | &.wv-trace-top-right {
129 | top: 0;
130 | right: @button-offset;
131 | }
132 |
133 | &.wv-trace-top-left,
134 | &.wv-trace-top-center,
135 | &.wv-trace-top-right {
136 | button {
137 | border-radius: 0 0 50% 50%;
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Styles/wv-trace-nav.less:
--------------------------------------------------------------------------------
1 | .wv-trace-nav {
2 | list-style-type: none;
3 | margin: 0;
4 | padding: 0;
5 | overflow: hidden;
6 | @color-accent: #be123c;
7 |
8 | li {
9 | float: left;
10 |
11 | & > a, & > span {
12 | display: flex;
13 | align-items: center;
14 | justify-content: center;
15 | text-align: center;
16 | padding: 0 7px;
17 | text-decoration: none;
18 |
19 | .wv-badge {
20 | margin-left: 5px;
21 | display: inline-flex;
22 | padding: 0px 5px;
23 | background: @color-accent;
24 | color: white;
25 | font-size: 11px;
26 | border-radius: 5px;
27 | }
28 |
29 | svg {
30 | margin-left: 5px;
31 | }
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/TraceView.razor:
--------------------------------------------------------------------------------
1 |
2 | This component is defined in the WebVella.BlazorTrace library.
3 |
4 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Utility/CompressionUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.IO.Compression;
4 | using System.Text;
5 |
6 | namespace WebVella.BlazorTrace;
7 | ///
8 | /// Provides utility methods for compressing and decompressing strings,
9 | /// particularly useful for JSON strings to reduce their size for storage or transmission.
10 | ///
11 | public static class CompressionUtility
12 | {
13 | ///
14 | /// Compresses a given string using GZip compression and returns the compressed data as a Base64 string.
15 | /// This is useful for reducing the size of JSON strings before storing or sending them.
16 | ///
17 | /// The original string (e.g., a JSON string) to compress.
18 | /// A Base64 encoded string representing the compressed data.
19 | /// Thrown if the input string is null.
20 | public static string CompressString(this string jsonString)
21 | {
22 | if (jsonString == null)
23 | {
24 | throw new ArgumentNullException(nameof(jsonString), "The string to compress cannot be null.");
25 | }
26 |
27 | // Convert the string to a byte array using UTF-8 encoding
28 | byte[] originalBytes = Encoding.UTF8.GetBytes(jsonString);
29 |
30 | using (MemoryStream memoryStream = new MemoryStream())
31 | {
32 | // Create a GZipStream to compress the data and write it to the memory stream
33 | using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
34 | {
35 | gzipStream.Write(originalBytes, 0, originalBytes.Length);
36 | } // The GZipStream is closed here, which flushes its buffer to the underlying MemoryStream
37 |
38 | // Get the compressed byte array from the memory stream
39 | byte[] compressedBytes = memoryStream.ToArray();
40 |
41 | // Convert the compressed byte array to a Base64 string for easy storage/transmission
42 | return Convert.ToBase64String(compressedBytes);
43 | }
44 | }
45 |
46 | ///
47 | /// Decompresses a Base64 encoded string that was previously compressed using GZip,
48 | /// and returns the original string (e.g., the original JSON string).
49 | ///
50 | /// The Base64 encoded compressed string to decompress.
51 | /// The original decompressed string.
52 | /// Thrown if the input string is null.
53 | /// Thrown if the input string is not a valid Base64 string.
54 | public static string DecompressString(this string compressedString)
55 | {
56 | if (compressedString == null)
57 | {
58 | throw new ArgumentNullException(nameof(compressedString), "The string to decompress cannot be null.");
59 | }
60 |
61 | // Convert the Base64 string back to a byte array
62 | byte[] compressedBytes = Convert.FromBase64String(compressedString);
63 |
64 | using (MemoryStream memoryStream = new MemoryStream(compressedBytes))
65 | {
66 | // Create a GZipStream to decompress the data from the memory stream
67 | using (GZipStream gzipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
68 | {
69 | // Create a new MemoryStream to hold the decompressed data
70 | using (MemoryStream decompressedStream = new MemoryStream())
71 | {
72 | // Copy the decompressed bytes from the GZipStream to the decompressedStream
73 | gzipStream.CopyTo(decompressedStream);
74 |
75 | // Get the decompressed byte array
76 | byte[] decompressedBytes = decompressedStream.ToArray();
77 |
78 | // Convert the decompressed byte array back to a string using UTF-8 encoding
79 | return Encoding.UTF8.GetString(decompressedBytes);
80 | }
81 | }
82 | }
83 | }
84 |
85 | // Example Usage (for demonstration purposes, typically in a separate Main method or test)
86 | public static void Main(string[] args)
87 | {
88 | string originalJson = "{\"name\": \"John Doe\", \"age\": 30, \"city\": \"New York\", \"occupation\": \"Software Engineer\", \"hobbies\": [\"reading\", \"hiking\", \"coding\"], \"address\": {\"street\": \"123 Main St\", \"zip\": \"10001\"}}";
89 |
90 | Console.WriteLine("Original JSON String Length: " + originalJson.Length);
91 | Console.WriteLine("Original JSON String: " + originalJson);
92 |
93 | // Compress the string
94 | string compressedBase64 = CompressString(originalJson);
95 | Console.WriteLine("\nCompressed (Base64) String Length: " + compressedBase64.Length);
96 | Console.WriteLine("Compressed (Base64) String: " + compressedBase64);
97 |
98 | // Decompress the string
99 | string decompressedJson = DecompressString(compressedBase64);
100 | Console.WriteLine("\nDecompressed JSON String Length: " + decompressedJson.Length);
101 | Console.WriteLine("Decompressed JSON String: " + decompressedJson);
102 |
103 | // Verify if the decompressed string is identical to the original
104 | bool areEqual = originalJson.Equals(decompressedJson);
105 | Console.WriteLine("\nOriginal and Decompressed strings are equal: " + areEqual);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Utility/EnumExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Globalization;
3 | using WebVella.BlazorTrace.Models;
4 |
5 | namespace WebVella.BlazorTrace;
6 |
7 | public static class EnumExtensions
8 | {
9 | public static string WvBTToDescriptionString(this TEnum e) where TEnum : IConvertible
10 | {
11 | string description = "";
12 |
13 | if (e is Enum)
14 | {
15 | Type type = e.GetType();
16 | var name = type.GetEnumName(e.ToInt32(CultureInfo.InvariantCulture));
17 | if (String.IsNullOrWhiteSpace(name)) return description;
18 |
19 | var memInfo = type.GetMember(name);
20 | var soAttributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
21 | if (soAttributes.Length > 0)
22 | {
23 | // we're only getting the first description we find
24 | // others will be ignored
25 | description = ((DescriptionAttribute)soAttributes[0]).Description;
26 | }
27 | }
28 |
29 | return description;
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Utility/WvTraceUtility.Converters.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Runtime.Serialization;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using WebVella.BlazorTrace.Models;
11 |
12 | namespace WebVella.BlazorTrace.Utility;
13 | public static partial class WvTraceUtility
14 | {
15 | public static string WvBTToKilobytesString(this long? bytes)
16 | {
17 | if (bytes == null) return "n/a";
18 |
19 | if (bytes < 0) return "err"; // Handle invalid input
20 | if (bytes == 0) return "0 KB";
21 | if (bytes <= 15) return bytes.ToString() + " bytes";
22 | const double kilobyteFactor = 1024.0;
23 | var kb = Math.Round((double)bytes / kilobyteFactor, 2, MidpointRounding.AwayFromZero);
24 | return kb.ToString() + " KB";
25 | }
26 | public static string WvBTToKilobytesString(this long bytes)
27 | {
28 | if (bytes < 0) return "err"; // Handle invalid input
29 | if (bytes == 0) return "0 KB";
30 | if (bytes <= 15) return bytes.ToString() + " bytes";
31 | const double kilobyteFactor = 1024.0;
32 | var kb = Math.Round((double)bytes / kilobyteFactor, 2, MidpointRounding.AwayFromZero);
33 | return kb.ToString() + " KB";
34 | }
35 | public static string WvBTGetMemoryInfoId(string assemblyFullName, string fieldName)
36 | => $"{assemblyFullName}$$${fieldName}";
37 | public static string WvBTGetFirstRenderString(this bool? firstRender)
38 | {
39 | if (firstRender == null) return "n/a";
40 | if (!firstRender.Value) return "no";
41 | return "yes";
42 | }
43 | public static string WvBTToDurationMSString(this long? duration)
44 | {
45 | if (duration == null) return "n/a";
46 | return $"{duration.Value} ms";
47 | }
48 | public static string WvBTToDurationMSString(this long duration)
49 | {
50 | return $"{duration} ms";
51 | }
52 | public static string GetLimitValueAsString(this long limit, WvTraceSessionLimitType type)
53 | {
54 | switch (type)
55 | {
56 | case WvTraceSessionLimitType.MemoryTotal:
57 | case WvTraceSessionLimitType.MemoryDelta:
58 | return limit.WvBTToKilobytesString();
59 | case WvTraceSessionLimitType.Duration:
60 | return limit.WvBTToDurationMSString();
61 | default:
62 | return limit.ToString();
63 | }
64 | }
65 |
66 | public static string WvBTToTimeString(this DateTimeOffset? timestamp)
67 | {
68 | if (timestamp == null) return "n/a";
69 | return $"{timestamp.Value.ToString(WvConstants.TimestampFormat)} ms";
70 | }
71 | public static string WvBTToTimeString(this DateTimeOffset timestamp)
72 | {
73 | return $"{timestamp.ToString(WvConstants.TimestampFormat)} ms";
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Utility/WvTraceUtility.Info.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Runtime.Serialization;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using WebVella.BlazorTrace.Models;
11 |
12 | namespace WebVella.BlazorTrace.Utility;
13 | public static partial class WvTraceUtility
14 | {
15 | public static WvTraceInfo? GetInfo(this object component, Guid? traceId, string? instanceTag, string methodName)
16 | {
17 | var componentType = component.GetType();
18 | return new WvTraceInfo
19 | {
20 | TraceId = traceId,
21 | MethodName = methodName,
22 | ComponentFullName = componentType.FullName,
23 | ComponentName = (componentType.FullName ?? "").Split(".", StringSplitOptions.RemoveEmptyEntries).LastOrDefault(),
24 | InstanceTag = instanceTag,
25 | ModuleName = componentType?.Module.Name?.Replace(".dll", "")
26 | };
27 | }
28 |
29 | public static WvTraceSessionMethodTrace? GetMatchingOnEnterTrace(this List traceList, Guid? traceId){
30 | var orderedTraceList = traceList.OrderBy(x=> x.EnteredOn);
31 | if(traceId is not null)
32 | return traceList.FirstOrDefault(x =>x.EnteredOn is not null && x.ExitedOn is null && x.TraceId == traceId.Value);
33 |
34 | //any not exited will do
35 | return traceList.FirstOrDefault(x =>x.EnteredOn is not null && x.ExitedOn is null);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Utility/WvTraceUtility.Memory.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Runtime.Serialization;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using WebVella.BlazorTrace.Models;
11 |
12 | namespace WebVella.BlazorTrace.Utility;
13 | public static partial class WvTraceUtility
14 | {
15 | public static long GetSize(this object obj,
16 | List memoryDetails,
17 | WvBlazorTraceConfiguration configuration,
18 | int maxDepth = 5)
19 | {
20 | if (obj == null) return 0;
21 | return MemorySizeCalculator.CalculateComponentMemorySize(
22 | component: obj,
23 | memoryDetails: memoryDetails,
24 | configuration: configuration,
25 | maxDepth: maxDepth
26 | );
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/Utility/WvTraceUtility.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Runtime.Serialization;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using WebVella.BlazorTrace.Models;
11 |
12 | namespace WebVella.BlazorTrace.Utility;
13 | public static partial class WvTraceUtility
14 | {
15 | public static void ConsoleLog(string message)
16 | {
17 | #if DEBUG
18 | Console.WriteLine($"$$$$$$ [{DateTime.Now.ToString("HH:mm:ss:ffff")}] =>{message} ");
19 | #endif
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/WebVella.BlazorTrace.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0;net9.0
5 | enable
6 | enable
7 | WebVella.BlazorTrace
8 | 1.0.6
9 | WebVella
10 | WebVella
11 | Easy to plugin library for tracing most common problems when building a Blazor application like unnecessary renders, memory leaks, slow components
12 | WebVella 2025
13 | https://github.com/WebVella/WebVella.BlazorTrace
14 | README.md
15 | https://github.com/WebVella/WebVella.BlazorTrace
16 | git
17 | blazor,trace,component,memory,execution time, duration
18 | Initial release
19 | LICENSE
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Always
34 |
35 |
36 |
37 |
38 |
39 | Always
40 |
41 |
42 |
43 |
44 |
45 |
46 | True
47 | \
48 |
49 |
50 | True
51 | \
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/WebVella.BlazorTrace.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.13.36105.23
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebVella.BlazorTrace", "WebVella.BlazorTrace.csproj", "{17B69929-6020-4C11-9300-16186BBE2B71}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebVella.BlazorTrace.Site", "..\..\site\WebVella.BlazorTrace.Site\WebVella.BlazorTrace.Site.csproj", "{46488E6F-6DDB-4582-9CF1-E30C7F37A71D}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebVella.BlazorTrace.Tests", "..\..\tests\WebVella.BlazorTrace.Tests\WebVella.BlazorTrace.Tests.csproj", "{AD3ED490-7A62-46E3-82E7-D5BB833281E2}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {17B69929-6020-4C11-9300-16186BBE2B71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {17B69929-6020-4C11-9300-16186BBE2B71}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {17B69929-6020-4C11-9300-16186BBE2B71}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {17B69929-6020-4C11-9300-16186BBE2B71}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {46488E6F-6DDB-4582-9CF1-E30C7F37A71D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {46488E6F-6DDB-4582-9CF1-E30C7F37A71D}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {46488E6F-6DDB-4582-9CF1-E30C7F37A71D}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {46488E6F-6DDB-4582-9CF1-E30C7F37A71D}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {AD3ED490-7A62-46E3-82E7-D5BB833281E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {AD3ED490-7A62-46E3-82E7-D5BB833281E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {AD3ED490-7A62-46E3-82E7-D5BB833281E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {AD3ED490-7A62-46E3-82E7-D5BB833281E2}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {20F00A6F-D9E2-477C-955D-8AB6103417B0}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/WvConstants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace WebVella.BlazorTrace;
8 | public static class WvConstants
9 | {
10 | public const string TimestampFormat = "HH:mm:ss ffff";
11 | }
12 |
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/compilerconfig.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "outputFile": "styles.css",
4 | "inputFile": "Styles/index.less"
5 | }
6 | ]
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/compilerconfig.json.defaults:
--------------------------------------------------------------------------------
1 | {
2 | "compilers": {
3 | "less": {
4 | "autoPrefix": "",
5 | "cssComb": "none",
6 | "ieCompat": true,
7 | "strictMath": false,
8 | "strictUnits": false,
9 | "relativeUrls": true,
10 | "rootPath": "",
11 | "sourceMapRoot": "",
12 | "sourceMapBasePath": "",
13 | "sourceMap": false
14 | },
15 | "sass": {
16 | "autoPrefix": "",
17 | "includePath": "",
18 | "indentType": "space",
19 | "indentWidth": 2,
20 | "outputStyle": "nested",
21 | "Precision": 5,
22 | "relativeUrls": true,
23 | "sourceMapRoot": "",
24 | "lineFeed": "",
25 | "sourceMap": false
26 | },
27 | "stylus": {
28 | "sourceMap": false
29 | },
30 | "babel": {
31 | "sourceMap": false
32 | },
33 | "coffeescript": {
34 | "bare": false,
35 | "runtimeMode": "node",
36 | "sourceMap": false
37 | },
38 | "handlebars": {
39 | "root": "",
40 | "noBOM": false,
41 | "name": "",
42 | "namespace": "",
43 | "knownHelpersOnly": false,
44 | "forcePartial": false,
45 | "knownHelpers": [],
46 | "commonjs": "",
47 | "amd": false,
48 | "sourceMap": false
49 | }
50 | },
51 | "minifiers": {
52 | "css": {
53 | "enabled": true,
54 | "termSemicolons": true,
55 | "gzip": false
56 | },
57 | "javascript": {
58 | "enabled": true,
59 | "termSemicolons": true,
60 | "gzip": false
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/src/WebVella.BlazorTrace/scripts.js:
--------------------------------------------------------------------------------
1 | window.WebVellaBlazorTrace = {
2 | escapeKeyEventListeners: {},
3 | escapeKeyEventListenerQueue: [],
4 | f1KeyEventListener: null,
5 | inited: false,
6 | initKeyListeners: function () {
7 | document.addEventListener("keydown", function (evtobj) {
8 | if (evtobj.code === "Escape") {
9 | if (!WebVellaBlazorTrace.escapeKeyEventListenerQueue || WebVellaBlazorTrace.escapeKeyEventListenerQueue.length == 0) return;
10 | evtobj.preventDefault();
11 | evtobj.stopPropagation();
12 | WebVellaBlazorTrace.executeEscapeKeyEventCallbacks(evtobj);
13 | }
14 | if (evtobj.code === "F1") {
15 | if (!WebVellaBlazorTrace.f1KeyEventListener) return;
16 | evtobj.preventDefault();
17 | evtobj.stopPropagation();
18 | WebVellaBlazorTrace.executeF1KeyEventCallbacks(evtobj);
19 | }
20 | });
21 | WebVellaBlazorTrace.inited = true;
22 | },
23 | addEscapeKeyEventListener: function (dotNetHelper, listenerId, methodName) {
24 | if (!WebVellaBlazorTrace.inited) {
25 | WebVellaBlazorTrace.initKeyListeners();
26 | }
27 | WebVellaBlazorTrace.escapeKeyEventListeners[listenerId] = { dotNetHelper: dotNetHelper, methodName: methodName };
28 | WebVellaBlazorTrace.escapeKeyEventListenerQueue.push(listenerId);
29 | return true;
30 | },
31 | executeEscapeKeyEventCallbacks: function (eventData) {
32 | if (WebVellaBlazorTrace.escapeKeyEventListenerQueue && WebVellaBlazorTrace.escapeKeyEventListenerQueue.length > 0) {
33 | var lastRegisteredListenerId = WebVellaBlazorTrace.escapeKeyEventListenerQueue[WebVellaBlazorTrace.escapeKeyEventListenerQueue.length - 1];
34 | const dotNetHelper = WebVellaBlazorTrace.escapeKeyEventListeners[lastRegisteredListenerId].dotNetHelper;
35 | const methodName = WebVellaBlazorTrace.escapeKeyEventListeners[lastRegisteredListenerId].methodName;
36 | if (dotNetHelper && methodName) {
37 | dotNetHelper.invokeMethodAsync(methodName, eventData.code);
38 | }
39 | }
40 | return true;
41 | },
42 | removeEscapeKeyEventListener: function (listenerId) {
43 | if (WebVellaBlazorTrace.escapeKeyEventListeners && WebVellaBlazorTrace.escapeKeyEventListeners[listenerId]) {
44 | delete WebVellaBlazorTrace.escapeKeyEventListeners[listenerId];
45 | WebVellaBlazorTrace.escapeKeyEventListenerQueue = WebVellaBlazorTrace.escapeKeyEventListenerQueue.filter(x => x != listenerId);
46 | }
47 | return true;
48 | },
49 |
50 | addF1KeyEventListener: function (dotNetHelper, methodName) {
51 | if (!WebVellaBlazorTrace.inited) {
52 | WebVellaBlazorTrace.initKeyListeners();
53 | }
54 | WebVellaBlazorTrace.f1KeyEventListener = { dotNetHelper: dotNetHelper, methodName: methodName };
55 | return true;
56 | },
57 | executeF1KeyEventCallbacks: function (eventData) {
58 | if (WebVellaBlazorTrace.f1KeyEventListener) {
59 | const dotNetHelper = WebVellaBlazorTrace.f1KeyEventListener.dotNetHelper;
60 | const methodName = WebVellaBlazorTrace.f1KeyEventListener.methodName;
61 | if (dotNetHelper && methodName) {
62 | dotNetHelper.invokeMethodAsync(methodName, eventData.code);
63 | }
64 | }
65 | return true;
66 | },
67 | removeF1KeyEventListener: function () {
68 | if (WebVellaBlazorTrace.f1KeyEventListener) {
69 | WebVellaBlazorTrace.f1KeyEventListener = null;
70 | }
71 | return true;
72 | }
73 | }
74 |
75 | document.addEventListener("DOMContentLoaded", function () {
76 | WebVellaBlazorTrace.init();
77 | });
--------------------------------------------------------------------------------
/tests/WebVella.BlazorTrace.Tests/Models/TestComponent.cs:
--------------------------------------------------------------------------------
1 | using Bunit;
2 | using Microsoft.AspNetCore.Components;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Microsoft.JSInterop;
5 | using Moq;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace WebVella.BlazorTrace.Tests;
13 | public class TestComponent : ComponentBase
14 | {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/tests/WebVella.BlazorTrace.Tests/WebVella.BlazorTrace.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0;net9.0
5 | enable
6 | enable
7 | false
8 |
9 |
10 |
11 |
12 |
13 | all
14 | runtime; build; native; contentfiles; analyzers; buildtransitive
15 |
16 |
17 |
18 |
19 | all
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/tests/WebVella.BlazorTrace.Tests/WvBlazorTraceService/WvBlazorTraceServiceTests.Limits.cs:
--------------------------------------------------------------------------------
1 | using WebVella.BlazorTrace.Models;
2 |
3 | namespace WebVella.BlazorTrace.Tests;
4 |
5 | public partial class WvBlazorTraceServiceTests : BaseTest
6 | {
7 |
8 | [Fact]
9 | public void LimitDuration1()
10 | {
11 | lock (_locker)
12 | {
13 | //given
14 | var options = new WvTraceMethodOptions {
15 | DurationLimitMS = 1
16 | };
17 | var firstRender = true;
18 | var moduleName = "WebVella.BlazorTrace.Tests";
19 | var componentName = "TestComponent";
20 | var componentFullName = moduleName + "." + componentName;
21 | var methodName = "SlowMethod";
22 | var traceId = Guid.NewGuid();
23 | var instanceTag = Guid.NewGuid().ToString();
24 | var customData = Guid.NewGuid().ToString();
25 | //when
26 | WvBlazorTraceServiceMock.Object.OnEnter(
27 | component: Component,
28 | traceId: traceId,
29 | options: options,
30 | firstRender: firstRender,
31 | instanceTag: instanceTag,
32 | customData: customData,
33 | methodName: methodName
34 | );
35 | Thread.Sleep(5);
36 | WvBlazorTraceServiceMock.Object.OnExit(
37 | component: Component,
38 | traceId: traceId,
39 | options: options,
40 | firstRender: firstRender,
41 | instanceTag: instanceTag,
42 | customData: customData,
43 | methodName: methodName
44 | );
45 |
46 | //than
47 | var queue = WvBlazorTraceServiceMock.Object.GetQueue();
48 | Assert.NotEmpty(queue);
49 | WvBlazorTraceServiceMock.Object.ForceProcessQueue();
50 | var (method,trace) = CheckTraceExists(
51 | moduleDict: WvBlazorTraceServiceMock.Object.GetModuleDict(),
52 | moduleName: moduleName,
53 | componentFullName: componentFullName,
54 | componentName: componentName,
55 | instanceTag: instanceTag,
56 | methodName: methodName,
57 | traceId: traceId
58 | );
59 | Assert.Single(method.LimitHits);
60 | var limitHit = method.LimitHits.First();
61 | Assert.Equal(WvTraceSessionLimitType.Duration,limitHit.Type);
62 | Assert.Equal(options.DurationLimitMS,limitHit.Limit);
63 | Assert.False(limitHit.IsOnEnter);
64 | }
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/tests/WebVella.BlazorTrace.Tests/WvBlazorTraceService/WvBlazorTraceServiceTests.MethodCalls.cs:
--------------------------------------------------------------------------------
1 | using WebVella.BlazorTrace.Models;
2 |
3 | namespace WebVella.BlazorTrace.Tests;
4 |
5 | public partial class WvBlazorTraceServiceTests : BaseTest
6 | {
7 |
8 | [Fact]
9 | public void OnEnterTestBaseCalls()
10 | {
11 | lock (_locker)
12 | {
13 | //given
14 | var options = new WvTraceMethodOptions { };
15 | var firstRender = true;
16 | var moduleName = "WebVella.BlazorTrace.Tests";
17 | var componentName = "TestComponent";
18 | var componentFullName = moduleName + "." + componentName;
19 | var methodsList = new List{
20 | "OnInitialized","OnInitializedAsync",
21 | "OnParametersSet","OnParametersSetAsync",
22 | "OnAfterRender","OnAfterRenderAsync",
23 | "ShouldRender",
24 | "Dispose","DisposeAsync",
25 | "OnEnterTestOther","OnEnterTestOtherAsync"
26 | };
27 |
28 | foreach (var methodName in methodsList)
29 | {
30 | var traceId = Guid.NewGuid();
31 | var instanceTag = Guid.NewGuid().ToString();
32 | var customData = Guid.NewGuid().ToString();
33 | //when
34 | Action action = () => WvBlazorTraceServiceMock.Object.OnEnter(
35 | component: Component,
36 | traceId: traceId,
37 | options: options,
38 | firstRender: firstRender,
39 | instanceTag: instanceTag,
40 | customData: customData,
41 | methodName: methodName
42 | );
43 | var ex = Record.Exception(action);
44 | Assert.Null(ex);
45 | //than
46 | var queue = WvBlazorTraceServiceMock.Object.GetQueue();
47 | Assert.NotEmpty(queue);
48 | WvBlazorTraceServiceMock.Object.ForceProcessQueue();
49 | var (method, trace) = CheckTraceExists(
50 | moduleDict: WvBlazorTraceServiceMock.Object.GetModuleDict(),
51 | moduleName: moduleName,
52 | componentFullName: componentFullName,
53 | componentName: componentName,
54 | instanceTag: instanceTag,
55 | methodName: methodName,
56 | traceId: traceId
57 | );
58 | Assert.NotNull(trace.EnteredOn);
59 | Assert.NotNull(trace.OnEnterOptions);
60 | Assert.Null(trace.ExitedOn);
61 | }
62 | }
63 | }
64 |
65 | [Fact]
66 | public void OnExitTestBaseCalls()
67 | {
68 | lock (_locker)
69 | {
70 | //given
71 | var options = new WvTraceMethodOptions { };
72 | var firstRender = true;
73 | var moduleName = "WebVella.BlazorTrace.Tests";
74 | var componentName = "TestComponent";
75 | var componentFullName = moduleName + "." + componentName;
76 | var methodsList = new List{
77 | "OnInitialized","OnInitializedAsync",
78 | "OnParametersSet","OnParametersSetAsync",
79 | "OnAfterRender","OnAfterRenderAsync",
80 | "ShouldRender",
81 | "Dispose","DisposeAsync",
82 | "OnEnterTestOther","OnEnterTestOtherAsync"
83 | };
84 | foreach (var methodName in methodsList)
85 | {
86 | var traceId = Guid.NewGuid();
87 | var instanceTag = Guid.NewGuid().ToString();
88 | var customData = Guid.NewGuid().ToString();
89 | //when
90 | Action action = () => WvBlazorTraceServiceMock.Object.OnExit(
91 | component: Component,
92 | traceId: traceId,
93 | options: options,
94 | firstRender: firstRender,
95 | instanceTag: instanceTag,
96 | customData: customData,
97 | methodName: methodName
98 | );
99 | var ex = Record.Exception(action);
100 | Assert.Null(ex);
101 | //than
102 | var queue = WvBlazorTraceServiceMock.Object.GetQueue();
103 | Assert.NotEmpty(queue);
104 | WvBlazorTraceServiceMock.Object.ForceProcessQueue();
105 | var (method, trace) = CheckTraceExists(
106 | moduleDict: WvBlazorTraceServiceMock.Object.GetModuleDict(),
107 | moduleName: moduleName,
108 | componentFullName: componentFullName,
109 | componentName: componentName,
110 | instanceTag: instanceTag,
111 | methodName: methodName,
112 | traceId: traceId
113 | );
114 | Assert.Null(trace.EnteredOn);
115 | Assert.NotNull(trace.ExitedOn);
116 | Assert.NotNull(trace.OnExitOptions);
117 | }
118 | }
119 | }
120 |
121 | [Fact]
122 | public void SignalTestBaseCalls()
123 | {
124 | lock (_locker)
125 | {
126 | //given
127 | var options = new WvTraceSignalOptions { };
128 | var moduleName = "WebVella.BlazorTrace.Tests";
129 | var signalName = "test-signal";
130 | var componentName = "TestComponent";
131 | var componentFullName = moduleName + "." + componentName;
132 | var methodName = "CustomMethod";
133 |
134 | var traceId = Guid.NewGuid();
135 | var instanceTag = Guid.NewGuid().ToString();
136 | var customData = Guid.NewGuid().ToString();
137 | //when
138 | Action action = () => WvBlazorTraceServiceMock.Object.OnSignal(
139 | caller: Component,
140 | signalName: signalName,
141 | instanceTag: instanceTag,
142 | customData: customData,
143 | options: options,
144 | methodName: methodName
145 | );
146 | var ex = Record.Exception(action);
147 | Assert.Null(ex);
148 | //than
149 | var queue = WvBlazorTraceServiceMock.Object.GetQueue();
150 | Assert.NotEmpty(queue);
151 | WvBlazorTraceServiceMock.Object.ForceProcessQueue();
152 | var (method, trace) = CheckSignalTraceExists(
153 | signalDict: WvBlazorTraceServiceMock.Object.GetSignalDict(),
154 | moduleName: moduleName,
155 | signalName : signalName,
156 | componentFullName: componentFullName,
157 | instanceTag: instanceTag,
158 | methodName: methodName
159 | );
160 | Assert.NotNull(trace.SendOn);
161 | Assert.NotNull(trace.Options);
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/tests/WebVella.BlazorTrace.Tests/WvBlazorTraceService/WvBlazorTraceServiceTests.Modal.cs:
--------------------------------------------------------------------------------
1 | using WebVella.BlazorTrace.Models;
2 | using WebVella.BlazorTrace.Utility;
3 | namespace WebVella.BlazorTrace.Tests;
4 |
5 | public partial class WvBlazorTraceServiceTests : BaseTest
6 | {
7 |
8 | [Fact]
9 | public void TraceRowGenerationSameSnapshot()
10 | {
11 | lock (_locker)
12 | {
13 | //given
14 | var primarySN = GetSnapshot();
15 | var mutedTraces = new List();
16 | var pins = new List();
17 |
18 | //when
19 | var result = new List();
20 | Action action = () => result = primarySN.GenerateMethodTraceRows(primarySN, mutedTraces,pins);
21 | var ex = Record.Exception(action);
22 | Assert.Null(ex);
23 | Assert.Single(result);
24 | var trRow = CheckTraceRowExists(
25 | traceRows: result,
26 | moduleName: ModuleName,
27 | componentFullName: ComponentFullName,
28 | componentName: ComponentName,
29 | instanceTag: InstanceTag,
30 | methodName: MethodName
31 | );
32 | Assert.Single(trRow.TraceList);
33 | Assert.NotNull(trRow.MethodComparison);
34 | Assert.Equal(0, trRow.MethodComparison.TraceListChange);
35 | Assert.Equal(0, trRow.MethodComparison.LastDurationChangeMS);
36 |
37 | Assert.NotNull(trRow.MemoryComparison);
38 | Assert.Equal(0, trRow.MemoryComparison.LastMemoryChangeBytes);
39 | }
40 | }
41 |
42 | [Fact]
43 | public void TraceRowGenerationSnapshotComparison()
44 | {
45 | lock (_locker)
46 | {
47 | //given
48 | var primarySN = GetSnapshot();
49 | var secondarySN = GetSnapshot();
50 | secondarySN.Id = Guid.NewGuid();
51 | secondarySN.Name = "secondary";
52 | var secondaryMethod = secondarySN.ModuleDict[ModuleName]
53 | .ComponentDict[ComponentFullName]
54 | .TaggedInstances[0]
55 | .OnInitialized;
56 | secondaryMethod.TraceList.Add(new WvTraceSessionMethodTrace
57 | {
58 | TraceId = Guid.NewGuid(),
59 | OnEnterCustomData = OnEnterCustomData,
60 | OnExitCustomData = OnEnterCustomData,
61 | EnteredOn = TimeStamp.AddSeconds(30),
62 | ExitedOn = TimeStamp2.AddSeconds(30).AddMilliseconds(DelayMS),
63 | OnEnterFirstRender = FirstRender,
64 | OnExitFirstRender = FirstRender,
65 | OnEnterMemoryBytes = MemoryBytes,
66 | OnEnterMemoryInfo = new List{
67 | new WvTraceMemoryInfo{
68 | AssemblyName = ModuleName,
69 | FieldName = FieldName,
70 | Size = MemoryBytes
71 | }
72 | },
73 | OnExitMemoryBytes = MemoryBytes + ExtraMemoryBytes,
74 | OnExitMemoryInfo = new List{
75 | new WvTraceMemoryInfo{
76 | AssemblyName = ModuleName,
77 | FieldName = FieldName,
78 | Size = MemoryBytes + ExtraMemoryBytes
79 | }
80 | },
81 | OnEnterOptions = MethodOptions,
82 | OnExitOptions = MethodOptions
83 | });
84 | var mutedTraces = new List();
85 | var pins = new List();
86 | //when
87 | var result = new List();
88 | Action action = () => result = primarySN.GenerateMethodTraceRows(secondarySN, mutedTraces, pins);
89 | var ex = Record.Exception(action);
90 | Assert.Null(ex);
91 | Assert.Single(result);
92 | var trRow = CheckTraceRowExists(
93 | traceRows: result,
94 | moduleName: ModuleName,
95 | componentFullName: ComponentFullName,
96 | componentName: ComponentName,
97 | instanceTag: InstanceTag,
98 | methodName: MethodName
99 | );
100 | Assert.Equal(2, trRow.TraceList.Count);
101 | Assert.Equal(MemoryBytes + ExtraMemoryBytes, trRow.LastMemoryBytes);
102 | Assert.Equal(DelayMS * 2, trRow.LastDurationMS);
103 | Assert.NotNull(trRow.MethodComparison);
104 | Assert.Equal(1, trRow.MethodComparison.TraceListChange);
105 | Assert.Equal(DelayMS, trRow.MethodComparison.LastDurationChangeMS);
106 |
107 | Assert.NotNull(trRow.MemoryComparison);
108 | Assert.Equal(ExtraMemoryBytes, trRow.MemoryComparison.LastMemoryChangeBytes);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------