mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 14:46:55 +01:00
Improve partner onboarding and documentation navigation (#174)
Lead with a complete plugin quick start and add task-oriented usage, troubleshooting, customization, and contribution guides. Preserve the broader plugin framing, correct conflicting contract guidance, support Agents folder reviews, and align repository validation. Convert existing sample references to clickable links without changing knowledge rules. Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com> Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
a21edfec46
commit
2b5550c346
276 changed files with 1287 additions and 756 deletions
|
|
@ -17,10 +17,10 @@ application-area: [all]
|
|||
|
||||
Use `ExtensionPublisher` for internal diagnostics that only the app publisher can interpret, such as cache behavior or private algorithm state. Use `All` for signals the tenant operator can act on, such as an integration failure, quota warning, or setup problem. Decide the audience independently from `DataClassification`; privacy guidance still governs whether the payload may be emitted at all.
|
||||
|
||||
See sample: `choose-telemetry-scope-by-audience.good.al`.
|
||||
See sample: [`choose-telemetry-scope-by-audience.good.al`](choose-telemetry-scope-by-audience.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Defaulting every call to `All`, including low-level implementation diagnostics, or defaulting every call to `ExtensionPublisher` and thereby hiding customer-actionable failures from environment telemetry. Review only when the message and surrounding branch make the intended audience clear; an ambiguous diagnostic is not enough to infer the wrong scope.
|
||||
|
||||
See sample: `choose-telemetry-scope-by-audience.bad.al`.
|
||||
See sample: [`choose-telemetry-scope-by-audience.bad.al`](choose-telemetry-scope-by-audience.bad.al).
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ application-area: [all]
|
|||
|
||||
Log `Discovered` when the user encounters the feature, `Set up` after its setup is completed, and `Used` when the user attempts it. Keep the same feature name throughout the funnel. Review ordering only when the changed repository context shows the feature's lifecycle; a single isolated `Used` call cannot prove that earlier states are absent elsewhere.
|
||||
|
||||
See sample: `feature-uptake-transitions-in-order.good.al`.
|
||||
See sample: [`feature-uptake-transitions-in-order.good.al`](feature-uptake-transitions-in-order.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Introducing a feature whose only uptake call jumps directly to `Set up` or `Used`, or using different feature-name literals for successive states. The calls compile and run, but the funnel silently omits the invalid transition.
|
||||
|
||||
See sample: `feature-uptake-transitions-in-order.bad.al`.
|
||||
See sample: [`feature-uptake-transitions-in-order.bad.al`](feature-uptake-transitions-in-order.bad.al).
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ application-area: [all]
|
|||
|
||||
Call `LogUsage` only after the operation has completed successfully. On a failure path, call `LogError` with the captured error text and call stack when the failure must be emitted explicitly. Use a past-tense event name for usage and a present-tense scenario name for errors.
|
||||
|
||||
See sample: `feature-usage-only-after-success.good.al`.
|
||||
See sample: [`feature-usage-only-after-success.good.al`](feature-usage-only-after-success.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Calling `LogUsage` before a Boolean result, `TryFunction`, `Codeunit.Run`, or HTTP status has been checked, or calling it in both success and failure branches. Do not flag an attempt recorded with `LogUptake(...Used)`; unlike `LogUsage`, that state intentionally records an attempt.
|
||||
|
||||
See sample: `feature-usage-only-after-success.bad.al`.
|
||||
See sample: [`feature-usage-only-after-success.bad.al`](feature-usage-only-after-success.bad.al).
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ Business Central prefixes AL custom-dimension keys with `al` in Application Insi
|
|||
|
||||
Choose stable PascalCase keys such as `Operation`, `Result`, and `RecordCount`. Keep the key set and meaning stable for a shipped event ID; add a new event ID or coordinate a schema migration when the meaning must change. Privacy guidance separately governs whether a dimension value may contain customer data.
|
||||
|
||||
See sample: `keep-custom-dimension-schema-stable.good.al`.
|
||||
See sample: [`keep-custom-dimension-schema-stable.good.al`](keep-custom-dimension-schema-stable.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Keys such as `'order no'` or `'result_code'`, or renaming/removing a key while retaining the same shipped event ID. A naming-only issue is advisory; changing an existing event's schema is the material compatibility defect. New keys on a new event ID are not a breaking change.
|
||||
|
||||
See sample: `keep-custom-dimension-schema-stable.bad.al`.
|
||||
See sample: [`keep-custom-dimension-schema-stable.bad.al`](keep-custom-dimension-schema-stable.bad.al).
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ application-area: [all]
|
|||
|
||||
Use `Error` for failed operations that need investigation and `Critical` only for abnormal termination or equivalent loss of service. Use `Warning` for degraded but completed behavior, `Normal` for successful business events, and `Verbose` for detailed diagnostics. Judge the outcome, not the procedure name: an expected optional lookup miss can legitimately remain `Normal` or `Verbose`.
|
||||
|
||||
See sample: `match-verbosity-to-signal-severity.good.al`.
|
||||
See sample: [`match-verbosity-to-signal-severity.good.al`](match-verbosity-to-signal-severity.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
A `Session.LogMessage` in a failed `TryFunction`, failed `Codeunit.Run`, unsuccessful HTTP response, or other explicit failure branch that uses `Verbosity::Normal` or `Verbose` without evidence that the failure is expected and benign.
|
||||
|
||||
See sample: `match-verbosity-to-signal-severity.bad.al`.
|
||||
See sample: [`match-verbosity-to-signal-severity.bad.al`](match-verbosity-to-signal-severity.bad.al).
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ The `Telemetry` and `Feature Telemetry` codeunits reach an extension publisher's
|
|||
|
||||
Place one internal logger implementation in one app for the publisher, forward its `LogMessage` method to `Session.LogMessage`, and register it from one event subscriber. Companion apps with the same publisher reuse that registration instead of each adding another. Evaluate absence only with repository or app-family context; a single-file diff cannot prove that no logger exists elsewhere.
|
||||
|
||||
See sample: `register-one-telemetry-logger-per-publisher.good.al`.
|
||||
See sample: [`register-one-telemetry-logger-per-publisher.good.al`](register-one-telemetry-logger-per-publisher.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Adding `FeatureTelemetry` calls to a complete app with no logger registration, or registering two logger implementations for apps that share the same publisher. The calls compile, but the telemetry module reports the missing or duplicate registration instead of behaving as intended.
|
||||
|
||||
See sample: `register-one-telemetry-logger-per-publisher.bad.al`.
|
||||
See sample: [`register-one-telemetry-logger-per-publisher.bad.al`](register-one-telemetry-logger-per-publisher.bad.al).
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ The convention used by Microsoft first-party AL code is a short prefix identifyi
|
|||
|
||||
Assign each `Session.LogMessage` call a real, registered event ID drawn from the extension's catalogue. Treat the ID as part of the public contract of the event — renaming it is a breaking change for consumers. Keep IDs short, deterministic, and free of personal or environment-specific tokens.
|
||||
|
||||
See sample: `telemetry-event-id-stable-unique.good.al`.
|
||||
See sample: [`telemetry-event-id-stable-unique.good.al`](telemetry-event-id-stable-unique.good.al).
|
||||
|
||||
## Anti Pattern
|
||||
|
||||
Calling `Session.LogMessage('0000', ...)` (or `'1234'`, `'TODO'`, an empty string, a GUID generated at runtime, or any other placeholder) leaves the event unsearchable and indistinguishable from every other event using the same placeholder. The catalogue entry never gets created because the developer "will fix it later", and the placeholder ships.
|
||||
|
||||
See sample: `telemetry-event-id-stable-unique.bad.al`.
|
||||
See sample: [`telemetry-event-id-stable-unique.bad.al`](telemetry-event-id-stable-unique.bad.al).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue