-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
1.5 performance regression fixes #2869
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,13 @@ | |
class LogStash::ShutdownEvent; end | ||
class LogStash::FlushEvent; end | ||
|
||
module LogStash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd add an extra module level here to add a "subject" example: module LogStash::Signal
FLUSH = LogStash::FlushEvent.new
SHUTDOWN = LogStash::ShutdownEvent.new
end Then:
or
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hum..around 10 plugins use it https://github.com/search?p=1&q=user%3Alogstash-plugins+LogStash%3A%3ASHUTDOWN&ref=searchresults&type=Code&utf8=%E2%9C%93 (I couldn't find a more accurate search for this) Alright, lets postpone this to > 1.5 |
||
FLUSH = LogStash::FlushEvent.new | ||
|
||
# LogStash::SHUTDOWN is used by plugins | ||
SHUTDOWN = LogStash::ShutdownEvent.new | ||
end | ||
|
||
# the logstash event object. | ||
# | ||
# An event is simply a tuple of (timestamp, data). | ||
|
@@ -48,25 +55,26 @@ class DeprecatedMethod < StandardError; end | |
TIMESTAMP_FAILURE_TAG = "_timestampparsefailure" | ||
TIMESTAMP_FAILURE_FIELD = "_@timestamp" | ||
|
||
METADATA = "@metadata".freeze | ||
METADATA_BRACKETS = "[#{METADATA}]".freeze | ||
|
||
# Floats outside of these upper and lower bounds are forcibly converted | ||
# to scientific notation by Float#to_s | ||
MIN_FLOAT_BEFORE_SCI_NOT = 0.0001 | ||
MAX_FLOAT_BEFORE_SCI_NOT = 1000000000000000.0 | ||
|
||
LOGGER = Cabin::Channel.get(LogStash) | ||
|
||
public | ||
def initialize(data = {}) | ||
@logger = Cabin::Channel.get(LogStash) | ||
@cancelled = false | ||
@data = data | ||
@accessors = LogStash::Util::Accessors.new(data) | ||
@data[VERSION] ||= VERSION_ONE | ||
@data[TIMESTAMP] = init_timestamp(@data[TIMESTAMP]) | ||
ts = @data[TIMESTAMP] | ||
@data[TIMESTAMP] = ts ? init_timestamp(ts) : LogStash::Timestamp.now | ||
|
||
@metadata = if @data.include?("@metadata") | ||
@data.delete("@metadata") | ||
else | ||
{} | ||
end | ||
@metadata = @data.delete(METADATA) || {} | ||
@metadata_accessors = LogStash::Util::Accessors.new(@metadata) | ||
end # def initialize | ||
|
||
|
@@ -113,9 +121,6 @@ def ruby_timestamp | |
raise DeprecatedMethod | ||
end # def unix_timestamp | ||
|
||
# field-related access | ||
METADATA = "@metadata".freeze | ||
METADATA_BRACKETS = "[#{METADATA}]".freeze | ||
public | ||
def [](fieldref) | ||
if fieldref.start_with?(METADATA_BRACKETS) | ||
|
@@ -267,12 +272,12 @@ def tag(value) | |
|
||
def init_timestamp(o) | ||
begin | ||
timestamp = o ? LogStash::Timestamp.coerce(o) : LogStash::Timestamp.now | ||
timestamp = LogStash::Timestamp.coerce(o) | ||
return timestamp if timestamp | ||
|
||
@logger.warn("Unrecognized #{TIMESTAMP} value, setting current time to #{TIMESTAMP}, original in #{TIMESTAMP_FAILURE_FIELD}field", :value => o.inspect) | ||
LOGGER.warn("Unrecognized #{TIMESTAMP} value, setting current time to #{TIMESTAMP}, original in #{TIMESTAMP_FAILURE_FIELD}field", :value => o.inspect) | ||
rescue LogStash::TimestampParserError => e | ||
@logger.warn("Error parsing #{TIMESTAMP} string, setting current time to #{TIMESTAMP}, original in #{TIMESTAMP_FAILURE_FIELD} field", :value => o.inspect, :exception => e.message) | ||
LOGGER.warn("Error parsing #{TIMESTAMP} string, setting current time to #{TIMESTAMP}, original in #{TIMESTAMP_FAILURE_FIELD} field", :value => o.inspect, :exception => e.message) | ||
end | ||
|
||
@data["tags"] ||= [] | ||
|
@@ -287,7 +292,7 @@ def to_hash_with_metadata | |
if @metadata.nil? | ||
to_hash | ||
else | ||
to_hash.merge("@metadata" => @metadata) | ||
to_hash.merge(METADATA => @metadata) | ||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# encoding: utf-8 | ||
require "logstash/namespace" | ||
require "logstash/event" | ||
require "logstash/logging" | ||
require "logstash/plugin" | ||
require "logstash/config/mixin" | ||
|
@@ -145,6 +146,24 @@ def filter(event) | |
raise "#{self.class}#filter must be overidden" | ||
end # def filter | ||
|
||
|
||
# in 1.5.0 multi_filter is meant to be used in the generated filter function in LogStash::Config::AST::Plugin only | ||
# and is temporary until we refactor the filter method interface to accept events list and return events list, | ||
# just list in multi_filter see https://github.com/elastic/logstash/issues/2872. | ||
# refactoring the filter method will mean updating all plugins which we want to avoid doing for 1.5.0. | ||
# | ||
# @param events [Array<LogStash::Event] list of events to filter | ||
# @return [Array<LogStash::Event] filtered events and any new events generated by the filter | ||
public | ||
def multi_filter(events) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm, I am not in love with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if sticking to multi_filter, I'd prefer filter_multi, b/c we're doing filter on multiple events, not multiple filters There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, we're actually calling filter multiple times, hence multi_filter... no? this method is only used in the generated filter function and is ephemeral per #2872 because it will change the signature to handle processing multiple events, can we just keep it as-is knowing it will go away soon? :P There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
result = [] | ||
events.each do |event| | ||
result << event | ||
filter(event){|new_event| result << new_event} | ||
end | ||
result | ||
end | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a comment on this? I am not sure what it exactly does? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. totally! on it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
public | ||
def execute(event, &block) | ||
filter(event, &block) | ||
|
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.
If the
multi_filter
method is replacing this generated code, the new method doesn't deal with thecancelled?
boolean?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.
From what I understand, (or think to understand) the cancel logic is here to remove the shutdown event from the queue? Am I right?
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.
Also, the new code expect events to be a one dimension array, the old code assumed multidimensional array. (see
flat_map
) I don't know enough about the background of the code to know if it is something we should worry about.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.
Split ond metrics can emits multiple events ^
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 already explained some of this in the issue comments: the events cancellation is now dealt with in the pipeline code. It is not for the shutdown but when a filter marks an event not to be sent to the output queue... think multiline: it will aggregate events and cancel them until the multiline boundary is reached.
flat_map
is not required anymore, previously each filter step was pushing an array in theevents
array but now only individual events are pushed soflat_map
is not needed anymore.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.
for event cancellation, see bottom of #2869 (comment)
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 agree to remove it, if each plugin emits events and not array.
We should have a clearer deprecation policy for third parties plugins. cc @suyograo
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.
no, plugins always yield only one event, this has not changed and we do not want to change any API at this point. The proposal for the filter method refactor is in #2872 and we'll do that in 1.6 or 2.0.
the previous generated code, to handle new events emitted by the filter was inserting these new events as an array in the events array, see generated code example in section 1.5.0-rc2 of #2869 (comment)
now, the
multi_filter
method takes care of that logic but adds individual events not as an array, soflat_map
is not required anymore.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.
Got it.