fluent-plugin-elasticsearch 1.4.0 → 1.5.0

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: 89a28c84005c362158da08a71ea7c10036df254d
4
- data.tar.gz: 87a5e6283b6e3bd057ec949ee95316460bc8f6da
3
+ metadata.gz: 90e3be14c80ad364758d6868ac2eeb3ff362d03c
4
+ data.tar.gz: 449226f062ac9c526d420e459fb25b731583d482
5
5
  SHA512:
6
- metadata.gz: fde384e1b97967886d1446785e1cdb5eedb1bf7f98ab7841d321d34886dc84ee95f255d8d86b289c03b40e469528efce6a288b63072a6fd9f40f5451b82bd043
7
- data.tar.gz: 35d51c4cc3508cf12e6c4971db4ab4c947c4688cc4f021a33c4d0bf1f325a03a013b1b1b30195be8a64296636997e757a518fdd5516234741824cec20151197b
6
+ metadata.gz: 0da741644cf316f00cb3aecf005933d465c076c4df8af080ec1a4d69bbd8d881de1298a5b734e1de2bf2e6cd36062579ae1e73a0e8684ec523dca3e7de89d84b
7
+ data.tar.gz: 1acd9c7b4e96059143dac1a4fc80eb8f170f74f934ee53304e112edaa01dadeccf4eb5fb44244ec4e16a55ef973a3534b60f61ea998249e892fecc675524886e
data/History.md CHANGED
@@ -1,7 +1,15 @@
1
- ## Changelog
1
+ ## Changelog [[tags]](https://github.com/uken/fluent-plugin-elasticsearch/tags)
2
2
 
3
3
  ### Future
4
4
 
