open-telemetry / opentelemetry-dotnet-contrib

This repository contains set of components extending functionality of the OpenTelemetry .NET SDK. Instrumentation libraries, exporters, and other components can find their home here.
https://opentelemetry.io
Apache License 2.0
478 stars 284 forks source link

Trace spans for Http requests not being created in Android #1712

Open farlop opened 6 months ago

farlop commented 6 months ago

Issue with OpenTelemetry.Instrumentation.Http

List of all OpenTelemetry NuGet packages and version that you are using (e.g. OpenTelemetry 1.3.2):

OpenTelemetry.Instrumentation.Http 1.8.1 OpenTelemetry.Exporter.Console 1.8.1 OpenTelemetry 1.8.1

Runtime version (e.g. net462, net48, net6.0, net7.0 etc. You can find this information from the *.csproj file):

net8.0-android

Is this a feature request or a bug?

What is the expected behavior?

Trace spans should be created for any Http request, regardless of the target OS

What is the actual behavior?

Trace spans are not being created in MAUI (Android)

Trace spans are created successfully in MAUI when running as Windows App.

See the following repro: MauiApp2.zip

Additional Context

The same problem occurs in Xamarin.Android

martinjt commented 6 months ago

@farlop Have you tried using the latest versions? I suspect this is an old issue.

farlop commented 5 months ago

Hi @martinjt.

The repro provided uses version 1.8.1 for all packages.

I've tried upgrading to 1.9.0-alpha.1 and tested again.

This is the output from the Console Exporter when MAUI app is launched locally in a Windows machine:

Activity.TraceId:            f8fbaea8c1025158e75ac51fab820a78
Activity.SpanId:             538a21eea0be5744
Activity.TraceFlags:         Recorded
Activity.ParentSpanId:       1c76c8e3a0c05081
Activity.ActivitySourceName: System.Net.Http
Activity.DisplayName:        GET
Activity.Kind:               Client
Activity.StartTime:          2024-06-07T08:23:13.2251197Z
Activity.Duration:           00:00:00.2168894
Activity.Tags:
    http.request.method: GET
    server.address: www.google.es
    server.port: 443
    url.full: https://www.google.es/
    network.protocol.version: 1.1
    http.response.status_code: 200
Resource associated with Activity:
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.9.0-alpha.1
    service.name: unknown_service:MauiApp2

Activity.TraceId:            f8fbaea8c1025158e75ac51fab820a78
Activity.SpanId:             1c76c8e3a0c05081
Activity.TraceFlags:         Recorded
Activity.ActivitySourceName: MauiApp2
Activity.DisplayName:        Test
Activity.Kind:               Internal
Activity.StartTime:          2024-06-07T08:23:13.2247627Z
Activity.Duration:           00:00:00.2537585
Resource associated with Activity:
    telemetry.sdk.name: opentelemetry
    telemetry.sdk.language: dotnet
    telemetry.sdk.version: 1.9.0-alpha.1
    service.name: unknown_service:MauiApp2

And this is the output when running on Android emulator:

[0:] Activity.TraceId:            4a4cd2c6ff993b1795654c4895735aab
[0:] Activity.SpanId:             88e6a1c20b8ee8ff
[0:] Activity.TraceFlags:         Recorded
[0:] Activity.ActivitySourceName: MauiApp2
[0:] Activity.DisplayName:        Test
[0:] Activity.Kind:               Internal
[0:] Activity.StartTime:          2024-06-07T08:26:27.6504492Z
[0:] Activity.Duration:           00:00:00.3021977
[0:] Resource associated with Activity:
[0:]     telemetry.sdk.name: opentelemetry
[0:]     telemetry.sdk.language: dotnet
[0:]     telemetry.sdk.version: 1.9.0-alpha.1
[0:]     service.name: unknown_service:nyname.mauiapp2
[0:] 

As you can see, it is missing the HttpClient inner span.

martinjt commented 5 months ago

So this looks like MAUI is not outputting the right information, perhaps using a custom HTTP client that doesn't generate use the diagnostic listeners properly.

@bijington anything you can tell us about the HTTP client in MAUI

bijington commented 5 months ago

So this looks like MAUI is not outputting the right information, perhaps using a custom HTTP client that doesn't generate use the diagnostic listeners properly.

@bijington anything you can tell us about the HTTP client in MAUI

I haven't looked into this issue myself but I can point you to this issue https://github.com/BretJohnson/aspire-mobile/issues/29 and possibly more importantly @bretjohnson that may know more

farlop commented 5 months ago

Just wanted to mention that the problem was already facing in a Xamarin app on Android. Could it be somehow related to monoandroid?

Enviado desde Outlook para Androidhttps://aka.ms/AAb9ysg


