Skip to content
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

Add TCP support with option {tcp: true} #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

catharinejm
Copy link

This is something I'm using and thought it might be welcome upstream.

Passing the option {tcp: true} establishes a TCP connection with the given host and port. Gzipping is disabled with TCP because it isn't supported properly by graylog. TCP GELF messages are NUL-delimited, and the gzip stream contains NULs, which confuses the server.

If this is used with gelf-stream and bunyan, an on('error', ...) handler must be bound to the gelf-stream stream because bunyan does not capture them (e.g. ECONNREFUSED). Disabling the stream (removing from bunyan) must also be handled manually, presumably in the error handler. The gelfling stream will attempt to connect any time a message is written to it and the connection is not open. That seemed more or less in keeping with the behavior of the UDP messaging.

// https://github.com/t0xa/gelfj/pull/61
this.tcpClient.write(JSON.stringify(this.convert(data)) + '\0', callback)
} else if (this.tcpConnecting)
setTimeout(retrySend, 10)
Copy link
Owner

Choose a reason for hiding this comment

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

This may result in race conditions and your data will be sent out of order. Eg:

  1. say tcpConnecting is true and tcpConnected is false
  2. _sendTcp is called with some data, so setTimeout will retry in 10ms
  3. in that time, tcpConnected is set to true
  4. then let's say _sendTcp is called with new data – that will now be sent first
  5. then when the setTimeout triggers, the first packet of data will be sent second

One way to avoid this is to create a queue – it could just be an array of bound callbacks – and then call each of these on connect.

I guess the other thing to do is just ignore it – and live with the fact that out of order messages may occur 😸

Copy link
Author

Choose a reason for hiding this comment

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

If I put the messages through convert before delaying them then they'd be timestamped in log order, even if they get sent out of order. That'd probably be OK since UDP doesn't guarantee delivery order either. What do you think?

Copy link
Owner

Choose a reason for hiding this comment

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

Ah yeah – great point. No idea if the Graylog server reorders them like it does with UDP, but in any case it's a pretty easy solution.

@mhart
Copy link
Owner

mhart commented Jun 25, 2015

Cool! Thanks for looking into this – I haven't looked at or used this library in years.

Everything seems pretty reasonable – just some minor comments – lemme know what you think.

@mhart
Copy link
Owner

mhart commented Jun 25, 2015

Also, would you be able to add a paragraph to the README? Basically something along the lines of this PR description would be perfect.

@catharinejm
Copy link
Author

I moved the convert call up to the parent send method and updated the README. If you like I can submit an additional PR to gelf-stream explaining the tcp option and how to handle errors there too.

Thanks for looking this over!

if (callback == null) callback = function() {}

var send = this.tcp ? this._sendTcp : this._sendUdp
send.call(this, this.convert(data), callback)
Copy link
Owner

Choose a reason for hiding this comment

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

Hmmm – I'm just looking at this and it looks like you're changing the signature for this?

send used to be able to accept a Buffer and an array of Buffers (as well as a message object which would be converted) – see https://github.com/mhart/gelfling/blob/master/gelfling.js#L25

Now you're calling this.convert(data) which will break in those cases.

Copy link
Author

Choose a reason for hiding this comment

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

Hmm, that's true. I'll have to rethink that.

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

Successfully merging this pull request may close these issues.

None yet

2 participants