Skip to content

Add OpenTelemetry via Application Insights demo (Java and .NET) - #146

Open
tungbq wants to merge 1 commit into
mainfrom
feat/add-opentelemetry-appinsights-java-dotnet-demo
Open

tungbq wants to merge 1 commit into
mainfrom
feat/add-opentelemetry-appinsights-java-dotnet-demo

Conversation

@tungbq

@tungbq tungbq commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Explicit ask, not tied to an issue: demo OpenTelemetry concepts using the real Application Insights agents for both Java and .NET specifically (not the vanilla OTel SDK/collector).

Summary

  • java-service (Spring Boot): auto-instrumented with the real Application Insights Java agent (-javaagent:applicationinsights-agent.jar).
  • dotnet-service (ASP.NET Core): auto-instrumented with the real Azure Monitor OpenTelemetry Distro (Azure.Monitor.OpenTelemetry.AspNetCore, UseAzureMonitor()).
  • One HTTP call chain, zero OpenTelemetry-aware code in either handler — the Java service calls the .NET service, and the demo proves the two show up as one connected trace, not two unrelated ones.

Why this is verifiable without an Azure subscription

Researched and then empirically verified directly (a researcher subagent's findings and my own hands-on testing initially disagreed, so I didn't take either at face value):

  • No connection string / malformed string → the .NET distro throws InvalidOperationException at startup; confirmed directly.
  • A syntactically valid but fake connection string (real Azure region endpoint, fake instrumentation key) → both agents attach fully, both apps run and serve real traffic — only the final export call to Azure is rejected. Java logs a clean 400 Invalid instrumentation key, which is itself proof telemetry was captured and an export was attempted, not proof it's broken.

demo_project.sh uses exactly this placeholder-but-well-formed connection string, and proves (not asserts):

  • both agents actually attached
  • the cross-service call produces identical OpenTelemetry trace IDs on both sides (each service reads its own auto-instrumented Span.current() / Activity.Current) — genuine W3C traceparent propagation across the JVM/CLR boundary
  • two unrelated, independent requests get two different trace IDs — ruling out a hardcoded value
  • the Java agent's real export attempt and its rejection, in the logs

Swap in a real APPLICATIONINSIGHTS_CONNECTION_STRING to see the same run land in an actual Azure Application Insights resource — documented in the project README.

  • .github/workflows/verify-opentelemetry-appinsights-demo.yml, matching the existing per-project verify-*.yml convention — needs only Docker, since both services and their agents run entirely inside their own containers.
  • README.md: new row (25), linking directly to the project folder.

Test plan

  • Ran the exact committed demo_project.sh end-to-end against real Docker containers, twice.
  • Verified directly (not from docs alone): agent-attach behavior with no/malformed connection string (crashes) vs. a well-formed-but-fake one (runs fine, export rejected) — for both Java and .NET.
  • Verified matching trace IDs across the real cross-service call, and distinct trace IDs across two independent calls.
  • shellcheck demo_project.sh — clean.
  • mvn test (Java) and dotnet build (.NET) — both clean.
  • Workflow YAML validated with yaml.safe_load.

Not tied to an existing issue - explicit ask: demo OpenTelemetry
concepts using the real Application Insights agents for both Java and
.NET, not the vanilla OTel SDK/collector.

- java-service (Spring Boot): auto-instrumented with the real
  Application Insights Java agent (-javaagent), calls...
- dotnet-service (ASP.NET Core): auto-instrumented with the real
  Azure Monitor OpenTelemetry Distro (Azure.Monitor.OpenTelemetry.
  AspNetCore, UseAzureMonitor()) - a second hop in one HTTP call
  chain, with zero OpenTelemetry-aware code in either handler.

Researched and empirically verified before building anything (a
researcher subagent + my own direct testing, since the two claims
disagreed): neither agent needs a REAL Azure resource to attach and
instrument - only a well-formed connection string. Confirmed directly:
- No connection string / malformed string -> the .NET distro throws
  InvalidOperationException at startup and Java can fail similarly.
- A syntactically valid but fake connection string (real region
  endpoint, fake instrumentation key) -> both agents attach fully, both
  apps run and serve real traffic, and only the final Azure export call
  is rejected (Java logs a clean "400 Invalid instrumentation key" -
  itself proof telemetry was captured and an export was attempted).

This is what makes the whole thing verifiable without an Azure
subscription: demo_project.sh runs both services with a placeholder
connection string and proves, not asserts:
- both agents actually attached (Java's startup banner; the .NET
  service simply not crashing, given the above)
- the real cross-service HTTP call produces IDENTICAL OpenTelemetry
  trace IDs on both sides (each service reads its own auto-
  instrumented Span.current() / Activity.Current and reports it) -
  genuine W3C traceparent propagation across the JVM/CLR boundary,
  zero manual trace-linking code
- two independent, unrelated requests get two DIFFERENT trace IDs -
  ruling out a hardcoded/constant value
- the Java agent's real export attempt and its rejection, in the logs

Swap in a real APPLICATIONINSIGHTS_CONNECTION_STRING to see the same
run land in an actual Azure Application Insights resource - documented
in the project README.

Adds .github/workflows/verify-opentelemetry-appinsights-demo.yml
(matching the existing per-project verify-*.yml convention - this one
needs only Docker, no kind/kubectl/helm, since both services and their
agents run entirely inside their own containers). README.md: new row
(25) linking directly to the project folder.

Tests: ran the exact committed demo_project.sh end-to-end against real
Docker containers, twice. shellcheck clean. mvn test / dotnet build
both clean.
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.

1 participant