logstash-filter-translate 2.0.2 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5522423e565a186cb510bff658b46dc95a6faafa
4
- data.tar.gz: 6a56306cc43c2e35376372f0a48283f8217030cc
3
+ metadata.gz: 8003929e0ef9c30f41f95b144ce3872b60cceaa7
4
+ data.tar.gz: b92c98f43df88c648a684f638cd04fed8e12336b
5
5
  SHA512:
6
- metadata.gz: db2cbcff7dad08c6b5f84fbf59f6400c734da6d723a6b453d36c7e5ca88814f55e26cb0100fe7989e7a7f4f29358bed8dcab4bc670982c993329a05e7566ee34
7
- data.tar.gz: 962fb927bd78ef64b90f0de95cef9042bf06be1c489af1c0901fa9a2ab7eb517dd9aa11f642a79fb1235d0e625e7fcd024d873e88041c1d9f4f31cde1093027f
6
+ metadata.gz: 2a65ab7595ecbd6eb16bbec0127f9052060c6601be096658b76b9ccdbb4ede9b176047adae3c9aaeeb8e17d22d6cf7f54a8bd6ca00bed52052c40b8f95494cbc
7
+ data.tar.gz: 0a7bb3d83cebf55531bf35bff3a626528932fe78de627e46ac0edc91fa7230296069943503529fec868f942a79dd914c74492550fd658ce69f98df98df458c51
@@ -1,7 +1,20 @@
1
+ # 2.1.3
2
+ - Depend on logstash-core-plugin-api instead of logstash-core, removing the need to mass update plugins on major releases of logstash
3
+ # 2.1.2
4
+ - New dependency requirements for logstash-core for the 5.0 release
5
+ ## 2.1.1
6
+ - Add more descriptive message with the dictionary could not be loaded,
7
+ also include test for it.
8
+
9
+ ## 2.1.0
10
+ - Added other formats, a part from YAML, to be used when loading
11
+ dictionaries from files in this plugin. Current supported formats are
12
+ YAML, JSON and CSV.
13
+
1
14
  ## 2.0.0
2
- - Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
3
- instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
4
- - Dependency on logstash-core update to 2.0
15
+ - Plugins were updated to follow the new shutdown semantic, this mainly allows Logstash to instruct input plugins to terminate gracefully,
16
+ instead of using Thread.raise on the plugins' threads. Ref: https://github.com/elastic/logstash/pull/3895
17
+ - Dependency on logstash-core update to 2.0
5
18
 
6
- # 0.1.10
19
+ ## 0.1.10
7
20
  - fix failing test due to a missing encoding: utf8 magic header
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Logstash Plugin
2
2
 
