Skip to content

telemetry [8]: send metrics to Application Insights - #774

Open
bfjelds (bfjelds) wants to merge 5 commits into
user/bfjelds/mjolnir/telemetry-upload-corefrom
user/bfjelds/mjolnir/appinsights-telemetry
Open

bfjelds (bfjelds) wants to merge 5 commits into
user/bfjelds/mjolnir/telemetry-upload-corefrom
user/bfjelds/mjolnir/appinsights-telemetry

Conversation

@bfjelds

@bfjelds bfjelds (bfjelds) commented Sep 3, 2026 •

Copy link
Copy Markdown
Member

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

Comment thread crates/trident/src/agentconfig.rs
Comment thread packaging/rpm/trident.spec Outdated
Comment thread .pipelines/templates/stages/trident_rpms/release.yml Outdated
Comment thread crates/trident/src/logging/appinsights.rs

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

The tracing sink can block servicing, sends incomplete HTTP requests, and includes a functional test that cannot observe its subscriber.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds opt-in Azure Monitor/Application Insights telemetry for Trident metrics and spans.

Changes:

  • Adds an Application Insights tracing layer and agent opt-in setting.
  • Compiles connection strings through build and packaging workflows.
  • Enables telemetry in test images and documents configuration.
File summaries
File Description
tests/images/trident-vm-testimage/base/updateimg-grub.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/updateimg-grub-verity.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/updateimg-grub-verity-azure.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/baseimg-usr-verity.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/baseimg-root-verity.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/baseimg-grub.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/baseimg-grub-verity.yaml Installs opt-in config.
tests/images/trident-vm-testimage/base/baseimg-grub-verity-azure.yaml Installs opt-in config.
tests/images/trident-verity-testimage/usr/host.yaml Installs opt-in config.
tests/images/trident-verity-testimage/usr/container.yaml Installs opt-in config.
tests/images/trident-verity-testimage/base/baseimg.yaml Installs opt-in config.
tests/images/trident-verity-testimage/base/baseimg-container.yaml Installs opt-in config.
tests/images/trident-testimage/base/baseimg.yaml Installs opt-in config.
tests/images/trident-mos/iso.yaml Installs opt-in config.
tests/images/trident-mos/containerhost-iso.yaml Installs opt-in config.
tests/images/trident-installer/base/baseimg.yaml Installs opt-in config.
tests/images/trident-installer/base/baseimg-split.yaml Installs opt-in config.
tests/images/trident-installer/base/baseimg-direct-streaming.yaml Installs opt-in config.
tests/images/trident-functest/base/baseimg.yaml Installs opt-in config.
tests/images/trident-container-testimage/base/baseimg.yaml Installs opt-in config.
tests/images/trident-container-installer/base/baseimg.yaml Installs opt-in config.
tests/images/common/trident.conf Defines telemetry opt-in.
tests/images/azurelinux-direct-streaming-testimage/base/baseimg.yaml Installs opt-in config.
tests/images/azl-installer/installer-iso.yaml Installs opt-in config.
packaging/rpm/trident.spec Exports build-time connection strings.
packaging/docker/Dockerfile.full Passes connection string to RPM builds.
docs/Reference/Agent-Configuration.md Documents telemetry configuration.
crates/trident/src/main.rs Conditionally registers telemetry tracing.
crates/trident/src/logging/mod.rs Registers the new logging module.
crates/trident/src/logging/appinsights.rs Implements Application Insights ingestion.
crates/trident/src/lib.rs Exports telemetry symbols and build value.
crates/trident/src/agentconfig.rs Parses the telemetry preference.
crates/trident/build.rs Tracks connection-string changes.
.pipelines/templates/stages/trident_rpms/release.yml Supplies the pipeline connection string.
Review details
  • Files reviewed: 34/34 changed files
  • Comments generated: 3
  • Review effort level: Balanced

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

Comment thread crates/trident/src/logging/appinsights.rs
Comment thread crates/trident/src/logging/appinsights.rs Outdated
Comment thread crates/trident/src/logging/appinsights.rs Outdated

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.

🔵 Needs a closer look

Telemetry currently blocks servicing threads during HTTP requests and compiled placeholder endpoints trigger guaranteed delivery failures.

Review details

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

crates/trident/src/logging/appinsights.rs:400

  • Issue: A single TCP read cannot reliably capture one complete HTTP request because TCP has no message boundaries. Evidence: headers and JSON body may arrive in separate reads even for this small request, making the body assertions intermittently fail. Suggestion: read through \r\n\r\n, parse Content-Length, then read the remaining body (and return a valid HTTP response), or use the repository's HTTP test server helper.
    packaging/rpm/trident.spec:26
  • Issue: This non-empty placeholder is accepted as a configured connection string and compiled into every distro build. Evidence: an opted-in host will attempt telemetry against placeholder-public... rather than taking the documented no-connection-string no-op path; the pipeline connection string has the same placeholder pattern. Suggestion: compile an empty value until real endpoints are available, or supply valid connection strings before merging the wiring.

