Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 14, 2025

Summary

This PR addresses issue #50 by adding a PivotSelector component to the browser telemetry documentation, allowing users to choose between two approaches:

  1. Razor Pages with JavaScript - Using the JavaScript OTEL SDK
  2. Blazor WebAssembly - Using .NET OpenTelemetry packages

Changes Made

  • Added PivotSelector and Pivot imports to enable-browser-telemetry.mdx
  • Wrapped existing "Razor Pages with JavaScript" content in a Pivot component
  • Added new "Blazor WebAssembly" content in a separate Pivot component
  • Fixed Blazor OTEL example to follow OpenTelemetry best practices (addresses review feedback)
  • Changed endpoint port from 21036 to 4318 (addresses review feedback)
  • Added HttpProtobuf protocol and API key header support (addresses original issue author feedback)
  • Test the documentation builds successfully
  • Verify the changes render correctly

Fixes Applied (Based on Code Review Feedback)

1. Fixed OpenTelemetry Best Practices (Comment #2535580905)

Issue: The original code created a new TracerProvider and ActivitySource on every button click, which is inefficient and goes against OpenTelemetry best practices.

Fix:

  • Moved initialization to OnInitialized() method
  • Reuse TracerProvider and ActivitySource instances
  • Added proper disposal via IDisposable implementation
  • Updated the click handler to only create activities, not providers

2. Fixed Port Number (Comment #2535580921)

Issue: The hardcoded endpoint URL used port 21036, which differs from the documented dashboard ports (16175, 4318, or 18890).

Fix:

  • Changed all instances of https://localhost:21036 to https://localhost:4318
  • Port 4318 is the standard HTTP OTLP port as documented earlier in the same file
  • Updated the note to clarify this is the documented port

3. Added Browser Compatibility Protocol (Original Issue Author Feedback)

Issue: The default gRPC protocol doesn't work in browsers. The examples were missing critical browser compatibility settings.

Fix:

  • Added options.Protocol = OtlpExportProtocol.HttpProtobuf; to both examples
  • Added @using OpenTelemetry.Exporter directive
  • Added code to parse and apply OTEL_EXPORTER_OTLP_HEADERS for API key authentication
  • Added caution note explaining when to use environment variables vs appsettings.json/IConfiguration

Updated Code Example

@using OpenTelemetry
@using OpenTelemetry.Exporter
@using OpenTelemetry.Resources
@using OpenTelemetry.Trace
@using System.Diagnostics
@implements IDisposable

<button @onclick="Trace">Trace</button>

@code {
    private TracerProvider? _tracerProvider;
    private ActivitySource? _activitySource;

    protected override void OnInitialized()
    {
        var resourceBuilder = ResourceBuilder.CreateDefault()
            .AddService("blazor-otel");

        _tracerProvider = Sdk.CreateTracerProviderBuilder()
            .SetResourceBuilder(resourceBuilder)
            .AddSource("ui")
            .AddOtlpExporter(options =>
            {
                var endpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_ENDPOINT") 
                    ?? "https://localhost:4318";
                options.Endpoint = new Uri(endpoint);
                options.Protocol = OtlpExportProtocol.HttpProtobuf;
                options.ExportProcessorType = ExportProcessorType.Simple;
                
                // Add API key header if available
                var headers = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS");
                if (!string.IsNullOrEmpty(headers))
                {
                    foreach (var header in headers.Split(','))
                    {
                        var parts = header.Split('=', 2);
                        if (parts.Length == 2)
                        {
                            options.Headers = $"{parts[0].Trim()}={parts[1].Trim()}";
                        }
                    }
                }
            })
            .Build();

        _activitySource = new ActivitySource("ui");
    }

    private void Trace()
    {
        using var activity = _activitySource?.StartActivity("trace-click", ActivityKind.Client);
        activity?.AddEvent(new ActivityEvent("Trace button click"));
    }

    public void Dispose()
    {
        _activitySource?.Dispose();
        _tracerProvider?.Dispose();
    }
}

Screenshot

Updated Blazor WebAssembly example with HttpProtobuf protocol and header support

Original prompt

Please start addressing issue #50. Please include a PivotSelector and Pivot for these new options: "Razor Pages with JavaScript" and "Blazor WebAssembly"


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…nd Blazor WebAssembly options

Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
Copilot AI changed the title [WIP] Add PivotSelector and Pivot for new options Add Blazor WebAssembly pivot to browser telemetry documentation Nov 14, 2025
Copilot finished work on behalf of IEvangelist November 14, 2025 19:05
Copilot AI requested a review from IEvangelist November 14, 2025 19:05
@IEvangelist IEvangelist marked this pull request as ready for review November 17, 2025 21:32
Copilot AI review requested due to automatic review settings November 17, 2025 21:32
Copilot finished reviewing on behalf of IEvangelist November 17, 2025 21:34
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds Blazor WebAssembly as an alternative approach to the existing JavaScript SDK for sending browser telemetry to the Aspire dashboard, addressing issue #50. This enables .NET developers to use familiar .NET OpenTelemetry APIs instead of JavaScript for telemetry configuration in browser applications.

  • Added a PivotSelector component to allow users to choose between "Razor Pages with JavaScript" and "Blazor WebAssembly" approaches
  • Documented Blazor WebAssembly configuration with OpenTelemetry packages, code examples, and best practices
  • Updated introductory text to be approach-agnostic

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

Comment on lines 357 to 371
using var otel = Sdk.CreateTracerProviderBuilder()
.SetResourceBuilder(resourceBuilder)
.AddSource("ui")
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("https://localhost:21036");
options.ExportProcessorType = ExportProcessorType.Simple;
})
.Build();
using var source = new ActivitySource("ui");
using (var activity = source.StartActivity("trace-click", ActivityKind.Client))
{
activity?.AddEvent(new ActivityEvent("Trace button click"));
}
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

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

Creating a new TracerProvider and ActivitySource on every button click is inefficient and goes against OpenTelemetry best practices. The tracer provider and activity source should be created once during application startup and reused. This pattern will create significant overhead in production scenarios. The best practices section mentions this issue, but the example code demonstrates the anti-pattern.

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

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

@copilot apply changes based on this feedback

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 481c3b5. The code now initializes TracerProvider and ActivitySource once in OnInitialized() and reuses them for each trace operation. Added proper disposal via IDisposable implementation.

Updated code example

.AddSource("ui")
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("https://localhost:21036");
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

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

The hardcoded endpoint URL uses port 21036, which differs from the dashboard configuration examples shown earlier in the document (ports 16175, 4318, or 18890). This inconsistency may confuse users. Consider using one of the documented ports or clarifying why this specific port is used.

Suggested change
options.Endpoint = new Uri("https://localhost:21036");
options.Endpoint = new Uri("https://localhost:4318");

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in commit 481c3b5. Changed all instances from port 21036 to 4318, which is the standard HTTP OTLP port documented in the dashboard configuration section.

Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 18, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • telemetry.astro.build
    • Triggering command: node /home/REDACTED/work/aspire.dev/aspire.dev/src/frontend/node_modules/.bin/astro dev (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of IEvangelist November 18, 2025 19:09
@IEvangelist
Copy link
Member

Hey @copilot please take a look at this op feedback #50 (comment)

Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 19, 2025

Hey @copilot please take a look at this op feedback #50 (comment)

Fixed in commit 61cf7a0. All three points from the original issue feedback have been addressed:

  1. Set protocol to OtlpExportProtocol.HttpProtobuf - Added to both examples with the @using OpenTelemetry.Exporter directive
  2. Handle API key authentication headers - Added code to parse and apply OTEL_EXPORTER_OTLP_HEADERS for secured dashboard endpoints
  3. Clarified environment variable usage - Added a caution note explaining when to use environment variables vs appsettings.json/IConfiguration for pure client-side apps

Updated Blazor WebAssembly example with HttpProtobuf protocol and header support

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/microsoft/aspire.dev/issues/comments/3549541959
    • Triggering command: curl -s REDACTED (http block)
  • telemetry.astro.build
    • Triggering command: node /home/REDACTED/work/aspire.dev/aspire.dev/src/frontend/node_modules/.bin/astro dev (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot finished work on behalf of IEvangelist November 19, 2025 03:47
@IEvangelist IEvangelist marked this pull request as draft November 20, 2025 16:50
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