3
+ [![Build
4
+ Status](http://build-eu-00.elastic.co/view/LS%20Plugins/view/LS%20Filters/job/logstash-plugin-filter-translate-unit/badge/icon)](http://build-eu-00.elastic.co/view/LS%20Plugins/view/LS%20Filters/job/logstash-plugin-filter-translate-unit/)
5
+
3
6
  This is a plugin for [Logstash](https://github.com/elastic/logstash).
4
7
 
5
8
  It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
@@ -1,13 +1,16 @@
1
1
  # encoding: utf-8
2
2
  require "logstash/filters/base"
3
3
  require "logstash/namespace"
4
+ require "json"
5
+ require "csv"
4
6
 
5
7
  # A general search and replace tool which uses a configured hash
6
- # and/or a YAML file to determine replacement values.
8
+ # and/or a file to determine replacement values. Currently supported are
9
+ # YAML, JSON and CSV files.
7
10
  #
8
11
  # The dictionary entries can be specified in one of two ways: First,
9
12
  # the `dictionary` configuration item may contain a hash representing
10
- # the mapping. Second, an external YAML file (readable by logstash) may be specified
13
+ # the mapping. Second, an external file (readable by logstash) may be specified
11
14
  # in the `dictionary_path` configuration item. These two methods may not be used
12
15
  # in conjunction; it will produce an error.
13
16
  #
@@ -39,7 +42,7 @@ class LogStash::Filters::Translate < LogStash::Filters::Base
39
42
  config :override, :validate => :boolean, :default => false
40
43
 
41
44
  # The dictionary to use for translation, when specified in the logstash filter
42
- # configuration item (i.e. do not use the `@dictionary_path` YAML file)
45
+ # configuration item (i.e. do not use the `@dictionary_path` file)
43
46
  # Example:
44
47
  # [source,ruby]
45
48
  # filter {
@@ -53,22 +56,27 @@ class LogStash::Filters::Translate < LogStash::Filters::Base
53
56
  # NOTE: it is an error to specify both `dictionary` and `dictionary_path`
54
57
  config :dictionary, :validate => :hash, :default => {}
55
58
 
56
- # The full path of the external YAML dictionary file. The format of the table
57
- # should be a standard YAML file. Make sure you specify any integer-based keys
58
- # in quotes. The YAML file should look something like this:
59
+ # The full path of the external dictionary file. The format of the table
60
+ # should be a standard YAML, JSON or CSV. Make sure you specify any integer-based keys
61
+ # in quotes. For example, the YAML file should look something like this:
59
62
  # [source,ruby]
60
63
  # "100": Continue
61
64
  # "101": Switching Protocols
62
65
  # merci: gracias
63
66
  # old version: new version
64
- #
67
+ #
65
68
  # NOTE: it is an error to specify both `dictionary` and `dictionary_path`
69
+ # NOTE: Currently supported formats are YAML, JSON and CSV, format selection is
70
+ # based on the file extension, json for JSON, (yaml|yml) for YAML and csv for CSV.
71
+ # NOTE: The JSON format only supports simple key/value, unnested objects. The CSV
72
+ # format expects exactly two columns with the first serving as the original text,
73
+ # the second column as the replacement
66
74
  config :dictionary_path, :validate => :path
67
75
 
68
76
  # When using a dictionary file, this setting will indicate how frequently
69
- # (in seconds) logstash will check the YAML file for updates.
77
+ # (in seconds) logstash will check the dictionary file for updates.
70
78
  config :refresh_interval, :validate => :number, :default => 300
71
-
79
+
72
80
  # The destination field you wish to populate with the translated code. The default
73
81
  # is a field named `translation`. Set this to the same value as source if you want
74
82
  # to do a substitution, in this case filter will allways succeed. This will clobber
@@ -86,7 +94,7 @@ class LogStash::Filters::Translate < LogStash::Filters::Base
86
94
  #
87
95
  # If logstash receives an event with the `data` field set to `foo`, and `exact => true`,
88
96
  # the destination field will be populated with the string `bar`.
89
-
97
+
90
98
  # If `exact => false`, and logstash receives the same event, the destination field
91
99
  # will be also set to `bar`. However, if logstash receives an event with the `data` field
92
100
  # set to `foofing`, the destination field will be set to `barfing`.
@@ -112,14 +120,13 @@ class LogStash::Filters::Translate < LogStash::Filters::Base
112
120
  # This configuration can be dynamic and include parts of the event using the `%{field}` syntax.
113
121
  config :fallback, :validate => :string
114
122
 
115
- public
116
123
  def register
117
124
  if @dictionary_path
118
125
  @next_refresh = Time.now + @refresh_interval
119
- registering = true
120
- load_yaml(registering)
126
+ raise_exception = true
127
+ load_dictionary(raise_exception)
121
128
  end
122
-
129
+
123
130
  @logger.debug? and @logger.debug("#{self.class.name}: Dictionary - ", :dictionary => @dictionary)
124
131
  if @exact
125
132
  @logger.debug? and @logger.debug("#{self.class.name}: Dictionary translation method - Exact")
@@ -128,36 +135,15 @@ class LogStash::Filters::Translate < LogStash::Filters::Base
128
135
  end
129
136
  end # def register
130
137
 
131
- public
132
- def load_yaml(registering=false)
133
- if !File.exists?(@dictionary_path)
134
- @logger.warn("dictionary file read failure, continuing with old dictionary", :path => @dictionary_path)
135
- return
136
- end
137
-
138
- begin
139
- @dictionary.merge!(YAML.load_file(@dictionary_path))
140
- rescue Exception => e
141
- if registering
142
- raise "#{self.class.name}: Bad Syntax in dictionary file #{@dictionary_path}"
143
- else
144
- @logger.warn("#{self.class.name}: Bad Syntax in dictionary file, continuing with old dictionary", :dictionary_path => @dictionary_path)
145
- end
146
- end
147
- end
148
-
149
- public
150
138
  def filter(event)
151
-
152
-
153
139
  if @dictionary_path
154
140
  if @next_refresh < Time.now
155
- load_yaml
141
+ load_dictionary
156
142
  @next_refresh = Time.now + @refresh_interval
157
143
  @logger.info("refreshing dictionary file")
158
144
  end
159
145
  end
160
-
146
+
161
147
  return unless event.include?(@field) # Skip translation in case event does not have @event field.
162
148
  return if event.include?(@destination) and not @override # Skip translation in case @destination field already exists and @override is disabled.
163
149
 
@@ -193,4 +179,61 @@ class LogStash::Filters::Translate < LogStash::Filters::Base
193
179
  @logger.error("Something went wrong when attempting to translate from dictionary", :exception => e, :field => @field, :event => event)
194
180
  end
195
181
  end # def filter
182
+
183
+ private
184
+
185
+ def load_dictionary(raise_exception=false)
186
+ if /.y[a]?ml$/.match(@dictionary_path)
187
+ load_yaml(raise_exception)
188
+ elsif @dictionary_path.end_with?(".json")
189
+ load_json(raise_exception)
190
+ elsif @dictionary_path.end_with?(".csv")
191
+ load_csv(raise_exception)
192
+ else
193
+ raise "#{self.class.name}: Dictionary #{@dictionary_path} have a non valid format"
194
+ end
195
+ rescue => e
196
+ loading_exception(e, raise_exception)
197
+ end
198
+
199
+ def load_yaml(raise_exception=false)
200
+ if !File.exists?(@dictionary_path)
201
+ @logger.warn("dictionary file read failure, continuing with old dictionary", :path => @dictionary_path)
202
+ return
203
+ end
204
+ merge_dictionary!(YAML.load_file(@dictionary_path), raise_exception)
205
+ end
206
+
207
+ def load_json(raise_exception=false)
208
+ if !File.exists?(@dictionary_path)
209
+ @logger.warn("dictionary file read failure, continuing with old dictionary", :path => @dictionary_path)
210
+ return
211
+ end
212
+ merge_dictionary!(JSON.parse(File.read(@dictionary_path)), raise_exception)
213
+ end
214
+
215
+ def load_csv(raise_exception=false)
216
+ if !File.exists?(@dictionary_path)
217
+ @logger.warn("dictionary file read failure, continuing with old dictionary", :path => @dictionary_path)
218
+ return
219
+ end
220
+ data = CSV.read(@dictionary_path).inject(Hash.new) do |acc, v|
221
+ acc[v[0]] = v[1]
222
+ acc
223
+ end
224
+ merge_dictionary!(data, raise_exception)
225
+ end
226
+
227
+ def merge_dictionary!(data, raise_exception=false)
228
+ @dictionary.merge!(data)
229
+ end
230
+
231
+ def loading_exception(e, raise_exception=false)
232
+ msg = "#{self.class.name}: #{e.message} when loading dictionary file at #{@dictionary_path}"
233
+ if raise_exception
234
+ raise RuntimeError.new(msg)
235
+ else
236
+ @logger.warn("#{msg}, continuing with old dictionary", :dictionary_path => @dictionary_path)
237
+ end
238
+ end
196
239
  end # class LogStash::Filters::Translate
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
 
3
3
  s.name = 'logstash-filter-translate'
4
- s.version = '2.0.2'
4
+ s.version = '2.1.3'
5
5
  s.licenses = ['Apache License (2.0)']
6
6
  s.summary = "A general search and replace tool which uses a configured hash and/or a YAML file to determine replacement values."
7
7
  s.description = "This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program"
@@ -20,7 +20,7 @@ Gem::Specification.new do |s|
20
20
  s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
21
21
 
22
22
  # Gem dependencies
23
- s.add_runtime_dependency "logstash-core", ">= 2.0.0.beta2", "< 3.0.0"
23
+ s.add_runtime_dependency "logstash-core-plugin-api", "~> 1.0"
24
24
 
25
25
  s.add_development_dependency 'logstash-devutils'
26
26
  end
@@ -120,4 +120,64 @@ describe LogStash::Filters::Translate do
120
120
  end
121
121
  end
122
122
 
123
+ describe "loading a dictionary" do
124
+
125
+ let(:dictionary_path) { File.join(File.dirname(__FILE__), "..", "fixtures", "dict-wrong.yml") }
126
+
127
+ let(:config) do
128
+ {
129
+ "field" => "status",
130
+ "destination" => "translation",
131
+ "dictionary_path" => dictionary_path,
132
+ "exact" => true,
133
+ "regex" => false
134
+ }
135
+ end
136
+
137
+ it "raises exception when loading" do
138
+ error = "(#{dictionary_path}): mapping values are not allowed here at line 1 column 45 when loading dictionary file at #{dictionary_path}"
139
+ expect { subject.register }.to raise_error("#{described_class}: #{error}")
140
+ end
141
+
142
+ context "when using a yml file" do
143
+ let(:dictionary_path) { File.join(File.dirname(__FILE__), "..", "fixtures", "dict.yml") }
144
+ let(:event) { LogStash::Event.new("status" => "a") }
145
+
146
+ it "return the exact translation" do
147
+ subject.register
148
+ subject.filter(event)
149
+ expect(event["translation"]).to eq(1)
150
+ end
151
+ end
152
+
153
+ context "when using a json file" do
154
+ let(:dictionary_path) { File.join(File.dirname(__FILE__), "..", "fixtures", "dict.json") }
155
+ let(:event) { LogStash::Event.new("status" => "b") }
156
+
157
+ it "return the exact translation" do
158
+ subject.register
159
+ subject.filter(event)
160
+ expect(event["translation"]).to eq(20)
161
+ end
162
+ end
163
+
164
+ context "when using a csv file" do
165
+ let(:dictionary_path) { File.join(File.dirname(__FILE__), "..", "fixtures", "dict.csv") }
166
+ let(:event) { LogStash::Event.new("status" => "c") }
167
+
168
+ it "return the exact translation" do
169
+ subject.register
170
+ subject.filter(event)
171
+ expect(event["translation"]).to eq("300")
172
+ end
173
+ end
174
+
175
+ context "when using an uknown file" do
176
+ let(:dictionary_path) { File.join(File.dirname(__FILE__), "..", "fixtures", "dict.other") }
177
+
178
+ it "return the exact translation" do
179
+ expect { subject.register }.to raise_error(RuntimeError, /Dictionary #{dictionary_path} have a non valid format/)
180
+ end
181
+ end
182
+ end
123
183
  end
@@ -0,0 +1 @@
1
+ foo: somebody said I should put a colon here: so I did
@@ -0,0 +1,3 @@
1
+ "a",100
2
+ "b",200
3
+ "c",300
@@ -0,0 +1,5 @@
1
+ {
2
+ "a" : 10,
3
+ "b" : 20,
4
+ "c" : 30
5
+ }
@@ -0,0 +1,3 @@
1
+ "a" | 400
2
+ "b" | 500
3
+ "c" | 600
@@ -0,0 +1,3 @@
1
+ a : 1
2
+ b : 2
3
+ c : 3
metadata CHANGED
@@ -1,39 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logstash-filter-translate
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elastic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-14 00:00:00.000000000 Z
11
+ date: 2016-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - '>='
16
+ - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 2.0.0.beta2
19
- - - <
20
- - !ruby/object:Gem::Version
21
- version: 3.0.0
22
- name: logstash-core
18
+ version: '1.0'
19
+ name: logstash-core-plugin-api
23
20
  prerelease: false
24
21
  type: :runtime
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - '>='
28
- - !ruby/object:Gem::Version
29
- version: 2.0.0.beta2
30
- - - <
24
+ - - "~>"
31
25
  - !ruby/object:Gem::Version
32
- version: 3.0.0
26
+ version: '1.0'
33
27
  - !ruby/object:Gem::Dependency
34
28
  requirement: !ruby/object:Gem::Requirement
35
29
  requirements:
36
- - - '>='
30
+ - - ">="
37
31
  - !ruby/object:Gem::Version
38
32
  version: '0'
39
33
  name: logstash-devutils
@@ -41,7 +35,7 @@ dependencies:
41
35
  type: :development
42
36
  version_requirements: !ruby/object:Gem::Requirement
43
37
  requirements:
44
- - - '>='
38
+ - - ">="
45
39
  - !ruby/object:Gem::Version
46
40
  version: '0'
47
41
  description: This gem is a logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/plugin install gemname. This gem is not a stand-alone program
@@ -59,6 +53,11 @@ files:
59
53
  - lib/logstash/filters/translate.rb
60
54
  - logstash-filter-translate.gemspec
61
55
  - spec/filters/translate_spec.rb
56
+ - spec/fixtures/dict-wrong.yml
57
+ - spec/fixtures/dict.csv
58
+ - spec/fixtures/dict.json
59
+ - spec/fixtures/dict.other
60
+ - spec/fixtures/dict.yml
62
61
  homepage: http://www.elastic.co/guide/en/logstash/current/index.html
63
62
  licenses:
64
63
  - Apache License (2.0)
@@ -71,12 +70,12 @@ require_paths:
71
70
  - lib
72
71
  required_ruby_version: !ruby/object:Gem::Requirement
73
72
  requirements:
74
- - - '>='
73
+ - - ">="
75
74
  - !ruby/object:Gem::Version
76
75
  version: '0'
77
76
  required_rubygems_version: !ruby/object:Gem::Requirement
78
77
  requirements:
79
- - - '>='
78
+ - - ">="
80
79
  - !ruby/object:Gem::Version
81
80
  version: '0'
82
81
  requirements: []
@@ -87,3 +86,8 @@ specification_version: 4
87
86
  summary: A general search and replace tool which uses a configured hash and/or a YAML file to determine replacement values.
88
87
  test_files:
89
88
  - spec/filters/translate_spec.rb
89
+ - spec/fixtures/dict-wrong.yml
90
+ - spec/fixtures/dict.csv
91
+ - spec/fixtures/dict.json
92
+ - spec/fixtures/dict.other
93
+ - spec/fixtures/dict.yml