logstash-core 2.2.4.snapshot1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of logstash-core might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/lib/logstash-core.rb +1 -0
- data/lib/logstash-core/logstash-core.rb +3 -0
- data/lib/logstash-core/version.rb +8 -0
- data/lib/logstash/agent.rb +391 -0
- data/lib/logstash/codecs/base.rb +50 -0
- data/lib/logstash/config/config_ast.rb +550 -0
- data/lib/logstash/config/cpu_core_strategy.rb +32 -0
- data/lib/logstash/config/defaults.rb +12 -0
- data/lib/logstash/config/file.rb +39 -0
- data/lib/logstash/config/grammar.rb +3503 -0
- data/lib/logstash/config/mixin.rb +518 -0
- data/lib/logstash/config/registry.rb +13 -0
- data/lib/logstash/environment.rb +98 -0
- data/lib/logstash/errors.rb +12 -0
- data/lib/logstash/filters/base.rb +205 -0
- data/lib/logstash/inputs/base.rb +116 -0
- data/lib/logstash/inputs/threadable.rb +18 -0
- data/lib/logstash/java_integration.rb +116 -0
- data/lib/logstash/json.rb +61 -0
- data/lib/logstash/logging.rb +91 -0
- data/lib/logstash/namespace.rb +13 -0
- data/lib/logstash/output_delegator.rb +172 -0
- data/lib/logstash/outputs/base.rb +91 -0
- data/lib/logstash/patches.rb +5 -0
- data/lib/logstash/patches/bugfix_jruby_2558.rb +51 -0
- data/lib/logstash/patches/cabin.rb +35 -0
- data/lib/logstash/patches/profile_require_calls.rb +47 -0
- data/lib/logstash/patches/rubygems.rb +38 -0
- data/lib/logstash/patches/stronger_openssl_defaults.rb +68 -0
- data/lib/logstash/pipeline.rb +499 -0
- data/lib/logstash/pipeline_reporter.rb +114 -0
- data/lib/logstash/plugin.rb +120 -0
- data/lib/logstash/program.rb +14 -0
- data/lib/logstash/runner.rb +124 -0
- data/lib/logstash/shutdown_watcher.rb +100 -0
- data/lib/logstash/util.rb +203 -0
- data/lib/logstash/util/buftok.rb +139 -0
- data/lib/logstash/util/charset.rb +35 -0
- data/lib/logstash/util/decorators.rb +52 -0
- data/lib/logstash/util/defaults_printer.rb +31 -0
- data/lib/logstash/util/filetools.rb +186 -0
- data/lib/logstash/util/java_version.rb +66 -0
- data/lib/logstash/util/password.rb +25 -0
- data/lib/logstash/util/plugin_version.rb +56 -0
- data/lib/logstash/util/prctl.rb +10 -0
- data/lib/logstash/util/retryable.rb +40 -0
- data/lib/logstash/util/socket_peer.rb +7 -0
- data/lib/logstash/util/unicode_trimmer.rb +81 -0
- data/lib/logstash/util/worker_threads_default_printer.rb +29 -0
- data/lib/logstash/util/wrapped_synchronous_queue.rb +41 -0
- data/lib/logstash/version.rb +14 -0
- data/locales/en.yml +204 -0
- data/logstash-core.gemspec +58 -0
- data/spec/conditionals_spec.rb +429 -0
- data/spec/logstash/agent_spec.rb +85 -0
- data/spec/logstash/config/config_ast_spec.rb +146 -0
- data/spec/logstash/config/cpu_core_strategy_spec.rb +123 -0
- data/spec/logstash/config/defaults_spec.rb +10 -0
- data/spec/logstash/config/mixin_spec.rb +158 -0
- data/spec/logstash/environment_spec.rb +56 -0
- data/spec/logstash/filters/base_spec.rb +251 -0
- data/spec/logstash/inputs/base_spec.rb +74 -0
- data/spec/logstash/java_integration_spec.rb +304 -0
- data/spec/logstash/json_spec.rb +96 -0
- data/spec/logstash/output_delegator_spec.rb +144 -0
- data/spec/logstash/outputs/base_spec.rb +40 -0
- data/spec/logstash/patches_spec.rb +90 -0
- data/spec/logstash/pipeline_reporter_spec.rb +85 -0
- data/spec/logstash/pipeline_spec.rb +455 -0
- data/spec/logstash/plugin_spec.rb +169 -0
- data/spec/logstash/runner_spec.rb +68 -0
- data/spec/logstash/shutdown_watcher_spec.rb +113 -0
- data/spec/logstash/util/buftok_spec.rb +31 -0
- data/spec/logstash/util/charset_spec.rb +74 -0
- data/spec/logstash/util/defaults_printer_spec.rb +50 -0
- data/spec/logstash/util/java_version_spec.rb +79 -0
- data/spec/logstash/util/plugin_version_spec.rb +64 -0
- data/spec/logstash/util/unicode_trimmer_spec.rb +55 -0
- data/spec/logstash/util/worker_threads_default_printer_spec.rb +45 -0
- data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +28 -0
- data/spec/logstash/util_spec.rb +35 -0
- metadata +364 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "logstash/namespace"
|
3
|
+
require "logstash/util"
|
4
|
+
|
5
|
+
# This class exists to format the settings for default worker threads
|
6
|
+
module LogStash module Util class WorkerThreadsDefaultPrinter
|
7
|
+
|
8
|
+
def initialize(settings)
|
9
|
+
@setting = settings.fetch(:pipeline_workers, 0)
|
10
|
+
@default = settings.fetch(:default_pipeline_workers, 0)
|
11
|
+
end
|
12
|
+
|
13
|
+
def visit(collector)
|
14
|
+
visit_setting(collector)
|
15
|
+
visit_default(collector)
|
16
|
+
end
|
17
|
+
|
18
|
+
def visit_setting(collector)
|
19
|
+
return if @setting == 0
|
20
|
+
collector.push("User set pipeline workers: #{@setting}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def visit_default(collector)
|
24
|
+
return if @default == 0
|
25
|
+
collector.push "Default pipeline workers: #{@default}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end end end
|
29
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module LogStash; module Util
|
4
|
+
class WrappedSynchronousQueue
|
5
|
+
java_import java.util.concurrent.SynchronousQueue
|
6
|
+
java_import java.util.concurrent.TimeUnit
|
7
|
+
|
8
|
+
def initialize()
|
9
|
+
@queue = java.util.concurrent.SynchronousQueue.new()
|
10
|
+
end
|
11
|
+
|
12
|
+
# Push an object to the queue if the queue is full
|
13
|
+
# it will block until the object can be added to the queue.
|
14
|
+
#
|
15
|
+
# @param [Object] Object to add to the queue
|
16
|
+
def push(obj)
|
17
|
+
@queue.put(obj)
|
18
|
+
end
|
19
|
+
alias_method(:<<, :push)
|
20
|
+
|
21
|
+
# Offer an object to the queue, wait for the specified amout of time.
|
22
|
+
# If adding to the queue was successfull it wil return true, false otherwise.
|
23
|
+
#
|
24
|
+
# @param [Object] Object to add to the queue
|
25
|
+
# @param [Integer] Time in milliseconds to wait before giving up
|
26
|
+
# @return [Boolean] True if adding was successfull if not it return false
|
27
|
+
def offer(obj, timeout_ms)
|
28
|
+
@queue.offer(obj, timeout_ms, TimeUnit::MILLISECONDS)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Blocking
|
32
|
+
def take
|
33
|
+
@queue.take()
|
34
|
+
end
|
35
|
+
|
36
|
+
# Block for X millis
|
37
|
+
def poll(millis)
|
38
|
+
@queue.poll(millis, TimeUnit::MILLISECONDS)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# The version of the logstash package (not the logstash-core gem version).
|
4
|
+
#
|
5
|
+
# Note to authors: this should not include dashes because 'gem' barfs if
|
6
|
+
# you include a dash in the version string.
|
7
|
+
|
8
|
+
# TODO: (colin) the logstash-core gem uses it's own version number in logstash-core/lib/logstash-core/version.rb
|
9
|
+
# there are some dependencies in logstash-core on the LOGSTASH_VERSION constant this is why
|
10
|
+
# the logstash version is currently defined here in logstash-core/lib/logstash/version.rb but
|
11
|
+
# eventually this file should be in the root logstash lib fir and dependencies in logstash-core should be
|
12
|
+
# fixed.
|
13
|
+
|
14
|
+
LOGSTASH_VERSION = "2.2.4.snapshot1"
|
data/locales/en.yml
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
# YAML notes
|
2
|
+
# |- means 'scalar block' useful for formatted text
|
3
|
+
# > means 'scalar block' but it chomps all newlines. Useful
|
4
|
+
# for unformatted text.
|
5
|
+
en:
|
6
|
+
oops: |-
|
7
|
+
An unexpected error occurred!
|
8
|
+
logstash:
|
9
|
+
environment:
|
10
|
+
jruby-required: >-
|
11
|
+
JRuby is required
|
12
|
+
missing-jars: >-
|
13
|
+
Could not find jar files under %{pattern}
|
14
|
+
pipeline:
|
15
|
+
worker-error: |-
|
16
|
+
A plugin had an unrecoverable error. Will restart this plugin.
|
17
|
+
Plugin: %{plugin}
|
18
|
+
Error: %{error}
|
19
|
+
worker-error-debug: |-
|
20
|
+
A plugin had an unrecoverable error. Will restart this plugin.
|
21
|
+
Plugin: %{plugin}
|
22
|
+
Error: %{error}
|
23
|
+
Exception: %{exception}
|
24
|
+
Stack: %{stacktrace}
|
25
|
+
plugin-loading-error: >-
|
26
|
+
Couldn't find any %{type} plugin named '%{name}'. Are you
|
27
|
+
sure this is correct? Trying to load the %{name} %{type} plugin
|
28
|
+
resulted in this error: %{error}
|
29
|
+
plugin-type-loading-error: >-
|
30
|
+
Could not find any plugin type named '%{type}'. Check for typos.
|
31
|
+
Valid plugin types are 'input' 'filter' and 'output'
|
32
|
+
output-worker-unsupported: >-
|
33
|
+
%{plugin} output plugin: setting 'workers => %{worker_count}' is not
|
34
|
+
supported by this plugin. I will continue working as if you had not set
|
35
|
+
this setting.
|
36
|
+
output-worker-unsupported-with-message: >-
|
37
|
+
%{plugin} output plugin: setting 'workers => %{worker_count}' is not
|
38
|
+
supported by this plugin. I will continue working as if you had not set
|
39
|
+
this setting. Reason: %{message}
|
40
|
+
plugin:
|
41
|
+
deprecated_milestone: >-
|
42
|
+
%{plugin} plugin is using the 'milestone' method to declare the version
|
43
|
+
of the plugin this method is deprecated in favor of declaring the
|
44
|
+
version inside the gemspec.
|
45
|
+
no_version: >-
|
46
|
+
%{name} plugin doesn't have a version. This plugin isn't well
|
47
|
+
supported by the community and likely has no maintainer.
|
48
|
+
version:
|
49
|
+
0-9-x:
|
50
|
+
Using version 0.9.x %{type} plugin '%{name}'. This plugin should work but
|
51
|
+
would benefit from use by folks like you. Please let us know if you
|
52
|
+
find bugs or have suggestions on how to improve this plugin.
|
53
|
+
0-1-x: >-
|
54
|
+
Using version 0.1.x %{type} plugin '%{name}'. This plugin isn't well
|
55
|
+
supported by the community and likely has no maintainer.
|
56
|
+
agent:
|
57
|
+
sighup: >-
|
58
|
+
SIGHUP received.
|
59
|
+
missing-configuration: >-
|
60
|
+
No configuration file was specified. Perhaps you forgot to provide
|
61
|
+
the '-f yourlogstash.conf' flag?
|
62
|
+
error: >-
|
63
|
+
Error: %{error}
|
64
|
+
sigint: >-
|
65
|
+
SIGINT received. Shutting down the pipeline.
|
66
|
+
sigterm: >-
|
67
|
+
SIGTERM received. Shutting down the pipeline.
|
68
|
+
slow_shutdown: |-
|
69
|
+
Received shutdown signal, but pipeline is still waiting for in-flight events
|
70
|
+
to be processed. Sending another ^C will force quit Logstash, but this may cause
|
71
|
+
data loss.
|
72
|
+
forced_sigint: >-
|
73
|
+
SIGINT received. Terminating immediately..
|
74
|
+
configtest-flag-information: |-
|
75
|
+
You may be interested in the '--configtest' flag which you can
|
76
|
+
use to validate logstash's configuration before you choose
|
77
|
+
to restart a running system.
|
78
|
+
configuration:
|
79
|
+
obsolete: >-
|
80
|
+
The setting `%{name}` in plugin `%{plugin}` is obsolete and is no
|
81
|
+
longer available. %{extra} If you have any questions about this, you
|
82
|
+
are invited to visit https://discuss.elastic.co/c/logstash and ask.
|
83
|
+
file-not-found: |-
|
84
|
+
No config files found: %{path}
|
85
|
+
Can you make sure this path is a logstash config file?
|
86
|
+
scheme-not-supported: |-
|
87
|
+
URI scheme not supported: %{path}
|
88
|
+
Either pass a local file path or "file|http://" URI
|
89
|
+
fetch-failed: |-
|
90
|
+
Unable to fetch config from: %{path}
|
91
|
+
Reason: %{message}
|
92
|
+
setting_missing: |-
|
93
|
+
Missing a required setting for the %{plugin} %{type} plugin:
|
94
|
+
|
95
|
+
%{type} {
|
96
|
+
%{plugin} {
|
97
|
+
%{setting} => # SETTING MISSING
|
98
|
+
...
|
99
|
+
}
|
100
|
+
}
|
101
|
+
setting_invalid: |-
|
102
|
+
Invalid setting for %{plugin} %{type} plugin:
|
103
|
+
|
104
|
+
%{type} {
|
105
|
+
%{plugin} {
|
106
|
+
# This setting must be a %{value_type}
|
107
|
+
# %{note}
|
108
|
+
%{setting} => %{value}
|
109
|
+
...
|
110
|
+
}
|
111
|
+
}
|
112
|
+
invalid_plugin_settings: >-
|
113
|
+
Something is wrong with your configuration.
|
114
|
+
invalid_plugin_settings_duplicate_keys: |-
|
115
|
+
Duplicate keys found in your configuration: [%{keys}]
|
116
|
+
At line: %{line}, column %{column} (byte %{byte})
|
117
|
+
after %{after}
|
118
|
+
invalid_plugin_register: >-
|
119
|
+
Cannot register %{plugin} %{type} plugin.
|
120
|
+
The error reported is:
|
121
|
+
%{error}
|
122
|
+
plugin_path_missing: >-
|
123
|
+
You specified a plugin path that does not exist: %{path}
|
124
|
+
no_plugins_found: |-
|
125
|
+
Could not find any plugins in "%{path}"
|
126
|
+
I tried to find files matching the following, but found none:
|
127
|
+
%{plugin_glob}
|
128
|
+
log_file_failed: |-
|
129
|
+
Failed to open %{path} for writing: %{error}
|
130
|
+
|
131
|
+
This is often a permissions issue, or the wrong
|
132
|
+
path was specified?
|
133
|
+
flag:
|
134
|
+
# Note: Wrap these at 55 chars so they display nicely when clamp emits
|
135
|
+
# them in an 80-character terminal
|
136
|
+
config: |+
|
137
|
+
Load the logstash config from a specific file
|
138
|
+
or directory. If a directory is given, all
|
139
|
+
files in that directory will be concatenated
|
140
|
+
in lexicographical order and then parsed as a
|
141
|
+
single config file. You can also specify
|
142
|
+
wildcards (globs) and any matched files will
|
143
|
+
be loaded in the order described above.
|
144
|
+
config-string: |+
|
145
|
+
Use the given string as the configuration
|
146
|
+
data. Same syntax as the config file. If no
|
147
|
+
input is specified, then the following is
|
148
|
+
used as the default input:
|
149
|
+
"%{default_input}"
|
150
|
+
and if no output is specified, then the
|
151
|
+
following is used as the default output:
|
152
|
+
"%{default_output}"
|
153
|
+
If you wish to use both defaults, please use
|
154
|
+
the empty string for the '-e' flag.
|
155
|
+
configtest: |+
|
156
|
+
Check configuration for valid syntax and then exit.
|
157
|
+
pipeline-workers: |+
|
158
|
+
Sets the number of pipeline workers to run.
|
159
|
+
filterworkers: |+
|
160
|
+
DEPRECATED. Now an alias for --pipeline-workers and -w
|
161
|
+
pipeline-batch-size: |+
|
162
|
+
Size of batches the pipeline is to work in.
|
163
|
+
pipeline-batch-delay: |+
|
164
|
+
When creating pipeline batches, how long to wait while polling
|
165
|
+
for the next event.
|
166
|
+
log: |+
|
167
|
+
Write logstash internal logs to the given
|
168
|
+
file. Without this flag, logstash will emit
|
169
|
+
logs to standard output.
|
170
|
+
verbosity: |+
|
171
|
+
Increase verbosity of logstash internal logs.
|
172
|
+
Specifying once will show 'informational'
|
173
|
+
logs. Specifying twice will show 'debug'
|
174
|
+
logs. This flag is deprecated. You should use
|
175
|
+
--verbose or --debug instead.
|
176
|
+
version: |+
|
177
|
+
Emit the version of logstash and its friends,
|
178
|
+
then exit.
|
179
|
+
pluginpath: |+
|
180
|
+
A path of where to find plugins. This flag
|
181
|
+
can be given multiple times to include
|
182
|
+
multiple paths. Plugins are expected to be
|
183
|
+
in a specific directory hierarchy:
|
184
|
+
'PATH/logstash/TYPE/NAME.rb' where TYPE is
|
185
|
+
'inputs' 'filters', 'outputs' or 'codecs'
|
186
|
+
and NAME is the name of the plugin.
|
187
|
+
quiet: |+
|
188
|
+
Quieter logstash logging. This causes only
|
189
|
+
errors to be emitted.
|
190
|
+
verbose: |+
|
191
|
+
More verbose logging. This causes 'info'
|
192
|
+
level logs to be emitted.
|
193
|
+
debug: |+
|
194
|
+
Most verbose logging. This causes 'debug'
|
195
|
+
level logs to be emitted.
|
196
|
+
debug-config: |+
|
197
|
+
Print the compiled config ruby code out as a debug log (you must also have --debug enabled).
|
198
|
+
WARNING: This will include any 'password' options passed to plugin configs as plaintext, and may result
|
199
|
+
in plaintext passwords appearing in your logs!
|
200
|
+
unsafe_shutdown: |+
|
201
|
+
Force logstash to exit during shutdown even
|
202
|
+
if there are still inflight events in memory.
|
203
|
+
By default, logstash will refuse to quit until all
|
204
|
+
received events have been pushed to the outputs.
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'logstash-core/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.authors = ["Elastic"]
|
8
|
+
gem.email = ["info@elastic.co"]
|
9
|
+
gem.description = %q{The core components of logstash, the scalable log and event management tool}
|
10
|
+
gem.summary = %q{logstash-core - The core components of logstash}
|
11
|
+
gem.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
|
12
|
+
gem.license = "Apache License (2.0)"
|
13
|
+
|
14
|
+
gem.files = Dir.glob(["logstash-core.gemspec", "lib/**/*.rb", "spec/**/*.rb", "locales/*"])
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = "logstash-core"
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.version = LOGSTASH_CORE_VERSION
|
19
|
+
|
20
|
+
gem.add_runtime_dependency "logstash-core-event", "~> 2.2.4.snapshot1"
|
21
|
+
|
22
|
+
gem.add_runtime_dependency "cabin", "~> 0.7.0" #(Apache 2.0 license)
|
23
|
+
gem.add_runtime_dependency "pry", "~> 0.10.1" #(Ruby license)
|
24
|
+
gem.add_runtime_dependency "stud", "~> 0.0.19" #(Apache 2.0 license)
|
25
|
+
gem.add_runtime_dependency "clamp", "~> 0.6.5" #(MIT license) for command line args/flags
|
26
|
+
gem.add_runtime_dependency "filesize", "0.0.4" #(MIT license) for :bytes config validator
|
27
|
+
gem.add_runtime_dependency "gems", "~> 0.8.3" #(MIT license)
|
28
|
+
gem.add_runtime_dependency "concurrent-ruby", "0.9.2"
|
29
|
+
gem.add_runtime_dependency "jruby-openssl", "0.9.13" # Required to support TLSv1.2
|
30
|
+
|
31
|
+
# TODO(sissel): Treetop 1.5.x doesn't seem to work well, but I haven't
|
32
|
+
# investigated what the cause might be. -Jordan
|
33
|
+
gem.add_runtime_dependency "treetop", "< 1.5.0" #(MIT license)
|
34
|
+
|
35
|
+
# upgrade i18n only post 0.6.11, see https://github.com/svenfuchs/i18n/issues/270
|
36
|
+
gem.add_runtime_dependency "i18n", "= 0.6.9" #(MIT license)
|
37
|
+
|
38
|
+
# filetools and rakelib
|
39
|
+
gem.add_runtime_dependency "minitar", "~> 0.5.4"
|
40
|
+
gem.add_runtime_dependency "rubyzip", "~> 1.1.7"
|
41
|
+
gem.add_runtime_dependency "thread_safe", "~> 0.3.5" #(Apache 2.0 license)
|
42
|
+
|
43
|
+
if RUBY_PLATFORM == 'java'
|
44
|
+
gem.platform = RUBY_PLATFORM
|
45
|
+
gem.add_runtime_dependency "jrjackson", "~> 0.3.7" #(Apache 2.0 license)
|
46
|
+
else
|
47
|
+
gem.add_runtime_dependency "oj" #(MIT-style license)
|
48
|
+
end
|
49
|
+
|
50
|
+
if RUBY_ENGINE == "rbx"
|
51
|
+
# rubinius puts the ruby stdlib into gems.
|
52
|
+
gem.add_runtime_dependency "rubysl"
|
53
|
+
|
54
|
+
# Include racc to make the xml tests pass.
|
55
|
+
# https://github.com/rubinius/rubinius/issues/2632#issuecomment-26954565
|
56
|
+
gem.add_runtime_dependency "racc"
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,429 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
module ConditionalFanciness
|
5
|
+
def description
|
6
|
+
return self.metadata[:description]
|
7
|
+
end
|
8
|
+
|
9
|
+
def conditional(expression, &block)
|
10
|
+
describe(expression) do
|
11
|
+
config <<-CONFIG
|
12
|
+
filter {
|
13
|
+
if #{expression} {
|
14
|
+
mutate { add_tag => "success" }
|
15
|
+
} else {
|
16
|
+
mutate { add_tag => "failure" }
|
17
|
+
}
|
18
|
+
}
|
19
|
+
CONFIG
|
20
|
+
instance_eval(&block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "conditionals in output" do
|
26
|
+
extend ConditionalFanciness
|
27
|
+
|
28
|
+
describe "simple" do
|
29
|
+
config <<-CONFIG
|
30
|
+
input {
|
31
|
+
generator {
|
32
|
+
message => '{"foo":{"bar"},"baz": "quux"}'
|
33
|
+
count => 1
|
34
|
+
}
|
35
|
+
}
|
36
|
+
output {
|
37
|
+
if [foo] == "bar" {
|
38
|
+
stdout { }
|
39
|
+
}
|
40
|
+
}
|
41
|
+
CONFIG
|
42
|
+
|
43
|
+
agent do
|
44
|
+
#LOGSTASH-2288, should not fail raising an exception
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "conditionals in filter" do
|
50
|
+
extend ConditionalFanciness
|
51
|
+
|
52
|
+
describe "simple" do
|
53
|
+
config <<-CONFIG
|
54
|
+
filter {
|
55
|
+
mutate { add_field => { "always" => "awesome" } }
|
56
|
+
if [foo] == "bar" {
|
57
|
+
mutate { add_field => { "hello" => "world" } }
|
58
|
+
} else if [bar] == "baz" {
|
59
|
+
mutate { add_field => { "fancy" => "pants" } }
|
60
|
+
} else {
|
61
|
+
mutate { add_field => { "free" => "hugs" } }
|
62
|
+
}
|
63
|
+
}
|
64
|
+
CONFIG
|
65
|
+
|
66
|
+
sample({"foo" => "bar"}) do
|
67
|
+
expect(subject["always"]).to eq("awesome")
|
68
|
+
expect(subject["hello"]).to eq("world")
|
69
|
+
expect(subject["fancy"]).to be_nil
|
70
|
+
expect(subject["free"]).to be_nil
|
71
|
+
end
|
72
|
+
|
73
|
+
sample({"notfoo" => "bar"}) do
|
74
|
+
expect(subject["always"]).to eq("awesome")
|
75
|
+
expect(subject["hello"]).to be_nil
|
76
|
+
expect(subject["fancy"]).to be_nil
|
77
|
+
expect(subject["free"]).to eq("hugs")
|
78
|
+
end
|
79
|
+
|
80
|
+
sample({"bar" => "baz"}) do
|
81
|
+
expect(subject["always"]).to eq("awesome")
|
82
|
+
expect(subject["hello"]).to be_nil
|
83
|
+
expect(subject["fancy"]).to eq("pants")
|
84
|
+
expect(subject["free"]).to be_nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "nested" do
|
89
|
+
config <<-CONFIG
|
90
|
+
filter {
|
91
|
+
if [nest] == 123 {
|
92
|
+
mutate { add_field => { "always" => "awesome" } }
|
93
|
+
if [foo] == "bar" {
|
94
|
+
mutate { add_field => { "hello" => "world" } }
|
95
|
+
} else if [bar] == "baz" {
|
96
|
+
mutate { add_field => { "fancy" => "pants" } }
|
97
|
+
} else {
|
98
|
+
mutate { add_field => { "free" => "hugs" } }
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
CONFIG
|
103
|
+
|
104
|
+
sample("foo" => "bar", "nest" => 124) do
|
105
|
+
expect(subject["always"]).to be_nil
|
106
|
+
expect(subject["hello"]).to be_nil
|
107
|
+
expect(subject["fancy"]).to be_nil
|
108
|
+
expect(subject["free"]).to be_nil
|
109
|
+
end
|
110
|
+
|
111
|
+
sample("foo" => "bar", "nest" => 123) do
|
112
|
+
expect(subject["always"]).to eq("awesome")
|
113
|
+
expect(subject["hello"]).to eq("world")
|
114
|
+
expect(subject["fancy"]).to be_nil
|
115
|
+
expect(subject["free"]).to be_nil
|
116
|
+
end
|
117
|
+
|
118
|
+
sample("notfoo" => "bar", "nest" => 123) do
|
119
|
+
expect(subject["always"]).to eq("awesome")
|
120
|
+
expect(subject["hello"]).to be_nil
|
121
|
+
expect(subject["fancy"]).to be_nil
|
122
|
+
expect(subject["free"]).to eq("hugs")
|
123
|
+
end
|
124
|
+
|
125
|
+
sample("bar" => "baz", "nest" => 123) do
|
126
|
+
expect(subject["always"]).to eq("awesome")
|
127
|
+
expect(subject["hello"]).to be_nil
|
128
|
+
expect(subject["fancy"]).to eq("pants")
|
129
|
+
expect(subject["free"]).to be_nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "comparing two fields" do
|
134
|
+
config <<-CONFIG
|
135
|
+
filter {
|
136
|
+
if [foo] == [bar] {
|
137
|
+
mutate { add_tag => woot }
|
138
|
+
}
|
139
|
+
}
|
140
|
+
CONFIG
|
141
|
+
|
142
|
+
sample("foo" => 123, "bar" => 123) do
|
143
|
+
expect(subject["tags"] ).to include("woot")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "the 'in' operator" do
|
148
|
+
config <<-CONFIG
|
149
|
+
filter {
|
150
|
+
if [foo] in [foobar] {
|
151
|
+
mutate { add_tag => "field in field" }
|
152
|
+
}
|
153
|
+
if [foo] in "foo" {
|
154
|
+
mutate { add_tag => "field in string" }
|
155
|
+
}
|
156
|
+
if "hello" in [greeting] {
|
157
|
+
mutate { add_tag => "string in field" }
|
158
|
+
}
|
159
|
+
if [foo] in ["hello", "world", "foo"] {
|
160
|
+
mutate { add_tag => "field in list" }
|
161
|
+
}
|
162
|
+
if [missing] in [alsomissing] {
|
163
|
+
mutate { add_tag => "shouldnotexist" }
|
164
|
+
}
|
165
|
+
if !("foo" in ["hello", "world"]) {
|
166
|
+
mutate { add_tag => "shouldexist" }
|
167
|
+
}
|
168
|
+
}
|
169
|
+
CONFIG
|
170
|
+
|
171
|
+
sample("foo" => "foo", "foobar" => "foobar", "greeting" => "hello world") do
|
172
|
+
expect(subject["tags"]).to include("field in field")
|
173
|
+
expect(subject["tags"]).to include("field in string")
|
174
|
+
expect(subject["tags"]).to include("string in field")
|
175
|
+
expect(subject["tags"]).to include("field in list")
|
176
|
+
expect(subject["tags"]).not_to include("shouldnotexist")
|
177
|
+
expect(subject["tags"]).to include("shouldexist")
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "the 'not in' operator" do
|
182
|
+
config <<-CONFIG
|
183
|
+
filter {
|
184
|
+
if "foo" not in "baz" { mutate { add_tag => "baz" } }
|
185
|
+
if "foo" not in "foo" { mutate { add_tag => "foo" } }
|
186
|
+
if !("foo" not in "foo") { mutate { add_tag => "notfoo" } }
|
187
|
+
if "foo" not in [somelist] { mutate { add_tag => "notsomelist" } }
|
188
|
+
if "one" not in [somelist] { mutate { add_tag => "somelist" } }
|
189
|
+
if "foo" not in [alsomissing] { mutate { add_tag => "no string in missing field" } }
|
190
|
+
}
|
191
|
+
CONFIG
|
192
|
+
|
193
|
+
sample("foo" => "foo", "somelist" => [ "one", "two" ], "foobar" => "foobar", "greeting" => "hello world", "tags" => [ "fancypantsy" ]) do
|
194
|
+
# verify the original exists
|
195
|
+
expect(subject["tags"]).to include("fancypantsy")
|
196
|
+
|
197
|
+
expect(subject["tags"]).to include("baz")
|
198
|
+
expect(subject["tags"]).not_to include("foo")
|
199
|
+
expect(subject["tags"]).to include("notfoo")
|
200
|
+
expect(subject["tags"]).to include("notsomelist")
|
201
|
+
expect(subject["tags"]).not_to include("somelist")
|
202
|
+
expect(subject["tags"]).to include("no string in missing field")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "operators" do
|
207
|
+
conditional "[message] == 'sample'" do
|
208
|
+
sample("sample") { expect(subject["tags"] ).to include("success") }
|
209
|
+
sample("different") { expect(subject["tags"] ).to include("failure") }
|
210
|
+
end
|
211
|
+
|
212
|
+
conditional "[message] != 'sample'" do
|
213
|
+
sample("sample") { expect(subject["tags"] ).to include("failure") }
|
214
|
+
sample("different") { expect(subject["tags"] ).to include("success") }
|
215
|
+
end
|
216
|
+
|
217
|
+
conditional "[message] < 'sample'" do
|
218
|
+
sample("apple") { expect(subject["tags"] ).to include("success") }
|
219
|
+
sample("zebra") { expect(subject["tags"] ).to include("failure") }
|
220
|
+
end
|
221
|
+
|
222
|
+
conditional "[message] > 'sample'" do
|
223
|
+
sample("zebra") { expect(subject["tags"] ).to include("success") }
|
224
|
+
sample("apple") { expect(subject["tags"] ).to include("failure") }
|
225
|
+
end
|
226
|
+
|
227
|
+
conditional "[message] <= 'sample'" do
|
228
|
+
sample("apple") { expect(subject["tags"] ).to include("success") }
|
229
|
+
sample("zebra") { expect(subject["tags"] ).to include("failure") }
|
230
|
+
sample("sample") { expect(subject["tags"] ).to include("success") }
|
231
|
+
end
|
232
|
+
|
233
|
+
conditional "[message] >= 'sample'" do
|
234
|
+
sample("zebra") { expect(subject["tags"] ).to include("success") }
|
235
|
+
sample("sample") { expect(subject["tags"] ).to include("success") }
|
236
|
+
sample("apple") { expect(subject["tags"] ).to include("failure") }
|
237
|
+
end
|
238
|
+
|
239
|
+
conditional "[message] =~ /sample/" do
|
240
|
+
sample("apple") { expect(subject["tags"] ).to include("failure") }
|
241
|
+
sample("sample") { expect(subject["tags"] ).to include("success") }
|
242
|
+
sample("some sample") { expect(subject["tags"] ).to include("success") }
|
243
|
+
end
|
244
|
+
|
245
|
+
conditional "[message] !~ /sample/" do
|
246
|
+
sample("apple") { expect(subject["tags"]).to include("success") }
|
247
|
+
sample("sample") { expect(subject["tags"]).to include("failure") }
|
248
|
+
sample("some sample") { expect(subject["tags"]).to include("failure") }
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "negated expressions" do
|
254
|
+
conditional "!([message] == 'sample')" do
|
255
|
+
sample("sample") { expect(subject["tags"]).not_to include("success") }
|
256
|
+
sample("different") { expect(subject["tags"]).not_to include("failure") }
|
257
|
+
end
|
258
|
+
|
259
|
+
conditional "!([message] != 'sample')" do
|
260
|
+
sample("sample") { expect(subject["tags"]).not_to include("failure") }
|
261
|
+
sample("different") { expect(subject["tags"]).not_to include("success") }
|
262
|
+
end
|
263
|
+
|
264
|
+
conditional "!([message] < 'sample')" do
|
265
|
+
sample("apple") { expect(subject["tags"]).not_to include("success") }
|
266
|
+
sample("zebra") { expect(subject["tags"]).not_to include("failure") }
|
267
|
+
end
|
268
|
+
|
269
|
+
conditional "!([message] > 'sample')" do
|
270
|
+
sample("zebra") { expect(subject["tags"]).not_to include("success") }
|
271
|
+
sample("apple") { expect(subject["tags"]).not_to include("failure") }
|
272
|
+
end
|
273
|
+
|
274
|
+
conditional "!([message] <= 'sample')" do
|
275
|
+
sample("apple") { expect(subject["tags"]).not_to include("success") }
|
276
|
+
sample("zebra") { expect(subject["tags"]).not_to include("failure") }
|
277
|
+
sample("sample") { expect(subject["tags"]).not_to include("success") }
|
278
|
+
end
|
279
|
+
|
280
|
+
conditional "!([message] >= 'sample')" do
|
281
|
+
sample("zebra") { expect(subject["tags"]).not_to include("success") }
|
282
|
+
sample("sample") { expect(subject["tags"]).not_to include("success") }
|
283
|
+
sample("apple") { expect(subject["tags"]).not_to include("failure") }
|
284
|
+
end
|
285
|
+
|
286
|
+
conditional "!([message] =~ /sample/)" do
|
287
|
+
sample("apple") { expect(subject["tags"]).not_to include("failure") }
|
288
|
+
sample("sample") { expect(subject["tags"]).not_to include("success") }
|
289
|
+
sample("some sample") { expect(subject["tags"]).not_to include("success") }
|
290
|
+
end
|
291
|
+
|
292
|
+
conditional "!([message] !~ /sample/)" do
|
293
|
+
sample("apple") { expect(subject["tags"]).not_to include("success") }
|
294
|
+
sample("sample") { expect(subject["tags"]).not_to include("failure") }
|
295
|
+
sample("some sample") { expect(subject["tags"]).not_to include("failure") }
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
299
|
+
|
300
|
+
describe "value as an expression" do
|
301
|
+
# testing that a field has a value should be true.
|
302
|
+
conditional "[message]" do
|
303
|
+
sample("apple") { expect(subject["tags"]).to include("success") }
|
304
|
+
sample("sample") { expect(subject["tags"]).to include("success") }
|
305
|
+
sample("some sample") { expect(subject["tags"]).to include("success") }
|
306
|
+
end
|
307
|
+
|
308
|
+
# testing that a missing field has a value should be false.
|
309
|
+
conditional "[missing]" do
|
310
|
+
sample("apple") { expect(subject["tags"]).to include("failure") }
|
311
|
+
sample("sample") { expect(subject["tags"]).to include("failure") }
|
312
|
+
sample("some sample") { expect(subject["tags"]).to include("failure") }
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
describe "logic operators" do
|
317
|
+
describe "and" do
|
318
|
+
conditional "[message] and [message]" do
|
319
|
+
sample("whatever") { expect(subject["tags"]).to include("success") }
|
320
|
+
end
|
321
|
+
conditional "[message] and ![message]" do
|
322
|
+
sample("whatever") { expect(subject["tags"]).to include("failure") }
|
323
|
+
end
|
324
|
+
conditional "![message] and [message]" do
|
325
|
+
sample("whatever") { expect(subject["tags"]).to include("failure") }
|
326
|
+
end
|
327
|
+
conditional "![message] and ![message]" do
|
328
|
+
sample("whatever") { expect(subject["tags"]).to include("failure") }
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
describe "or" do
|
333
|
+
conditional "[message] or [message]" do
|
334
|
+
sample("whatever") { expect(subject["tags"]).to include("success") }
|
335
|
+
end
|
336
|
+
conditional "[message] or ![message]" do
|
337
|
+
sample("whatever") { expect(subject["tags"]).to include("success") }
|
338
|
+
end
|
339
|
+
conditional "![message] or [message]" do
|
340
|
+
sample("whatever") { expect(subject["tags"]).to include("success") }
|
341
|
+
end
|
342
|
+
conditional "![message] or ![message]" do
|
343
|
+
sample("whatever") { expect(subject["tags"]).to include("failure") }
|
344
|
+
end
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "field references" do
|
349
|
+
conditional "[field with space]" do
|
350
|
+
sample("field with space" => "hurray") do
|
351
|
+
expect(subject["tags"]).to include("success")
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
conditional "[field with space] == 'hurray'" do
|
356
|
+
sample("field with space" => "hurray") do
|
357
|
+
expect(subject["tags"]).to include("success")
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
conditional "[nested field][reference with][some spaces] == 'hurray'" do
|
362
|
+
sample({"nested field" => { "reference with" => { "some spaces" => "hurray" } } }) do
|
363
|
+
expect(subject["tags"]).to include("success")
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
describe "new events from root" do
|
369
|
+
config <<-CONFIG
|
370
|
+
filter {
|
371
|
+
if [type] == "original" {
|
372
|
+
clone {
|
373
|
+
clones => ["clone"]
|
374
|
+
}
|
375
|
+
}
|
376
|
+
if [type] == "original" {
|
377
|
+
mutate { add_field => { "cond1" => "true" } }
|
378
|
+
} else {
|
379
|
+
mutate { add_field => { "cond2" => "true" } }
|
380
|
+
}
|
381
|
+
}
|
382
|
+
CONFIG
|
383
|
+
|
384
|
+
sample({"type" => "original"}) do
|
385
|
+
expect(subject).to be_an(Array)
|
386
|
+
expect(subject.length).to eq(2)
|
387
|
+
|
388
|
+
expect(subject[0]["type"]).to eq("original")
|
389
|
+
expect(subject[0]["cond1"]).to eq("true")
|
390
|
+
expect(subject[0]["cond2"]).to eq(nil)
|
391
|
+
|
392
|
+
expect(subject[1]["type"]).to eq("clone")
|
393
|
+
# expect(subject[1]["cond1"]).to eq(nil)
|
394
|
+
# expect(subject[1]["cond2"]).to eq("true")
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
describe "multiple new events from root" do
|
399
|
+
config <<-CONFIG
|
400
|
+
filter {
|
401
|
+
if [type] == "original" {
|
402
|
+
clone {
|
403
|
+
clones => ["clone1", "clone2"]
|
404
|
+
}
|
405
|
+
}
|
406
|
+
if [type] == "clone1" {
|
407
|
+
mutate { add_field => { "cond1" => "true" } }
|
408
|
+
} else if [type] == "clone2" {
|
409
|
+
mutate { add_field => { "cond2" => "true" } }
|
410
|
+
}
|
411
|
+
}
|
412
|
+
CONFIG
|
413
|
+
|
414
|
+
sample({"type" => "original"}) do
|
415
|
+
# puts subject.inspect
|
416
|
+
expect(subject[0]["cond1"]).to eq(nil)
|
417
|
+
expect(subject[0]["cond2"]).to eq(nil)
|
418
|
+
|
419
|
+
expect(subject[1]["type"]).to eq("clone1")
|
420
|
+
expect(subject[1]["cond1"]).to eq("true")
|
421
|
+
expect(subject[1]["cond2"]).to eq(nil)
|
422
|
+
|
423
|
+
expect(subject[2]["type"]).to eq("clone2")
|
424
|
+
expect(subject[2]["cond1"]).to eq(nil)
|
425
|
+
expect(subject[2]["cond2"]).to eq("true")
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|