gax-java icon indicating copy to clipboard operation
gax-java copied to clipboard

What's the correct way to set "user-agent" header?

Open songy23 opened this issue 6 years ago • 7 comments

Hello GAX-Java maintainers,

This is Yang from OpenCensus team. Recently we've been working on adding the user-agent header to our Stackdriver Monitoring exporters for all languages. This allows Stackdriver Monitoring to group the uploaded metrics by different sources (e.g from OpenCensus vs. from other libraries), by looking at the value of the user-agent header.

However, I've noticed that in Java the way to set user-agent header is different from other languages. For example, in GAX-Go we have the ClientOption where we can directly set user-agent. Later this header will be merged with the Google user-agent headers: https://github.com/googleapis/google-api-go-client/blob/master/monitoring/v3/monitoring-gen.go#L96-L101.

In Java however, we don't have this kind of option in ClientSettings. If I understand correctly, we should provide a FixedHeaderProvider with the user-agent header to ClientSettings instead. In our case, the Stackdriver MetricServiceClient uses gRPC so we need to set HeaderProvider to the gRPC channel provider. Here's what I did in https://github.com/census-instrumentation/opencensus-java/pull/1518.

However, I also saw the comments below in GrpcHeaderInterceptor:

// User-Agent is overridden on gRPC level. The custom User-Agent is supposed to be provided
// differently and only merging with gRPC default value for User-Agent is permitted.
// Specifically the User-Agent will be provided via ManagedChannelBuilder#userAgent(String)
// during channel construction (calling #getUserAgentHeader() to get the value, initialized
// here).

I got a bit confused by that. Does it mean no matter what custom header value we set for user-agent, it will be discarded and override by gRPC? Or does it work in a similar way in Go that we merge the custom value with the Google default value?

songy23 avatar Oct 26 '18 18:10 songy23

Friendly ping.

I saw that in C++ we also have the WithUserAgent option: https://github.com/census-instrumentation/opencensus-cpp/pull/234. Looks like GAX-Java is the only library that doesn't have this option.

songy23 avatar Nov 06 '18 18:11 songy23

Currently working on porting the Cloud KMS Java samples from the Apiary client to the GAPIC clients, and this is a gap. I'm looking for this to be exposed in ClientSettings as well, so that we don't lose this functionality-- we have Apiary clients that are setting it, and therefore helping us to get useful metrics (see e.g. Tink)

bdhess avatar Nov 14 '18 12:11 bdhess

As the comment says ("only merging with gRPC default value for User-Agent is permitted"), the user-agent value is merged with the grpc one.

Assigning to @vam-google for any follow-up questions.

garrettjonesgoogle avatar Nov 15 '18 14:11 garrettjonesgoogle

Thanks @garrettjonesgoogle for the explanation. I think my question is answered. Since @bdhess mentioned you want to add the WithUserAgent() option to ClientSettings, this issue can be left open to keep track of the progress of that. (Or you can open a new issue and close this one.)

songy23 avatar Nov 15 '18 17:11 songy23

@sduskis - did this get deprioritized? This functionality is fairly important for gathering good metrics. Can we get this scheduled?

bdhess avatar Dec 11 '18 18:12 bdhess

@bdhess, @sduskis, @songy23 I'm really confused by this issue and do not understand what we are trying to achieve here.

Yes, there are differences between Go and Java clients, there are many of them. Actually all of the clients (in all 7 languages) have many differences. Trying to make Java clients to have same surface as Go clients for a particular feature (like WithUserAgent here) does not seem like a valid goal, because:

  • even if we make them same here it does not eliminate multiple other discrepancies (what is so special about this one?)
  • why are we trying to make Java look like Go, why not Go look like Java?
  • even if we agreed on making the changes there are technical issues with it:
    • there is no such thing as gapic-specific "CallOption" in java, we are not going to add it to support WithUserAgent field. Note ClientCoption in Go and <Client>Settings in Java gapics are fundamentally different things - the first one is a "static" file checked in in to repo and shared by multiple clients, the second one is generated for each individual client separately and is used only by that client.
    • Making java gapics look like Go clients will make them look less like java manual clients (which reside in same google-cloud-java repository, for example the storage client). HeaderProvider is needed to set user-agent for both types of clients (manual and generated). So we are potentially sacrificing java clients "internal" consistency for a cross-language consistency.

I would strongly suggest closing this issue unless there are very-very strong objective reasons to keep it.

vam-google avatar Dec 11 '18 20:12 vam-google

My original question is just asking if using FixedHeaderProvider is the correct way to set "user-agent" header. I asked this question because clients in all other languages provided APIs to set it directly, while Java doesn't. IMO this is a missing functionality in (and only in) Java.

However if you think users should always use FixedHeaderProvider, please document it somewhere since it's not easy to find this option.

why are we trying to make Java look like Go, why not Go look like Java?

Just FYI not only Go. Python, C++ also have this option.

songy23 avatar Dec 12 '18 02:12 songy23

You can use a custom implementation of the HeaderProvider for maximum flexibility.

meltsufin avatar Sep 28 '22 18:09 meltsufin