From: Shaun Lawrence @.> Sent: Friday, June 7, 2024 11:56:59 AM To: open-telemetry/opentelemetry-dotnet-contrib @.> Cc: Andrés Valor @.>; Mention @.> Subject: Re: [open-telemetry/opentelemetry-dotnet-contrib] Trace spans for Http requests not being created in Android (Issue #1712)

So this looks like MAUI is not outputting the right information, perhaps using a custom HTTP client that doesn't generate use the diagnostic listeners properly.

@bijingtonhttps://github.com/bijington anything you can tell us about the HTTP client in MAUI

I haven't looked into this issue myself but I can point you to this issue BretJohnson/aspire-mobile#29https://github.com/BretJohnson/aspire-mobile/issues/29 and possibly more importantly @BretJohnsonhttps://github.com/BretJohnson that may know more

— Reply to this email directly, view it on GitHubhttps://github.com/open-telemetry/opentelemetry-dotnet-contrib/issues/1712#issuecomment-2154504205, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AAUNMHU4ALJ3MUEH4HQ4HVDZGF7WXAVCNFSM6AAAAABHPHWRWCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJUGUYDIMRQGU. You are receiving this because you were mentioned.Message ID: @.***>

BretJohnson commented 5 months ago

I tracked down the root cause of this. The problem is at initialization time. https://github.com/open-telemetry/opentelemetry-dotnet provides open telemetry client functionality via IHostedService. MAUI as of today is a service container but doesn't have built in support for microsoft.extensions.hosting - it's not a hosted service container. In particular, services that are registered in a MAUI app can be queried but no one calls IHostedService.StartAsync on them, to start services that intended to run in the background. Currently the OpenTelemetry client service requires this, to initialize some trace stuff. If the initialization step is forced (I hacked in some code to loop thru all services and call IHostedService.StartAsync on services that support IHostedService), then it in fact does work.

That's the background, but I'd like to make a proper fix here & am open to suggestions. I see three options:

  1. Productize my hack above in the aspire-mobile NuGet. That can work, but it's kind of hacky, maybe 50 lines of code, and the shutdown case isn't handled well currently.
  2. Have MAUI provide first class support for microsoft.extensions.hosting. This may be the right thing long term, but we discussed, and I don't think it's going to happen for .NET9 (let alone .NET8).
  3. Use some kind of alternate APIs, if they exist, to initialize the OpenTelemetry C# client and avoid the need for the IHostedService.StartAsync. What do you all think about this option? Are there such alternate APIs today?
farlop commented 5 months ago

While I agree in the second option as the long term solution, I believe that something else is needed in short term for existing MAUI and Xamarin applications.

I can imagine a compatibility package with a helper class that exposes an extension method to the TracerProviderBuilder and forces that initialization you mentioned on first option.

martinjt commented 5 months ago

@BretJohnson I'm sure those are issues, and we can solve them, however, I think the example here might be different.

The example is that some spans are making it through, but others aren't.

That would imply that something is happening differently in the HttpClient specifically. This happens in blazor too since it uses a different httphandler that doesn't enable diagnostics.

BretJohnson commented 4 months ago

Sorry, as I meant to post here earlier, but we did track this down. If you set <HttpActivityPropagationSupport>true</HttpActivityPropagationSupport> in the csproj for the Android app, that should make it work - I confirmed it working after. The issue is that by default for .NET Android the affected code isn't present, for code size reasons, but enabling this includes the needed support. If the OpenTelemetry diagnostics support is only used in debug builds, you may wish to only enable the setting for Debug, continuing to get the code size benefit for Release builds. But that said, I'm not sure how much difference it actually makes for code size.

farlop commented 4 months ago

I've checked adding <HttpActivityPropagationSupport>true</HttpActivityPropagationSupport> to the .csproj file and I can confirm it works now:

[0:] Activity.TraceId:            ce47faf9e82d79d4309b8cef4812fc00
[0:] Activity.SpanId:             c87483ea6b67235e
[0:] Activity.TraceFlags:         Recorded
[0:] Activity.ParentSpanId:       86cc88de2ac90b7c
[0:] Activity.ActivitySourceName: System.Net.Http
[0:] Activity.DisplayName:        GET
[0:] Activity.Kind:               Client
[0:] Activity.StartTime:          2024-07-23T14:40:09.2694793Z
[0:] Activity.Duration:           00:00:00.7126078
[0:] Activity.Tags:
[0:]     http.request.method: GET
[0:]     server.address: www.google.es
[0:]     server.port: 443
[0:]     url.full: https://www.google.es/
[0:]     network.protocol.version: 1.1
[0:]     http.response.status_code: 200
[0:] Resource associated with Activity:
[0:]     service.name: http-service-example
[0:]     service.instance.id: 7884ce29-2d2e-4d46-a598-2d34d1e7a60f
[0:]     telemetry.sdk.name: opentelemetry
[0:]     telemetry.sdk.language: dotnet
[0:]     telemetry.sdk.version: 1.9.0
[0:] 
[0:] Activity.TraceId:            ce47faf9e82d79d4309b8cef4812fc00
[0:] Activity.SpanId:             86cc88de2ac90b7c
[0:] Activity.TraceFlags:         Recorded
[0:] Activity.ActivitySourceName: MauiApp2
[0:] Activity.DisplayName:        Test
[0:] Activity.Kind:               Internal
[0:] Activity.StartTime:          2024-07-23T14:40:06.1411833Z
[0:] Activity.Duration:           00:00:11.4750889
[0:] Resource associated with Activity:
[0:]     service.name: http-service-example
[0:]     service.instance.id: 7884ce29-2d2e-4d46-a598-2d34d1e7a60f
[0:]     telemetry.sdk.name: opentelemetry
[0:]     telemetry.sdk.language: dotnet
[0:]     telemetry.sdk.version: 1.9.0
[0:] 

Unfortunately, this doesn't seem to work in a Xamarin Android application. Is this property something that was added for newer .NET versions?

Is there any way to somehow achieve this behavior in Xamarin Android?

Thank you for your efforts :)