Skip to content
This repository has been archived by the owner on Aug 30, 2019. It is now read-only.

implement stream decoding #227

Merged
merged 3 commits into from
Feb 10, 2017
Merged

implement stream decoding #227

merged 3 commits into from
Feb 10, 2017

Conversation

galdor
Copy link

@galdor galdor commented Feb 8, 2017

See commit messages for more information.

@LeoCavaille LeoCavaille modified the milestone: 5.12 Feb 9, 2017
@galdor galdor force-pushed the nicolas/stream-decoding branch from 84ecb4f to f86e6ec Compare February 9, 2017 16:49
@galdor
Copy link
Author

galdor commented Feb 9, 2017

Small update to add more tests for the LimitedReader/io.EOF workaround.

Copy link

@ufoot ufoot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, need to run it for some time & get some real world metrics before shipping, but could indeed be nice, memory-wise.

}
default:
HTTPEndpointNotSupported([]string{tagServiceHandler, fmt.Sprintf("v:%s", v)}, w)
contentType := req.Header.Get("Content-Type")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm mixed here. One one hand, doing it this way makes the code more compact, and slightly more permissive, but this is fine. OTOH, doing this, we loose the information that "v01 and v02 are JSON only while v03 is JSON & MsgPack and has to decide depending on Content-Type". As I understand it, this code will accept any protocol on any enpoint. Maybe just state with a comment that MsgPack should only be for v03? Because for now, we know it, but we can still "forget it" when we migrate.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We filter msgpack payloads for v0.1 and v0.2 in httpHandleWithVersion. Since decoding is handled in decodeReceiverPayload, handlers don't have to think about the format of the payload. The only exception is the manual JSON decoding for v0.1, but we're going to deprecate v0.1 anyway.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, my bad, I missed the fact httpHandleWithVersion was doing the filtering, sorry for the noise.

// Some libraries (e.g. msgp) will ignore read data if err is not nil.
// We reset err if something was read, and the next read will return
// io.EOF with no data.
if err == io.EOF && n > 0 {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Nicolas Martyanoff added 3 commits February 10, 2017 13:42
bytes.Buffer already implements io.Reader.
It's perfectly normal for a reader to return n>0 and EOF:

    Callers should always process the n > 0 bytes returned before
    considering the error err. Doing so correctly handles I/O errors
    that happen after reading some bytes and also both of the allowed
    EOF behaviors.
        -- https://golang.org/pkg/io/#Reader

Infortunately, github.com/tinylib/msgp does not handle this case, and
return immediately if err != nil, without checking whether data were
read.

This workaround set the error to nil if there are data available. The
next read will return n=0 and EOF.
@galdor galdor force-pushed the nicolas/stream-decoding branch from f86e6ec to af6f9d5 Compare February 10, 2017 13:02
Copy link

@ufoot ufoot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

default:
HTTPEndpointNotSupported([]string{tagTraceHandler, fmt.Sprintf("v:%s", v)}, w)
return
}

HTTPOK(w)

if contentLength > 0 {
atomic.AddInt64(&r.stats.TracesBytes, int64(contentLength))
bytesRead := req.Body.(*model.LimitedReader).Count
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@galdor galdor merged commit 6f0b980 into master Feb 10, 2017
@galdor galdor deleted the nicolas/stream-decoding branch February 10, 2017 16:25

r.decoderPool.Release(dec)
case v02:
fallthrough
Copy link

@clutchski clutchski Feb 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: i don't like fallthrough because it sort of hinders local reasoning (oh ... this is handled later, keep reading).

why not just case v01, v02

case "application/msgpack":
return msgp.Decode(r, dest)

case "application/json":

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment about fall through

@@ -46,10 +49,9 @@ const (
// HTTPReceiver is a collector that uses HTTP protocol and just holds
// a chan where the spans received are sent one by one
type HTTPReceiver struct {
traces chan model.Trace
services chan model.ServicesMetadata
decoderPool *model.DecoderPool

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the second time i've made this comment over the last year, but the decoder pool was added to a fix a performance bottleneck (i think it's so we could re-use the decoding buffers, but it's been a while).

can you verify this has no impact?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants