Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Do not Merge] [Otlp Exporter] Remove Google.Protobuf and Grpc.Net.Client dependency #5731

Conversation

vishweshbankwar
Copy link
Member

@vishweshbankwar vishweshbankwar commented Jul 1, 2024

Towards #5730 #5450

Changes

  • Removes Google.Protobuf dependency for serialization for Trace exporter. Implements a custom Serializer as per the OTLP spec.
  • For Grpc, uses HttpClient for sending HTTP/2 requests. Dependency on Grpc.Core.Api is kept as is for error handling (creating RpcExceptions) (Can be removed as well by forking certain types).
  • Custom implementation is put behind a feature flag OTEL_DOTNET_EXPERIMENTAL_USE_CUSTOM_PROTOBUF_SERIALIZER for now.

Note: This is a proof of concept PR to collect the initial feedback and is not intended to be merged. Smaller follow-up PRs will be done once the approach is finalized.

Merge requirement checklist

  • CONTRIBUTING guidelines followed (license requirements, nullable enabled, static analysis, etc.)
  • Unit tests added/updated
  • Appropriate CHANGELOG.md files updated for non-trivial changes
  • Changes in public API reviewed (if applicable)

@github-actions github-actions bot added the pkg:OpenTelemetry.Exporter.OpenTelemetryProtocol Issues related to OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package label Jul 1, 2024
if (attributeCount < maxAttributeCount)
{
/*
// Alternate approach
Copy link
Member Author

Choose a reason for hiding this comment

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

@CodeBlanch - Could you take a look at this to see if it matches your expectation? I have not done the complete implementation yet, but can change if the direction looks good to you.

Copy link

codecov bot commented Jul 1, 2024

Codecov Report

Attention: Patch coverage is 76.60377% with 248 lines in your changes missing coverage. Please review.

Project coverage is 85.31%. Comparing base (6250307) to head (5e78598).
Report is 298 commits behind head on main.

Files Patch % Lines
...entation/Custom/ExportClient/GrpcProtocolHelper.cs 57.01% 49 Missing ⚠️
...rotocol/Implementation/Custom/Serializer/Writer.cs 54.71% 48 Missing ⚠️
.../Implementation/Custom/Serializer/OtlpTagWriter.cs 0.00% 41 Missing ⚠️
...TelemetryProtocol/OtlpExporterOptionsExtensions.cs 25.00% 36 Missing ⚠️
...ation/Custom/Serializer/WireTypesSizeCalculator.cs 29.03% 22 Missing ⚠️
...ol/Implementation/Custom/Transmission/OtlpRetry.cs 77.27% 15 Missing ⚠️
...ementation/Custom/Serializer/ActivitySerializer.cs 94.53% 10 Missing ⚠️
...tlpExporterPersistentStorageTransmissionHandler.cs 86.15% 9 Missing ⚠️
...tation/Custom/ExportClient/OtlpGrpcExportClient.cs 86.53% 7 Missing ⚠️
...om/Transmission/OtlpExporterTransmissionHandler.cs 88.23% 4 Missing ⚠️
... and 4 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #5731      +/-   ##
==========================================
+ Coverage   83.38%   85.31%   +1.93%     
==========================================
  Files         297      273      -24     
  Lines       12531    12103     -428     
==========================================
- Hits        10449    10326     -123     
+ Misses       2082     1777     -305     
Flag Coverage Δ
unittests ?
unittests-Project-Experimental 85.31% <76.60%> (?)
unittests-Project-Stable 85.42% <76.60%> (?)

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

Files Coverage Δ
...tation/Custom/Serializer/ActivitySizeCalculator.cs 100.00% <100.00%> (ø)
...ntation/Custom/Serializer/CommonTypesSerializer.cs 100.00% <100.00%> (ø)
.../Implementation/Custom/Transmission/RetryHelper.cs 100.00% <100.00%> (ø)
...etryProtocol/Implementation/ExperimentalOptions.cs 90.90% <100.00%> (-9.10%) ⬇️
...metryProtocol/OtlpTraceExporterHelperExtensions.cs 97.33% <100.00%> (+0.66%) ⬆️
...rter.OpenTelemetryProtocol/OtlpTraceExporterNew.cs 100.00% <100.00%> (ø)
...tion/Custom/ExportClient/TrailingHeadersHelpers.cs 50.00% <50.00%> (ø)
...ion/Custom/Serializer/CommonTypesSizeCalculator.cs 98.00% <98.00%> (ø)
...ansmission/OtlpExporterRetryTransmissionHandler.cs 80.00% <80.00%> (ø)
...tation/Custom/ExportClient/OtlpHttpExportClient.cs 91.89% <91.89%> (ø)
... and 10 more

... and 226 files with indirect coverage changes

@vishweshbankwar vishweshbankwar requested a review from JamesNK July 1, 2024 16:47
@vishweshbankwar vishweshbankwar changed the title [Do not Merge] Remove Google.Protobuf and Grpc.Net.Client dependency [Do not Merge] [Otlp Exporter] Remove Google.Protobuf and Grpc.Net.Client dependency Jul 1, 2024
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

// Includes work from:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think that it will require us to extend LICENCSE.md/create rd-party notice and include it into nuget package. It is required by Apache license,

Copy link
Member

Choose a reason for hiding this comment

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

We actually already have one: https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/THIRD-PARTY-NOTICES.TXT

Both LICENSE.txt and THIRD-PARTY-NOTICES.TXT get included in the packages today. Ex: https://nuget.info/packages/OpenTelemetry.Exporter.OpenTelemetryProtocol/1.9.0

@rajkumar-rangaraj
Copy link
Contributor

Directions look good to me. When you plan to create smaller PRs, consider adding detailed comments at the top of every method to help ease the review and later debugging process, as most of the methods perform calculations.

}
else
{
if (!ActivityListPool.TryTake(out var newList))
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need such complex storage? I understand that we need to track a single ActivitySource.Name for the instrumentation scope. Can we rely on Activity.Source and a simple thing like isSeen during the serialization process?

ref byte[] buffer,
int cursor,
int fieldNumber,
ReadOnlySpan<char> value,
Copy link
Member

Choose a reason for hiding this comment

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

@vishweshbankwar I pushed an update so Writer understands how to write a ReadOnlySpan<char> to the buffer. Previously we called ToString in TagWriter which would have caused a lot of extra allocations. Also updated this so it calls into the code to grow the buffer if needed before writing instead of having two branches with one performing that check per-byte/char written. Should be much faster this way and I think simpler.

Copy link
Contributor

This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or Pushing will instruct the bot to automatically remove the label. This bot runs once per day.

@github-actions github-actions bot added the Stale Issues and pull requests which have been flagged for closing due to inactivity label Jul 16, 2024
Copy link
Contributor

Closed as inactive. Feel free to reopen if this PR is still being worked on.

@github-actions github-actions bot closed this Jul 23, 2024
@github-actions github-actions bot added perf Performance related and removed Stale Issues and pull requests which have been flagged for closing due to inactivity labels Jul 31, 2024
Comment on lines +289 to +297
if (isBrowser)
{
detail += " If the gRPC call is cross domain then CORS must be correctly configured. Access-Control-Expose-Headers needs to include 'grpc-status' and 'grpc-message'.";
}

if (isWinHttp)
{
detail += " Using gRPC with WinHttp has Windows and package version requirements. See https://aka.ms/aspnet/grpc/netstandard for details.";
}
Copy link
Contributor

Choose a reason for hiding this comment

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

You don't need to worry about grpc-web or CORS.
Do you plan on supporting WinHttpHandler for .NET Framework support?

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you plan on supporting WinHttpHandler for .NET Framework support?

No

// We do not need to return back response and deadline for successful response so using cached value.
return SuccessExportResponse;
}
catch (Exception ex)
Copy link
Contributor

Choose a reason for hiding this comment

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

This whole catch block is a bit of a mess. Why not separate catch statements?

// https://github.com/grpc/grpc-dotnet/blob/1416340c85bb5925b5fed0c101e7e6de71e367e0/src/Grpc.Net.Client/Internal/GrpcCall.cs#L799-L803
// Utilizing the inner exception here to determine deadline exceeded related failures.
// https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclient.sendasync?view=net-8.0#remarks
if (ex.InnerException is TimeoutException)
Copy link
Contributor

Choose a reason for hiding this comment

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

Using HttpClient.Timeout for deadline is probably ok. I assume you have global deadline duration that is applied to all requests so timetout works.

For Grpc.Net.Client, the deadline can differ per call.

var dataLength = contentLength - 5;
BinaryPrimitives.WriteUInt32BigEndian(data, (uint)dataLength);

// TODO: Support compression.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you ever send compressed gRPC request data today? If you don't, then it's not needed.

You probably need to handle compressed responses. There might be an OTLP gRPC server that sends a compressed response for some reason.

Copy link
Member Author

Choose a reason for hiding this comment

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

My understanding is users can specify grpc-encoding header which will result in compressed payload to be transmitted.

// grpc-dotnet calls specifies the HttpCompletion.ResponseHeadersRead.
// However, it is useful specifically for streaming calls?
// https://github.com/grpc/grpc-dotnet/blob/1416340c85bb5925b5fed0c101e7e6de71e367e0/src/Grpc.Net.Client/Internal/GrpcCall.cs#L485-L486
return this.HttpClient.SendAsync(request, cancellationToken).GetAwaiter().GetResult();
Copy link
Contributor

Choose a reason for hiding this comment

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

This is blocking so you need to worry about thread pool starvation. Are OTLP gRPC calls made on a dedicated thread? If so, that means a maximum of one thread is blocked and this isn't a bad.

Copy link
Member

@cijothomas cijothomas Aug 6, 2024

Choose a reason for hiding this comment

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

Are OTLP gRPC calls made on a dedicated thread

Yes. (but there will be 3 such threads created by traces,logs,metrics)

Comment on lines +30 to +48
public static readonly string ResponseTrailersKey = "__ResponseTrailers";

public static HttpHeaders TrailingHeaders(this HttpResponseMessage responseMessage)
{
#if !NETSTANDARD2_0 && !NET462
return responseMessage.TrailingHeaders;
#else
if (responseMessage.RequestMessage.Properties.TryGetValue(ResponseTrailersKey, out var headers) &&
headers is HttpHeaders httpHeaders)
{
return httpHeaders;
}

// App targets .NET Standard 2.0 and the handler hasn't set trailers
// in RequestMessage.Properties with known key. Return empty collection.
// Client call will likely fail because it is unable to get a grpc-status.
return ResponseTrailers.Empty;
#endif
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you plan to support .NET Framework with WinHttpHandler? If not, then this can be simplified to always return TrailingHeaders.

Copy link
Contributor

This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or Pushing will instruct the bot to automatically remove the label. This bot runs once per day.

@github-actions github-actions bot added the Stale Issues and pull requests which have been flagged for closing due to inactivity label Aug 14, 2024
Copy link
Contributor

Closed as inactive. Feel free to reopen if this PR is still being worked on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
perf Performance related pkg:OpenTelemetry.Exporter.OpenTelemetryProtocol Issues related to OpenTelemetry.Exporter.OpenTelemetryProtocol NuGet package Stale Issues and pull requests which have been flagged for closing due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants