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

CIP-5010 align with upstream #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ jobs:
fail-fast: false
matrix:
rvm:
- 2.7
- 2.6
- 2.5
- 2.4
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -32,4 +31,3 @@ jobs:
# - google-fluentd-notifications+travis@google.com
# on_success: change
# on_failure: change

17 changes: 17 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

AllCops:
TargetRubyVersion: 2.6
NewCops: disable

# Rakefile doesn't need to be executable.
Lint/ScriptPermission:
Enabled: false

# Offense count: 2
Metrics/AbcSize:
Max: 120
Expand All @@ -31,3 +39,12 @@ Metrics/MethodLength:
# Offense count: 3
Metrics/PerceivedComplexity:
Max: 50

# Offense count: 1
# Configuration parameters: CountComments.
Metrics/BlockLength:
Max: 50

# TODO: Re-enable this and fix frozen strings.
Style/FrozenStringLiteralComment:
Enabled: false
3 changes: 2 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ task :fix_perms do
files.each do |file|
mode = File.stat(file).mode & 0o777
next unless mode & 0o444 != 0o444

puts "Changing mode of #{file} from #{mode.to_s(8)} to "\
"#{(mode | 0o444).to_s(8)}"
chmod mode | 0o444, file
end
end

desc 'Run unit tests and RuboCop to check for style violations'
task all: [:test, :rubocop, :fix_perms]
task all: %i[rubocop test fix_perms]

task default: :all
12 changes: 6 additions & 6 deletions fluent-plugin-detect-exceptions.gemspec
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
Gem::Specification.new do |gem|
gem.name = 'fluent-plugin-detect-exceptions'
gem.description = <<-eos
gem.description = <<-DESCRIPTION
Fluentd output plugin which detects exception stack traces in a stream of
JSON log messages and combines all single-line messages that belong to the
same stack trace into one multi-line message.
This is an official Google Ruby gem.
eos
DESCRIPTION
gem.summary = \
'fluentd output plugin for combining stack traces as multi-line JSON logs'
gem.homepage = \
'https://github.com/GoogleCloudPlatform/fluent-plugin-detect-exceptions'
gem.license = 'Apache-2.0'
gem.version = '0.0.14'
gem.version = '0.0.15'
gem.authors = ['Stackdriver Agents']
gem.email = ['stackdriver-agents@google.com']
gem.required_ruby_version = Gem::Requirement.new('>= 2.0')
gem.required_ruby_version = Gem::Requirement.new('>= 2.6')

gem.files = Dir['**/*'].keep_if { |file| File.file?(file) }
gem.test_files = gem.files.grep(/^(test)/)
gem.require_paths = ['lib']

gem.add_runtime_dependency 'fluentd', '>= 0.10'

gem.add_development_dependency 'flexmock', '~> 2.0'
gem.add_development_dependency 'rake', '~> 10.3'
gem.add_development_dependency 'rubocop', '= 0.42.0'
gem.add_development_dependency 'rubocop', '= 1.48.1'
gem.add_development_dependency 'test-unit', '~> 3.0'
gem.add_development_dependency 'flexmock', '~> 2.0'
end
92 changes: 46 additions & 46 deletions lib/fluent/plugin/exception_detector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ module ExceptionDetectorConfig
class RuleTarget
attr_accessor :pattern, :to_state

def initialize(p, s)
@pattern = p
@to_state = s
def initialize(pattern, state)
@pattern = pattern
@to_state = state
end

def ==(other)
Expand Down Expand Up @@ -52,28 +52,28 @@ def self.supported
end

