API Review: Diagnostic Monitor API#5565
API Review: Diagnostic Monitor API#5565chetanpandey1266 wants to merge 1 commit intouser/chetanpandey/DiagnosticMonitorAPIfrom
Conversation
shrinaths
left a comment
There was a problem hiding this comment.
Prose, Grammar, and Voice Review
Line-by-line pass focused on grammar, tone, and narrative voice consistency. Suggested corrections are inline below. The overall prose quality is good — these are polish items to bring the spec to Microsoft documentation standard.
| instances and profiles within an environment. Existing APIs such as | ||
| `ServerCertificateErrorDetected` are per-WebView or per-profile, | ||
| interactive (they expect a response), and each has its own event | ||
| shape. |
There was a problem hiding this comment.
Prose: Broken parallelism + verify API name
The subject shifts from “APIs” (plural) to “each” mid-list, breaking parallel structure. Also, please verify ServerCertificateErrorDetected is the exact API name — it may be ServerCertificateErrorReceived in the current SDK.
Suggested correction:
instances and profiles within an environment. Existing APIs such as
`ServerCertificateErrorDetected` are per-WebView or per-profile
and interactive (they expect a response); each has its own event
shape.
| The Diagnostic Monitor API introduces an observation-only monitor | ||
| object that delivers diagnostic signals from all layers — WebView, | ||
| Profile, and Environment — through a single `DiagnosticReceived` | ||
| event. Host apps create a monitor from the environment and opt in | ||
| per category using `AddDiagnosticReceivedFilter`. |
There was a problem hiding this comment.
Prose: Person shift (3rd person here vs 2nd person in Description)
This paragraph uses third person (“Host apps create a monitor”) but the Description section that follows switches to second person (“You create...”). Pick one voice consistently. Microsoft docs standard is 2nd person for narrative.
Suggested correction:
The Diagnostic Monitor API introduces an observation-only monitor
object that delivers diagnostic signals from all layers — WebView,
Profile, and Environment — through a single DiagnosticReceived
event. You create a monitor from the environment and opt in per
category using AddDiagnosticReceivedFilter.
| JSON details to your telemetry backend. | ||
| * **Targeted monitoring** — filter to specific error codes, HTTP | ||
| methods, or profile names using the JSON filter. | ||
| * **Multiple consumers** — create separate monitors for telemetry | ||
| and a debug panel, each with independent filters. |
There was a problem hiding this comment.
Prose: Capitalize first word after em dash
Per Microsoft style guidelines, capitalize the first word after the em dash since these are standalone imperative sentences.
Suggested correction:
* **Telemetry** — Subscribe to all network errors and forward the
JSON details to your telemetry backend.
* **Targeted monitoring** — Filter to specific error codes, HTTP
methods, or profile names using the JSON filter.
* **Multiple consumers** — Create separate monitors for telemetry
and a debug panel, each with independent filters.
| restrict which events are delivered. An empty JSON `"{}"` receives | ||
| all events in that category. A non-empty JSON applies field-level | ||
| matching. Calling the method again for the same category replaces |
There was a problem hiding this comment.
Prose: “JSON” is not a countable noun
“An empty JSON” and “A non-empty JSON” are grammatically incorrect. JSON is a format/notation, not a countable object.
Suggested correction:
You can pass a JSON object to AddDiagnosticReceivedFilter to
restrict which events are delivered. An empty JSON object ("{}") matches
all events in that category. A non-empty JSON object applies field-level
| /// errors, TLS handshake failures, connection timeouts, | ||
| /// HTTP error status codes (4xx/5xx), CORS violations, | ||
| /// and mixed-content blocks. | ||
| COREWEBVIEW2_DIAGNOSTIC_CATEGORY_NETWORK_ERROR, |
There was a problem hiding this comment.
Prose: “mixed-content blocks” is ambiguous
“blocks” could mean “blocked requests” or “content blocks.”
Suggested correction:
/// Network request failure including DNS resolution
/// errors, TLS handshake failures, connection timeouts,
/// HTTP error status codes (4xx/5xx), CORS violations,
/// and mixed-content blocked requests.
| /// matches **any** value in each specified field | ||
| /// (OR within a field, AND across fields). String |
There was a problem hiding this comment.
Prose: Markdown bold will not render in IDL comments
**any** uses markdown bold syntax, but IDL /// comments are plain text — the asterisks will render as literal **any** in generated docs.
Suggested correction:
/// matches any value in each specified field
/// (OR within a field, AND across fields). String
| /// On failure the filter state is unchanged. | ||
| HRESULT AddDiagnosticReceivedFilter( |
There was a problem hiding this comment.
Prose: Missing comma after introductory phrase
Suggested correction:
/// Returns E_INVALIDARG if the JSON is malformed.
/// On failure, the filter state is unchanged.
| /// The handler is invoked on the thread that created | ||
| /// the environment every time a diagnostic signal | ||
| /// passes a filter added with | ||
| /// `AddDiagnosticReceivedFilter`. | ||
| /// |
There was a problem hiding this comment.
Prose: Run-on sentence — hard to parse
“the environment every time” reads as a run-on because the reader cannot tell where “environment” ends and “every time” begins.
Suggested correction:
/// Subscribes to diagnostic events on this monitor.
/// The handler is invoked on the thread that created
/// the environment. It fires every time a diagnostic
/// signal passes a filter added with
/// AddDiagnosticReceivedFilter.
| /// receives diagnostic signals from all layers — | ||
| /// WebView, Profile, and Environment — that match its | ||
| /// filters. | ||
| /// |
There was a problem hiding this comment.
Prose: Repetitive phrasing + missing comma
The phrase “all layers — WebView, Profile, and Environment —” appears 4+ times in the spec. After the first use in Background, subsequent uses can simply say “all layers.” Also, line 469 needs a comma before “but.”
Suggested correction for lines 459-462:
/// Creates a new diagnostic monitor. The monitor
/// receives diagnostic signals from all layers that
/// match its filters.
///
And for line 469:
/// The monitor is active immediately, but no events
| WebView = 0, | ||
|
|
||
| /// Signal from a profile / NetworkContext. | ||
| Profile = 1, |
There was a problem hiding this comment.
Prose: “NetworkContext” — is this a real type?
If NetworkContext is a real WebView2 type, format it as a code reference (backtick it). If it is a general concept, use lowercase.
Suggested correction (if not a type):
/// Signal from a profile or its network context.
shrinaths
left a comment
There was a problem hiding this comment.
Code Sample Issue: The destructor calls m_monitor.Reset() without first calling remove_DiagnosticReceived. This teaches an anti-pattern — callbacks may fire during or after destruction. Best-practice samples should demonstrate proper cleanup order.
Suggested correction:
DiagnosticComponent::~DiagnosticComponent()
{
if (m_monitor)
{
// Unsubscribe before releasing the monitor to
// ensure no callbacks arrive during teardown.
m_monitor->remove_DiagnosticReceived(
m_diagnosticToken);
m_monitor.Reset();
}
}| // events and clears filters. | ||
| m_monitor.Reset(); | ||
| } | ||
|
|
There was a problem hiding this comment.
Code Sample Issue: The destructor calls m_monitor.Reset() without first calling remove_DiagnosticReceived. This teaches an anti-pattern — callbacks may fire during or after destruction. Best-practice samples should demonstrate proper cleanup order.
Suggested correction:
DiagnosticComponent::~DiagnosticComponent()
{
if (m_monitor)
{
// Unsubscribe before releasing the monitor to
// ensure no callbacks arrive during teardown.
m_monitor->remove_DiagnosticReceived(
m_diagnosticToken);
m_monitor.Reset();
}
}|
|
||
| ## Filter with field-level JSON criteria | ||
|
|
||
| You can pass a JSON object to `AddDiagnosticReceivedFilter` to |
There was a problem hiding this comment.
Code Sample Issue: Dispose() calls _monitor?.Dispose() without first unsubscribing from DiagnosticReceived. This can cause callbacks on a disposed object.
Suggested correction:
public void Dispose()
{
if (_monitor != null)
{
// Unsubscribe before disposing the monitor.
_monitor.DiagnosticReceived -=
OnDiagnosticReceived;
_monitor.Dispose();
_monitor = null;
}
}|
|
||
| private void OnDiagnosticReceived( | ||
| CoreWebView2DiagnosticMonitor sender, | ||
| CoreWebView2DiagnosticEventArgs args) |
There was a problem hiding this comment.
Code Sample Issue: The handler uses CoreWebView2DiagnosticMonitor sender — but existing WebView2 .NET events use object sender per .NET convention. If using TypedEventHandler<TSender, TArgs> (WinRT), the strong-typed sender is correct, but please verify this matches the actual projection and clarify in the spec which projection (WinRT vs .NET SDK) is being shown.
Suggested correction (if .NET SDK):
private void OnDiagnosticReceived(
object sender,
CoreWebView2DiagnosticEventArgs args)| _monitor.AddDiagnosticReceivedFilter( | ||
| CoreWebView2DiagnosticCategory.NetworkError, | ||
| @"{ | ||
| ""profileName"": ""Default"", |
There was a problem hiding this comment.
Code Sample Issue: This sample references _environment but the class never declares this field. Either show a full class with the field declaration, or add the declaration before the method.
Suggested correction:
private CoreWebView2Environment _environment;
private void SetupFilteredDiagnostics()
{
_monitor = _environment.CreateDiagnosticMonitor();| } | ||
| ``` | ||
|
|
||
| ### .NET C# |
There was a problem hiding this comment.
Code Sample Issue: The error codes -105 and -7 are opaque — a developer copying this code has no idea what they mean. Name them in the comment, and consider adding a link to the Chromium net_error_list.h reference in an API Notes section.
Suggested correction:
// Only receive DNS (ERR_NAME_NOT_RESOLVED, -105)
// and timeout (ERR_TIMED_OUT, -7) errors
// for GET/POST requests from the `Default` profile.| [propget] HRESULT Category( | ||
| [out, retval] | ||
| COREWEBVIEW2_DIAGNOSTIC_CATEGORY* value); | ||
|
|
There was a problem hiding this comment.
IDL Issue: [v1_enum] is a classic COM IDL attribute. If this spec is authored in MIDL3, all enums are 32-bit by default and [v1_enum] is unnecessary. Please verify whether this attribute is still required in your toolchain — if not, remove both instances (here and line 318) to keep the IDL clean.
If this section is intentionally showing the generated classic COM IDL (for Win32 C++ consumers), then keeping [v1_enum] is correct, but consider labeling the section to clarify which IDL dialect is being shown.
| /// events but should not convert it to wall-clock time. | ||
| [propget] HRESULT Timestamp( | ||
| [out, retval] INT64* value); | ||
|
|
There was a problem hiding this comment.
IDL Naming Issue: The SOURCE_SCOPE compound is unusual in the WebView2 enum vocabulary. The SOURCE qualifier adds no value. Consider simplifying to COREWEBVIEW2_DIAGNOSTIC_SCOPE (and CoreWebView2DiagnosticScope in .NET/WinRT). Rename: COREWEBVIEW2_DIAGNOSTIC_SCOPE, COREWEBVIEW2_DIAGNOSTIC_SCOPE_WEB_VIEW, COREWEBVIEW2_DIAGNOSTIC_SCOPE_PROFILE, COREWEBVIEW2_DIAGNOSTIC_SCOPE_ENVIRONMENT.
| /// "uri": "https://www.contoso.com/api/data" | ||
| /// } | ||
| /// ``` | ||
| /// |
There was a problem hiding this comment.
IDL Naming Issue: WebView2 convention names event args after the event: DiagnosticReceived -> ICoreWebView2DiagnosticReceivedEventArgs. The current name ICoreWebView2DiagnosticEventArgs breaks this pattern (cf. ServerCertificateErrorDetectedEventArgs). Rename to ICoreWebView2DiagnosticReceivedEventArgs (COM) / CoreWebView2DiagnosticReceivedEventArgs (.NET) throughout the spec.
| /// events and clears all filters. | ||
| [uuid(E4F5A6B7-C8D9-0123-ABCD-456789012345), | ||
| object, pointer_default(unique)] | ||
| interface ICoreWebView2DiagnosticMonitor : IUnknown { |
There was a problem hiding this comment.
IDL API Shape Issue (Blocking): The category parameter is redundant -- args.Category already exposes it. Returning {} for a mismatched category silently hides bugs. Either (a) remove the parameter entirely and rename to GetDetailsAsJson(), or (b) return E_INVALIDARG on mismatch instead of silent empty JSON. Option (a) is recommended as it eliminates the mismatch class entirely. Suggested correction: HRESULT GetDetailsAsJson([out, retval] LPWSTR* value); and correspondingly in .NET: String GetDetailsAsJson();
|
|
||
| /// Subscribes to diagnostic events on this monitor. | ||
| /// The handler is invoked on the thread that created | ||
| /// the environment every time a diagnostic signal |
There was a problem hiding this comment.
IDL Naming Issue: The spec says 'Calling this method again for the same category replaces the previous filter.' This is replace/set semantics, but the Add prefix implies accumulation (like add_DiagnosticReceived which truly accumulates handlers). This will confuse developers. Suggest renaming to SetDiagnosticFilter / RemoveDiagnosticFilter -- shorter, clearer, and accurately conveys replace semantics.
| /// `protocol` is the protocol scheme (e.g. "https"). | ||
| /// `uri` is the request URI. | ||
| /// | ||
| /// For categories the runtime does not yet populate, |
There was a problem hiding this comment.
Blocking API Issue: Scope tells the kind of source (WebView/Profile/Environment) but not which instance produced the event. The filter supports profileName but the returned details JSON does not include it -- so you can filter by profile but cannot attribute received events to a profile. Add ProfileName and WebViewId properties to the event args: [propget] HRESULT ProfileName([out, retval] LPWSTR* value); [propget] HRESULT WebViewId([out, retval] LPWSTR* value); ProfileName should return empty string when Scope is Environment. WebViewId should return empty string when Scope is not WebView.
| /// On failure the filter state is unchanged. | ||
| HRESULT AddDiagnosticReceivedFilter( | ||
| [in] COREWEBVIEW2_DIAGNOSTIC_CATEGORY category, | ||
| [in] LPCWSTR jsonFilter); |
There was a problem hiding this comment.
Blocking API Issue: The spec only states events are raised on the environment-creating thread. It does not specify whether CreateDiagnosticMonitor, Add/RemoveDiagnosticReceivedFilter, and remove_DiagnosticReceived must also be called on that thread/apartment. Add explicit STA affinity documentation to the interface comment, e.g.: 'All members of this interface must be called on the same thread that created the ICoreWebView2Environment. Calling from a different thread returns RPC_E_WRONG_THREAD. Handlers must not block this thread.' This is consistent with other WebView2 APIs.
| eventHandler, | ||
| [out] EventRegistrationToken* token); | ||
|
|
||
| /// Removes a handler previously added with |
There was a problem hiding this comment.
IDL Consistency Issue: The filter JSON uses field name uriPattern but the details JSON (line 377) returns uri. This naming inconsistency will confuse developers who naturally expect to filter on the same field name that appears in the event data. Suggest unifying to uri everywhere -- the fact that wildcards are supported in the filter value is already documented in the matching rules and does not need to be encoded in the field name.
| /// `ICoreWebView2DiagnosticMonitor`. Each instance | ||
| /// represents a single diagnostic signal. | ||
| [uuid(A1B2C3D4-E5F6-7890-ABCD-EF1234567890), | ||
| object, pointer_default(unique)] |
There was a problem hiding this comment.
Convention Issue: Existing WebView2 specs use the header '## Win32 C++' (not '## COM'). Similarly, '### .NET C#' in the Examples section (line 161) should be '### .NET, WinRT' to match the established WebView2 spec conventions (cf. BrowserProcessExited.md, ClearBrowsingData.md).
Add Diagnostic Monitor API spec — Introduces ICoreWebView2DiagnosticMonitor, a new observation-only API that
delivers diagnostic signals (e.g., network failures) from all WebViews, profiles, and the environment through a
single DiagnosticReceived event. Host apps create a monitor via CreateDiagnosticMonitor and opt in per category
using AddDiagnosticReceivedFilter.