Skip to content

Fix telemetry component assembly identification - #4490

Merged
marcschier merged 9 commits into
masterfrom
copilot/fix-telemetry-extensions-activity-source
Sep 16, 2026
Merged

marcschier merged 9 commits into
masterfrom
copilot/fix-telemetry-extensions-activity-source

Conversation

Copilot AI commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Description

Telemetry extensions resolved meters and activity sources as Opc.Ua.Types, with results dependent on helper inlining. This prevented reliable attribution to the emitting component.

  • Existing telemetry contract: Add CreateMeter(Assembly) and GetActivitySource(Assembly) directly to ITelemetryContext. The separate IAssemblyTelemetryContext interface has been removed.
  • Reliable component attribution: Capture the caller assembly in non-inlined CreateMeter, GetActivitySource, and StartActivity extensions, then forward it to the existing telemetry context.
  • Call-site routing and fallback: Keep non-null meter calls on telemetry.CreateMeter(). Use explicit TelemetryExtensions.CreateMeter(telemetry) for nullable-context fallback. Preserve default meter/activity-source fallback when a context returns null.
  • Coverage and documentation: Cover caller-assembly naming, direct-context and extension routing, activity creation, and null-result fallback. Update diagnostics examples, OpenTelemetry filters, and migration guidance.
  • CI compatibility and listener safety: Use portable null guards in shared sample/fuzz telemetry code. Resolve the server test fixture activity source before registering its listener, preventing recursive source construction while preserving source filtering and sampling.

Compatibility: Direct implementations of ITelemetryContext must implement the two new assembly-aware members. TelemetryContextBase supplies both. This interface addition is documented in the 2.0 migration guide; legacy implementer compatibility is not claimed.

Local validation

Both original CI failures were reproduced locally before the fixes: a legacy-target compiler error and a stack overflow in the unchanged tracing integration test.

Scope Targets Result per target
ServerFixtureTelemetryTests.ActivityListenerSamplesOnlyResolvedSource (logging enabled/disabled) net10.0, net48 Passed: 2, Failed: 0, Skipped: 0
Unchanged TraceableRequestHeaderTest.ReadValuesWithTracingAsync net10.0, net48 Passed: 1, Failed: 0, Skipped: 0
ConsoleReferenceServer, ConsoleReferenceClient, encoder fuzz tools, certificate fuzz tools net472, net48 All four builds succeeded; 0 warnings, 0 errors

The full solution test suite was not run locally. No existing assertions, test selection, coverage thresholds, or CI requirements were weakened.

Related Issues

Checklist

  • I have signed the CLA and read the CONTRIBUTING doc.
  • I have added tests that prove my fix is effective or that my feature works and increased code coverage.
  • I have added all necessary documentation.
  • I have verified that my changes do not introduce (new) build or analyzer warnings.
  • I ran all tests locally using the UA.slnx solution against at least .net framework and .net 10, and all passed.
  • I fixed all failing and flaky tests in the CI pipelines and all CodeQL warnings.
  • I have addressed all PR feedback received.

@CLAassistant

CLAassistant commented Sep 15, 2026 •

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ marcschier
❌ Copilot
You have signed the CLA already but the status is still pending? Let us recheck it.

Copilot AI and others added 3 commits September 15, 2026 09:49
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix telemetry source identification in ActivitySource Fix telemetry component assembly identification Sep 15, 2026
Copilot AI requested a review from marcschier September 15, 2026 10:15
@marcschier
marcschier marked this pull request as ready for review September 15, 2026 10:33
Copilot AI lite review requested due to automatic review settings September 15, 2026 10:33
@marcschier
marcschier enabled auto-merge (squash) September 15, 2026 10:33
@marcschier

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

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.

🟡 Changes recommended

Restore legacy null-result fallbacks and address the documentation and missing fallback-test findings.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This pull request makes telemetry attribution assembly-aware while preserving compatibility with legacy telemetry contexts.

Changes:

  • Adds assembly-aware telemetry contracts and caller-assembly routing.
  • Updates client, security, and cache metric call sites.
  • Adds tests and migration/diagnostic documentation.
