logstash-core 5.6.16-java → 6.0.0.alpha1-java

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.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/gemspec_jars.rb +4 -7
  3. data/lib/logstash-core/logstash-core.jar +0 -0
  4. data/lib/logstash-core/version.rb +4 -8
  5. data/lib/logstash-core_jars.rb +12 -26
  6. data/lib/logstash/agent.rb +261 -246
  7. data/lib/logstash/api/commands/default_metadata.rb +1 -1
  8. data/lib/logstash/api/commands/hot_threads_reporter.rb +5 -11
  9. data/lib/logstash/api/commands/node.rb +3 -2
  10. data/lib/logstash/api/commands/stats.rb +3 -2
  11. data/lib/logstash/bootstrap_check/bad_java.rb +16 -0
  12. data/lib/logstash/bootstrap_check/bad_ruby.rb +12 -0
  13. data/lib/logstash/bootstrap_check/default_config.rb +17 -0
  14. data/lib/logstash/compiler.rb +38 -0
  15. data/lib/logstash/compiler/lscl.rb +566 -0
  16. data/lib/logstash/compiler/lscl/lscl_grammar.rb +3503 -0
  17. data/lib/logstash/compiler/treetop_monkeypatches.rb +92 -0
  18. data/lib/logstash/config/config_ast.rb +4 -82
  19. data/lib/logstash/config/mixin.rb +73 -41
  20. data/lib/logstash/config/pipeline_config.rb +48 -0
  21. data/lib/logstash/config/source/base.rb +16 -0
  22. data/lib/logstash/config/source/local.rb +215 -0
  23. data/lib/logstash/config/source_loader.rb +125 -0
  24. data/lib/logstash/converge_result.rb +103 -0
  25. data/lib/logstash/environment.rb +6 -19
  26. data/lib/logstash/errors.rb +2 -0
  27. data/lib/logstash/execution_context.rb +4 -7
  28. data/lib/logstash/filter_delegator.rb +6 -9
  29. data/lib/logstash/inputs/base.rb +0 -2
  30. data/lib/logstash/instrument/collector.rb +5 -7
  31. data/lib/logstash/instrument/metric_store.rb +12 -12
  32. data/lib/logstash/instrument/metric_type/mean.rb +0 -5
  33. data/lib/logstash/instrument/namespaced_metric.rb +0 -4
  34. data/lib/logstash/instrument/namespaced_null_metric.rb +0 -4
  35. data/lib/logstash/instrument/null_metric.rb +0 -10
  36. data/lib/logstash/instrument/periodic_poller/cgroup.rb +85 -168
  37. data/lib/logstash/instrument/periodic_poller/jvm.rb +5 -5
  38. data/lib/logstash/instrument/periodic_poller/pq.rb +3 -7
  39. data/lib/logstash/instrument/periodic_pollers.rb +1 -3
  40. data/lib/logstash/instrument/wrapped_write_client.rb +24 -33
  41. data/lib/logstash/logging/logger.rb +15 -47
  42. data/lib/logstash/namespace.rb +0 -1
  43. data/lib/logstash/output_delegator.rb +5 -7
  44. data/lib/logstash/outputs/base.rb +0 -2
  45. data/lib/logstash/pipeline.rb +159 -87
  46. data/lib/logstash/pipeline_action.rb +13 -0
  47. data/lib/logstash/pipeline_action/base.rb +29 -0
  48. data/lib/logstash/pipeline_action/create.rb +47 -0
  49. data/lib/logstash/pipeline_action/reload.rb +48 -0
  50. data/lib/logstash/pipeline_action/stop.rb +23 -0
  51. data/lib/logstash/plugin.rb +0 -1
  52. data/lib/logstash/plugins/hooks_registry.rb +6 -0
  53. data/lib/logstash/plugins/registry.rb +0 -1
  54. data/lib/logstash/program.rb +14 -0
  55. data/lib/logstash/queue_factory.rb +5 -1
  56. data/lib/logstash/runner.rb +58 -80
  57. data/lib/logstash/settings.rb +3 -27
  58. data/lib/logstash/state_resolver.rb +41 -0
  59. data/lib/logstash/util/java_version.rb +6 -0
  60. data/lib/logstash/util/safe_uri.rb +12 -148
  61. data/lib/logstash/util/thread_dump.rb +4 -7
  62. data/lib/logstash/util/wrapped_acked_queue.rb +36 -39
  63. data/lib/logstash/util/wrapped_synchronous_queue.rb +29 -39
  64. data/lib/logstash/version.rb +10 -8
  65. data/locales/en.yml +3 -54
  66. data/logstash-core.gemspec +8 -35
  67. data/spec/{logstash/api/modules → api/lib/api}/logging_spec.rb +10 -1
  68. data/spec/{logstash/api/modules → api/lib/api}/node_plugins_spec.rb +2 -1
  69. data/spec/{logstash/api/modules → api/lib/api}/node_spec.rb +3 -3
  70. data/spec/{logstash/api/modules → api/lib/api}/node_stats_spec.rb +3 -7
  71. data/spec/{logstash/api/modules → api/lib/api}/plugins_spec.rb +3 -4
  72. data/spec/{logstash/api/modules → api/lib/api}/root_spec.rb +2 -2
  73. data/spec/api/lib/api/support/resource_dsl_methods.rb +87 -0
  74. data/spec/{logstash/api/commands/stats_spec.rb → api/lib/commands/stats.rb} +2 -7
  75. data/spec/{logstash/api → api/lib}/errors_spec.rb +1 -1
  76. data/spec/{logstash/api → api/lib}/rack_app_spec.rb +0 -0
  77. data/spec/api/spec_helper.rb +106 -0
  78. data/spec/logstash/agent/converge_spec.rb +286 -0
  79. data/spec/logstash/agent/metrics_spec.rb +244 -0
  80. data/spec/logstash/agent_spec.rb +213 -225
  81. data/spec/logstash/compiler/compiler_spec.rb +584 -0
  82. data/spec/logstash/config/config_ast_spec.rb +8 -47
  83. data/spec/logstash/config/mixin_spec.rb +2 -42
  84. data/spec/logstash/config/pipeline_config_spec.rb +75 -0
  85. data/spec/logstash/config/source/local_spec.rb +395 -0
  86. data/spec/logstash/config/source_loader_spec.rb +122 -0
  87. data/spec/logstash/converge_result_spec.rb +179 -0
  88. data/spec/logstash/event_spec.rb +0 -66
  89. data/spec/logstash/execution_context_spec.rb +8 -12
  90. data/spec/logstash/filter_delegator_spec.rb +12 -24
  91. data/spec/logstash/inputs/base_spec.rb +7 -5
  92. data/spec/logstash/instrument/periodic_poller/cgroup_spec.rb +92 -225
  93. data/spec/logstash/instrument/periodic_poller/jvm_spec.rb +1 -1
  94. data/spec/logstash/instrument/periodic_poller/os_spec.rb +32 -29
  95. data/spec/logstash/instrument/wrapped_write_client_spec.rb +33 -33
  96. data/spec/logstash/legacy_ruby_event_spec.rb +13 -4
  97. data/spec/logstash/output_delegator_spec.rb +11 -20
  98. data/spec/logstash/outputs/base_spec.rb +7 -5
  99. data/spec/logstash/pipeline_action/create_spec.rb +83 -0
  100. data/spec/logstash/pipeline_action/reload_spec.rb +83 -0
  101. data/spec/logstash/pipeline_action/stop_spec.rb +37 -0
  102. data/spec/logstash/pipeline_pq_file_spec.rb +1 -1
  103. data/spec/logstash/pipeline_spec.rb +81 -137
  104. data/spec/logstash/plugin_spec.rb +2 -1
  105. data/spec/logstash/plugins/hooks_registry_spec.rb +6 -0
  106. data/spec/logstash/queue_factory_spec.rb +13 -1
  107. data/spec/logstash/runner_spec.rb +29 -140
  108. data/spec/logstash/settings/writable_directory_spec.rb +10 -13
  109. data/spec/logstash/settings_spec.rb +0 -91
  110. data/spec/logstash/state_resolver_spec.rb +156 -0
  111. data/spec/logstash/timestamp_spec.rb +2 -6
  112. data/spec/logstash/util/java_version_spec.rb +22 -0
  113. data/spec/logstash/util/safe_uri_spec.rb +0 -56
  114. data/spec/logstash/util/wrapped_synchronous_queue_spec.rb +22 -0
  115. data/spec/support/helpers.rb +9 -11
  116. data/spec/support/matchers.rb +96 -6
  117. data/spec/support/mocks_classes.rb +80 -0
  118. data/spec/support/shared_contexts.rb +2 -27
  119. metadata +100 -149
  120. data/lib/logstash/config/loader.rb +0 -107
  121. data/lib/logstash/config/modules_common.rb +0 -103
  122. data/lib/logstash/config/source/modules.rb +0 -55
  123. data/lib/logstash/config/string_escape.rb +0 -27
  124. data/lib/logstash/dependency_report.rb +0 -131
  125. data/lib/logstash/dependency_report_runner.rb +0 -17
  126. data/lib/logstash/elasticsearch_client.rb +0 -142
  127. data/lib/logstash/instrument/global_metrics.rb +0 -13
  128. data/lib/logstash/instrument/periodic_poller/dlq.rb +0 -24
  129. data/lib/logstash/modules/cli_parser.rb +0 -74
  130. data/lib/logstash/modules/elasticsearch_config.rb +0 -22
  131. data/lib/logstash/modules/elasticsearch_importer.rb +0 -37
  132. data/lib/logstash/modules/elasticsearch_resource.rb +0 -10
  133. data/lib/logstash/modules/file_reader.rb +0 -36
  134. data/lib/logstash/modules/kibana_base.rb +0 -24
  135. data/lib/logstash/modules/kibana_client.rb +0 -124
  136. data/lib/logstash/modules/kibana_config.rb +0 -105
  137. data/lib/logstash/modules/kibana_dashboards.rb +0 -36
  138. data/lib/logstash/modules/kibana_importer.rb +0 -17
  139. data/lib/logstash/modules/kibana_resource.rb +0 -10
  140. data/lib/logstash/modules/kibana_settings.rb +0 -40
  141. data/lib/logstash/modules/logstash_config.rb +0 -120
  142. data/lib/logstash/modules/resource_base.rb +0 -38
  143. data/lib/logstash/modules/scaffold.rb +0 -52
  144. data/lib/logstash/modules/settings_merger.rb +0 -23
  145. data/lib/logstash/modules/util.rb +0 -17
  146. data/lib/logstash/util/dead_letter_queue_manager.rb +0 -61
  147. data/lib/logstash/util/environment_variables.rb +0 -43
  148. data/spec/logstash/config/loader_spec.rb +0 -38
  149. data/spec/logstash/config/string_escape_spec.rb +0 -24
  150. data/spec/logstash/instrument/periodic_poller/dlq_spec.rb +0 -17
  151. data/spec/logstash/modules/logstash_config_spec.rb +0 -56
  152. data/spec/logstash/modules/scaffold_spec.rb +0 -234
  153. data/spec/logstash/pipeline_dlq_commit_spec.rb +0 -109
  154. data/spec/logstash/settings/splittable_string_array_spec.rb +0 -51
  155. data/spec/logstash/util/wrapped_acked_queue_spec.rb +0 -49
  156. data/versions-gem-copy.yml +0 -12
