logstash-filter-translate 2.0.2 → 2.1.3

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.
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