File summaries
File Summary
tests/Opc.Ua.Types.Tests/Diagnostics/TelemetryExtensionsTests.cs Tests assembly attribution and legacy behavior.
src/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs Routes assembly-aware telemetry; restore legacy null fallbacks (moderate, 2 votes) and add legacy StartActivity coverage (nit, 1 vote).
src/Opc.Ua.Types/Diagnostics/TelemetryContextBase.cs Implements assembly-aware telemetry factories.
src/Opc.Ua.Types/Diagnostics/IAssemblyTelemetryContext.cs Defines the optional assembly-aware contract.
src/Opc.Ua.Core/Stack/Client/ClientBase.cs Routes client meter creation.
src/Opc.Ua.Core/Stack/Client/Channels/ClientChannelManager.cs Routes optional channel metrics.
src/Opc.Ua.Core/Security/Crypto/CryptoProviderAuditor.cs Routes crypto metrics.
src/Opc.Ua.Core/Security/Certificates/CertificateManager/CertificateCache.cs Routes certificate-cache metrics.
src/Opc.Ua.Client/NodeCache/NodeCache.cs Routes node-cache metrics.
docs/migrate/2.0.x/telemetry.md Documents telemetry migration compatibility.
docs/Diagnostics.md Documents the contract and usage; interface inheritance and explicit extension invocation need correction (nits, 3 and 1 votes).
Review details

Suppressed comments (4)

docs/Diagnostics.md:79

  • Because ITelemetryContext already declares an instance CreateMeter(), the usage example telemetry.CreateMeter() later in this document binds to that instance member rather than this extension and still loses caller-assembly attribution. Update the example and guidance to invoke TelemetryExtensions.CreateMeter(telemetry) explicitly, as the stack call sites do.
**Always use the extension methods**. The metric and tracing extensions
capture the component assembly at the call site, and all extensions
provide a default context when the supplied `ITelemetryContext` is
`null`. They use `IAssemblyTelemetryContext` when available and preserve
the fixed sources returned by existing `ITelemetryContext`

src/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs:136

  • The legacy branch drops the existing ?? Default.ActivitySource fallback. An existing ITelemetryContext implementation that returns null from its ActivitySource property will now return null instead of the default source, contradicting the extension's documented non-null/fallback behavior.
                : context.ActivitySource;

src/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs:163

  • StartActivity used to obtain the source through GetActivitySource(), which fell back to Default.ActivitySource for legacy contexts. This direct legacy branch now passes a null ActivitySource to StartActivity and can throw when an existing context returns null; preserve the fallback here.
                : context.ActivitySource;

src/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs:164

  • The legacy compatibility path in StartActivity is not exercised by the added tests: LegacyContextUsesExistingSources only checks CreateMeter and GetActivitySource, while this branch now reads the legacy ActivitySource directly and starts an activity. Add a listener and assert that StartActivity succeeds with the legacy source so a regression in this fallback cannot pass unnoticed.
            ITelemetryContext context = telemetry ?? Default;
            ActivitySource activitySource = context is IAssemblyTelemetryContext assemblyContext
                ? assemblyContext.GetActivitySource(assembly)
                : context.ActivitySource;
            return activitySource.StartActivity(name, kind);
  • Files reviewed: 11/11 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs Outdated
Comment thread docs/Diagnostics.md Outdated
Comment thread src/Opc.Ua.Core/Security/Crypto/CryptoProviderAuditor.cs Outdated

@romanett romanett 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.

I´d say adding new Methods taking an assembly to the existing ITelemetryContext is an accepted breaking change in 2.0.
And applying the inling patch.
Then revert the routing through TeleemtryContext extensions

@marcschier

Copy link
Copy Markdown
Collaborator

@copilot fix ci and address all feedback

Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>
auto-merge was automatically disabled September 15, 2026 14:29

Head branch was pushed to by a user without write access

@romanett

Copy link
Copy Markdown
Contributor

@copilot update the PR Description to reflect the new edits

@romanett
romanett self-requested a review September 15, 2026 14:43
Co-authored-by: marcschier <11168470+marcschier@users.noreply.github.com>

Copilot AI commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot fix ci and address all feedback

Addressed in 759fcdf and c8c0031: moved assembly-aware methods onto ITelemetryContext, retained non-inlined attribution, restored null-result fallbacks, reverted explicit extension routing, updated implementations/tests/docs, and synchronized the migration bundle. The full .NET 10 solution builds and all 10,506 executed Types tests pass. New GitHub checks are awaiting workflow approval (action_required, zero jobs), not reporting code failures.

Copilot AI commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

@copilot update the PR Description to reflect the new edits