@@ -12,7 +12,7 @@ module LogStash
12
12
  end
13
13
 
14
14
  def host
15
- @@host ||= Socket.gethostname
15
+ Socket.gethostname
16
16
  end
17
17
 
18
18
  def version
@@ -1,5 +1,4 @@
1
1
  # encoding: utf-8
2
- java_import 'org.logstash.instrument.reports.ThreadsReport'
3
2
 
4
3
  class HotThreadsReport
5
4
  STRING_SEPARATOR_LENGTH = 80.freeze
@@ -8,7 +7,8 @@ class HotThreadsReport
8
7
  def initialize(cmd, options)
9
8
  @cmd = cmd
10
9
  filter = { :stacktrace_size => options.fetch(:stacktrace_size, HOT_THREADS_STACK_TRACES_SIZE_DEFAULT) }
11
- @thread_dump = ::LogStash::Util::ThreadDump.new(options.merge(:dump => ThreadsReport.generate(filter)))
10
+ jr_dump = JRMonitor.threads.generate(filter)
11
+ @thread_dump = ::LogStash::Util::ThreadDump.new(options.merge(:dump => jr_dump))
12
12
  end
13
13
 
14
14
  def to_s
@@ -17,12 +17,7 @@ class HotThreadsReport
17
17
  report << '=' * STRING_SEPARATOR_LENGTH
