Skip to content

Plugin Trace Log implementation#341

Merged
mkholt merged 4 commits into
masterfrom
verify-trace-messages-5a8
Jul 6, 2026
Merged

Plugin Trace Log implementation#341
mkholt merged 4 commits into
masterfrom
verify-trace-messages-5a8

Conversation

@mkholt

@mkholt mkholt commented Jul 6, 2026

Copy link
Copy Markdown
Member

Evaluate ITracingService messages via String.Format and expose collected trace log

Trace messages with format args are now evaluated through String.Format so
invalid format strings surface during testing instead of being silently
swallowed. Arg-less messages remain verbatim, matching platform behavior.

Trace messages are also collected by the default tracing service factory and
exposed via XrmMockupBase.TraceLog (with ClearTraceLog) so tests can assert on
emitted trace output.

Group trace messages per plugin execution via PluginTraceLog

Trace messages are now grouped by the plugin execution that produced them,
mirroring the plugintracelog records of a real Dynamics 365 environment. Each
XrmMockupBase.PluginTraceLog entry captures the invoking type, message name,
primary entity, operation type, depth, correlation id, mode, request id,
execution start time, duration, the ordered list of trace messages and any
exception details.

PluginTrigger now times each sync/async plugin execution, captures thrown
exceptions and records an entry with the execution's own trace messages.
Internal XrmMockup system plugins are excluded. Configuration/secure
configuration and plugin step ids are not modeled by XrmMockup and remain null.

Extend grouped trace log to custom APIs and workflow activities

The per-execution trace grouping introduced for plugins now also covers custom
API executions and workflow activity executions (sync and async). A shared
PluginTraceRecorder helper centralizes the timing, exception capture and trace
message collection used by all three paths; CustomApiManager and WorkflowManager
now route their executions through it.

Custom API entries record the request name as the message and Plugin operation
type; workflow entries record the workflow name as the type, WorkflowActivity
operation type and the workflow's sync/async mode. Directly-invoked workflows
(ExecuteWorkflowRequest, which has no plugin context) are executed but not logged.

Co-Authored-By: Claude noreply@anthropic.com via Conducktor conducktor@contextand.com

mkholt and others added 3 commits July 6, 2026 09:42
…ted trace log

Trace messages with format args are now evaluated through String.Format so
invalid format strings surface during testing instead of being silently
swallowed. Arg-less messages remain verbatim, matching platform behavior.

Trace messages are also collected by the default tracing service factory and
exposed via XrmMockupBase.TraceLog (with ClearTraceLog) so tests can assert on
emitted trace output.

Co-Authored-By: Claude <noreply@anthropic.com> via Conducktor <conducktor@contextand.com>
Trace messages are now grouped by the plugin execution that produced them,
mirroring the plugintracelog records of a real Dynamics 365 environment. Each
XrmMockupBase.PluginTraceLog entry captures the invoking type, message name,
primary entity, operation type, depth, correlation id, mode, request id,
execution start time, duration, the ordered list of trace messages and any
exception details.

PluginTrigger now times each sync/async plugin execution, captures thrown
exceptions and records an entry with the execution's own trace messages.
Internal XrmMockup system plugins are excluded. Configuration/secure
configuration and plugin step ids are not modeled by XrmMockup and remain null.

Co-Authored-By: Claude <noreply@anthropic.com> via Conducktor <conducktor@contextand.com>
The per-execution trace grouping introduced for plugins now also covers custom
API executions and workflow activity executions (sync and async). A shared
PluginTraceRecorder helper centralizes the timing, exception capture and trace
message collection used by all three paths; CustomApiManager and WorkflowManager
now route their executions through it.

Custom API entries record the request name as the message and Plugin operation
type; workflow entries record the workflow name as the type, WorkflowActivity
operation type and the workflow's sync/async mode. Directly-invoked workflows
(ExecuteWorkflowRequest, which has no plugin context) are executed but not logged.

