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.

Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/lib/logstash-core.rb +1 -0
  3. data/lib/logstash-core/logstash-core.rb +3 -0
  4. data/lib/logstash-core/version.rb +8 -0
  5. data/lib/logstash/agent.rb +391 -0
  6. data/lib/logstash/codecs/base.rb +50 -0
  7. data/lib/logstash/config/config_ast.rb +550 -0
  8. data/lib/logstash/config/cpu_core_strategy.rb +32 -0
  9. data/lib/logstash/config/defaults.rb +12 -0
  10. data/lib/logstash/config/file.rb +39 -0
  11. data/lib/logstash/config/grammar.rb +3503 -0
  12. data/lib/logstash/config/mixin.rb +518 -0
  13. data/lib/logstash/config/registry.rb +13 -0
  14. data/lib/logstash/environment.rb +98 -0
  15. data/lib/logstash/errors.rb +12 -0
  16. data/lib/logstash/filters/base.rb +205 -0
  17. data/lib/logstash/inputs/base.rb +116 -0
  18. data/lib/logstash/inputs/threadable.rb +18 -0
  19. data/lib/logstash/java_integration.rb +116 -0
  20. data/lib/logstash/json.rb +61 -0
  21. data/lib/logstash/logging.rb +91 -0
  22. data/lib/logstash/namespace.rb +13 -0
  23. data/lib/logstash/output_delegator.rb +172 -0
  24. data/lib/logstash/outputs/base.rb +91 -0
  25. data/lib/logstash/patches.rb +5 -0
  26. data/lib/logstash/patches/bugfix_jruby_2558.rb +51 -0
  27. data/lib/logstash/patches/cabin.rb +35 -0
  28. data/lib/logstash/patches/profile_require_calls.rb +47 -0
  29. data/lib/logstash/patches/rubygems.rb +38 -0
  30. data/lib/logstash/patches/stronger_openssl_defaults.rb +68 -0
  31. data/lib/logstash/pipeline.rb +499 -0
  32. data/lib/logstash/pipeline_reporter.rb +114 -0
  33. data/lib/logstash/plugin.rb +120 -0
  34. data/lib/logstash/program.rb +14 -0
  35. data/lib/logstash/runner.rb +124 -0
  36. data/lib/logstash/shutdown_watcher.rb +100 -0
  37. data/lib/logstash/util.rb +203 -0
  38. data/lib/logstash/util/buftok.rb +139 -0
  39. data/lib/logstash/util/charset.rb +35 -0
  40. data/lib/logstash/util/decorators.rb +52 -0
  41. data/lib/logstash/util/defaults_printer.rb +31 -0
  42. data/lib/logstash/util/filetools.rb +186 -0
  43. data/lib/logstash/util/java_version.rb +66 -0
  44. data/lib/logstash/util/password.rb +25 -0
  45. data/lib/logstash/util/plugin_version.rb +56 -0
  46. data/lib/logstash/util/prctl.rb +10 -0
  47. data/lib/logstash/util/retryable.rb +40 -0
  48. data/lib/logstash/util/socket_peer.rb +7 -0
  49. data/lib/logstash/util/unicode_trimmer.rb +81 -0
  50. data/lib/logstash/util/worker_threads_default_printer.rb +29 -0
  51. data/lib/logstash/util/wrapped_synchronous_queue.rb +41 -0
  52. data/lib/logstash/version.rb +14 -0
  53. data/locales/en.yml +204 -0
  54. data/logstash-core.gemspec +58 -0
  55. data/spec/conditionals_spec.rb +429 -0
  56. data/spec/logstash/agent_spec.rb +85 -0
  57. data/spec/logstash/config/config_ast_spec.rb +146 -0
  58. data/spec/logstash/config/cpu_core_strategy_spec.rb +123 -0
  59. data/spec/logstash/config/defaults_spec.rb +10 -0
  60. data/spec/logstash/config/mixin_spec.rb +158 -0
  61. data/spec/logstash/environment_spec.rb +56 -0
  62. data/spec/logstash/filters/base_spec.rb +251 -0
  63. data/spec/logstash/inputs/base_spec.rb +74 -0
  64. data/spec/logstash/java_integration_spec.rb +304 -0
  65. data/spec/logstash/json_spec.rb +96 -0
  66. data/spec/logstash/output_delegator_spec.rb +144 -0
  67. data/spec/logstash/outputs/base_spec.rb +40 -0
  68. data/spec/logstash/patches_spec.rb +90 -0
  69. data/spec/logstash/pipeline_reporter_spec.rb +85 -0
  70. data/spec/logstash/pipeline_spec.rb +455 -0
  71. data/spec/logstash/plugin_spec.rb +169 -0
  72. data/spec/logstash/runner_spec.rb +68 -0
  73. data/spec/logstash/shutdown_watcher_spec.rb +113 -0
  74. data/spec/logstash/util/buftok_spec.rb +31 -0
  75. data/spec/logstash/util/charset_spec.rb +74 -0
  76. data/spec/logstash/util/defaults_printer_spec.rb +50 -0
  77. data/spec/logstash/util/java_version_spec.rb +79 -0
  78. data/spec/logstash/util/plugin_version_spec.rb +64 -0
  79. data/spec/logstash/util/unicode_trimmer_spec.rb +55 -0
  80. data/spec/logstash/util/worker_threads_default_printer_spec.rb +45 -0
  81. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +28 -0
  82. data/spec/logstash/util_spec.rb +35 -0
  83. 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"
@@ -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