18
18
  report << "\n"
19
19
  hash[:threads].each do |thread|
20
- line_str = I18n.t("logstash.web_api.hot_threads.thread_title",
21
- :percent_of_cpu_time => thread[:percent_of_cpu_time],
22
- :thread_state => thread[:state],
23
- :thread_name => thread[:name],
24
- :thread_id => thread[:thread_id])
25
- thread_report = "#{line_str} \n"
20
+ thread_report = "#{I18n.t("logstash.web_api.hot_threads.thread_title", :percent_of_cpu_time => thread[:percent_of_cpu_time], :thread_state => thread[:state], :thread_name => thread[:name])} \n"
26
21
  thread_report << "#{thread[:path]}\n" if thread[:path]
27
22
  thread[:traces].each do |trace|
28
23
  thread_report << "\t#{trace}\n"
@@ -36,10 +31,9 @@ class HotThreadsReport
36
31
 
37
32
  def to_hash
38
33
  hash = { :time => Time.now.iso8601, :busiest_threads => @thread_dump.top_count, :threads => [] }
39
- @thread_dump.each do |_hash|
34
+ @thread_dump.each do |thread_name, _hash|
40
35
  thread_name, thread_path = _hash["thread.name"].split(": ")
41
36
  thread = { :name => thread_name,
42
- :thread_id => _hash["thread.id"],
43
37
  :percent_of_cpu_time => cpu_time_as_percent(_hash),
44
38
  :state => _hash["thread.state"]
45
39
  }
