-
Notifications
You must be signed in to change notification settings - Fork 66
feat: [Geneva Exporter] Add configurable User-Agent Header #400
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
base: main
Are you sure you want to change the base?
Conversation
opentelemetry-exporter-geneva/geneva-uploader/src/config_service/client.rs
Outdated
Show resolved
Hide resolved
opentelemetry-exporter-geneva/geneva-uploader/src/config_service/client.rs
Outdated
Show resolved
Hide resolved
opentelemetry-exporter-geneva/geneva-uploader/src/config_service/client.rs
Outdated
Show resolved
Hide resolved
If this is the only intention, then should we choose the User Agent ourselves instead of letting the user override it and potentially misuse or erroneously use it. We should be able to get hold of the executable name through |
…ust-contrib into custom-user-agent
…ust-contrib into custom-user-agent
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #400 +/- ##
=======================================
+ Coverage 48.1% 48.7% +0.6%
=======================================
Files 69 70 +1
Lines 9811 9969 +158
=======================================
+ Hits 4720 4859 +139
- Misses 5091 5110 +19 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Intention is to provide the applications to provide the customization for the User-Agent- according to the format they want (which could be say |
format!("{prefix} (GenevaUploader/0.1)") | ||
}; | ||
|
||
HeaderValue::from_str(&user_agent).map_err(|e| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this method does the ASCII characters validation check anyway so we could get avoid checking that ourselves.
for (i, ch) in prefix.char_indices() { | ||
match ch { | ||
// Control characters that would break HTTP headers | ||
'\r' | '\n' | '\0' => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think had initially suggested checking for control characters in a comment, but I realized they would anyway be outside of the ASCII range so we would never allow control characters as long as we only accept ASCII.
And the ASCII check is already done by HeaderValue::from_str()
method, so we can probably get rid of this whole method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems HeaderValue::from_str()
allows non-ascii chars
https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=1e264800416082c69cbb17c474caab02
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I am good to remove the validation altogether, and let the reqwest crate handle it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems
HeaderValue::from_str()
allows non-ascii chars https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=1e264800416082c69cbb17c474caab02
This led to some new learnings. The documentation for HeaderValue::from_str()
method says that it doesn't allow non-ASCII characters so I would have expected the test cases you shared to fail. I then found this is in the documentation for HeaderValue
struct:
In practice, HTTP header field values are usually valid ASCII. However, the HTTP spec allows for a header value to contain opaque bytes as well. In this case, the header field value is not able to be represented as a string.
To handle this, the HeaderValue is useable as a type and can be compared with strings and implements Debug. A to_str fn is provided that returns an Err if the header value contains non visible ascii characters.
This means that we need to check if HeaderValue::from_str(str).is_ok() && HeaderValue::from_str(str).unwrap().to_str().is_ok()
to rule out the non-ASCII inputs.
Check this: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=9802b30e262c93e92e71fd92fcb543dd
pub async fn new(cfg: GenevaClientConfig) -> Result<Self, String> { | ||
// Build config client config | ||
// Validate user agent prefix once and build headers once for both services | ||
// This avoids duplicate validation and header building in config and ingestion services |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a duplicate validation since build_geneva_headers
method also calls validate_user_agent_prefix
method.
Changes
The
User-Agent
HTTP header should ideally identify the application making the request, not just the library.This PR adds configurable User-Agent header support to the Geneva Uploader, allowing applications to identify themselves in HTTP requests to Geneva services.
So the approach with the PR is:
None
RustGenevaClient/0.1
Some("MyApp/2.1.0")
MyApp/2.1.0 (RustGenevaClient/0.1)
Also added support to provide the user-agent header in the Ingestion Service (along with Config Service)
Merge requirement checklist
CHANGELOG.md
files updated for non-trivial, user-facing changes