Skip to content

Conversation

@thomasschickinger
Copy link
Contributor

@thomasschickinger thomasschickinger commented Mar 9, 2017

This PR solves the following issues:

  1. Text logs on GCE do not contain a trailing line end. Hence, we need to add it when combining exception stacks.
  2. The fact that remove_tag_prefix is optional is a pitfall for users because re-emitting a log entry with the same tag causes an infinite recursion in fluentd.
  3. Flushing individual text log lines did not work because the first_record field was only populated for JSON logs.

The version number is bumped to 0.0.6

@bernii
Copy link

bernii commented Apr 6, 2017

I'm getting a following exception when using this branch

2017-04-06 16:00:14 +0000 [warn]: fluent/root_agent.rb:199:handle_emits_error: emit transaction failed: error_class=TypeError error="no implicit conversion of nil into String" tag="raw.coreos-systemd"
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/exception_detector.rb:229:in `block in combined_message'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/exception_detector.rb:228:in `each'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/exception_detector.rb:228:in `combined_message'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/exception_detector.rb:246:in `flush'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/exception_detector.rb:288:in `update_buffer'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/exception_detector.rb:221:in `push'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/out_detect_exceptions.rb:101:in `block in process_record'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/out_detect_exceptions.rb:131:in `synchronize'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/out_detect_exceptions.rb:131:in `synchronize'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/out_detect_exceptions.rb:88:in `process_record'
  2017-04-06 16:00:14 +0000 [warn]: fluent/event_router.rb:81:emit: /usr/local/bundle/gems/fluent-plugin-detect-exceptions-0.0.6/lib/fluent/plugin/out_detect_exceptions.rb:80:in `block in emit'

@thomasschickinger
Copy link
Contributor Author

Judging from the line where this error is reported (exception_detector.rb:229), I'd guess that $RS is not defined in your environment. Could you try replacing it with "\n" and check whether the error disappears?

@bernii
Copy link

bernii commented Apr 6, 2017

Yeah I was not sure, not a Rubyist here ;-) You're right, that fixes it.
I'm using the official ruby:2.2.0 image from dockerhub, wondering if I should use something different or if I can somehow set $RS in the env?

def combined_message
combined = ''
@messages.each do |m|
combined << $RS if !combined.empty? && !combined.end_with?("\n")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we program defensively and use "\n" if $RS is nil?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Used a member variable for that in order to ensure that this is looked up only once.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is a static value that should never change. How about making it a class variable instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

README.rdoc Outdated
{output plugin for fluentd}[http://docs.fluentd.org/articles/output-plugin-overview]
which scans a log stream text messages or JSON records for multi-line exception
stack traces: If a consecutive sequence of log messages forms an exception stack
which scans a log stream text messages or JSON records containing single
Copy link
Contributor

Choose a reason for hiding this comment

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

a log stream of text messages?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

README.rdoc Outdated
are so similar (e.g. because they contain the timestamp of the log entry) that
this loss of information is irrelevant.

When combining exception lines, it is ensured that they enter with a line
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, can't parse this. Did you mean s/enter/end/?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, thanks.

README.rdoc Outdated
this loss of information is irrelevant.

When combining exception lines, it is ensured that they enter with a line
separator. If they don't, a line separator is added to the original log message.
Copy link
Contributor

Choose a reason for hiding this comment

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

The second sentence is redundant (implied by "is ensured").

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK

README.rdoc Outdated
Default: ''.

[remove_tag_prefix] The prefix to remove from the input tag when outputting
a record. A prefix has to be a complete tag part.
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's change the heading to [remove_tag_prefix (required)] for consistency with other fluentd docs (e.g., in_tail) and make it the first parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

README.rdoc Outdated
tag foo.bar.baz is transformed to bar.baz and the input tag
'foofoo.bar' is not modified. Default: empty string.
'foofoo.bar' is not modified.
Removing a tag prefix is needed to avoid infinite
Copy link
Contributor

Choose a reason for hiding this comment

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

How about we put it in terms of what the user can/has to do, e.g.:

This must be non-empty to avoid infinite recursion in fluentd.

Speaking of which, do you want to check that this is non-empty and reject the config if it is? Removing the default simply ensures that this is specified by the user, not that it has a non-empty value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor

Choose a reason for hiding this comment

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

What about the second part of the suggestion (writing code to check that this is non-empty)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Check and test added.

gem.required_ruby_version = Gem::Requirement.new('>= 2.0')

gem.files = Dir['**/*'].keep_if { |file| File.file?(file) }
gem.files = Dir['**/*'].keep_if{ |file| File.file?(file) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious: why did you have to remove the space before the opening brace?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't. Fixed.


gem.files = Dir['**/*'].keep_if { |file| File.file?(file) }
gem.files = Dir['**/*'].keep_if{ |file| File.file?(file) &&
!file.end_with?('gem') }
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: should this be !file.end_with?('.gem')?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

force_flush if @max_lines > 0 && @messages.length == @max_lines
end

def combined_message
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not happy with defining a method for this -- too much Ruby magic. You are essentially injecting newlines after trace lines that don't have them, right? Why not do it as a comprehension, e.g.:

combined_message = @messages.inject([]) {|r, e| r << e; r << $RS unless e.empty? || e.end_with?("\n"); r}.join

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@thomasschickinger
Copy link
Contributor Author

All comments addressed. PTAL.

def combined_message
combined = ''
@messages.each do |m|
combined << $RS if !combined.empty? && !combined.end_with?("\n")
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a static value that should never change. How about making it a class variable instead?

README.rdoc Outdated
tag foo.bar.baz is transformed to bar.baz and the input tag
'foofoo.bar' is not modified. Default: empty string.
'foofoo.bar' is not modified.
Removing a tag prefix is needed to avoid infinite
Copy link
Contributor

Choose a reason for hiding this comment

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

What about the second part of the suggestion (writing code to check that this is non-empty)?

@thomasschickinger
Copy link
Contributor Author

Hi Igor, comments addressed. PTAL.

@timoreimann
Copy link

we've been running into the same problem this PR fixes recently.

@igorpeshansky is there still anything left blocking from moving forward with this PR?

@mirwan
Copy link

mirwan commented Dec 22, 2017

Hi
About point 2, I proposed PR#20. The combination of remove_tag_prefix and prepend_tag_prefix could prevent from entering an infinite loop.

@neeraj9194
Copy link

neeraj9194 commented May 2, 2018

is this ever going to release???

@yanweiguo
Copy link
Member

Got the same issue this PR fixes. @igorpeshansky any update?

@aplsms
Copy link

aplsms commented Oct 1, 2018

any updates?

@irizzant
Copy link

I'm having the same issues with Java exceptions not having and ending new line char.
Any news?

@callicles
Copy link

Same here @igorpeshansky would be great if that could be merged

@jkohen
Copy link

jkohen commented Aug 12, 2019

@igorpeshansky what does it take to resolve this PR?

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.