logstash-core 1.5.1.snapshot1-java → 1.5.2-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.
Potentially problematic release.
This version of logstash-core might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/lib/logstash/agent.rb +2 -8
- data/lib/logstash/environment.rb +1 -1
- data/lib/logstash/event.rb +3 -50
- data/lib/logstash/filters/base.rb +3 -21
- data/lib/logstash/inputs/base.rb +3 -8
- data/lib/logstash/java_integration.rb +5 -1
- data/lib/logstash/runner.rb +4 -0
- data/lib/logstash/string_interpolation.rb +139 -0
- data/lib/logstash/util/decorators.rb +46 -0
- data/lib/logstash/util/java_version.rb +61 -0
- data/lib/logstash/util/unicode_trimmer.rb +80 -0
- data/lib/logstash/version.rb +1 -1
- data/logstash-core.gemspec +2 -2
- data/spec/core/event_spec.rb +4 -0
- data/spec/coverage_helper.rb +14 -0
- data/spec/inputs/base_spec.rb +61 -0
- data/spec/lib/logstash/java_integration_spec.rb +17 -0
- data/spec/license_spec.rb +52 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/util/java_version_spec.rb +66 -0
- data/spec/util/unicode_trimmer_spec.rb +53 -0
- metadata +30 -7
- data/lib/logstash/util/fieldreference.rb +0 -68
- data/spec/util/fieldeval_spec.rb +0 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1d4a0fc2ffd05d5ca9bb3d6d9c8c1ffeeed3e8e
|
4
|
+
data.tar.gz: 62546e37ec4e051369782ea1f3ad37d444e774aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 949ed2af6b2b3100f7bf57a708c8b3081d60cb310374f19262beef13fa9c8426154f9eb85c3ba26ed06a641a1a8dd4d0198949805c53838d485047fd542d347f
|
7
|
+
data.tar.gz: ab49a4f44669506b310d2f80195177f563bb513320a3e0d7e44d86ddfb28deb713756e69c9fac7d73a993dd7a3134406cfdf9278f09af9863e13ba38f1329c5e
|
data/lib/logstash/agent.rb
CHANGED
@@ -172,14 +172,8 @@ class LogStash::Agent < Clamp::Command
|
|
172
172
|
|
173
173
|
if [:info, :debug].include?(verbosity?) || debug? || verbose?
|
174
174
|
show_version_ruby
|
175
|
-
|
176
|
-
if
|
177
|
-
show_version_java
|
178
|
-
end
|
179
|
-
|
180
|
-
if [:debug].include?(verbosity?) || debug?
|
181
|
-
show_gems
|
182
|
-
end
|
175
|
+
show_version_java if LogStash::Environment.jruby?
|
176
|
+
show_gems if [:debug].include?(verbosity?) || debug?
|
183
177
|
end
|
184
178
|
end # def show_version
|
185
179
|
|
data/lib/logstash/environment.rb
CHANGED
data/lib/logstash/event.rb
CHANGED
@@ -3,10 +3,10 @@ require "time"
|
|
3
3
|
require "date"
|
4
4
|
require "cabin"
|
5
5
|
require "logstash/namespace"
|
6
|
-
require "logstash/util/fieldreference"
|
7
6
|
require "logstash/util/accessors"
|
8
7
|
require "logstash/timestamp"
|
9
8
|
require "logstash/json"
|
9
|
+
require "logstash/string_interpolation"
|
10
10
|
|
11
11
|
# transcient pipeline events for normal in-flow signaling as opposed to
|
12
12
|
# flow altering exceptions. for now having base classes is adequate and
|
@@ -217,57 +217,10 @@ class LogStash::Event
|
|
217
217
|
#
|
218
218
|
# If a %{name} value is an array, then we will join by ','
|
219
219
|
# If a %{name} value does not exist, then no substitution occurs.
|
220
|
-
#
|
221
|
-
# TODO(sissel): It is not clear what the value of a field that
|
222
|
-
# is an array (or hash?) should be. Join by comma? Something else?
|
223
220
|
public
|
224
221
|
def sprintf(format)
|
225
|
-
|
226
|
-
|
227
|
-
format = ("%.15f" % format).sub(/0*$/,"")
|
228
|
-
else
|
229
|
-
format = format.to_s
|
230
|
-
end
|
231
|
-
if format.index("%").nil?
|
232
|
-
return format
|
233
|
-
end
|
234
|
-
|
235
|
-
return format.gsub(/%\{[^}]+\}/) do |tok|
|
236
|
-
# Take the inside of the %{ ... }
|
237
|
-
key = tok[2 ... -1]
|
238
|
-
|
239
|
-
if key[0] == "+" && !@data.has_key?(TIMESTAMP)
|
240
|
-
raise LogStash::Error, "Unable to format \"#{key}\" in string \"#{format}\", #{TIMESTAMP} field not found"
|
241
|
-
end
|
242
|
-
|
243
|
-
if key == "+%s"
|
244
|
-
# Got %{+%s}, support for unix epoch time
|
245
|
-
next @data[TIMESTAMP].to_i
|
246
|
-
elsif key[0,1] == "+"
|
247
|
-
t = @data[TIMESTAMP]
|
248
|
-
formatter = org.joda.time.format.DateTimeFormat.forPattern(key[1 .. -1])\
|
249
|
-
.withZone(org.joda.time.DateTimeZone::UTC)
|
250
|
-
#next org.joda.time.Instant.new(t.tv_sec * 1000 + t.tv_usec / 1000).toDateTime.toString(formatter)
|
251
|
-
# Invoke a specific Instant constructor to avoid this warning in JRuby
|
252
|
-
# > ambiguous Java methods found, using org.joda.time.Instant(long)
|
253
|
-
org.joda.time.Instant.java_class.constructor(Java::long).new_instance(
|
254
|
-
t.tv_sec * 1000 + t.tv_usec / 1000
|
255
|
-
).to_java.toDateTime.toString(formatter)
|
256
|
-
else
|
257
|
-
value = self[key]
|
258
|
-
case value
|
259
|
-
when nil
|
260
|
-
tok # leave the %{foo} if this field does not exist in this event.
|
261
|
-
when Array
|
262
|
-
value.join(",") # Join by ',' if value is an array
|
263
|
-
when Hash
|
264
|
-
LogStash::Json.dump(value) # Convert hashes to json
|
265
|
-
else
|
266
|
-
value # otherwise return the value
|
267
|
-
end # case value
|
268
|
-
end # 'key' checking
|
269
|
-
end # format.gsub...
|
270
|
-
end # def sprintf
|
222
|
+
LogStash::StringInterpolation.evaluate(self, format)
|
223
|
+
end
|
271
224
|
|
272
225
|
def tag(value)
|
273
226
|
# Generalize this method for more usability
|
@@ -4,6 +4,7 @@ require "logstash/event"
|
|
4
4
|
require "logstash/logging"
|
5
5
|
require "logstash/plugin"
|
6
6
|
require "logstash/config/mixin"
|
7
|
+
require "logstash/util/decorators"
|
7
8
|
|
8
9
|
class LogStash::Filters::Base < LogStash::Plugin
|
9
10
|
include LogStash::Config::Mixin
|
@@ -179,21 +180,7 @@ class LogStash::Filters::Base < LogStash::Plugin
|
|
179
180
|
# matches the filter's conditions (right type, etc)
|
180
181
|
protected
|
181
182
|
def filter_matched(event)
|
182
|
-
@add_field.
|
183
|
-
field = event.sprintf(field)
|
184
|
-
value = [value] if !value.is_a?(Array)
|
185
|
-
value.each do |v|
|
186
|
-
v = event.sprintf(v)
|
187
|
-
if event.include?(field)
|
188
|
-
event[field] = [event[field]] if !event[field].is_a?(Array)
|
189
|
-
event[field] << v
|
190
|
-
else
|
191
|
-
event[field] = v
|
192
|
-
end
|
193
|
-
@logger.debug? and @logger.debug("filters/#{self.class.name}: adding value to field",
|
194
|
-
:field => field, :value => value)
|
195
|
-
end
|
196
|
-
end
|
183
|
+
LogStash::Util::Decorators.add_fields(@add_field,event,"filters/#{self.class.name}")
|
197
184
|
|
198
185
|
@remove_field.each do |field|
|
199
186
|
field = event.sprintf(field)
|
@@ -202,12 +189,7 @@ class LogStash::Filters::Base < LogStash::Plugin
|
|
202
189
|
event.remove(field)
|
203
190
|
end
|
204
191
|
|
205
|
-
@add_tag.
|
206
|
-
tag = event.sprintf(tag)
|
207
|
-
@logger.debug? and @logger.debug("filters/#{self.class.name}: adding tag",
|
208
|
-
:tag => tag)
|
209
|
-
(event["tags"] ||= []) << tag
|
210
|
-
end
|
192
|
+
LogStash::Util::Decorators.add_tags(@add_tag,event,"filters/#{self.class.name}")
|
211
193
|
|
212
194
|
@remove_tag.each do |tag|
|
213
195
|
break if event["tags"].nil?
|
data/lib/logstash/inputs/base.rb
CHANGED
@@ -5,6 +5,7 @@ require "logstash/plugin"
|
|
5
5
|
require "logstash/logging"
|
6
6
|
require "logstash/config/mixin"
|
7
7
|
require "logstash/codecs/base"
|
8
|
+
require "logstash/util/decorators"
|
8
9
|
|
9
10
|
# This is the base class for Logstash inputs.
|
10
11
|
class LogStash::Inputs::Base < LogStash::Plugin
|
@@ -109,14 +110,8 @@ class LogStash::Inputs::Base < LogStash::Plugin
|
|
109
110
|
# Only set 'type' if not already set. This is backwards-compatible behavior
|
110
111
|
event["type"] = @type if @type && !event.include?("type")
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
event["tags"] += @tags
|
115
|
-
end
|
116
|
-
|
117
|
-
@add_field.each do |field, value|
|
118
|
-
event[field] = value
|
119
|
-
end
|
113
|
+
LogStash::Util::Decorators.add_fields(@add_field,event,"inputs/#{self.class.name}")
|
114
|
+
LogStash::Util::Decorators.add_tags(@tags,event,"inputs/#{self.class.name}")
|
120
115
|
end
|
121
116
|
|
122
117
|
protected
|
data/lib/logstash/runner.rb
CHANGED
@@ -16,6 +16,7 @@ class LogStash::Runner
|
|
16
16
|
|
17
17
|
def main(args)
|
18
18
|
require "logstash/util"
|
19
|
+
require "logstash/util/java_version"
|
19
20
|
require "stud/trap"
|
20
21
|
require "stud/task"
|
21
22
|
@startup_interruption_trap = Stud::trap("INT") { puts "Interrupted"; exit 0 }
|
@@ -27,6 +28,9 @@ class LogStash::Runner
|
|
27
28
|
return 1
|
28
29
|
end
|
29
30
|
|
31
|
+
# Print a warning to STDERR for bad java versions
|
32
|
+
LogStash::Util::JavaVersion.warn_on_bad_java_version
|
33
|
+
|
30
34
|
Stud::untrap("INT", @startup_interruption_trap)
|
31
35
|
|
32
36
|
task = run(args)
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require "thread_safe"
|
2
|
+
require "forwardable"
|
3
|
+
|
4
|
+
module LogStash
|
5
|
+
module StringInterpolation
|
6
|
+
extend self
|
7
|
+
|
8
|
+
# Floats outside of these upper and lower bounds are forcibly converted
|
9
|
+
# to scientific notation by Float#to_s
|
10
|
+
MIN_FLOAT_BEFORE_SCI_NOT = 0.0001
|
11
|
+
MAX_FLOAT_BEFORE_SCI_NOT = 1000000000000000.0
|
12
|
+
|
13
|
+
CACHE = ThreadSafe::Cache.new
|
14
|
+
TEMPLATE_TAG_REGEXP = /%\{[^}]+\}/
|
15
|
+
|
16
|
+
def evaluate(event, template)
|
17
|
+
if template.is_a?(Float) && (template < MIN_FLOAT_BEFORE_SCI_NOT || template >= MAX_FLOAT_BEFORE_SCI_NOT)
|
18
|
+
return ("%.15f" % template).sub(/0*$/,"")
|
19
|
+
end
|
20
|
+
|
21
|
+
template = template.to_s
|
22
|
+
|
23
|
+
return template if not_cachable?(template)
|
24
|
+
|
25
|
+
compiled = CACHE.get_or_default(template, nil) || CACHE.put(template, compile_template(template))
|
26
|
+
compiled.evaluate(event)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def not_cachable?(template)
|
31
|
+
template.index("%").nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def compile_template(template)
|
35
|
+
nodes = Template.new
|
36
|
+
|
37
|
+
position = 0
|
38
|
+
matches = template.to_enum(:scan, TEMPLATE_TAG_REGEXP).map { |m| $~ }
|
39
|
+
|
40
|
+
matches.each do |match|
|
41
|
+
tag = match[0][2..-2]
|
42
|
+
start = match.offset(0).first
|
43
|
+
nodes << StaticNode.new(template[position..(start-1)]) if start > 0
|
44
|
+
nodes << identify(tag)
|
45
|
+
position = match.offset(0).last
|
46
|
+
end
|
47
|
+
|
48
|
+
if position < template.size - 1
|
49
|
+
nodes << StaticNode.new(template[position..-1])
|
50
|
+
end
|
51
|
+
|
52
|
+
optimize(nodes)
|
53
|
+
end
|
54
|
+
|
55
|
+
def optimize(nodes)
|
56
|
+
nodes.size == 1 ? nodes.first : nodes
|
57
|
+
end
|
58
|
+
|
59
|
+
def identify(tag)
|
60
|
+
if tag == "+%s"
|
61
|
+
EpocNode.new
|
62
|
+
elsif tag[0, 1] == "+"
|
63
|
+
DateNode.new(tag[1..-1])
|
64
|
+
else
|
65
|
+
KeyNode.new(tag)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Template
|
71
|
+
extend Forwardable
|
72
|
+
def_delegators :@nodes, :<<, :push, :size, :first
|
73
|
+
|
74
|
+
def initialize
|
75
|
+
@nodes = []
|
76
|
+
end
|
77
|
+
|
78
|
+
def evaluate(event)
|
79
|
+
@nodes.collect { |node| node.evaluate(event) }.join
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class EpocNode
|
84
|
+
def evaluate(event)
|
85
|
+
t = event.timestamp
|
86
|
+
raise LogStash::Error, "Unable to format in string \"#{@format}\", #{LogStash::Event::TIMESTAMP} field not found" unless t
|
87
|
+
t.to_i.to_s
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class StaticNode
|
92
|
+
def initialize(content)
|
93
|
+
@content = content
|
94
|
+
end
|
95
|
+
|
96
|
+
def evaluate(event)
|
97
|
+
@content
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class KeyNode
|
102
|
+
def initialize(key)
|
103
|
+
@key = key
|
104
|
+
end
|
105
|
+
|
106
|
+
def evaluate(event)
|
107
|
+
value = event[@key]
|
108
|
+
|
109
|
+
case value
|
110
|
+
when nil
|
111
|
+
"%{#{@key}}"
|
112
|
+
when Array
|
113
|
+
value.join(",")
|
114
|
+
when Hash
|
115
|
+
Logstash::Json.dump(value)
|
116
|
+
else
|
117
|
+
value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class DateNode
|
123
|
+
def initialize(format)
|
124
|
+
@format = format
|
125
|
+
@formatter = org.joda.time.format.DateTimeFormat.forPattern(@format)
|
126
|
+
.withZone(org.joda.time.DateTimeZone::UTC)
|
127
|
+
end
|
128
|
+
|
129
|
+
def evaluate(event)
|
130
|
+
t = event.timestamp
|
131
|
+
|
132
|
+
raise LogStash::Error, "Unable to format in string \"#{@format}\", #{LogStash::Event::TIMESTAMP} field not found" unless t
|
133
|
+
|
134
|
+
org.joda.time.Instant.java_class.constructor(Java::long).new_instance(
|
135
|
+
t.tv_sec * 1000 + t.tv_usec / 1000
|
136
|
+
).to_java.toDateTime.toString(@formatter)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "logstash/namespace"
|
4
|
+
require "logstash/util"
|
5
|
+
|
6
|
+
module LogStash::Util
|
7
|
+
|
8
|
+
# Decorators provides common manipulation on the event data.
|
9
|
+
module Decorators
|
10
|
+
extend self
|
11
|
+
|
12
|
+
@logger = Cabin::Channel.get(LogStash)
|
13
|
+
|
14
|
+
# fields is a hash of field => value
|
15
|
+
# where both `field` and `value` can use sprintf syntax.
|
16
|
+
def add_fields(fields,event, pluginname)
|
17
|
+
fields.each do |field, value|
|
18
|
+
field = event.sprintf(field)
|
19
|
+
value = Array(value)
|
20
|
+
value.each do |v|
|
21
|
+
v = event.sprintf(v)
|
22
|
+
if event.include?(field)
|
23
|
+
event[field] = Array(event[field])
|
24
|
+
event[field] << v
|
25
|
+
else
|
26
|
+
event[field] = v
|
27
|
+
end
|
28
|
+
@logger.debug? and @logger.debug("#{pluginname}: adding value to field",
|
29
|
+
:field => field, :value => value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# tags is an array of string. sprintf syntax can be used.
|
35
|
+
def add_tags(tags, event, pluginname)
|
36
|
+
tags.each do |tag|
|
37
|
+
tag = event.sprintf(tag)
|
38
|
+
@logger.debug? and @logger.debug("#{pluginname}: adding tag",
|
39
|
+
:tag => tag)
|
40
|
+
(event["tags"] ||= []) << tag
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end # module LogStash::Util::Decorators
|
45
|
+
|
46
|
+
end # module LogStash::Util
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'cabin'
|
2
|
+
|
3
|
+
module LogStash::Util::JavaVersion
|
4
|
+
def self.logger
|
5
|
+
@logger ||= Cabin::Channel.get(LogStash)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Print a warning if we're on a bad version of java
|
9
|
+
def self.warn_on_bad_java_version
|
10
|
+
if self.bad_java_version?(self.version)
|
11
|
+
msg = "!!! Please upgrade your java version, the current version '#{self.version}' may cause problems. We recommend a minimum version of 1.7.0_51"
|
12
|
+
STDERR.puts(msg)
|
13
|
+
logger.warn(msg)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Return the current java version string. Returns nil if this is a non-java platform (e.g. MRI).
|
18
|
+
def self.version
|
19
|
+
return nil unless LogStash::Environment.jruby?
|
20
|
+
java.lang.System.getProperty("java.runtime.version")
|
21
|
+
end
|
22
|
+
|
23
|
+
# Takes a string of a java version ex: "1.8.0_24-beta"
|
24
|
+
# and returns a parsed map of the components.
|
25
|
+
# nil inputs will be returned as nil.
|
26
|
+
def self.parse_java_version(version_string)
|
27
|
+
return nil if version_string.nil?
|
28
|
+
|
29
|
+
# Crazy java versioning rules @ http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
|
30
|
+
# The regex below parses this all correctly http://rubular.com/r/sInQc3Nc7f
|
31
|
+
|
32
|
+
match = version_string.match(/\A(\d+)\.(\d+)\.(\d+)(_(\d+))?(-(.+))?\Z/)
|
33
|
+
major, minor, patch, ufull, update, bfull, build = match.captures
|
34
|
+
|
35
|
+
{
|
36
|
+
:full => version_string,
|
37
|
+
:major => major.to_i,
|
38
|
+
:minor => minor.to_i,
|
39
|
+
:patch => patch.to_i,
|
40
|
+
:update => update.to_i, # this is always coerced to an int (a nil will be zero) to make comparisons easier
|
41
|
+
:build => build # not an integer, could be b06 for instance!,
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Determine if the given java version string is a bad version of java
|
46
|
+
# If it is, return true, if it isn't return false.
|
47
|
+
# Accepts nil, returning nil.
|
48
|
+
def self.bad_java_version?(version_string)
|
49
|
+
return nil if version_string.nil?
|
50
|
+
|
51
|
+
parsed = parse_java_version(version_string)
|
52
|
+
|
53
|
+
if parsed[:major] == 1 && parsed[:minor] == 7 && parsed[:patch] == 0 && parsed[:update] < 51
|
54
|
+
true
|
55
|
+
elsif parsed[:major] == 1 && parsed[:minor] < 7
|
56
|
+
true
|
57
|
+
else
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module UnicodeTrimmer
|
2
|
+
# The largest possible unicode chars are 4 bytes
|
3
|
+
# http://stackoverflow.com/questions/9533258/what-is-the-maximum-number-of-bytes-for-a-utf-8-encoded-character
|
4
|
+
# http://tools.ietf.org/html/rfc3629
|
5
|
+
MAX_CHAR_BYTES = 4
|
6
|
+
|
7
|
+
# Takes a unicode string and makes sure it fits in a max of `desired_bytes`
|
8
|
+
# This aims to be somewhat efficient about this for the average case and get as close to
|
9
|
+
# O(1) as possible. Given certain distributions of multi-byte characters it'll be slower
|
10
|
+
# It tries to find the point the truncation *should* happen based on the average byte size.
|
11
|
+
# If that snips it in the wrong place it'll try to add or remove chars to get it to the right
|
12
|
+
# spot and preserve as much data as possible.
|
13
|
+
public
|
14
|
+
def self.trim_bytes(orig_str, desired_bytes)
|
15
|
+
return orig_str if orig_str.bytesize <= desired_bytes
|
16
|
+
|
17
|
+
pre_shortened = pre_shorten(orig_str, desired_bytes)
|
18
|
+
|
19
|
+
case pre_shortened.bytesize <=> desired_bytes
|
20
|
+
when 0
|
21
|
+
pre_shortened
|
22
|
+
when 1
|
23
|
+
shrink_bytes(pre_shortened, orig_str, desired_bytes)
|
24
|
+
when -1
|
25
|
+
grow_bytes(pre_shortened, orig_str, desired_bytes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
# Try to cut the string at the right place based on the avg. byte size
|
31
|
+
def self.pre_shorten(orig_str, desired_bytes)
|
32
|
+
# Compute the average size to get an idea of where should chop
|
33
|
+
orig_len = orig_str.length
|
34
|
+
orig_bs = orig_str.bytesize
|
35
|
+
avg_size = (orig_bs.to_f / orig_len.to_f)
|
36
|
+
|
37
|
+
# Try to do an initial shortening based on the average char size
|
38
|
+
# The goal here is to get us somewhere above or below the boundary quickly
|
39
|
+
orig_extra_bytes = orig_bs - desired_bytes
|
40
|
+
pre_shorten_by = (orig_extra_bytes / avg_size).to_i
|
41
|
+
orig_str.slice(0, orig_len - pre_shorten_by)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def self.grow_bytes(pre_shortened, orig_str, desired_bytes)
|
46
|
+
res_str = pre_shortened.clone()
|
47
|
+
|
48
|
+
loop do
|
49
|
+
bs = res_str.bytesize
|
50
|
+
deficit = desired_bytes - bs
|
51
|
+
lengthen_by = deficit / MAX_CHAR_BYTES
|
52
|
+
lengthen_by = 1 if lengthen_by < 1
|
53
|
+
append = orig_str.slice(res_str.length, lengthen_by)
|
54
|
+
|
55
|
+
break if (bs + append.bytesize) > desired_bytes
|
56
|
+
|
57
|
+
res_str << append
|
58
|
+
end
|
59
|
+
|
60
|
+
res_str
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def self.shrink_bytes(pre_shortened, orig_str, desired_bytes)
|
65
|
+
res_str = pre_shortened.clone()
|
66
|
+
|
67
|
+
loop do
|
68
|
+
bs = res_str.bytesize
|
69
|
+
break if bs <= desired_bytes
|
70
|
+
|
71
|
+
extra = bs - desired_bytes
|
72
|
+
shorten_by = extra / MAX_CHAR_BYTES
|
73
|
+
shorten_by = 1 if shorten_by < 1
|
74
|
+
|
75
|
+
res_str.slice!(res_str.length - shorten_by)
|
76
|
+
end
|
77
|
+
|
78
|
+
res_str
|
79
|
+
end
|
80
|
+
end
|
data/lib/logstash/version.rb
CHANGED
data/logstash-core.gemspec
CHANGED
@@ -18,10 +18,11 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.version = LOGSTASH_VERSION.gsub(/-/, '.')
|
19
19
|
|
20
20
|
gem.add_runtime_dependency "cabin", "~> 0.7.0" #(Apache 2.0 license)
|
21
|
-
gem.add_runtime_dependency "pry", "~> 0.10.1"
|
21
|
+
gem.add_runtime_dependency "pry", "~> 0.10.1" #(Ruby license)
|
22
22
|
gem.add_runtime_dependency "stud", "~> 0.0.19" #(Apache 2.0 license)
|
23
23
|
gem.add_runtime_dependency "clamp", "~> 0.6.5" #(MIT license) for command line args/flags
|
24
24
|
gem.add_runtime_dependency "filesize", "0.0.4" #(MIT license) for :bytes config validator
|
25
|
+
gem.add_runtime_dependency "gems", "~> 0.8.3" #(MIT license)
|
25
26
|
|
26
27
|
# TODO(sissel): Treetop 1.5.x doesn't seem to work well, but I haven't
|
27
28
|
# investigated what the cause might be. -Jordan
|
@@ -32,7 +33,6 @@ Gem::Specification.new do |gem|
|
|
32
33
|
|
33
34
|
# filetools and rakelib
|
34
35
|
gem.add_runtime_dependency "minitar", "~> 0.5.4"
|
35
|
-
|
36
36
|
gem.add_runtime_dependency "thread_safe", "~> 0.3.5" #(Apache 2.0 license)
|
37
37
|
|
38
38
|
if RUBY_PLATFORM == 'java'
|
data/spec/core/event_spec.rb
CHANGED
@@ -63,6 +63,10 @@ describe LogStash::Event do
|
|
63
63
|
expect(subject.sprintf("%{+HH}")).to eq("00")
|
64
64
|
end
|
65
65
|
|
66
|
+
it "should support mixed string" do
|
67
|
+
expect(subject.sprintf("foo %{+YYYY-MM-dd} %{type}")).to eq("foo 2013-01-01 sprintf")
|
68
|
+
end
|
69
|
+
|
66
70
|
it "should raise error with %{+format} syntax when @timestamp field is missing", :if => RUBY_ENGINE == "jruby" do
|
67
71
|
str = "logstash-%{+YYYY}"
|
68
72
|
subj = subject.clone
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Useful module to help loading all logstash content when
|
2
|
+
# running coverage analysis
|
3
|
+
module CoverageHelper
|
4
|
+
|
5
|
+
SKIP_LIST = ["lib/bootstrap/rspec.rb", "lib/logstash/util/prctl.rb"]
|
6
|
+
|
7
|
+
def self.eager_load
|
8
|
+
Dir.glob("lib/**/*.rb") do |file|
|
9
|
+
next if SKIP_LIST.include?(file)
|
10
|
+
require file
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/spec/inputs/base_spec.rb
CHANGED
@@ -1,6 +1,67 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require "spec_helper"
|
3
3
|
|
4
|
+
# use a dummy NOOP input to test Inputs::Base
|
5
|
+
class LogStash::Inputs::NOOP < LogStash::Inputs::Base
|
6
|
+
config_name "noop"
|
7
|
+
milestone 2
|
8
|
+
|
9
|
+
def register; end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "LogStash::Inputs::Base#decorate" do
|
14
|
+
it "should add tag" do
|
15
|
+
input = LogStash::Inputs::NOOP.new("tags" => "value")
|
16
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
17
|
+
input.instance_eval {decorate(evt)}
|
18
|
+
expect(evt["tags"]).to eq(["value"])
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should add multiple tag" do
|
22
|
+
input = LogStash::Inputs::NOOP.new("tags" => ["value1","value2"])
|
23
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
24
|
+
input.instance_eval {decorate(evt)}
|
25
|
+
expect(evt["tags"]).to eq(["value1","value2"])
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should allow duplicates tag" do
|
29
|
+
input = LogStash::Inputs::NOOP.new("tags" => ["value","value"])
|
30
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
31
|
+
input.instance_eval {decorate(evt)}
|
32
|
+
expect(evt["tags"]).to eq(["value","value"])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should add tag with sprintf" do
|
36
|
+
input = LogStash::Inputs::NOOP.new("tags" => "%{type}")
|
37
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
38
|
+
input.instance_eval {decorate(evt)}
|
39
|
+
expect(evt["tags"]).to eq(["noop"])
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should add single field" do
|
43
|
+
input = LogStash::Inputs::NOOP.new("add_field" => {"field" => "value"})
|
44
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
45
|
+
input.instance_eval {decorate(evt)}
|
46
|
+
expect(evt["field"]).to eq("value")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should add single field with sprintf" do
|
50
|
+
input = LogStash::Inputs::NOOP.new("add_field" => {"%{type}" => "%{type}"})
|
51
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
52
|
+
input.instance_eval {decorate(evt)}
|
53
|
+
expect(evt["noop"]).to eq("noop")
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should add multiple field" do
|
57
|
+
input = LogStash::Inputs::NOOP.new("add_field" => {"field" => ["value1", "value2"], "field2" => "value"})
|
58
|
+
evt = LogStash::Event.new({"type" => "noop"})
|
59
|
+
input.instance_eval {decorate(evt)}
|
60
|
+
expect(evt["field"]).to eq(["value1","value2"])
|
61
|
+
expect(evt["field2"]).to eq("value")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
4
65
|
describe "LogStash::Inputs::Base#fix_streaming_codecs" do
|
5
66
|
it "should carry the charset setting along when switching" do
|
6
67
|
require "logstash/inputs/tcp"
|
@@ -82,6 +82,23 @@ describe "Java integration" do
|
|
82
82
|
context "Java::JavaUtil::Collection" do
|
83
83
|
subject{Java::JavaUtil::ArrayList.new(initial_array)}
|
84
84
|
|
85
|
+
context "when inspecting" do
|
86
|
+
let(:items) { [:a, {:b => :c}] }
|
87
|
+
subject { java.util.ArrayList.new(items) }
|
88
|
+
|
89
|
+
it "should include the contents of the Collection" do
|
90
|
+
expect(subject.inspect).to include(items.inspect)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should include the class name" do
|
94
|
+
expect(subject.inspect).to include("ArrayList")
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should include the hash code of the collection" do
|
98
|
+
expect(subject.inspect).to include(subject.hashCode.to_s)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
85
102
|
context "when deleting a unique instance" do
|
86
103
|
let(:initial_array) {["foo", "bar"]}
|
87
104
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rakelib/default_plugins'
|
3
|
+
|
4
|
+
describe "Project licenses" do
|
5
|
+
|
6
|
+
let(:expected_licenses) {
|
7
|
+
##
|
8
|
+
# Expected licenses are Apache License 2.0, BSD license, MIT license and the ruby one,
|
9
|
+
# this not exclude that this list change in the feature.
|
10
|
+
##
|
11
|
+
Regexp.union([ /mit/,
|
12
|
+
/apache*/,
|
13
|
+
/bsd/,
|
14
|
+
/ruby/,
|
15
|
+
/lgpl/])
|
16
|
+
}
|
17
|
+
|
18
|
+
shared_examples "runtime license test" do
|
19
|
+
|
20
|
+
subject(:gem_name) do |example|
|
21
|
+
example.metadata[:example_group][:parent_example_group][:description]
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:spec) { Gem::Specification.find_all_by_name(gem_name)[0] }
|
25
|
+
|
26
|
+
it "have an expected license" do
|
27
|
+
spec.licenses.each do |license|
|
28
|
+
expect(license.downcase).to match(expected_licenses)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "has runtime dependencies with expected licenses" do
|
33
|
+
spec.runtime_dependencies.map { |dep| dep.to_spec }.each do |runtime_spec|
|
34
|
+
next unless runtime_spec
|
35
|
+
runtime_spec.licenses.each do |license|
|
36
|
+
expect(license.downcase).to match(expected_licenses)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "logstash-core" do
|
43
|
+
it_behaves_like "runtime license test"
|
44
|
+
end
|
45
|
+
|
46
|
+
installed_plugins.each do |plugin|
|
47
|
+
describe plugin do
|
48
|
+
it_behaves_like "runtime license test"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1 +1,10 @@
|
|
1
|
+
require_relative 'coverage_helper'
|
2
|
+
# In order to archive an expected coverage analysis we need to eager load
|
3
|
+
# all logstash code base, otherwise it will not get a good analysis.
|
4
|
+
CoverageHelper.eager_load if ENV['COVERAGE']
|
5
|
+
|
1
6
|
require "logstash/devutils/rspec/spec_helper"
|
7
|
+
|
8
|
+
def installed_plugins
|
9
|
+
Gem::Specification.find_all.select { |spec| spec.metadata["logstash_plugin"] }.map { |plugin| plugin.name }
|
10
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'logstash/util/java_version'
|
3
|
+
|
4
|
+
describe "LogStash::Util::JavaVersion" do
|
5
|
+
subject(:mod) { LogStash::Util::JavaVersion }
|
6
|
+
|
7
|
+
it "should get the current java version if we're on Java" do
|
8
|
+
if LogStash::Environment.jruby?
|
9
|
+
expect(LogStash::Util::JavaVersion.version).to be_a(String)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should mark a bad beta version as bad" do
|
14
|
+
expect(mod.bad_java_version?("1.7.0_45-beta")).to be_truthy
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should mark a bad standard version as bad" do
|
18
|
+
expect(mod.bad_java_version?("1.6.0")).to be_truthy
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should mark a good standard java version as good" do
|
22
|
+
expect(mod.bad_java_version?("1.7.0_51")).to be_falsey
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should mark a good beta version as good" do
|
26
|
+
expect(mod.bad_java_version?("1.8.0-beta")).to be_falsey
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "parsing java versions" do
|
30
|
+
it "should return nil on a nil version" do
|
31
|
+
expect(mod.parse_java_version(nil)).to be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
shared_examples("version parsing") do |desc, string, major, minor, patch, update, build|
|
35
|
+
context("#{desc} with version #{string}") do
|
36
|
+
subject(:parsed) { LogStash::Util::JavaVersion.parse_java_version(string) }
|
37
|
+
|
38
|
+
it "should have the correct major version" do
|
39
|
+
expect(parsed[:major]).to eql(major)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have the correct minor version" do
|
43
|
+
expect(parsed[:minor]).to eql(minor)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should have the correct patch version" do
|
47
|
+
expect(parsed[:patch]).to eql(patch)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should have the correct update version" do
|
51
|
+
expect(parsed[:update]).to eql(update)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should have the correct build string" do
|
55
|
+
expect(parsed[:build]).to eql(build)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
include_examples("version parsing", "a plain version", "1.3.0", 1, 3, 0, 0, nil)
|
61
|
+
include_examples("version parsing", "an update", "1.4.0_03", 1, 4, 0, 3, nil)
|
62
|
+
include_examples("version parsing", "a build", "1.4.0-beta", 1, 4, 0, 0,"beta")
|
63
|
+
include_examples("version parsing", "an update+build", "1.4.0_03-beta", 1, 4, 0, 3, "beta")
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
require "logstash/util/unicode_trimmer"
|
4
|
+
require "flores/rspec"
|
5
|
+
require "flores/random"
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
Flores::RSpec.configure(config)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "truncating unicode strings correctly" do
|
12
|
+
context "with extra bytes before the snip" do
|
13
|
+
let(:ustr) { "Testing «ταБЬℓσ»: 1<2 & 4+1>3, now 20% off!" }
|
14
|
+
|
15
|
+
it "should truncate to exact byte boundaries when possible" do
|
16
|
+
expect(UnicodeTrimmer.trim_bytes(ustr, 21).bytesize).to eql(21)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should truncate below the bytesize when splitting a byte" do
|
20
|
+
expect(UnicodeTrimmer.trim_bytes(ustr, 20).bytesize).to eql(18)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not truncate the string when the bytesize is already OK" do
|
24
|
+
expect(UnicodeTrimmer.trim_bytes(ustr, ustr.bytesize)).to eql(ustr)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with extra bytes after the snip" do
|
29
|
+
let(:ustr) { ": 1<2 & 4+1>3, now 20% off! testing «ταБЬℓσ»" }
|
30
|
+
|
31
|
+
it "should truncate to exact byte boundaries when possible" do
|
32
|
+
expect(UnicodeTrimmer.trim_bytes(ustr, 21).bytesize).to eql(21)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should truncate below the bytesize when splitting a byte" do
|
36
|
+
expect(UnicodeTrimmer.trim_bytes(ustr, 52).bytesize).to eql(51)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not truncate the string when the bytesize is already OK" do
|
40
|
+
expect(UnicodeTrimmer.trim_bytes(ustr, ustr.bytesize)).to eql(ustr)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "randomized testing" do
|
45
|
+
let(:text) { Flores::Random.text(1..1000) }
|
46
|
+
let(:size) { Flores::Random.integer(1..text.bytesize) }
|
47
|
+
let(:expected_range) { (size - 4)..size }
|
48
|
+
|
49
|
+
stress_it "should be near the boundary of requested size" do
|
50
|
+
expect(expected_range).to include(UnicodeTrimmer.trim_bytes(text, size).bytesize)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.2
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Jordan Sissel
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-06-
|
13
|
+
date: 2015-06-30 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: cabin
|
@@ -82,6 +82,20 @@ dependencies:
|
|
82
82
|
version: 0.0.4
|
83
83
|
prerelease: false
|
84
84
|
type: :runtime
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: gems
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 0.8.3
|
92
|
+
requirement: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.8.3
|
97
|
+
prerelease: false
|
98
|
+
type: :runtime
|
85
99
|
- !ruby/object:Gem::Dependency
|
86
100
|
name: treetop
|
87
101
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -192,20 +206,23 @@ files:
|
|
192
206
|
- lib/logstash/program.rb
|
193
207
|
- lib/logstash/runner.rb
|
194
208
|
- lib/logstash/sized_queue.rb
|
209
|
+
- lib/logstash/string_interpolation.rb
|
195
210
|
- lib/logstash/threadwatchdog.rb
|
196
211
|
- lib/logstash/timestamp.rb
|
197
212
|
- lib/logstash/util.rb
|
198
213
|
- lib/logstash/util/accessors.rb
|
199
214
|
- lib/logstash/util/buftok.rb
|
200
215
|
- lib/logstash/util/charset.rb
|
201
|
-
- lib/logstash/util/
|
216
|
+
- lib/logstash/util/decorators.rb
|
202
217
|
- lib/logstash/util/filetools.rb
|
218
|
+
- lib/logstash/util/java_version.rb
|
203
219
|
- lib/logstash/util/password.rb
|
204
220
|
- lib/logstash/util/plugin_version.rb
|
205
221
|
- lib/logstash/util/prctl.rb
|
206
222
|
- lib/logstash/util/require-helper.rb
|
207
223
|
- lib/logstash/util/retryable.rb
|
208
224
|
- lib/logstash/util/socket_peer.rb
|
225
|
+
- lib/logstash/util/unicode_trimmer.rb
|
209
226
|
- lib/logstash/version.rb
|
210
227
|
- locales/en.yml
|
211
228
|
- logstash-core.gemspec
|
@@ -218,19 +235,22 @@ files:
|
|
218
235
|
- spec/core/plugin_spec.rb
|
219
236
|
- spec/core/runner_spec.rb
|
220
237
|
- spec/core/timestamp_spec.rb
|
238
|
+
- spec/coverage_helper.rb
|
221
239
|
- spec/filters/base_spec.rb
|
222
240
|
- spec/inputs/base_spec.rb
|
223
241
|
- spec/lib/logstash/bundler_spec.rb
|
224
242
|
- spec/lib/logstash/java_integration_spec.rb
|
243
|
+
- spec/license_spec.rb
|
225
244
|
- spec/logstash/agent_spec.rb
|
226
245
|
- spec/outputs/base_spec.rb
|
227
246
|
- spec/spec_helper.rb
|
228
247
|
- spec/util/accessors_spec.rb
|
229
248
|
- spec/util/charset_spec.rb
|
230
|
-
- spec/util/fieldeval_spec.rb
|
231
249
|
- spec/util/gemfile_spec.rb
|
250
|
+
- spec/util/java_version_spec.rb
|
232
251
|
- spec/util/json_spec.rb
|
233
252
|
- spec/util/plugin_version_spec.rb
|
253
|
+
- spec/util/unicode_trimmer_spec.rb
|
234
254
|
- spec/util_spec.rb
|
235
255
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
236
256
|
licenses:
|
@@ -247,9 +267,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
247
267
|
version: '0'
|
248
268
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
249
269
|
requirements:
|
250
|
-
- - '
|
270
|
+
- - '>='
|
251
271
|
- !ruby/object:Gem::Version
|
252
|
-
version:
|
272
|
+
version: '0'
|
253
273
|
requirements: []
|
254
274
|
rubyforge_project:
|
255
275
|
rubygems_version: 2.2.2
|
@@ -266,17 +286,20 @@ test_files:
|
|
266
286
|
- spec/core/plugin_spec.rb
|
267
287
|
- spec/core/runner_spec.rb
|
268
288
|
- spec/core/timestamp_spec.rb
|
289
|
+
- spec/coverage_helper.rb
|
269
290
|
- spec/filters/base_spec.rb
|
270
291
|
- spec/inputs/base_spec.rb
|
271
292
|
- spec/lib/logstash/bundler_spec.rb
|
272
293
|
- spec/lib/logstash/java_integration_spec.rb
|
294
|
+
- spec/license_spec.rb
|
273
295
|
- spec/logstash/agent_spec.rb
|
274
296
|
- spec/outputs/base_spec.rb
|
275
297
|
- spec/spec_helper.rb
|
276
298
|
- spec/util/accessors_spec.rb
|
277
299
|
- spec/util/charset_spec.rb
|
278
|
-
- spec/util/fieldeval_spec.rb
|
279
300
|
- spec/util/gemfile_spec.rb
|
301
|
+
- spec/util/java_version_spec.rb
|
280
302
|
- spec/util/json_spec.rb
|
281
303
|
- spec/util/plugin_version_spec.rb
|
304
|
+
- spec/util/unicode_trimmer_spec.rb
|
282
305
|
- spec/util_spec.rb
|
@@ -1,68 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require "logstash/namespace"
|
3
|
-
require "logstash/util"
|
4
|
-
|
5
|
-
module LogStash::Util::FieldReference
|
6
|
-
|
7
|
-
def compile(accessor)
|
8
|
-
if accessor[0,1] != '['
|
9
|
-
return <<-"CODE"
|
10
|
-
lambda do |store, &block|
|
11
|
-
return block.nil? ? store[#{accessor.inspect}] : block.call(store, #{accessor.inspect})
|
12
|
-
end
|
13
|
-
CODE
|
14
|
-
end
|
15
|
-
|
16
|
-
code = "lambda do |store, &block|\n"
|
17
|
-
selectors = accessor.scan(/(?<=\[).+?(?=\])/)
|
18
|
-
selectors.each_with_index do |tok, i|
|
19
|
-
last = (i == selectors.count() - 1)
|
20
|
-
code << " # [#{tok}]#{ last ? " (last selector)" : "" }\n"
|
21
|
-
|
22
|
-
if last
|
23
|
-
code << <<-"CODE"
|
24
|
-
return block.call(store, #{tok.inspect}) unless block.nil?
|
25
|
-
CODE
|
26
|
-
end
|
27
|
-
|
28
|
-
code << <<-"CODE"
|
29
|
-
store = store.is_a?(Array) ? store[#{tok.to_i}] : store[#{tok.inspect}]
|
30
|
-
return store if store.nil?
|
31
|
-
CODE
|
32
|
-
|
33
|
-
end
|
34
|
-
code << "return store\nend"
|
35
|
-
#puts code
|
36
|
-
return code
|
37
|
-
end # def compile
|
38
|
-
|
39
|
-
def exec(accessor, store, &block)
|
40
|
-
@__fieldeval_cache ||= {}
|
41
|
-
@__fieldeval_cache[accessor] ||= eval(compile(accessor))
|
42
|
-
return @__fieldeval_cache[accessor].call(store, &block)
|
43
|
-
end
|
44
|
-
|
45
|
-
def set(accessor, value, store)
|
46
|
-
# The assignment can fail if the given field reference (accessor) does not exist
|
47
|
-
# In this case, we'll want to set the value manually.
|
48
|
-
if exec(accessor, store) { |hash, key| hash[key] = value }.nil?
|
49
|
-
return (store[accessor] = value) if accessor[0,1] != "["
|
50
|
-
|
51
|
-
# No existing element was found, so let's set one.
|
52
|
-
*parents, key = accessor.scan(/(?<=\[)[^\]]+(?=\])/)
|
53
|
-
parents.each do |p|
|
54
|
-
if store.include?(p)
|
55
|
-
store = store[p]
|
56
|
-
else
|
57
|
-
store[p] = {}
|
58
|
-
store = store[p]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
store[key] = value
|
62
|
-
end
|
63
|
-
|
64
|
-
return value
|
65
|
-
end
|
66
|
-
|
67
|
-
extend self
|
68
|
-
end # module LogStash::Util::FieldReference
|
data/spec/util/fieldeval_spec.rb
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
require "logstash/util/fieldreference"
|
3
|
-
|
4
|
-
describe LogStash::Util::FieldReference, :if => true do
|
5
|
-
|
6
|
-
context "using simple accessor" do
|
7
|
-
|
8
|
-
it "should retrieve value" do
|
9
|
-
str = "hello"
|
10
|
-
m = eval(subject.compile(str))
|
11
|
-
data = { "hello" => "world" }
|
12
|
-
expect(m.call(data)).to eq(data[str])
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should handle delete in block" do
|
16
|
-
str = "simple"
|
17
|
-
m = eval(subject.compile(str))
|
18
|
-
data = { "simple" => "things" }
|
19
|
-
m.call(data) { |obj, key| obj.delete(key) }
|
20
|
-
expect(data).to be_empty
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should handle assignment in block" do
|
24
|
-
str = "simple"
|
25
|
-
m = eval(subject.compile(str))
|
26
|
-
data = {}
|
27
|
-
expect(m.call(data) { |obj, key| obj[key] = "things" }).to eq("things")
|
28
|
-
expect(data).to eq({ "simple" => "things" })
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should handle assignment using set" do
|
32
|
-
str = "simple"
|
33
|
-
data = {}
|
34
|
-
expect(subject.set(str, "things", data)).to eq("things")
|
35
|
-
expect(data).to eq({ "simple" => "things" })
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
context "using accessor path" do
|
40
|
-
|
41
|
-
it "should retrieve shallow value" do
|
42
|
-
str = "[hello]"
|
43
|
-
m = eval(subject.compile(str))
|
44
|
-
data = { "hello" => "world" }
|
45
|
-
expect(m.call(data)).to eq("world")
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should retrieve deep value" do
|
49
|
-
str = "[hello][world]"
|
50
|
-
m = eval(subject.compile(str))
|
51
|
-
data = { "hello" => { "world" => "foo", "bar" => "baz" } }
|
52
|
-
expect(m.call(data)).to eq(data["hello"]["world"])
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should handle delete in block" do
|
56
|
-
str = "[hello][world]"
|
57
|
-
m = eval(subject.compile(str))
|
58
|
-
data = { "hello" => { "world" => "foo", "bar" => "baz" } }
|
59
|
-
m.call(data) { |obj, key| obj.delete(key) }
|
60
|
-
|
61
|
-
# Make sure the "world" key is removed.
|
62
|
-
expect(data["hello"]).to eq({ "bar" => "baz" })
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should not handle assignment in block" do
|
66
|
-
str = "[hello][world]"
|
67
|
-
m = eval(subject.compile(str))
|
68
|
-
data = {}
|
69
|
-
expect(m.call(data) { |obj, key| obj[key] = "things" }).to be_nil
|
70
|
-
expect(data).to be_empty
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should set shallow value" do
|
74
|
-
str = "[hello]"
|
75
|
-
data = {}
|
76
|
-
expect(subject.set(str, "foo", data)).to eq("foo")
|
77
|
-
expect(data).to eq({ "hello" => "foo" })
|
78
|
-
end
|
79
|
-
|
80
|
-
it "should set deep value" do
|
81
|
-
str = "[hello][world]"
|
82
|
-
data = {}
|
83
|
-
expect(subject.set(str, "foo", data)).to eq("foo")
|
84
|
-
expect(data).to eq({ "hello" => { "world" => "foo" } })
|
85
|
-
end
|
86
|
-
|
87
|
-
it "should retrieve array item" do
|
88
|
-
data = { "hello" => { "world" => ["a", "b"], "bar" => "baz" } }
|
89
|
-
m = eval(subject.compile("[hello][world][0]"))
|
90
|
-
expect(m.call(data)).to eq(data["hello"]["world"][0])
|
91
|
-
|
92
|
-
m = eval(subject.compile("[hello][world][1]"))
|
93
|
-
expect(m.call(data)).to eq(data["hello"]["world"][1])
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|