crates/trident/src/logging/appinsights.rs:207

  • Issue: This performs a blocking HTTP request directly inside the tracing layer callback, so telemetry is not isolated from servicing. Evidence: reqwest::blocking::Client::send() holds the thread that emitted each metric/span for up to REQUEST_TIMEOUT (5 seconds); Trident has many sequential instrumented spans, so an offline or slow endpoint can add repeated delays and can block Tokio worker threads in daemon mode. Suggestion: enqueue envelopes with a non-blocking try_send and let a bounded background worker perform/batch HTTP requests, dropping telemetry when the queue is full.
        let response = match self.client.post(&self.track_url).json(&envelope).send() {
  • Files reviewed: 34/34 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

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

HTTP rejection handling, failure log levels, and nondeterministic TCP test framing remain unresolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

crates/trident/src/logging/appinsights.rs:427

  • Issue: The functional test assumes one TCP read contains the complete HTTP request. Evidence: TCP may return only part of the headers or body even for a small request, making the subsequent JSON assertions nondeterministic. Suggestion: read through the header terminator, parse Content-Length, continue until the full body arrives, and return a valid HTTP response.
  • Files reviewed: 36/36 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread crates/trident/src/logging/appinsights.rs Outdated
Comment thread crates/trident/src/logging/background_uploader.rs Outdated

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

Telemetry-only configuration breaks non-default datastore provisioning, and queued telemetry can substantially delay process shutdown.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (3)

Previously missed (2) — in code that hasn't changed since the last review.

crates/trident/src/agentconfig.rs:52

  • Issue: Adding Telemetry as an independent setting makes a telemetry-only config incompatible with non-default datastore provisioning. Evidence: configure_agent_config treats any existing file without DatastorePath= as explicitly using the default and returns ImageBadAgentConfiguration; the documented Telemetry=OptIn-only file (and every newly opted-in test image) therefore disables the prior path that created a requested non-default datastore configuration. Suggestion: update configure_agent_config to merge a missing DatastorePath entry into an existing mutable config while preserving Telemetry, and cover that combination in its tests.
    crates/trident/src/logging/appinsights.rs:430
  • Issue: This functional test assumes one TCP read contains the complete HTTP request. Evidence: TCP may split headers and body across reads, so the body assertions can fail even though the sender posted a valid request. Suggestion: read through the declared Content-Length (and return a valid HTTP response) before sending the captured request to the assertion thread.

crates/trident/src/logging/appinsights.rs:233

  • Issue: Enqueuing every telemetry item can still block command termination for an unbounded time. Evidence: BackgroundUploadHandle uses an unbounded channel, while BackgroundUploader::drop closes the sender and joins a worker that deliberately drains every queued request serially; a slow endpoint can therefore add up to five seconds per pending metric/span at process exit. Suggestion: use a bounded/drop-on-full telemetry queue and discard pending telemetry during shutdown, or isolate telemetry in a worker whose shutdown does not drain indefinitely.
        if let Err(e) = self.uploader.upload(
            &self.track_url,
            body,
            REQUEST_TIMEOUT,
            Some(CONTENT_TYPE_JSON),
  • Files reviewed: 36/36 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread docs/Reference/Agent-Configuration.md Outdated

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

The new TCP-based functional test can fail nondeterministically because it assumes one read contains the complete HTTP request.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

crates/trident/src/logging/appinsights.rs:430

  • Issue: This functional test assumes one TCP read returns the entire HTTP request, which TCP does not guarantee. Evidence: the assertions inspect both the request line and JSON body, but a successful read may contain only a partial header or body, making the test flaky. Suggestion: read through the declared Content-Length and return a minimal HTTP response, or use an HTTP mock server that captures the complete request.
  • Files reviewed: 36/36 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread docs/Reference/Agent-Configuration.md Outdated
@bfjelds

Copy link
Copy Markdown
Member Author

Addressed a suppressed Copilot finding (review summary, not a posted inline thread): test_app_insights_sender_posts_event assumed a single TCP read returns the complete HTTP request, which TCP does not guarantee, making the test potentially flaky for larger/slower requests.

Fixed by reading until the header terminator arrives, then parsing Content-Length and reading until the full body has too, and sending a minimal response so the client request completes cleanly. Fixed in 044618e.

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.

🔵 Needs a closer look

Placeholder endpoints activate nonfunctional telemetry, and queued uploads can substantially delay shutdown.

Review details

Suppressed comments (2)

Previously missed (2) — in code that hasn't changed since the last review.

crates/trident/src/logging/appinsights.rs:233

  • Issue: Enqueueing makes callbacks asynchronous, but telemetry can still delay command completion substantially. Evidence: BackgroundUploader::drop joins its worker, and upload_loop drains every queued item sequentially; a slow endpoint returning success just under the 5-second timeout can therefore make shutdown wait up to five seconds per metric/span. Suggestion: give best-effort telemetry a bounded/non-draining shutdown policy, or add a bounded total flush deadline that discards remaining telemetry items.
    packaging/rpm/trident.spec:26
  • Issue: This non-empty placeholder activates telemetry in distro builds even though it cannot identify a real Application Insights resource. Evidence: parse_connection_string accepts it as valid, and the test images opt in, so released/test binaries attempt delivery to a placeholder and then disable that origin after the inevitable failure; the pipeline repeats the same pattern at release.yml:67. This also contradicts the PR description saying population is deferred. Suggestion: keep the compiled value empty until a real resource-specific connection string is supplied, or land the real build-time value atomically with this wiring.
  • Files reviewed: 36/36 changed files
  • Comments generated: 0 new
  • Review effort level: Balanced

@bfjelds

Copy link
Copy Markdown
Member Author

Replying to the Copilot review summary comment (suppressed findings, no inline thread exists for either):

appinsights.rs:233 — shutdown can wait up to ~5s per queued item

Agreed this is accurate, but it's an accepted tradeoff, not a bug: upload_loop drains the queue on shutdown so that telemetry already enqueued before a graceful stop actually gets a chance to land, rather than being silently dropped. The wait is bounded per-item by REQUEST_TIMEOUT (5s), and in practice the queue is tiny (a handful of lifecycle events per run); a slow/hanging endpoint is the worst case, and test_upload_loop_failed_host_is_ignored_for_future_uploads already ensures a failing origin gets disabled after one failure so it can't repeatedly stall future uploads. We're fine trading a few seconds of shutdown latency for "best effort" telemetry actually being delivered. Not changing this.

trident.spec:26 / release.yml:67 — placeholder connection string is a valid-looking value

Also accurate, but intentional and already flagged: both spots carry an explicit # TODO: replace with the real ... connection string. comment — deliberately calling out state pending a follow-up once the real AI resources exist, not a permanent placeholder. parse_connection_string correctly accepting it as well-formed is expected (it's syntactically valid, just pointing at a non-existent resource); delivery will simply fail once and that origin gets disabled by the same failure-handling logic noted above, so it doesn't loop or block anything. No functional risk — leaving the TODOs as the tracking mechanism.

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

Sovereign-cloud connection strings can route to the wrong endpoint, and telemetry can starve existing log uploads.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details
  • Files reviewed: 36/36 changed files
  • Comments generated: 2
  • Review effort level: Balanced

Comment thread crates/trident/src/logging/appinsights.rs
Comment thread crates/trident/src/main.rs Outdated

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.

Copilot review overview

🟡 Changes recommended

gRPC-client tracing can truncate daemon metrics, and an early CLI error path misattributes installation telemetry.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Comment thread crates/trident/src/main.rs

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.

Copilot review overview

🔵 Needs a closer look

It combines telemetry transport, persistent identity migration, packaging, and concurrency-sensitive daemon behavior.

Review effort: Balanced
Findings: None

Resolved since last review (1)

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.

🔵 Needs a closer look

Cross-cutting changes to persisted IDs, CLI/daemon execution, and uploader shutdown need build and integration validation plus final human review.

No open issues 🎉

Review effort: Balanced

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.

🔵 Needs a closer look

The custom ingestion protocol and concurrent shutdown behavior require human validation before approval.

2 open issues

Review effort: Balanced

Comment thread crates/trident/src/main.rs Outdated
Comment thread crates/trident/src/main.rs

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.

🔵 Needs a closer look

Asynchronous delivery and reboot-time shutdown interactions need human review and runtime validation before approval.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

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.

🔵 Needs a closer look

Outbound host-data delivery and shutdown/reboot integration need final human validation because end-to-end runtime behavior was not verified in this review.

No open issues 🎉

Review effort: Balanced

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.

🔵 Needs a closer look

Concurrent uploading and reboot/shutdown integration warrant human validation because execution of the added tests and live ingestion were not verified.

No open issues 🎉

Review effort: Balanced

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

The daemon reboot path does not drain queued telemetry before requesting a reboot, risking loss of the reboot event and servicing metrics.

1 open issue

Review effort: Balanced

Comment thread crates/trident/src/main.rs

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

Successful upload responses are buffered without a size limit, creating a memory-exhaustion risk, and the telemetry documentation misstates which commands write metrics.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread crates/trident/src/logging/appinsights.rs Outdated
bfjelds (bfjelds) and others added 4 commits October 28, 2026 21:49
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: d0e7cadc-8f44-443f-affe-6ce8e856a218

Copilot-Session: 43cb811b-f191-4d90-852f-e3373041ca11
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43cb811b-f191-4d90-852f-e3373041ca11
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43cb811b-f191-4d90-852f-e3373041ca11
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43cb811b-f191-4d90-852f-e3373041ca11

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

The test server advertises a persistent HTTP connection but closes it after one request, risking connection resets and intermittent test timeouts.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread crates/trident/src/logging/appinsights.rs Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 43cb811b-f191-4d90-852f-e3373041ca11

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.

🔵 Needs a closer look

The new Application Insights ingestion and reboot-time flushing paths require validation against a real Azure endpoint and systemd; the supplied tests use local mocks.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

This branch has not been deployed

No deployments
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