JAVA_RULES = [
rule([:start_state, :java_start_exception],
rule(%i[start_state java_start_exception],
/(?:Exception|Error|Throwable|V8 errors stack trace)[:\r\n]/,
:java_after_exception),
rule(:java_after_exception, /^[\t !]*nested exception is:[\t !]*/,
:java_start_exception),
rule(:java_after_exception, /^[\r\n]*$/, :java_after_exception),
rule([:java_after_exception, :java], /^[\t !]+(?:eval )?at /, :java),
rule(%i[java_after_exception java], /^[\t !]+(?:eval )?at /, :java),

rule([:java_after_exception, :java],
rule(%i[java_after_exception java],
# C# nested exception.
/^[\t !]+--- End of inner exception stack trace ---$/,
:java),

rule([:java_after_exception, :java],
rule(%i[java_after_exception java],
# C# exception from async code.
/^--- End of stack trace from previous (?x:
)location where exception was thrown ---$/,
:java),

rule([:java_after_exception, :java], /^[\t !]*(?:Caused by|Suppressed):/,
rule(%i[java_after_exception java], /^[\t !]*(?:Caused by|Suppressed):/,
:java_after_exception),
rule([:java_after_exception, :java],
rule(%i[java_after_exception java],
/^[\t !]*... \d+ (?:more|common frames omitted)/, :java)
].freeze

Expand All @@ -94,16 +94,16 @@ def self.supported
].freeze

GO_RULES = [
rule([:start_state, :go_after_panic], /\bpanic: /, :go_after_panic),
rule(:start_state, :go_after_panic], /\bpanic: /, :go_after_panic),
rule(:start_state, /http: panic serving/, :go_goroutine),
rule(:go_after_panic, /^$/, :go_goroutine),
rule([:go_after_panic, :go_after_signal, :go_frame_1],
rule(%i[go_after_panic go_after_signal go_frame_line1],
/^$/, :go_goroutine),
rule(:go_after_panic, /^\[signal /, :go_after_signal),
rule(:go_goroutine, /^goroutine \d+ \[[^\]]+\]:$/, :go_frame_1),
rule(:go_frame_1, /^(?:[^\s.:]+\.\.?)*[^\s.():]+\(|^created by /,
:go_frame_2),
rule(:go_frame_2, /^\s/, :go_frame_1)
rule(:go_goroutine, /^goroutine \d+ \[[^\]]+\]:$/, :go_frame_line1),
rule(:go_frame_line1, /^(?:[^\s.:]+\.\.?)*[^\s.():]+\(|^created by /,
:go_frame_line2),
rule(:go_frame_line2, /^\s/, :go_frame_line1)
].freeze

RUBY_RULES = [
Expand All @@ -129,22 +129,22 @@ def self.supported
rule(:dart_exc, /^Concurrent modification/, :dart_stack),
rule(:dart_exc, /^Out of Memory/, :dart_stack),
rule(:dart_exc, /^Stack Overflow/, :dart_stack),
rule(:dart_exc, /^'.+?':.+?$/, :dart_type_err_1),
rule(:dart_type_err_1, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_type_err_1, /^.+?$/, :dart_type_err_2),
rule(:dart_type_err_2, /^.*?\^.*?$/, :dart_type_err_3),
rule(:dart_type_err_3, /^$/, :dart_type_err_4),
rule(:dart_type_err_4, /^$/, :dart_stack),
rule(:dart_exc, /^FormatException/, :dart_format_err_1),
rule(:dart_format_err_1, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_format_err_1, /^./, :dart_format_err_2),
rule(:dart_format_err_2, /^.*?\^/, :dart_format_err_3),
rule(:dart_format_err_3, /^$/, :dart_stack),
rule(:dart_exc, /^NoSuchMethodError:/, :dart_method_err_1),
rule(:dart_method_err_1, /^Receiver:/, :dart_method_err_2),
rule(:dart_method_err_2, /^Tried calling:/, :dart_method_err_3),
rule(:dart_method_err_3, /^Found:/, :dart_stack),
rule(:dart_method_err_3, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_exc, /^'.+?':.+?$/, :dart_type_err_line1),
rule(:dart_type_err_line1, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_type_err_line1, /^.+?$/, :dart_type_err_line2),
rule(:dart_type_err_line2, /^.*?\^.*?$/, :dart_type_err_line3),
rule(:dart_type_err_line3, /^$/, :dart_type_err_line4),
rule(:dart_type_err_line4, /^$/, :dart_stack),
rule(:dart_exc, /^FormatException/, :dart_format_err_line1),
rule(:dart_format_err_line1, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_format_err_line1, /^./, :dart_format_err_line2),
rule(:dart_format_err_line2, /^.*?\^/, :dart_format_err_line3),
rule(:dart_format_err_line3, /^$/, :dart_stack),
rule(:dart_exc, /^NoSuchMethodError:/, :dart_method_err_line1),
rule(:dart_method_err_line1, /^Receiver:/, :dart_method_err_line2),
rule(:dart_method_err_line2, /^Tried calling:/, :dart_method_err_line3),
rule(:dart_method_err_line3, /^Found:/, :dart_stack),
rule(:dart_method_err_line3, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_stack, /^#\d+\s+.+?\(.+?\)$/, :dart_stack),
rule(:dart_stack, /^<asynchronous suspension>$/, :dart_stack)
].freeze
Expand All @@ -168,7 +168,7 @@ def self.supported
all: ALL_RULES
}.freeze

DEFAULT_FIELDS = %w(message log).freeze
DEFAULT_FIELDS = %w[message log].freeze
end

# State machine that consumes individual log lines and detects
Expand Down Expand Up @@ -236,6 +236,7 @@ def reset
def transition(line)
@rules[@state].each do |r|
next unless line =~ r.pattern

@state = r.to_state
return true
end
Expand Down Expand Up @@ -280,14 +281,14 @@ def push(time_sec, record)
@exception_detector.reset
detection_status = :no_trace
else
force_flush if @max_bytes > 0 &&
force_flush if @max_bytes.positive? &&
@buffer_size + message.length > @max_bytes
detection_status = @exception_detector.update(message)
end

update_buffer(detection_status, time_sec, record, message)

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

def flush
Expand Down Expand Up @@ -332,8 +333,7 @@ def extract_message(record)
end

def update_buffer(detection_status, time_sec, record, message)
trigger_emit = detection_status == :no_trace ||
detection_status == :end_trace
trigger_emit = %i[no_trace end_trace].include?(detection_status)
if @messages.empty? && trigger_emit
@emit.call(time_sec, record)
return
Expand Down Expand Up @@ -361,16 +361,16 @@ def add(time_sec, record, message)
@first_timestamp = time_sec
@buffer_start_time = Time.now
end
unless message.nil?
message_with_line_break =
if @force_line_breaks && !@messages.empty? && !message.include?("\n")
"\n" + message
else
message
end
@messages << message_with_line_break
@buffer_size += message_with_line_break.length
end
return if message.nil?

message_with_line_break =
if @force_line_breaks && !@messages.empty? && !message.include?("\n")
"\n#{message}"
else
message
end
@messages << message_with_line_break
@buffer_size += message_with_line_break.length
end
end
end
21 changes: 10 additions & 11 deletions lib/fluent/plugin/out_detect_exceptions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ def multi_workers_ready?
def configure(conf)
super

if multiline_flush_interval
@check_flush_interval = [multiline_flush_interval * 0.1, 1].max
end
@check_flush_interval = [multiline_flush_interval * 0.1, 1].max if multiline_flush_interval

@languages = languages.map(&:to_sym)

Expand All @@ -61,11 +59,11 @@ def configure(conf)
def start
super

if multiline_flush_interval
@flush_buffer_mutex = Mutex.new
@stop_check = false
@thread = Thread.new(&method(:check_flush_loop))
end
return unless multiline_flush_interval

@flush_buffer_mutex = Mutex.new
@stop_check = false
@thread = Thread.new(&method(:check_flush_loop))
end

def before_shutdown
Expand All @@ -81,8 +79,8 @@ def shutdown
super
end

def emit(tag, es, chain)
es.each do |time_sec, record|
def emit(tag, entries, chain)
entries.each do |time_sec, record|
process_record(tag, time_sec, record)
end
chain.next
Expand Down Expand Up @@ -125,13 +123,14 @@ def check_flush_loop
@flush_buffer_mutex.sleep(@check_flush_interval)
now = Time.now
break if @stop_check

@accumulators.each_value do |acc|
acc.force_flush if now - acc.buffer_start_time >
@multiline_flush_interval
end
end
end
rescue
rescue StandardError
log.error 'error in check_flush_loop', error: $ERROR_INFO.to_s
log.error_backtrace
end
Expand Down
10 changes: 5 additions & 5 deletions test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@

require 'rubygems'
require 'bundler'

begin
Bundler.setup(:default, :development)
rescue Bundler::BundlerError => e
# rubocop:disable Style/StderrPuts
$stderr.puts e.message
$stderr.puts 'Run `bundle install` to install missing gems'
# rubocop:enable Style/StderrPuts
exit e.status_code
end

require 'test/unit'

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'fluent/test'

unless ENV.key?('VERBOSE')
nulllogger = Object.new
nulllogger.instance_eval do |_|
def respond_to_missing?
def respond_to_missing?(_method, _include_private = false)
true
end

def method_missing(_method, *_args) # rubocop:disable Style/MethodMissing
def method_missing(_method, *_args)
# pass
end
end
# global $log variable is used by fluentd
Expand Down
Loading
Loading