-
Notifications
You must be signed in to change notification settings - Fork 1.9k
[v3] Add Diagnostics Metrics Tracking to MAUI Applications #31058
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a comprehensive diagnostics and metrics tracking system for .NET MAUI applications, focusing on layout performance monitoring with an extensible architecture for future observability needs. The implementation provides zero-allocation instrumentation for layout operations with proper feature switches for AOT/trimming scenarios.
Key changes include:
- Core diagnostics infrastructure with ActivitySource and Metrics tracking for "Microsoft.Maui"
- Layout performance instrumentation for
IView.Measure()
andIView.Arrange()
operations - Extensible plugin system through
IDiagnosticTagger
,IDiagnosticMetrics
, andIDiagnosticInstrumentation
interfaces
Reviewed Changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
RuntimeFeature.cs | Adds feature switch for System.Diagnostics.Metrics.Meter support |
MauiAppBuilder.cs | Integrates diagnostics configuration into MAUI app startup |
MauiDiagnostics.cs | Core diagnostics hub managing ActivitySource, Meter, and plugin coordination |
MauiDiagnosticsExtensions.cs | Extension methods for diagnostics registration and IView integration |
ViewDiagnosticTagger.cs | Base tagger adding element.type tags for all IView instances |
ControlsViewDiagnosticTagger.cs | Controls-specific tagger adding Element and VisualElement property tags |
Layout*Instrumentation.cs | Zero-allocation struct instrumentation for measure/arrange operations |
LayoutDiagnosticMetrics.cs | Layout-specific metrics definitions with counters and histograms |
DiagnosticInstrumentation.cs | Factory for creating layout instrumentation instances |
IDiagnostic*.cs | Plugin interfaces for taggers, metrics, and instrumentation |
VisualElement.cs | Adds instrumentation calls to IView.Measure() and IView.Arrange() implementations |
AppHostBuilderExtensions.cs | Registers Controls-specific diagnostics during setup |
MauiControlsDiagnosticsExtensions.cs | Controls layer diagnostics configuration |
MauiProgram.cs | Sample implementation showing ActivityListener and MeterListener usage |
This comment was marked as outdated.
This comment was marked as outdated.
Context: https://github.com/jonathanpeppers/MauiAspireWithTelemetry/tree/peppers Context: dotnet/maui#31058 We are in the process of adding `Metrics` to .NET MAUI to enable `dotnet-counters` such as: > dotnet-counters monitor --dsrouter android --counters Microsoft.Maui Press p to pause, r to resume, q to quit. Status: Running Name Current Value [Microsoft.Maui] maui.layout.arrange_count ({times}) 6 maui.layout.arrange_duration (ns) Percentile 50 518,656 95 2,367,488 99 2,367,488 maui.layout.measure_count ({times}) 11 maui.layout.measure_duration (ns) Percentile 50 389,632 95 28,475,392 99 28,475,392 For this to work, you'd unfortunately need to build the app with: dotnet build -c Release -p:EnableDiagnostics=true -p:MetricsSupport=true -p:EventSourceSupport=true That's way too many properties to mess with! So, we should make the defaults: * For `Release` mode, `$(Optimize)` is `true`. * Only if `$(AndroidEnableProfiler)` and `$(EnableDiagnostics)` are not `true`, then: * `$(MetricsSupport)` is `false`. * `$(EventSourceSupport)` is `false`. I also refactored other properties that default to `false` in Release mode by checking the `$(Optimize)` property.
|
Context: https://github.com/jonathanpeppers/MauiAspireWithTelemetry/tree/peppers Context: dotnet/maui#31058 We are in the process of adding `Metrics` to .NET MAUI to enable `dotnet-counters` such as: > dotnet-counters monitor --dsrouter android --counters Microsoft.Maui Press p to pause, r to resume, q to quit. Status: Running Name Current Value [Microsoft.Maui] maui.layout.arrange_count ({times}) 6 maui.layout.arrange_duration (ns) Percentile 50 518,656 95 2,367,488 99 2,367,488 maui.layout.measure_count ({times}) 11 maui.layout.measure_duration (ns) Percentile 50 389,632 95 28,475,392 99 28,475,392 For this to work, you'd unfortunately need to build the app with: dotnet build -c Release -p:EnableDiagnostics=true -p:MetricsSupport=true -p:EventSourceSupport=true That's way too many properties to mess with! So, we should make the defaults: * For `Release` mode, `$(Optimize)` is `true`. * Only if `$(AndroidEnableProfiler)` and `$(EnableDiagnostics)` are not `true`, then: * `$(MetricsSupport)` is `false`. * `$(EventSourceSupport)` is `false`. I also refactored other properties that default to `false` in Release mode by checking the `$(Optimize)` property.
Context: https://github.com/jonathanpeppers/MauiAspireWithTelemetry/tree/peppers Context: dotnet/maui#31058 We are in the process of adding `Metrics` to .NET MAUI to enable `dotnet-counters` such as: > dotnet-counters monitor --dsrouter android --counters Microsoft.Maui Press p to pause, r to resume, q to quit. Status: Running Name Current Value [Microsoft.Maui] maui.layout.arrange_count ({times}) 6 maui.layout.arrange_duration (ns) Percentile 50 518,656 95 2,367,488 99 2,367,488 maui.layout.measure_count ({times}) 11 maui.layout.measure_duration (ns) Percentile 50 389,632 95 28,475,392 99 28,475,392 For this to work, you'd unfortunately need to build the app with: dotnet build -c Release -p:EnableDiagnostics=true -p:MetricsSupport=true -p:EventSourceSupport=true That's way too many properties to mess with! So, we should make the defaults: * For `Release` mode, `$(Optimize)` is `true`. * Only if `$(AndroidEnableProfiler)` and `$(EnableDiagnostics)` are not `true`, then: * `$(MetricsSupport)` is `false`. * `$(EventSourceSupport)` is `false`. I also refactored other properties that default to `false` in Release mode by checking the `$(Optimize)` property.
…icsSupport'. Context: dotnet/maui#31058 Context: dotnet/android#10388 We are in the process of adding `Metrics` to .NET MAUI to enable `dotnet-counters` such as: > dotnet-counters monitor --dsrouter ios --counters Microsoft.Maui Press p to pause, r to resume, q to quit. Status: Running Name Current Value [Microsoft.Maui] maui.layout.arrange_count ({times}) 6 maui.layout.arrange_duration (ns) Percentile 50 518,656 95 2,367,488 99 2,367,488 maui.layout.measure_count ({times}) 11 maui.layout.measure_duration (ns) Percentile 50 389,632 95 28,475,392 99 28,475,392 For this to work, you'd unfortunately need to build the app with: dotnet build -c Release -p:EnableDiagnostics=true -p:MetricsSupport=true -p:EventSourceSupport=true That's way too many properties to mess with! So, we should make the defaults: * For `Release` mode, `$(Optimize)` is `true`. * Only if `$(EnableDiagnostics)` is not `true`, then: * `$(MetricsSupport)` is `false`. * `$(EventSourceSupport)` is `false`.
…icsSupport'. (#23543) Context: dotnet/maui#31058 Context: dotnet/android#10388 We are in the process of adding `Metrics` to .NET MAUI to enable `dotnet-counters` such as: > dotnet-counters monitor --dsrouter ios --counters Microsoft.Maui Press p to pause, r to resume, q to quit. Status: Running Name Current Value [Microsoft.Maui] maui.layout.arrange_count ({times}) 6 maui.layout.arrange_duration (ns) Percentile 50 518,656 95 2,367,488 99 2,367,488 maui.layout.measure_count ({times}) 11 maui.layout.measure_duration (ns) Percentile 50 389,632 95 28,475,392 99 28,475,392 For this to work, you'd unfortunately need to build the app with: dotnet build -c Release -p:EnableDiagnostics=true -p:MetricsSupport=true -p:EventSourceSupport=true That's way too many properties to mess with! So, we should make the defaults: * For `Release` mode, `$(Optimize)` is `true`. * Only if `$(EnableDiagnostics)` is not `true`, then: * `$(MetricsSupport)` is `false`. * `$(EventSourceSupport)` is `false`.
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description of Change
Note
This is an alternate version #30130 and #31049 with just the core tracking features.
This PR introduces comprehensive diagnostics and metrics tracking for .NET MAUI applications, focusing on layout performance monitoring with an extensible architecture for future observability needs.
🎯 What This Adds
Core Diagnostics Infrastructure:
"Microsoft.Maui"
- Tracks layout operations with detailed timing"Microsoft.Maui"
- Records counters and histograms for performance analysisSystem.Diagnostics.Metrics.Meter.IsSupported
- Runtime enable/disable for AOT/trimmingLayout Performance Tracking:
IView.Measure()
andIView.Arrange()
operationsusing
pattern📊 Metrics Collected
maui.layout.measure_count
maui.layout.measure_duration
maui.layout.arrange_count
maui.layout.arrange_duration
🏷️ Diagnostic Tags
All Views:
element.type
- Full type nameControls (Element/VisualElement):
element.id
,element.automation_id
,element.class_id
,element.style_id
element.class
,element.frame
🔌 Extensibility Interfaces
The diagnostics system provides three key interfaces for extensibility:
IDiagnosticTagger
Purpose: Add contextual tags to activities and metrics
IDiagnosticMetrics
Purpose: Define domain-specific metrics collections
MauiDiagnostics.GetMetrics<T>()
IDiagnosticInstrumentation
Purpose: Represent a single diagnostic measurement session
using
statement pattern for zero-overhead tracking🔧 Architecture
Extensible Plugin System:
Usage in VisualElement:
📝 Custom Instrumentation Example
Here's how to extend the system with custom navigation metrics:
This pattern enables teams to add domain-specific observability (navigation, data binding, network requests, etc.) while leveraging the shared infrastructure.
Other Examples
Simple Activities
We can just fire off activities without complex things:
Or, if we want the default tags:
Simple Meters
Very Simple Metrics (Not Great)
Because the meter instance caches the particular counter, we can always just fetch. Not great, but it will work.
Instrumentation without Activity but persisted Meter (Bit Heavy)
Instrumentation with Activity (Bit Heavy)
⚡ Performance
🗂️ Files Added
Core Infrastructure:
src/Core/src/Diagnostics/IDiagnostic*.cs
- Plugin interfacesLayout Instrumentation:
src/Core/src/Diagnostics/Instrumentation/Layout*.cs
- Layout-specific trackingTagging System:
This provides a solid foundation for MAUI observability that teams can extend for their specific monitoring needs while maintaining excellent performance characteristics.
Issues Fixed
Fixes #28091