-
Notifications
You must be signed in to change notification settings - Fork 344
Change BINARY to be resizable and stream-oriented. #223
Conversation
Glad to see us moving on this. I have a few high level design suggestions.
|
2182e75
to
1d5cb2a
Compare
Hey @yurishkuro thanks for the feedback! So this is an updated PR with the mentioned changes (the only thing was that I left out for now the |
@@ -0,0 +1,41 @@ | |||
/* | |||
* Copyright 2016-2017 The OpenTracing Authors |
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.
nit: as this is new code, (c) is only 2017 (same in other files)
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.
:) Had missed that, will fix.
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.
Oh, btw, if I use 2017
alone the build fails. Guess we need to issue a PR for fixing this part in pom.xml ;)
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.
+1 on the overall approach. Suggest soliciting other reviews, especially from people who were asking for binary format in the first place, and with at least these two questions:
- agreement on the inbound/outbound terminology (if we could re-phrase in terms of inject/extract it would be better, less conceptual overhead)
- the exact shape of read/write methods.
/** | ||
* @return whether this instance is outbound and supports writing. | ||
*/ | ||
boolean isOutbound(); |
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.
are these required? We didn't have them in TextMap afaik. E.g. I don't know why a Tracer would want to call these.
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.
Would be more of helper methods (as the Binary
format either supports injection or extraction, not both). We can remove them if you think they don't bring enough 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.
+1 to remove, does not add much 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.
Makes sense. Lets get rid of them.
* | ||
* @param b the data. | ||
*/ | ||
void write(byte[] b) 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.
I don't have a strong opinion about the exact read/write API, but would it make more sense to model these functions after nio ReadableByteChannel and WritableByteChannel? They each have just a single method, but it's based on ByteBuffer, which I'm guessing makes them equivalent to several overloaded methods of Input/OutputStream, and certainly more flexible than write(byte[] b)
(which requires an allocation if you're writing in batches of different sizes). Maybe it's not an issue for propagation codecs specifically.
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.
Agreed. I believe ByteBuffer provides a greater level of flexibility while still being able to wrap (without copy) a byte[] with ByteBuffer.wrap
/** | ||
* @return A newly allocated byte array with the written data. | ||
*/ | ||
byte[] getOutboundData(); |
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.
seems premature. Can always be implemented with a loop by calling read(), although less efficiently without knowing the full size of the payload.
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.
So this is for the written data (when inject()
was called), and this is supposed to be called after inject()
to retrieve all those bytes. The alternatives is to let the user pass us a ByteArrayOutputStream
(or similar) at Adapters.outboundBinary()
. What do you think?
Regarding the naming, what about |
What's missing for me is MockTracer support. I would like to see tests with MockTracer inject/extract binary data. |
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 is a good start. Adding some tests specifically for the new format to opentracing-mock
would be helpful. I feel what people need is simply a single wrapper for output and input streams which satisfies the tracer inject/extract api.
|
||
import java.io.IOException; | ||
|
||
public final class Adapters { |
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 do not see a real benefit of having this class. Simply calling the appropriate constructor of BinaryAdapter
in a call to inject or extract should do.
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 idea is to put other formats here, so we can abstract the actual implementations, so we don't have to expose BinaryAdapter
and others.
/** | ||
* @return whether this instance is outbound and supports writing. | ||
*/ | ||
boolean isOutbound(); |
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.
+1 to remove, does not add much value
|
||
return inputStream.read(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.
Limiting the methods of ByteArrayOutputStream
and ByteArrayInputStream
to only read(byte[] b)
and write(byte[] b)
may limit tracing implementation libraries. Suppose this class simply had two getters:
public InputStream getInput() {
if (inputStream == null) {
throw new UnsupportedOperationException();
}
return inputStream;
}
public OutputStream getOutput() {
if (outputStream == null) {
throw new UnsupportedOperationException();
}
return outputStream;
}
This would allow much greater flexibility to the tracing implementations (by not being rigid on what/how to read and when to close) and yet satisfy the api as defined by inject
and extract
.
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 personally think exposing the actual stream objects would be overloading the API, trying to cover all cases and scenarios eventually. In any case, if this is truly needed, can be added in the future.
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.
On a second thought: we may as well remove the write/read methods and end up exposing the streams too (after prototyping the MockTracer
support for BINARY) ;)
|
||
byte[] buff = new byte[4]; | ||
|
||
assertEquals(4, binary.read(buff)); |
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.
nit: let's define some constants
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 is a very, very simple test, no need to put constants. Maybe we can have assertEquals(buff.length, binary.read(buff))
and that should be an improvement already ;)
@malafeev Oh, sure, will cook some examples - the thing is that I need to add support for the |
binary.write(ByteBuffer.wrap(stream.toByteArray())); | ||
|
||
} catch (IOException e) { | ||
throw new IllegalArgumentException("Corrupted data"); |
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 be RuntimeException?
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.
Makes sense.
*/ | ||
public static Binary injectBinary(OutputStream stream) { | ||
if (stream == null) | ||
throw new IllegalArgumentException("stream"); |
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.
isn't better "stream cannot be null" message?
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 would use curly braces in all if
blocks even with only one statement
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.
Oh, definitely. Missed this one.
@carlosalberto great! |
This is an updated PR including:
With the support for BINARY in |
@carlosalberto LGTM |
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.
LGTM
* Change BINARY to be resizable and stream-oriented. * Abstract the Binary adapter and have an Adapters class to return it. * Remove the isInbound/isOutbound methods from BinaryAdapter. * Make Binary use the Channel paradigm for injection/extraction * Have binary methods in Adapters named after inject/extract. * Add a BINARY propagator for MockTracer. * Throw RuntimeException in case of errors during BINARY's injection. * Put braces around if-blocks for Adapters/BinaryAdapter. * Use verbose messages for null parameters in Adapters.
* Code cleanup (opentracing#199) - Propagate @deprecated annotation to implementations - Remove redundant "static final" definition from interface - Use Collections.emptyMap instead of Collections.EMPTY_MAP to preserve type * Add support for multi reference and expose references context and type from MockSpan. (opentracing#213) * Publish test artifact for Globaltracer testutil (opentracing#209) * Fix MockTracer.ChildOf not fail if there is a null argument passed (opentracing#226) * Make ChildOf not fail if there is a null argument passed * Moved tracer test to where it belongs. Fixed typo. * Use correct reference in Javadoc (opentracing#230) * MockTracer use text map propag in the default constructor (opentracing#179) * Implement a simpler Span propagation without lifetime handling. (opentracing#188) - Scope replaces ActiveSpan, without sharing a common ancestor with Span. - ScopeManager replaces ActiveSpanSource. - No reference-count to handle Span's lifetime. - A simple thread-local based ScopeManager. * travis publish.sh allow releases from branches (opentracing#191) * Travis allow release from non master branches (opentracing#192) * Travis allow release from non master branches Publis script compares remote branch with current checkout. This passes travis_branch into git checkout command so it will compare the same branches. * Fix comments * Travis publish script, remove -RC on git checkout (opentracing#193) * Update the Travis script to allow publishing from v.0.0.0 branches. (opentracing#195) Thing is, we cannot publish from 0.0.0-style branches as they are excluded, based on the current global Travis configuration, thus we try to publish from branches following a v.0.0.0 style, if any. * Readme document release process for release candidates (opentracing#198) * Readme document release process for release candidates * Adjust publish.sh to work with release from master branch * Add Examples for async use cases (opentracing#197) * Add examples for async as test cases This includes execution flow similar to: * Actor ask/tell * Promises with callbacks * Work interleaved on a thread using suspend/resume. The implementations of these execution models are obviously very simplistic, but intended to emphasize the tracing aspect. * Update README files to reflect the Scope concept. (opentracing#217) * Let Tracer.activeSpan() be a shorthand for ScopeManager's active Span. (opentracing#228) * Let Tracer.activeSpan() be a shorthand for ScopeManager's active Span. * Document the null case for Tracer.activeSpan(). * Have Tracer.activeSpan() return null. * Remove @link for Tracer.activeSpan(). 'Nested' links do not happen to exist under javadoc, so Tracer.scopeManager().active().span() is now not a link. * Change BINARY to be resizable and stream-oriented. (opentracing#223) * Change BINARY to be resizable and stream-oriented. * Abstract the Binary adapter and have an Adapters class to return it. * Remove the isInbound/isOutbound methods from BinaryAdapter. * Make Binary use the Channel paradigm for injection/extraction * Have binary methods in Adapters named after inject/extract. * Add a BINARY propagator for MockTracer. * Throw RuntimeException in case of errors during BINARY's injection. * Put braces around if-blocks for Adapters/BinaryAdapter. * Use verbose messages for null parameters in Adapters. * SpanBuilder deprecate startManual (opentracing#225) * SpanBuilder deprecate startManual * Fix review comments * Remove default finish behaviour for `activate()` (opentracing#219) * Do not auto finish on scope.close * Fix review comments * Fix review comments * Add explanatory statement about not auto-finishing * Define only activate(s, bool) * Use the parameterless startActive() in a forgotten test in MockTracerTest.
This is an effort to provide a stream-based, resizable BINARY format, inspired by #99 and its feedback.
BinaryHolder
is an adapter for eitherByteArrayOutputStream
orByteArrayInputStream
, depending on whether the format was created for injection or extraction.I exposed two static methods to try to make purpose clear, i.e.
createInjectionHolder()
,createExtractionHolder
, instead of using simple constructor(s).Any feedback is appreciated ;)