@@ -48,7 +42,7 @@ class HotThreadsReport
48
42
  _hash["thread.stacktrace"].each do |trace|
49
43
  traces << trace
50
44
  end
51
- thread[:traces] = traces
45
+ thread[:traces] = traces unless traces.empty?
52
46
  hash[:threads] << thread
53
47
  end
54
48
  { :hot_threads => hash }
@@ -20,8 +20,8 @@ module LogStash
20
20
  def pipeline(pipeline_id = LogStash::SETTINGS.get("pipeline.id").to_sym)
21
21
  stats = extract_metrics(
22
22
  [:stats, :pipelines, pipeline_id, :config],
23
- :workers, :batch_size, :batch_delay, :config_reload_automatic, :config_reload_interval, :dead_letter_queue_enabled, :dead_letter_queue_path
24
- ).reject{|_, v|v.nil?}
23
+ :workers, :batch_size, :batch_delay, :config_reload_automatic, :config_reload_interval
24
+ )
25
25
  stats.merge(:id => pipeline_id)
26
26
  end
27
27
 
@@ -40,6 +40,7 @@ module LogStash
40
40
  {
41
41
  :pid => ManagementFactory.getRuntimeMXBean().getName().split("@").first.to_i,
42
42
  :version => java.lang.System.getProperty("java.version"),
43
+ :vm_name => java.lang.System.getProperty("java.vm.name"),
43
44
  :vm_version => java.lang.System.getProperty("java.version"),
44
45
  :vm_vendor => java.lang.System.getProperty("java.vendor"),
45
46
  :vm_name => java.lang.System.getProperty("java.vm.name"),
@@ -54,6 +54,7 @@ module LogStash
54
54
  def memory
55
55
  memory = service.get_shallow(:jvm, :memory)
56
56
  {
57
+ :heap_used_in_bytes => memory[:heap][:used_in_bytes],
57
58
  :heap_used_percent => memory[:heap][:used_percent],
58
59
  :heap_committed_in_bytes => memory[:heap][:committed_in_bytes],
59
60
  :heap_max_in_bytes => memory[:heap][:max_in_bytes],
@@ -107,8 +108,8 @@ module LogStash
107
108
  },
108
109
  :reloads => stats[:reloads],
109
110
  :queue => stats[:queue]
110
- }.merge(stats[:dlq] ? {:dead_letter_queue => stats[:dlq]} : {})
111
- end
111
+ }
112
+ end
112
113
  end # module PluginsStats
113
114
  end
114
115
  end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+ require "logstash/util"
