Skip to content
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
81 changes: 67 additions & 14 deletions lib/logstash/filters/clone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,86 @@
require "logstash/filters/base"
require "logstash/namespace"

# The clone filter is for duplicating events.
# A clone will be made for each type in the clone list.
# The original event is left unchanged.
# The clone filter is for creating copy of the original event.
# *The original event is left unchanged,* all modifier such as `add_field` or `add_tag`
# will be applied to the newly created copy.
#
# The default configuration will create an exact copy of the event
# [source, ruby]
# filter {
# clone {}
# }
#
# You can manipulate the copy using the `add_field`, `add_tag` configurations.
# Following configuration will add a `clone` tag to the copy event.
# [source, ruby]
# filter {
# clone {
# add_tag => "clone"
# }
# }
#
# In case you need to create several copies of the original event, you must set
# `mode => "multiple"` and specifies an identifier for each copy.
# By default this identifier is stored in the `type` field,
# but you can use a different field specifying the `clone_field` setting.
#
# For example, following configuration will create 3 copies of the original event
# [source,ruby]
# filter {
# clone {
# mode => "multiple"
# clones => ["clone1","clone2","clone3"]
# }
# }
#
class LogStash::Filters::Clone < LogStash::Filters::Base

config_name "clone"

# A new clone will be created with the given type for each type in this list.

# How this filter should operate
# * 'single' => create an exact copy
# * 'multiple' => create several copies using identifiers from the `clones` config
config :mode, :validate => ["single", "multiple"], :default => "single"
Copy link
Member

Choose a reason for hiding this comment

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

I've been thinking about this, what if instead of having single/multiple setting with :mode, set instead a default for :clones ? For example:

config :clones, :validate => :array, :default => ["clone"]

this way the default behaviour of clone {} is the creation of 1 clone, and the clone will have type => clone


# In `multiple` mode, specify which event field to use for storing the copy identifier
config :clone_field, :validate => :string, :default => "type"

# In `multiple` mode, a new clone will be created for each identifier in this list.
config :clones, :validate => :array, :default => []

public
def register
# Nothing to do
if @mode == "single" && clones.length > 0
#TODO WARN that the mode setting should be correctly set
@mode = "multiple"
elsif @mode == "multiple" && clones.length == 1
#TODO WARN That the "simple" mode could be use with the add_field config
elsif @mode == "multiple" && clones.length == 0
#TODO WARN That this filter is doing nothing
end
end

public
def filter(event)

@clones.each do |type|
clone = event.clone
clone["type"] = type
filter_matched(clone)
@logger.debug("Cloned event", :clone => clone, :event => event)

# Push this new event onto the stack at the LogStash::FilterWorker
yield clone
if @mode == "multiple"
@clones.each do |identifier|
yield clone(event,identifier)
end
else
yield clone(event,nil)
end
end

def clone(event, identifier)
clone = event.clone
if identifier
clone[@clone_field] = identifier
end
filter_matched(clone)
@logger.debug? && @logger.debug("Cloned event", :clone => clone, :event => event)
return clone
end

end # class LogStash::Filters::Clone
16 changes: 16 additions & 0 deletions spec/filters/clone_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@

describe LogStash::Filters::Clone do

describe "no-config behaviour" do
let(:config) { {} }
let(:filter) { LogStash::Filters::Clone.new(config) }

let(:attrs) { { } }
let(:event) { LogStash::Event.new(attrs) }

before(:each) do
filter.register
end

it "create one exact clone of the event" do
expect { |b| filter.filter( event, &b) }.to yield_control.once
end
end

describe "all defaults" do
type "original"
config <<-CONFIG
Expand Down