gax-java
gax-java copied to clipboard
What's the correct way to set "user-agent" header?
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?
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.
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)
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.
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.)
@sduskis - did this get deprioritized? This functionality is fairly important for gathering good metrics. Can we get this scheduled?
@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.
- there is no such thing as gapic-specific "CallOption" in java, we are not going to add it to support WithUserAgent field. Note
I would strongly suggest closing this issue unless there are very-very strong objective reasons to keep it.
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.
You can use a custom implementation of the HeaderProvider
for maximum flexibility.