3
+ require "logstash/util/java_version"
4
+ require "logstash/errors"
5
+
6
+ module LogStash module BootstrapCheck
7
+ class BadJava
8
+ def self.check(settings)
9
+ # Exit on bad java versions
10
+ LogStash::Util::JavaVersion.validate_java_version!
11
+ rescue => e
12
+ # Just rewrap the original exception
13
+ raise LogStash::BootstrapCheckError, e.message
14
+ end
15
+ end
16
+ end end
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ require "logstash/errors"
3
+
4
+ module LogStash module BootstrapCheck
5
+ class BadRuby
6
+ def self.check(settings)
7
+ if RUBY_VERSION < "1.9.2"
8
+ raise LogStash::BootstrapCheckError, "Ruby 1.9.2 or later is required. (You are running: " + RUBY_VERSION + ")"
9
+ end
10
+ end
11
+ end
12
+ end end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+ require "logstash/errors"
3
+
4
+ module LogStash module BootstrapCheck
5
+ class DefaultConfig
6
+ def self.check(settings)
7
+ if settings.get("config.string").nil? && settings.get("path.config").nil?
8
+ raise LogStash::BootstrapCheckError, I18n.t("logstash.runner.missing-configuration")
9
+ end
10
+
11
+ if settings.get("config.reload.automatic") && settings.get("path.config").nil?
12
+ # there's nothing to reload
13
+ raise LogStash::BootstrapCheckError, I18n.t("logstash.runner.reload-without-config-path")
14
+ end
15
+ end
16
+ end
17
+ end end
@@ -0,0 +1,38 @@
1
+ require 'logstash/util/loggable'
2
+ require 'logstash/compiler/lscl/lscl_grammar'
3
+
4
+ java_import org.logstash.config.ir.Pipeline
5
+ java_import org.logstash.config.ir.graph.Graph;
6
+ java_import org.logstash.config.ir.graph.PluginVertex;
7
+
8
+ module LogStash; class Compiler
9
+ include ::LogStash::Util::Loggable
10
+
11
+ def self.compile_pipeline(config_str, source_file=nil)
12
+ graph_sections = self.compile_graph(config_str, source_file)
13
+ pipeline = org.logstash.config.ir.Pipeline.new(
14
+ graph_sections[:input],
15
+ graph_sections[:filter],
16
+ graph_sections[:output]
17
+ )
18
+ end
19
+
20
+ def self.compile_ast(config_str, source_file=nil)
21
+ grammar = LogStashCompilerLSCLGrammarParser.new
22
+ config = grammar.parse(config_str)
23
+
24
+ if config.nil?
25
+ raise ConfigurationError, grammar.failure_reason
26
+ end
27
+
28
+ config
29
+ end
30
+
31
+ def self.compile_imperative(config_str, source_file=nil)
32
+ compile_ast(config_str, source_file).compile(source_file)
33
+ end
34
+
35
+ def self.compile_graph(config_str, source_file=nil)
36
+ Hash[compile_imperative(config_str, source_file).map {|section,icompiled| [section, icompiled.toGraph]}]
37
+ end
38
+ end; end
@@ -0,0 +1,566 @@
1
+ # encoding: utf-8
2
+ require 'logstash/errors'
3
+ require "treetop"
4
+ require "logstash/compiler/treetop_monkeypatches"
5
+ java_import org.logstash.config.ir.DSL
6
+ java_import org.logstash.common.SourceWithMetadata
7
+
8
+ module LogStashCompilerLSCLGrammar; module LogStash; module Compiler; module LSCL; module AST
9
+ # Helpers for parsing LSCL files
10
+ module Helpers
11
+ def source_meta
12
+ line, column = line_and_column
13
+ org.logstash.common.SourceWithMetadata.new(source_file, line, column, self.text_value)
14
+ end
15
+
16
+ def source_file=(value)
17
+ set_meta(:source_file, value)
18
+ end
19
+
20
+ def source_file
21
+ get_meta(:source_file)
22
+ end
23
+
24
+ def compose(*statements)
25
+ compose_for(section_type.to_sym).call(source_meta, *statements)
26
+ end
27
+
28
+ def compose_for(section_sym)
29
+ if section_sym == :filter
30
+ jdsl.method(:iComposeSequence)
31
+ else
32
+ jdsl.method(:iComposeParallel)
33
+ end
34
+ end
35
+
36
+ def line_and_column
37
+ start = self.interval.first
38
+ [self.input.line_of(start), self.input.column_of(start)]
39
+ end
40
+
41
+ def empty_source_meta()
42
+ org.logstash.common.SourceWithMetadata.new()
43
+ end
44
+
45
+ def jdsl
46
+ org.logstash.config.ir.DSL
47
+ end
48
+
49
+ def self.jdsl
50
+ org.logstash.config.ir.DSL
51
+ end
52
+
53
+ AND_METHOD = jdsl.method(:eAnd)
54
+ OR_METHOD = jdsl.method(:eOr)
55
+ end
56
+
57
+ class Node < Treetop::Runtime::SyntaxNode
58
+ include Helpers
59
+
60
+ def section_type
61
+ if recursive_select_parent(Plugin).any?
62
+ return "codec"
63
+ else
64
+ section = recursive_select_parent(PluginSection)
65
+ return section.first.plugin_type.text_value
66
+ end
67
+ end
68
+ end
69
+
70
+ class Config < Node
71
+ include Helpers
72
+
73
+ def compile(source_file=nil)
74
+ # There is no way to move vars across nodes in treetop :(
75
+ self.source_file = source_file
76
+
77
+ sections = recursive_select(PluginSection)
78
+
79
+ section_map = {
80
+ :input => [],
81
+ :filter => [],
82
+ :output => []
83
+ }
84
+
85
+ sections.each do |section|
86
+ section_name = section.plugin_type.text_value.to_sym
87
+ section_expr = section.expr
88
+ raise "Unknown section name #{section_name}!" if ![:input, :output, :filter].include?(section_name)
89
+ ::Array[section_expr].each do |se|
90
+ section_map[section_name].concat se
91
+ end
92
+ end
93
+
94
+ section_map.keys.each do |key|
95
+ section_map[key] = compose_for(key).call(empty_source_meta, *section_map[key])
96
+ end
97
+
98
+ section_map
99
+ end
100
+ end
101
+
102
+ class Comment < Node; end
103
+ class Whitespace < Node; end
104
+
105
+ class PluginSection < Node
106
+ def expr
107
+ recursive_select(Branch, Plugin).map(&:expr)
108
+ end
109
+ end
110
+
111
+ class Plugins < Node; end
112
+ class Plugin < Node
113
+ def expr
114
+ jdsl.iPlugin(source_meta, plugin_type_enum, self.plugin_name, self.expr_attributes)
115
+ end
116
+
117
+ def plugin_type_enum
118
+ case section_type
119
+ when "input"
120
+ Java::OrgLogstashConfigIr::PluginDefinition::Type::INPUT
121
+ when "codec"
122
+ Java::OrgLogstashConfigIr::PluginDefinition::Type::CODEC
123
+ when "filter"
124
+ Java::OrgLogstashConfigIr::PluginDefinition::Type::FILTER
125
+ when "output"
126
+ Java::OrgLogstashConfigIr::PluginDefinition::Type::OUTPUT
127
+ end
128
+ end
129
+
130
+ def plugin_name
131
+ return name.text_value
132
+ end
133
+
134
+ def expr_attributes
135
+ # Turn attributes into a hash map
136
+ self.attributes.recursive_select(Attribute).map(&:expr).map {|k,v|
137
+ if v.java_kind_of?(Java::OrgLogstashConfigIrExpression::ValueExpression)
138
+ [k, v.get]
139
+ else
140
+ [k,v]
141
+ end
142
+ }.reduce({}) do |hash,kv|
143
+ k,v = kv
144
+ hash[k] = v
145
+ hash
146
+ end
147
+
148
+ end
149
+ end
150
+
151
+ class Name < Node
152
+ def expr
153
+ return text_value
154
+ end
155
+ end
156
+
157
+ class Attribute < Node
158
+ def expr
159
+ [name.text_value, value.expr]
160
+ end
161
+ end
162
+
163
+ class RValue < Node; end
164
+ class Value < RValue; end
165
+
166
+ class Bareword < Value
167
+ def expr
168
+ jdsl.eValue(source_meta, text_value)
169
+ end
170
+ end
171
+
172
+ class String < Value
173
+ def expr
174
+ jdsl.e_value(source_meta, text_value[1...-1])
175
+ end
176
+ end
177
+
178
+ class RegExp < Value
179
+ def expr
180
+ # Strip the slashes off
181
+ jdsl.eRegex(text_value[1..-2])
182
+ end
183
+ end
184
+
185
+ class Number < Value
186
+ def expr
187
+ jdsl.eValue(source_meta, text_value.include?(".") ?
188
+ text_value.to_f :
189
+ text_value.to_i)
190
+ end
191
+ end
192
+
193
+ class Array < Value
194
+ def expr
195
+ jdsl.eValue(source_meta, recursive_select(Value).map(&:expr).map(&:get))
196
+ end
197
+ end
198
+
199
+ class Hash < Value
200
+ def validate!
201
+ duplicate_values = find_duplicate_keys
202
+
203
+ if duplicate_values.size > 0
204
+ raise ConfigurationError.new(
205
+ I18n.t("logstash.runner.configuration.invalid_plugin_settings_duplicate_keys",
206
+ :keys => duplicate_values.join(', '),
207
+ :line => input.line_of(interval.first),
208
+ :column => input.column_of(interval.first),
209
+ :byte => interval.first + 1,
210
+ :after => input[0..interval.first]
211
+ )
212
+ )
213
+ end
214
+ end
215
+
216
+ def find_duplicate_keys
217
+ values = recursive_select(HashEntry).collect { |hash_entry| hash_entry.name.text_value }
218
+ values.find_all { |v| values.count(v) > 1 }.uniq
219
+ end
220
+
221
+ def expr
222
+ validate!
223
+ ::Hash[recursive_select(HashEntry).map(&:expr)]
224
+ end
225
+ end
226
+
227
+ class HashEntries < Node; end
228
+
229
+ class HashEntry < Node
230
+ def expr
231
+ return [name.expr.get, value.expr.get()]
232
+ end
233
+ end
234
+
235
+ class Branch < Node
236
+ def expr
237
+ # Build this stuff as s-expressions for convenience at first
238
+ # This will turn if/elsif/else blocks into nested if/else trees
239
+
240
+ exprs = []
241
+ else_stack = [] # For turning if / elsif / else into nested ifs
242
+
243
+ self.recursive_select(Plugin, If, Elsif, Else).each do |node|
244
+ if node.is_a?(If)
245
+ exprs << :if
246
+ exprs << expr_cond(node)
247
+ exprs << expr_body(node)
248
+ elsif node.is_a?(Elsif)
249
+ condition = expr_cond(node)
250
+ body = expr_body(node)
251
+ else_stack << [:if, condition, body]
252
+ elsif node.is_a?(Else)
253
+ body = expr_body(node)
254
+ if else_stack.size >= 1
255
+ else_stack.last << body
256
+ else
257
+ exprs << body
258
+ end
259
+ end
260
+ end
261
+
262
+ else_stack.reverse.each_cons(2) do |cons|
263
+ later,earlier = cons
264
+ earlier << later
265
+ end
266
+ exprs << else_stack.first
267
+
268
+ # Then convert to the imperative java IR
269
+ javaify_sexpr(exprs)
270
+ end
271
+
272
+ def javaify_sexpr(sexpr)
273
+ return nil if sexpr.nil?
274
+
275
+ head, tail = sexpr.first
276
+ tail = sexpr[1..-1]
277
+
278
+ if head == :if
279
+ condition, t_branch, f_branch = tail
280
+
281
+ java_t_branch = t_branch && javaify_sexpr(t_branch)
282
+ java_f_branch = f_branch && javaify_sexpr(f_branch)
283
+
284
+ if java_t_branch || java_f_branch
285
+ jdsl.iIf(condition, java_t_branch || jdsl.noop, java_f_branch || jdsl.noop)
286
+ else
287
+ jdsl.noop()
288
+ end
289
+ elsif head == :compose
290
+ tail && tail.size > 0 ? compose(*tail) : jdsl.noop
291
+ else
292
+ raise "Unknown expression #{sexpr}!"
293
+ end
294
+ end
295
+
296
+ def expr_cond(node)
297
+ node.elements.find {|e| e.is_a?(Condition)}.expr
298
+ end
299
+
300
+ def expr_body(node)
301
+ [:compose, *node.recursive_select(Plugin, Branch).map(&:expr)]
302
+ end
303
+ end
304
+
305
+ # Branch covers all these
306
+ class BranchEntry < Node; end
307
+ class If < BranchEntry; end
308
+ class Elsif < BranchEntry; end
309
+ class Else < BranchEntry; end
310
+
311
+ class Condition < Node
312
+ include Helpers
313
+
314
+ def expr
315
+ first_element = elements.first
316
+ rest_elements = elements.size > 1 ? elements[1].recursive_select(BooleanOperator, Expression, SelectorElement) : []
317
+
318
+ all_elements = [first_element, *rest_elements]
319
+
320
+ if all_elements.size == 1
321
+ elem = all_elements.first
322
+ if elem.is_a?(Selector)
323
+ eventValue = elem.recursive_select(SelectorElement).first.expr
324
+ jdsl.eTruthy(source_meta, eventValue)
325
+ elsif elem.is_a?(RegexpExpression)
326
+ elem.expr
327
+ else
328
+ join_conditions(all_elements)
329
+ end
330
+ else
331
+ join_conditions(all_elements)
332
+ end
333
+ end
334
+
335
+ def precedence(op)
336
+ # Believe this is right for logstash?
337
+ case op
338
+ when AND_METHOD
339
+ 2
340
+ when OR_METHOD
341
+ 1
342
+ else
343
+ raise ArgumentError, "Unexpected operator #{op}"
344
+ end
345
+ end
346
+
347
+ # Converts an sexpr of :and or :or to the java imperative IR
348
+ def jconvert(sexpr)
349
+ raise "jconvert cannot handle nils!" if sexpr.nil?
350
+
351
+ if sexpr.java_kind_of?(Java::OrgLogstashConfigIrExpression::Expression)
352
+ return sexpr
353
+ end
354
+
355
+ op, left, right = sexpr
356
+
357
+ left_c = jconvert(left)
358
+ right_c = jconvert(right)
359
+
360
+ case op
361
+ when :and
362
+ return jdsl.eAnd(left, right);
363
+ when :or
364
+ return jdsl.eOr(left, right);
365
+ else
366
+ raise "Unknown op #{jop}"
367
+ end
368
+ end
369
+
370
+ def join_conditions(all_elements)
371
+ # Use Dijkstra's shunting yard algorithm
372
+ out = []
373
+ operators = []
374
+
375
+ all_elements.each do |e|
376
+ e_exp = e.expr
377
+
378
+ if e.is_a?(BooleanOperator)
379
+ if operators.last && precedence(operators.last) > precedence(e_exp)
380
+ out << operators.pop
381
+ end
382
+ operators << e_exp
383
+ else
384
+ out << e_exp
385
+ end
386
+ end
387
+ operators.reverse.each {|o| out << o}
388
+
389
+ stack = []
390
+ expr = []
391
+ out.each do |e|
392
+ if e.is_a?(Symbol)
393
+ rval, lval = stack.pop, stack.pop
394
+ stack << jconvert([e, lval, rval])
395
+ elsif e.nil?
396
+ raise "Nil expr encountered! This should not happen!"
397
+ else
398
+ stack << e
399
+ end
400
+ end
401
+
402
+ stack_to_expr(stack)
403
+ end
404
+
405
+ def stack_to_expr(stack)
406
+ raise "Got an empty stack! This should not happen!" if stack.empty?
407
+ stack = stack.reverse # We need to work the stack in reverse order
408
+
409
+ working_stack = []
410
+ while elem = stack.pop
411
+ if elem.is_a?(::Method)
412
+ right, left = working_stack.pop, working_stack.pop
413
+ working_stack << elem.call(left, right)
414
+ else
415
+ working_stack << elem
416
+ end
417
+ end
418
+
419
+ raise "Invariant violated! Stack size > 1" if working_stack.size > 1
420
+
421
+ working_stack.first
422
+ end
423
+ end
424
+
425
+ module Expression
426
+ def expr
427
+ # If we have a more specific type (like a Negative expression) use that
428
+ if defined?(super)
429
+ return super
430
+ end
431
+
432
+ exprs = self.recursive_select(Condition, Selector).map(&:expr)
433
+
434
+ raise "Exprs should only have one part!" if exprs.size != 1
435
+ exprs.first
436
+ end
437
+ end
438
+
439
+ module NegativeExpression
440
+ include Helpers
441
+
442
+ def expr
443
+ exprs = self.recursive_select(Condition, Selector).map(&:expr)
444
+ raise "Negative exprs should only have one part!" if exprs.size != 1
445
+ jdsl.eNot(source_meta, exprs.first)
446
+ end
447
+ end
448
+
449
+ module ComparisonExpression
450
+ include Helpers
451
+
452
+ def expr
453
+ lval, comparison_method, rval = self.recursive_select(Selector, Expression, ComparisonOperator, Number, String).map(&:expr)
454
+ comparison_method.call(source_meta, lval, rval)
455
+ end
456
+ end
457
+
458
+ module InExpression
459
+ include Helpers
460
+
461
+ def expr
462
+ item, list = recursive_select(RValue)
463
+ jdsl.eIn(source_meta, item.expr, list.expr)
464
+ end
465
+ end
466
+
467
+ module NotInExpression
468
+ include Helpers
469
+
470
+ def expr
471
+ item, list = recursive_select(RValue)
472
+ jdsl.eNot(source_meta, jdsl.eIn(item.expr, list.expr))
473
+ end
474
+ end
475
+
476
+ # Not implemented because no one uses this
477
+ class MethodCall < Node; end
478
+
479
+ class RegexpExpression < Node
480
+ def expr
481
+ selector, operator_method, regexp = recursive_select(
482
+ Selector,
483
+ LogStash::Compiler::LSCL::AST::RegExpOperator,
484
+ LogStash::Compiler::LSCL::AST::RegExp,
485
+ LogStash::Compiler::LSCL::AST::String # Strings work as rvalues! :p
486
+ ).map(&:expr)
487
+
488
+ # Handle string rvalues, they just get turned into regexps
489
+ # Maybe we really shouldn't handle these anymore...
490
+ if regexp.class == org.logstash.config.ir.expression.ValueExpression
491
+ regexp = jdsl.eRegex(regexp.get)
492
+ end
493
+
494
+ raise "Expected a selector in #{text_value}!" unless selector
495
+ raise "Expected a regexp in #{text_value}!" unless regexp
496
+
497
+ operator_method.call(source_meta, selector, regexp);
498
+ end
499
+ end
500
+
501
+ module BranchOrPlugin; end
502
+
503
+ module ComparisonOperator
504
+ include Helpers
505
+
506
+ def expr
507
+ case self.text_value
508
+ when "=="
509
+ jdsl.method(:eEq)
510
+ when "!="
511
+ jdsl.method(:eNeq)
512
+ when ">"
513
+ jdsl.method(:eGt)
514
+ when "<"
515
+ jdsl.method(:eLt)
516
+ when ">="
517
+ jdsl.method(:eGte)
518
+ when "<="
519
+ jdsl.method(:eLte)
520
+ else
521
+ raise "Unknown operator #{self.text_value}"
522
+ end
523
+ end
524
+ end
525
+
526
+ module RegExpOperator
527
+ include Helpers
528
+
529
+ def expr
530
+ if self.text_value == '!~'
531
+ jdsl.method(:eRegexNeq)
532
+ elsif self.text_value == '=~'
533
+ jdsl.method(:eRegexEq)
534
+ else
535
+ raise "Unknown regex operator #{self.text_value}"
536
+ end
537
+ end
538
+ end
539
+
540
+ module BooleanOperator
541
+ include Helpers
542
+
543
+ def expr
544
+ case self.text_value
545
+ when "and"
546
+ AND_METHOD
547
+ when "or"
548
+ OR_METHOD
549
+ else
550
+ raise "Unknown operator #{self.text_value}"
551
+ end
552
+ end
553
+ end
554
+
555
+ class Selector < RValue
556
+ def expr
557
+ jdsl.eEventValue(source_meta, text_value)
558
+ end
559
+ end
560
+
561
+ class SelectorElement < Node;
562
+ def expr
563
+ jdsl.eEventValue(source_meta, text_value)
564
+ end
565
+ end
566
+ end; end; end; end; end;