-
Notifications
You must be signed in to change notification settings - Fork 936
Remove Guava dependencies from SDK #2148
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
Conversation
|
CC @thisthat |
Oberon00
left a comment
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.
Thank you for the work! Since this is a rather big PR, maybe it could be split up a bit. zPages may be worth splitting out (if we want to get rid of Guava there at all), and the core SDK (sdk-all + dependencies + maybe core propagators/exporters) could be split out since that part would be straightforward.
| } | ||
|
|
||
| @VisibleForTesting | ||
| // Visible for testing |
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 we should add such an annotation to the API package or some util package. It is useful documentation and a bit nicer than a comment.
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.
The annotation has been around for a looong time and I've never seen any tooling use it. Is it much better than a comment? Then we wouldn't need to maintain the annotation.
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.
Hmm, no strong opinion. If you think the annotation fits badly, comments should be fine too.
| } | ||
| int b; | ||
| while ((b = is.read()) != -1) { | ||
| os.write(b); |
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.
Byte-wise reading looks quite inefficient.
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.
Oops for some reason thought this was in-memory
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.
Wouldn't the overhead be even worse then, relatively speaking? EDIT: Depending on whether the I/O does some internal buffering.
| private boolean isOnEcs() { | ||
| return (!Strings.isNullOrEmpty(sysEnv.get(ECS_METADATA_KEY_V3)) | ||
| || !Strings.isNullOrEmpty(sysEnv.get(ECS_METADATA_KEY_V4))); | ||
| String metadata = sysEnv.getOrDefault(ECS_METADATA_KEY_V3, ""); |
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.
With the getOrDefault, can't you keep it as a single expression? Also, I think we have some isNullOrEmpty helper already in the propagator-utils.
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.
Yeah don't think we can use propagator classes here. We could move it to API to the internal package, but so far we don't leak internal classes across artifacts in this repo. I think it's ok though so if others thing so too I could do that.
| try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(file))) { | ||
| while (true) { | ||
| int read = is.read(result); | ||
| if (read < 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.
Shouldn't one abort also if read == 0? AFAIK this is documented to only happen at EOF.
| return ""; | ||
| } | ||
|
|
||
| private static byte[] readAllBytes(String path) throws IOException { |
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.
Even in Java 7, there is a stdlib API that does that: https://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#readAllBytes(java.nio.file.Path)
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.
Not on Android - but I realized, this module should not have the Android sniffer on... Nice!
| .filter(s -> !s.isEmpty()) | ||
| .map(String::trim) |
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.
| .filter(s -> !s.isEmpty()) | |
| .map(String::trim) |
Should not be needed. Also spaces may be relevant here.
| if (keyValuePair.get(0).equals(PARAM_SPAN_NAME)) { | ||
| try { | ||
| queryMap.put( | ||
| keyValuePair.get(0), URLDecoder.decode(keyValuePair.get(1), "UTF-8")); |
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.
Why only decode selectively here? Shouldn't all keys and values be decoded?
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.
Think I agree - would probably fix that separately from guava refactoring.
| public T readProperties(Properties properties) { | ||
| return fromConfigMap(Maps.fromProperties(properties), NamingConvention.DOT); | ||
| Map<String, String> map = new HashMap<>(properties.size()); | ||
| properties.forEach((key, value) -> map.put((String) key, (String) value)); |
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 a normal foreach loop would be more readable.
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.
Hmm - I've always appreciated Java 8's Map.forEach since Entry can be a bit gross :)
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.
Alternatively, how about some casting? https://stackoverflow.com/a/17209434/2128694
Map<String, String> map = (Map<String, String>)(Map)properties;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.
Thanks!
| Collections.unmodifiableSet( | ||
| Arrays.stream(stringValue.split(",")) | ||
| .filter(s -> !s.isEmpty()) | ||
| .map(String::trim) |
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 you might need to swap the order of trim/isEmpty to match Guava. AFAIK omitEmptyStrings only sets a boolean. But I may be wrong here.
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.
Whether or not it matches guava, this logic seems right. Values that are only whitespace shouldn't be used, I don't think.
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.
My not splitting the PRs up in advance caused this review to be a bit hectic, sorry about that. While GitHub doesn't have the outdated mark here, if I remember correctly, the code used to be in the wrong order and @Oberon00 commented and I fixed it so it should be good now.
| traceConfig.getMaxNumberOfAttributesPerLink() > 0, "maxNumberOfAttributesPerLink"); | ||
| Preconditions.checkArgument( | ||
| traceConfig.getMaxLengthOfAttributeValues() >= -1, "maxLengthOfAttributeValues"); | ||
| if (traceConfig.getMaxNumberOfAttributes() <= 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.
Didn't we have some Utils.checkArgument function?
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.
Yeah we have it in API - if we're ok with cross-referencing from other artifacts (guess it's ok) I'll use 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.
Yeah, the SDK uses API classes quite a bit (obviously because it has to implement it!). I think this is a fine usage, as long as it's not in a strictly "internal" package.
anuraaga
left a comment
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.
Sure let me split zpages out
| } | ||
|
|
||
| @VisibleForTesting | ||
| // Visible for testing |
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.
The annotation has been around for a looong time and I've never seen any tooling use it. Is it much better than a comment? Then we wouldn't need to maintain the annotation.
| private boolean isOnEcs() { | ||
| return (!Strings.isNullOrEmpty(sysEnv.get(ECS_METADATA_KEY_V3)) | ||
| || !Strings.isNullOrEmpty(sysEnv.get(ECS_METADATA_KEY_V4))); | ||
| String metadata = sysEnv.getOrDefault(ECS_METADATA_KEY_V3, ""); |
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.
Yeah don't think we can use propagator classes here. We could move it to API to the internal package, but so far we don't leak internal classes across artifacts in this repo. I think it's ok though so if others thing so too I could do that.
| } | ||
| int b; | ||
| while ((b = is.read()) != -1) { | ||
| os.write(b); |
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.
Oops for some reason thought this was in-memory
| return ImmutableMap.copyOf(queryMap); | ||
| Arrays.stream(queryString.split("&")) | ||
| .filter(s -> !s.isEmpty()) | ||
| .map(String::trim) |
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.
Hmm - not sure just reproing the current code for now
| if (keyValuePair.get(0).equals(PARAM_SPAN_NAME)) { | ||
| try { | ||
| queryMap.put( | ||
| keyValuePair.get(0), URLDecoder.decode(keyValuePair.get(1), "UTF-8")); |
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.
Think I agree - would probably fix that separately from guava refactoring.
| public T readProperties(Properties properties) { | ||
| return fromConfigMap(Maps.fromProperties(properties), NamingConvention.DOT); | ||
| Map<String, String> map = new HashMap<>(properties.size()); | ||
| properties.forEach((key, value) -> map.put((String) key, (String) value)); |
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.
Hmm - I've always appreciated Java 8's Map.forEach since Entry can be a bit gross :)
| traceConfig.getMaxNumberOfAttributesPerLink() > 0, "maxNumberOfAttributesPerLink"); | ||
| Preconditions.checkArgument( | ||
| traceConfig.getMaxLengthOfAttributeValues() >= -1, "maxLengthOfAttributeValues"); | ||
| if (traceConfig.getMaxNumberOfAttributes() <= 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.
Yeah we have it in API - if we're ok with cross-referencing from other artifacts (guess it's ok) I'll use it
| @Override | ||
| public int compare(Event e1, Event e2) { | ||
| return Long.compare(e1.getEpochNanos(), e2.getEpochNanos()); | ||
| private static String escapeHtml(String html) { |
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.
Yeah this is the one line that gets most benefit from Guava. I'm mixed, 2MB dependency just for this function, mostly :)
| os.write(b); | ||
| byte[] buf = new byte[8192]; | ||
| while (is.read(buf) != -1) { | ||
| os.write(buf); |
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.
You can't write the full buffer here. You need to check how many bytes you actually read into the buffer, which may be less.
2106b56 to
d962c1c
Compare
Oberon00
left a comment
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.
Some cleanups should be considered, but all in all 👍
| public T readProperties(Properties properties) { | ||
| return fromConfigMap(Maps.fromProperties(properties), NamingConvention.DOT); | ||
| Map<String, String> map = new HashMap<>(properties.size()); | ||
| properties.forEach((key, value) -> map.put((String) key, (String) value)); |
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.
Alternatively, how about some casting? https://stackoverflow.com/a/17209434/2128694
Map<String, String> map = (Map<String, String>)(Map)properties;
jkwatson
left a comment
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.
Thanks!
For #1944
Remaining are gRPC-based artifacts (always use guava), opencensus shim (it's going away in new implementation type), and jfr (will probably use weak-lock-free for it after raphw/weak-lock-free#12)