I can’t edit the PR body from this session: the available GitHub API tools are read-only for PR metadata, and the authenticated browser requires unavailable OAuth. The description should replace the optional IAssemblyTelemetryContext/extension-routing sections with: assembly-aware overloads on ITelemetryContext; non-inlined caller capture; direct telemetry.CreateMeter() routing; nullable/null-result extension fallbacks; updated implementations, tests, docs, and migration bundle; .NET 10 solution build and 10,506 Types tests passing.

@marcschier
marcschier enabled auto-merge (squash) September 15, 2026 15:44
@marcschier
marcschier dismissed romanett’s stale review September 15, 2026 15:44

Addressed requests

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Code coverage

✅ Coverage gate passed.

Check Result Threshold
✅ Project line rate 87.03% (264182/303539 lines) >= 70.00%
✅ Project branch rate 77.15% >= 60.00%
⚠️ Patch coverage 54.55% (18/33 changed lines) >= 60.00% (<= 100 changed lines, advisory)
ℹ️ Baseline delta (advisory) +13.43 pp 73.60% recorded
Uncovered changed lines
  • src/Opc.Ua.Core.Diagnostics/Replay/MockClientReplay.cs: 607, 612
  • src/Opc.Ua.Core.Diagnostics/Dissection/ServiceCallReassembler.cs: 660, 665
  • src/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs: 105, 107, 108, 126, 128, 129, 150, 152, 153
  • src/Opc.Ua.Core.Diagnostics/Dissection/OfflineSecureChannel.cs: 415, 421

Coverage is above the recorded baseline - consider ratcheting coverage-thresholds.json.

Thresholds live in coverage-thresholds.json. Whole report before exclusions: line 86.18%, branch 76.35%.

@codecov

codecov Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 39.39394% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.08%. Comparing base (93559d0) to head (4a0c4b7).
⚠️ Report is 3 commits behind head on master.

Files with missing lines Patch % Lines
...rc/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs 40.00% 9 Missing and 3 partials ⚠️
...ore.Diagnostics/Dissection/OfflineSecureChannel.cs 0.00% 2 Missing ⚠️
...e.Diagnostics/Dissection/ServiceCallReassembler.cs 0.00% 2 Missing ⚠️
...Opc.Ua.Core.Diagnostics/Replay/MockClientReplay.cs 0.00% 2 Missing ⚠️
...c/Opc.Ua.Types/Diagnostics/TelemetryContextBase.cs 71.42% 0 Missing and 2 partials ⚠️

❌ Your patch check has failed because the patch coverage (39.39%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4490      +/-   ##
==========================================
+ Coverage   81.06%   81.08%   +0.01%     
==========================================
  Files        2056     2056              
  Lines      303366   303539     +173     
  Branches    52579    52613      +34     
==========================================
+ Hits       245932   246125     +193     
+ Misses      39219    39192      -27     
- Partials    18215    18222       +7     
Flag Coverage Δ
actions 81.08% <39.39%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ore.Diagnostics/Dissection/OfflineSecureChannel.cs 92.56% <0.00%> (-1.27%) ⬇️
...e.Diagnostics/Dissection/ServiceCallReassembler.cs 61.11% <0.00%> (-0.49%) ⬇️
...Opc.Ua.Core.Diagnostics/Replay/MockClientReplay.cs 42.32% <0.00%> (-0.32%) ⬇️
...c/Opc.Ua.Types/Diagnostics/TelemetryContextBase.cs 66.66% <71.42%> (-2.57%) ⬇️
...rc/Opc.Ua.Types/Diagnostics/TelemetryExtensions.cs 26.15% <40.00%> (+5.32%) ⬆️

... and 46 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Use the existing portable ValueGuards helper in assembly-aware sample and fuzz telemetry overloads. Resolve the server fixture activity source before registering its listener so ShouldListenTo cannot recursively create the same cold source. Preserve source filtering and sampling, add both-branch listener regression coverage, and document safe listener setup.
@marcschier

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@marcschier marcschier added the ready Ready to merge once CI Passes label Sep 16, 2026
@marcschier
marcschier merged commit d7dd1b0 into master Sep 16, 2026
278 of 279 checks passed
@marcschier
marcschier deleted the copilot/fix-telemetry-extensions-activity-source branch September 29, 2026 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready Ready to merge once CI Passes

Projects

None yet

6 participants