5
+ ### 1.5.0
6
+ - add `routing_key` (#158)
7
+ - add `time_key_exclude_timestamp` to exclude `@timestamp` (#161)
8
+ - convert index names to lowercase (#163)
9
+ - add `remove_keys` (#164)
10
+ - add `flatten_hashes` (#168)
11
+ - add `target_type_key` (#169)
12
+
5
13
  ### 1.4.0
6
14
  - add `target_index_key` to specify target index (#153)
7
15
  - add `time_key_format` for faster time format parsing (#154)
@@ -0,0 +1,10 @@
1
+ Pull Request Description HERE
2
+
3
+ (check all that apply)
4
+ - [ ] tests added
5
+ - [ ] tests passing
6
+ - [ ] README updated (if needed)
7
+ - [ ] README Table of Contents updated (if needed)
8
+ - [ ] History.md and `version` in gemspec are untouched
9
+ - [ ] backward compatible
10
+ - [ ] feature works in `elasticsearch_dynamic` (not required but recommended)
data/README.md CHANGED
@@ -22,18 +22,24 @@ Note: For Amazon Elasticsearch Service please consider using [fluent-plugin-aws-
22
22
  + [logstash_dateformat](#logstash_dateformat)
23
23
  + [time_key_format](#time_key_format)
24
24
  + [time_key](#time_key)
25
+ + [time_key_exclude_timestamp](#time_key_exclude_timestamp)
25
26
  + [utc_index](#utc_index)
26
27
  + [target_index_key](#target_index_key)
28
+ + [target_type_key](#target_type_key)
27
29
  + [request_timeout](#request_timeout)
28
30
  + [reload_connections](#reload_connections)
29
31
  + [reload_on_failure](#reload_on_failure)
30
32
  + [resurrect_after](#resurrect_after)
31
33
  + [include_tag_key, tag_key](#include_tag_key-tag_key)
32
34
  + [id_key](#id_key)
35
+ + [parent_key](#parent_key)
36
+ + [routing_key](#routing_key)
37
+ + [remove_keys](#remove_keys)
33
38
  + [write_operation](#write_operation)
34
39
  + [Client/host certificate options](#clienthost-certificate-options)
35
40
  + [Proxy Support](#proxy-support)
36
41
  + [Buffered output options](#buffered-output-options)
42
+ + [Hash flattening](#hash-flattening)
37
43
  + [Not seeing a config you need?](#not-seeing-a-config-you-need)
38
44
  + [Dynamic configuration](#dynamic-configuration)
39
45
  * [Contact](#contact)
@@ -117,7 +123,7 @@ logstash_dateformat %Y.%m. # defaults to "%Y.%m.%d"
117
123
 
118
124
  ### time_key_format
119
125
 
120
- The format of the time stamp field (`@timestamp` or what you specify with [time_key][#time_key]). This parameter only has an effect when [logstash_format][#logstash_format] is true as it only affects the name of the index we write to. Please see [Time#strftime](http://ruby-doc.org/core-1.9.3/Time.html#method-i-strftime) for information about the value of this format.
126
+ The format of the time stamp field (`@timestamp` or what you specify with [time_key](#time_key)). This parameter only has an effect when [logstash_format](#logstash_format) is true as it only affects the name of the index we write to. Please see [Time#strftime](http://ruby-doc.org/core-1.9.3/Time.html#method-i-strftime) for information about the value of this format.
121
127
 
122
128
  Setting this to a known format can vastly improve your log ingestion speed if all most of your logs are in the same format. If there is an error parsing this format the timestamp will default to the ingestion time. If you are on Ruby 2.0 or later you can get a further performance improvment by installing the "strptime" gem: `fluent-gem install strptime`.
123
129
 
@@ -161,6 +167,16 @@ The output will be
161
167
  }
162
168
  ```
163
169
 
170
+ See `time_key_exclude_timestamp` to avoid adding `@timestamp`.
171
+
172
+ ### time_key_exclude_timestamp
173
+
174
+ ```
175
+ time_key_exclude_timestamp false
176
+ ```
177
+
178
+ By default, setting `time_key` will copy the value to an additional field `@timestamp`. When setting `time_key_exclude_timestamp true`, no additional field will be added.
179
+
164
180
  ### utc_index
165
181
 
166
182
  ```
@@ -202,6 +218,10 @@ The output would be
202
218
 
203
219
  and this record will be written to the specified index (`logstash-2014.12.19`) rather than `fallback`.
204
220
 
221
+ ### target_type_key
222
+
223
+ Similar to `target_index_key` config, find the type name to write to in the record under this key. If key not found in record - fallback to `type_name` (default "fluentd").
224
+
205
225
  ### request_timeout
206
226
 
207
227
  You can specify HTTP request timeout.
@@ -275,6 +295,38 @@ This following record `{"name":"Johnny","request_id":"87d89af7daffad6"}` will tr
275
295
  { "name": "Johnny", "request_id": "87d89af7daffad6" }
276
296
  ```
277
297
 
298
+ ### parent_key
299
+
300
+ ```
301
+ parent_key a_parent # use "a_parent" field value to set _parent in elasticsearch command
302
+ ```
303
+
304
+ If your input is
305
+ ```
306
+ { "name": "Johnny", "a_parent": "my_parent" }
307
+ ```
308
+
309
+ ElasticSearch command would be
310
+
311
+ ```
312
+ { "index" : { "_index" : "****", "_type" : "****", "_id" : "****", "_parent" : "my_parent" } }
313
+ { "name": "Johnny", "a_parent": "my_parent" }
314
+ ```
315
+
316
+ if `parent_key` is not configed or the `parent_key` is absent in input record, nothing will happen.
317
+
318
+ ### routing_key
319
+
320
+ Similar to `parent_key` config, will add `_routing` into elasticsearch command if `routing_key` is set and the field does exist in input event.
321
+
322
+ ### remove_keys
323
+
324
+ ```
325
+ parent_key a_parent
326
+ routing_key a_routing
327
+ remove_keys a_parent, a_routing # a_parent and a_routing fileds wont be sent to elasticsearch
328
+ ```
329
+
278
330
  ### write_operation
279
331
 
280
332
  The write_operation can be any of:
@@ -318,7 +370,26 @@ retry_wait 1.0
318
370
  num_threads 1
319
371
  ```
320
372
 
321
- The value for option `buffer_chunk_limit` should not exceed value `http.max_content_length` in your Elasticsearch setup (by default it is 104857600 bytes).
373
+ The value for option `buffer_chunk_limit` should not exceed value `http.max_content_length` in your Elasticsearch setup (by default it is 100mb).
374
+
375
+ ### Hash flattening
376
+
377
+ Elasticsearch will complain if you send object and concrete values to the same field. For example, you might have logs that look this, from different places:
378
+
379
+ {"people" => 100}
380
+ {"people" => {"some" => "thing"}}
381
+
382
+ The second log line will be rejected by the Elasticsearch parser because objects and concrete values can't live in the same field. To combat this, you can enable hash flattening.
383
+
384
+ ```
385
+ flatten_hashes true
386
+ flatten_hashes_separator _
387
+ ```
388
+
389
+ This will produce elasticsearch output that looks like this:
390
+ {"people_some" => "thing"}
391
+
392
+ Note that the flattener does not deal with arrays at this time.
322
393
 
323
394
  ### Not seeing a config you need?
324
395
 
@@ -3,7 +3,7 @@ $:.push File.expand_path('../lib', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'fluent-plugin-elasticsearch'
6
- s.version = '1.4.0'
6
+ s.version = '1.5.0'
7
7
  s.authors = ['diogo', 'pitr']
8
8
  s.email = ['pitr.vern@gmail.com', 'me@diogoterror.com']
9
9
  s.description = %q{ElasticSearch output plugin for Fluent event collector}
@@ -21,6 +21,7 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
21
21
  config_param :scheme, :string, :default => 'http'
22
22
  config_param :hosts, :string, :default => nil
23
23
  config_param :target_index_key, :string, :default => nil
24
+ config_param :target_type_key, :string, :default => nil
24
25
  config_param :time_key_format, :string, :default => nil
25
26
  config_param :logstash_format, :bool, :default => false
26
27
  config_param :logstash_prefix, :string, :default => "logstash"
@@ -31,16 +32,21 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
31
32
  config_param :id_key, :string, :default => nil
32
33
  config_param :write_operation, :string, :default => "index"
33
34
  config_param :parent_key, :string, :default => nil
35
+ config_param :routing_key, :string, :default => nil
34
36
  config_param :request_timeout, :time, :default => 5
35
37
  config_param :reload_connections, :bool, :default => true
36
38
  config_param :reload_on_failure, :bool, :default => false
37
39
  config_param :resurrect_after, :time, :default => 60
38
40
  config_param :time_key, :string, :default => nil
41
+ config_param :time_key_exclude_timestamp, :bool, :default => false
39
42
  config_param :ssl_verify , :bool, :default => true
40
43
  config_param :client_key, :string, :default => nil
41
44
  config_param :client_cert, :string, :default => nil
42
45
  config_param :client_key_pass, :string, :default => nil
43
46
  config_param :ca_file, :string, :default => nil
47
+ config_param :remove_keys, :string, :default => nil
48
+ config_param :flatten_hashes, :bool, :default => false
49
+ config_param :flatten_hashes_separator, :string, :default => "_"
44
50
 
45
51
  include Fluent::SetTagKeyMixin
46
52
  config_set_default :include_tag_key, false
@@ -53,6 +59,10 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
53
59
  def configure(conf)
54
60
  super
55
61
  @time_parser = TimeParser.new(@time_key_format, @router)
62
+
63
+ if @remove_keys
64
+ @remove_keys = @remove_keys.split(/\s*,\s*/)
65
+ end
56
66
  end
57
67
 
58
68
  def start
@@ -186,10 +196,29 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
186
196
  end
187
197
  end
188
198
 
199
+ def flatten_record(record, prefix=[])
200
+ ret = {}
201
+ if record.is_a? Hash
202
+ record.each { |key, value|
203
+ ret.merge! flatten_record(value, prefix + [key.to_s])
204
+ }
205
+ elsif record.is_a? Array
206
+ # Don't mess with arrays, leave them unprocessed
207
+ ret.merge!({prefix.join(@flatten_hashes_separator) => record})
208
+ else
209
+ return {prefix.join(@flatten_hashes_separator) => record}
210
+ end
211
+ ret
212
+ end
213
+
189
214
  def write(chunk)
190
215
  bulk_message = []
191
216
 
192
217
  chunk.msgpack_each do |tag, time, record|
218
+ if @flatten_hashes
219
+ record = flatten_record(record)
220
+ end
221
+
193
222
  next unless record.is_a? Hash
194
223
  if @target_index_key && record[@target_index_key]
195
224
  target_index = record.delete @target_index_key
@@ -199,7 +228,7 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
199
228
  dt = @time_parser.parse(record["@timestamp"], time)
200
229
  elsif record.has_key?(@time_key)
201
230
  dt = @time_parser.parse(record[@time_key], time)
202
- record['@timestamp'] = record[@time_key]
231
+ record['@timestamp'] = record[@time_key] unless time_key_exclude_timestamp
203
232
  else
204
233
  dt = Time.at(time).to_datetime
205
234
  record.merge!({"@timestamp" => dt.to_s})
@@ -209,18 +238,31 @@ class Fluent::ElasticsearchOutput < Fluent::BufferedOutput
209
238
  else
210
239
  target_index = @index_name
211
240
  end
212
-
241
+
242
+ # Change target_index to lower-case since Elasticsearch doesn't
243
+ # allow upper-case characters in index names.
244
+ target_index = target_index.downcase
245
+
213
246
  if @include_tag_key
214
247
  record.merge!(@tag_key => tag)
215
248
  end
249
+
250
+ if @target_type_key && record[@target_type_key]
251
+ target_type = record.delete @target_type_key
252
+ else
253
+ target_type = @type_name
254
+ end
255
+
256
+ meta = {"_index" => target_index, "_type" => target_type}
216
257
 
217
- meta = {"_index" => target_index, "_type" => type_name}
218
- if @id_key && record[@id_key]
219
- meta['_id'] = record[@id_key]
258
+ @meta_config_map ||= { 'id_key' => '_id', 'parent_key' => '_parent', 'routing_key' => '_routing' }
259
+ @meta_config_map.each_pair do |config_name, meta_key|
260
+ record_key = self.instance_variable_get("@#{config_name}")
261
+ meta[meta_key] = record[record_key] if record_key && record[record_key]
220
262
  end
221
263
 
222
- if @parent_key && record[@parent_key]
223
- meta['_parent'] = record[@parent_key]
264
+ if @remove_keys
265
+ @remove_keys.each { |key| record.delete(key) }
224
266
  end
225
267
 
226
268
  append_record_to_messages(@write_operation, meta, record, bulk_message)
@@ -11,6 +11,7 @@ class Fluent::ElasticsearchOutputDynamic < Fluent::ElasticsearchOutput
11
11
  config_param :port, :string, :default => "9200"
12
12
  config_param :logstash_format, :string, :default => "false"
13
13
  config_param :utc_index, :string, :default => "true"
14
+ config_param :time_key_exclude_timestamp, :bool, :default => false
14
15
  config_param :reload_connections, :string, :default => "true"
15
16
  config_param :reload_on_failure, :string, :default => "false"
16
17
  config_param :resurrect_after, :string, :default => "60"
@@ -131,7 +132,7 @@ class Fluent::ElasticsearchOutputDynamic < Fluent::ElasticsearchOutput
131
132
  time = Time.parse record["@timestamp"]
132
133
  elsif record.has_key?(dynamic_conf['time_key'])
133
134
  time = Time.parse record[dynamic_conf['time_key']]
134
- record['@timestamp'] = record[dynamic_conf['time_key']]
135
+ record['@timestamp'] = record[dynamic_conf['time_key']] unless time_key_exclude_timestamp
135
136
  else
136
137
  record.merge!({"@timestamp" => Time.at(time).to_datetime.to_s})
137
138
  end
@@ -144,18 +145,22 @@ class Fluent::ElasticsearchOutputDynamic < Fluent::ElasticsearchOutput
144
145
  else
145
146
  target_index = dynamic_conf['index_name']
146
147
  end
147
-
148
+
149
+ # Change target_index to lower-case since Elasticsearch doesn't
150
+ # allow upper-case characters in index names.
151
+ target_index = target_index.downcase
152
+
148
153
  if @include_tag_key
149
154
  record.merge!(dynamic_conf['tag_key'] => tag)
150
155
  end
151
156
 
152
157
  meta = {"_index" => target_index, "_type" => dynamic_conf['type_name']}
153
- if dynamic_conf['id_key'] && record[dynamic_conf['id_key']]
154
- meta['_id'] = record[dynamic_conf['id_key']]
155
- end
156
158
 
157
- if dynamic_conf['parent_key'] && record[dynamic_conf['parent_key']]
158
- meta['_parent'] = record[dynamic_conf['parent_key']]
159
+ @meta_config_map ||= { 'id_key' => '_id', 'parent_key' => '_parent', 'routing_key' => '_routing' }
160
+ @meta_config_map.each_pair do |config_name, meta_key|
161
+ if dynamic_conf[config_name] && record[dynamic_conf[config_name]]
162
+ meta[meta_key] = record[dynamic_conf[config_name]]
163
+ end
159
164
  end
160
165
 
161
166
  if dynamic_conf['hosts']
@@ -164,6 +169,10 @@ class Fluent::ElasticsearchOutputDynamic < Fluent::ElasticsearchOutput
164
169
  host = "#{dynamic_conf['host']}:#{dynamic_conf['port']}"
165
170
  end
166
171
 
172
+ if @remove_keys
173
+ @remove_keys.each { |key| record.delete(key) }
174
+ end
175
+
167
176
  append_record_to_messages(dynamic_conf["write_operation"], meta, record, bulk_message[host])
168
177
  end
169
178
 
@@ -17,7 +17,7 @@ class ElasticsearchOutput < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  def sample_record
20
- {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent'}
20
+ {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}
21
21
  end
22
22
 
23
23
  def stub_elastic_ping(url="http://localhost:9200")
@@ -156,6 +156,17 @@ class ElasticsearchOutput < Test::Unit::TestCase
156
156
  driver.run
157
157
  assert_equal('myindex', index_cmds.first['index']['_index'])
158
158
  end
159
+
160
+ def test_writes_to_speficied_index_uppercase
161
+ driver.configure("index_name MyIndex\n")
162
+ stub_elastic_ping
163
+ stub_elastic
164
+ driver.emit(sample_record)
165
+ driver.run
166
+ # Allthough index_name has upper-case characters,
167
+ # it should be set as lower-case when sent to elasticsearch.
168
+ assert_equal('myindex', index_cmds.first['index']['_index'])
169
+ end
159
170
 
160
171
  def test_writes_to_target_index_key
161
172
  driver.configure("target_index_key @target_index\n")
@@ -167,7 +178,7 @@ class ElasticsearchOutput < Test::Unit::TestCase
167
178
  assert_equal('local-override', index_cmds.first['index']['_index'])
168
179
  assert_nil(index_cmds[1]['@target_index'])
169
180
  end
170
-
181
+
171
182
  def test_writes_to_target_index_key_logstash
172
183
  driver.configure("target_index_key @target_index\n")
173
184
  driver.configure("logstash_format true\n")
@@ -178,6 +189,19 @@ class ElasticsearchOutput < Test::Unit::TestCase
178
189
  driver.run
179
190
  assert_equal('local-override', index_cmds.first['index']['_index'])
180
191
  end
192
+
193
+ def test_writes_to_target_index_key_logstash_uppercase
194
+ driver.configure("target_index_key @target_index\n")
195
+ driver.configure("logstash_format true\n")
196
+ time = Time.parse Date.today.to_s
197
+ stub_elastic_ping
198
+ stub_elastic
199
+ driver.emit(sample_record.merge('@target_index' => 'Local-Override'), time)
200
+ driver.run
201
+ # Allthough @target_index has upper-case characters,
202
+ # it should be set as lower-case when sent to elasticsearch.
203
+ assert_equal('local-override', index_cmds.first['index']['_index'])
204
+ end
181
205
 
182
206
  def test_writes_to_target_index_key_fallack
183
207
  driver.configure("target_index_key @target_index\n")
@@ -209,6 +233,36 @@ class ElasticsearchOutput < Test::Unit::TestCase
209
233
  assert_equal('mytype', index_cmds.first['index']['_type'])
210
234
  end
211
235
 
236
+ def test_writes_to_target_type_key
237
+ driver.configure("target_type_key @target_type\n")
238
+ stub_elastic_ping
239
+ stub_elastic
240
+ record = sample_record.clone
241
+ driver.emit(sample_record.merge('@target_type' => 'local-override'))
242
+ driver.run
243
+ assert_equal('local-override', index_cmds.first['index']['_type'])
244
+ assert_nil(index_cmds[1]['@target_type'])
245
+ end
246
+
247
+ def test_writes_to_target_type_key_fallack_to_default
248
+ driver.configure("target_type_key @target_type\n")
249
+ stub_elastic_ping
250
+ stub_elastic
251
+ driver.emit(sample_record)
252
+ driver.run
253
+ assert_equal('fluentd', index_cmds.first['index']['_type'])
254
+ end
255
+
256
+ def test_writes_to_target_type_key_fallack_to_type_name
257
+ driver.configure("target_type_key @target_type\n")
258
+ driver.configure("type_name mytype\n")
259
+ stub_elastic_ping
260
+ stub_elastic
261
+ driver.emit(sample_record)
262
+ driver.run
263
+ assert_equal('mytype', index_cmds.first['index']['_type'])
264
+ end
265
+
212
266
  def test_writes_to_speficied_host
213
267
  driver.configure("host 192.168.33.50\n")
214
268
  stub_elastic_ping("http://192.168.33.50:9200")
@@ -258,6 +312,40 @@ class ElasticsearchOutput < Test::Unit::TestCase
258
312
  assert_equal(2000, total)
259
313
  end
260
314
 
315
+ def test_nested_record_with_flattening_on
316
+ driver.configure("flatten_hashes true
317
+ flatten_hashes_separator |")
318
+
319
+ original_hash = {"foo" => {"bar" => "baz"}, "people" => [
320
+ {"age" => "25", "height" => "1ft"},
321
+ {"age" => "30", "height" => "2ft"}
322
+ ]}
323
+
324
+ expected_output = {"foo|bar"=>"baz", "people" => [
325
+ {"age" => "25", "height" => "1ft"},
326
+ {"age" => "30", "height" => "2ft"}
327
+ ]}
328
+
329
+ stub_elastic_ping
330
+ stub_elastic
331
+ driver.emit(original_hash)
332
+ driver.run
333
+ assert_equal expected_output, index_cmds[1]
334
+ end
335
+
336
+ def test_nested_record_with_flattening_off
337
+ # flattening off by default
338
+
339
+ original_hash = {"foo" => {"bar" => "baz"}}
340
+ expected_output = {"foo" => {"bar" => "baz"}}
341
+
342
+ stub_elastic_ping
343
+ stub_elastic
344
+ driver.emit(original_hash)
345
+ driver.run
346
+ assert_equal expected_output, index_cmds[1]
347
+ end
348
+
261
349
  def test_makes_bulk_request
262
350
  stub_elastic_ping
263
351
  stub_elastic
@@ -315,6 +403,20 @@ class ElasticsearchOutput < Test::Unit::TestCase
315
403
  driver.run
316
404
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
317
405
  end
406
+
407
+ def test_writes_to_logstash_index_with_specified_prefix_uppercase
408
+ driver.configure("logstash_format true
409
+ logstash_prefix MyPrefix")
410
+ time = Time.parse Date.today.to_s
411
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
412
+ stub_elastic_ping
413
+ stub_elastic
414
+ driver.emit(sample_record, time)
415
+ driver.run
416
+ # Allthough logstash_prefix has upper-case characters,
417
+ # it should be set as lower-case when sent to elasticsearch.
418
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
419
+ end
318
420
 
319
421
  def test_writes_to_logstash_index_with_specified_dateformat
320
422
  driver.configure("logstash_format true
@@ -383,6 +485,17 @@ class ElasticsearchOutput < Test::Unit::TestCase
383
485
  assert_equal(index_cmds[1]['@timestamp'], ts)
384
486
  end
385
487
 
488
+ def test_uses_custom_time_key_exclude_timekey
489
+ driver.configure("logstash_format true
490
+ time_key vtm
491
+ time_key_exclude_timestamp true\n")
492
+ stub_elastic_ping
493
+ stub_elastic
494
+ ts = DateTime.new(2001,2,3).to_s
495
+ driver.emit(sample_record.merge!('vtm' => ts))
496
+ driver.run
497
+ assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be messing')
498
+ end
386
499
 
387
500
  def test_uses_custom_time_key_format
388
501
  driver.configure("logstash_format true
@@ -502,6 +615,52 @@ class ElasticsearchOutput < Test::Unit::TestCase
502
615
  assert(!index_cmds[0]['index'].has_key?('_parent'))
503
616
  end
504
617
 
618
+ def test_adds_routing_key_when_configured
619
+ driver.configure("routing_key routing_id\n")
620
+ stub_elastic_ping
621
+ stub_elastic
622
+ driver.emit(sample_record)
623
+ driver.run
624
+ assert_equal(index_cmds[0]['index']['_routing'], 'routing')
625
+ end
626
+
627
+ def test_doesnt_add_routing_key_if_missing_when_configured
628
+ driver.configure("routing_key another_routing_id\n")
629
+ stub_elastic_ping
630
+ stub_elastic
631
+ driver.emit(sample_record)
632
+ driver.run
633
+ assert(!index_cmds[0]['index'].has_key?('_routing'))
634
+ end
635
+
636
+ def test_adds_routing_key_when_not_configured
637
+ stub_elastic_ping
638
+ stub_elastic
639
+ driver.emit(sample_record)
640
+ driver.run
641
+ assert(!index_cmds[0]['index'].has_key?('_routing'))
642
+ end
643
+
644
+ def test_remove_one_key
645
+ driver.configure("remove_keys key1\n")
646
+ stub_elastic_ping
647
+ stub_elastic
648
+ driver.emit(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
649
+ driver.run
650
+ assert(!index_cmds[1].has_key?('key1'))
651
+ assert(index_cmds[1].has_key?('key2'))
652
+ end
653
+
654
+ def test_remove_multi_keys
655
+ driver.configure("remove_keys key1, key2\n")
656
+ stub_elastic_ping
657
+ stub_elastic
658
+ driver.emit(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
659
+ driver.run
660
+ assert(!index_cmds[1].has_key?('key1'))
661
+ assert(!index_cmds[1].has_key?('key2'))
662
+ end
663
+
505
664
  def test_request_error
506
665
  stub_elastic_ping
507
666
  stub_elastic_unavailable
@@ -15,7 +15,7 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
15
15
  end
16
16
 
17
17
  def sample_record
18
- {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent'}
18
+ {'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}
19
19
  end
20
20
 
21
21
  def stub_elastic_ping(url="http://localhost:9200")
@@ -154,6 +154,15 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
154
154
  driver.run
155
155
  assert_equal('myindex', index_cmds.first['index']['_index'])
156
156
  end
157
+
158
+ def test_writes_to_speficied_index_uppercase
159
+ driver.configure("index_name MyIndex\n")
160
+ stub_elastic_ping
161
+ stub_elastic
162
+ driver.emit(sample_record)
163
+ driver.run
164
+ assert_equal('myindex', index_cmds.first['index']['_index'])
165
+ end
157
166
 
158
167
  def test_writes_to_speficied_type
159
168
  driver.configure("type_name mytype\n")
@@ -266,6 +275,18 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
266
275
  driver.run
267
276
  assert_equal(logstash_index, index_cmds.first['index']['_index'])
268
277
  end
278
+
279
+ def test_writes_to_logstash_index_with_specified_prefix_uppercase
280
+ driver.configure("logstash_format true
281
+ logstash_prefix MyPrefix")
282
+ time = Time.parse Date.today.to_s
283
+ logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
284
+ stub_elastic_ping
285
+ stub_elastic
286
+ driver.emit(sample_record, time)
287
+ driver.run
288
+ assert_equal(logstash_index, index_cmds.first['index']['_index'])
289
+ end
269
290
 
270
291
  def test_writes_to_logstash_index_with_specified_dateformat
271
292
  driver.configure("logstash_format true
@@ -334,6 +355,18 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
334
355
  assert_equal(index_cmds[1]['@timestamp'], ts)
335
356
  end
336
357
 
358
+ def test_uses_custom_time_key_exclude_timestamp
359
+ driver.configure("logstash_format true
360
+ time_key vtm
361
+ time_key_exclude_timestamp true\n")
362
+ stub_elastic_ping
363
+ stub_elastic
364
+ ts = DateTime.new(2001,2,3).to_s
365
+ driver.emit(sample_record.merge!('vtm' => ts))
366
+ driver.run
367
+ assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
368
+ end
369
+
337
370
  def test_doesnt_add_tag_key_by_default
338
371
  stub_elastic_ping
339
372
  stub_elastic
@@ -404,6 +437,52 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
404
437
  assert(!index_cmds[0]['index'].has_key?('_parent'))
405
438
  end
406
439
 
440
+ def test_adds_routing_key_when_configured
441
+ driver.configure("routing_key routing_id\n")
442
+ stub_elastic_ping
443
+ stub_elastic
444
+ driver.emit(sample_record)
445
+ driver.run
446
+ assert_equal(index_cmds[0]['index']['_routing'], 'routing')
447
+ end
448
+
449
+ def test_doesnt_add_routing_key_if_missing_when_configured
450
+ driver.configure("routing_key another_routing_id\n")
451
+ stub_elastic_ping
452
+ stub_elastic
453
+ driver.emit(sample_record)
454
+ driver.run
455
+ assert(!index_cmds[0]['index'].has_key?('_routing'))
456
+ end
457
+
458
+ def test_adds_routing_key_when_not_configured
459
+ stub_elastic_ping
460
+ stub_elastic
461
+ driver.emit(sample_record)
462
+ driver.run
463
+ assert(!index_cmds[0]['index'].has_key?('_routing'))
464
+ end
465
+
466
+ def test_remove_one_key
467
+ driver.configure("remove_keys key1\n")
468
+ stub_elastic_ping
469
+ stub_elastic
470
+ driver.emit(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
471
+ driver.run
472
+ assert(!index_cmds[1].has_key?('key1'))
473
+ assert(index_cmds[1].has_key?('key2'))
474
+ end
475
+
476
+ def test_remove_multi_keys
477
+ driver.configure("remove_keys key1, key2\n")
478
+ stub_elastic_ping
479
+ stub_elastic
480
+ driver.emit(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
481
+ driver.run
482
+ assert(!index_cmds[1].has_key?('key1'))
483
+ assert(!index_cmds[1].has_key?('key2'))
484
+ end
485
+
407
486
  def test_request_error
408
487
  stub_elastic_ping
409
488
  stub_elastic_unavailable
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-elasticsearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - diogo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-02-18 00:00:00.000000000 Z
12
+ date: 2016-05-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
@@ -124,6 +124,7 @@ files:
124
124
  - Gemfile
125
125
  - History.md
126
126
  - LICENSE.txt
127
+ - PULL_REQUEST_TEMPLATE.md
127
128
  - README.md
128
129
  - Rakefile
129
130
  - fluent-plugin-elasticsearch.gemspec