Co-Authored-By: Claude <noreply@anthropic.com> via Conducktor <conducktor@contextand.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class trace capture to XrmMockup365 so tests can assert on emitted ITracingService output, and introduces a Dynamics-like per-execution “plugin trace log” (including custom APIs and workflow activities) with timing and exception details.

Changes:

  • Evaluate ITracingService.Trace(format, args) via string.Format (when args provided) and expose a collected flat TraceLog on XrmMockupBase.
  • Record grouped per-execution trace entries (PluginTraceLog) for plugins/custom APIs/workflow activities via a shared PluginTraceRecorder.
  • Extend tests and test assemblies to validate formatting behavior, flat trace collection, grouped trace metadata, and exception capture.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/XrmMockup365Test/TestTracingService.cs Adds coverage for format-evaluation behavior, flat trace collection, and grouped per-execution trace logging (plugins/custom APIs/workflows).
tests/TestPluginAssembly365/Plugins/AccountTraceThrowPlugin.cs Test plugin that traces then throws to validate exception capture in grouped trace logs.
tests/TestPluginAssembly365/Plugins/AccountTracePlugin.cs Test plugin that emits trace messages to validate trace collection and ordering.
tests/TestPluginAssembly365/CustomApis/TraceApi.cs Custom API emitting traces to validate grouped trace logging for custom API execution.
tests/TestPluginAssembly365/CodeActivities/AccountWorkflowActivity.cs Adds a trace message to validate grouped trace logging for workflow activity execution.
src/XrmMockup365/XrmMockupBase.cs Exposes TraceLog/ClearTraceLog and grouped PluginTraceLog/ClearPluginTraceLog; clears trace log on reset.
src/XrmMockup365/Workflow/WorkflowManager.cs Routes workflow executions through PluginTraceRecorder and threads workflow name for logging metadata.
src/XrmMockup365/TracingServiceFactory.cs Default tracing factory now records emitted messages and exposes them via TraceLog/Clear.
src/XrmMockup365/TracingService.cs Implements platform-like formatting semantics, collects per-instance messages, and supports an optional sink for factory-level collection.
src/XrmMockup365/PluginTraceLog.cs Introduces grouped trace-log model and operation type enum.
src/XrmMockup365/Plugin/PluginTrigger.cs Wraps plugin execution with timing/exception capture and grouped trace recording; adds option to skip recording.
src/XrmMockup365/Plugin/PluginTraceRecorder.cs Central helper to time execution, collect per-execution trace messages, and record grouped trace entries.
src/XrmMockup365/Plugin/PluginManager.cs Excludes internal/system plugins from grouped trace logging.
src/XrmMockup365/Plugin/CustomApiManager.cs Routes custom API execution through PluginTraceRecorder to produce grouped trace entries.
src/XrmMockup365/Internal/ICoreOperations.cs Adds core API surface for recording grouped trace entries.
src/XrmMockup365/Core.cs Stores grouped trace entries with thread-safety and clears them on environment reset.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/XrmMockup365/Plugin/PluginTraceRecorder.cs
Comment thread src/XrmMockup365/TracingService.cs Outdated
Comment thread src/XrmMockup365/XrmMockupBase.cs Outdated
- PluginTraceRecorder: fall back to the TargetInvocationException itself when
  it has no inner exception, so ExceptionDispatchInfo.Capture is never handed
  null (which would mask the original failure).
- TracingService: expose Messages as a read-only wrapper so callers cannot cast
  it back to List<string> and mutate recorded trace output.
- XrmMockupBase: return Array.Empty<string>() rather than allocating a new list
  on every TraceLog access when a custom tracing factory is configured.

Co-Authored-By: Claude <noreply@anthropic.com> via Conducktor <conducktor@contextand.com>
@mkholt
mkholt merged commit dac180d into master Jul 6, 2026
2 checks passed
@mkholt
mkholt deleted the verify-trace-messages-5a8 branch July 6, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants