fluent-plugin-elasticsearch 2.7.0 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +4 -0
- data/fluent-plugin-elasticsearch.gemspec +1 -1
- data/lib/fluent/plugin/out_elasticsearch.rb +34 -5
- data/lib/fluent/plugin/out_elasticsearch_dynamic.rb +0 -2
- data/test/plugin/test_out_elasticsearch.rb +47 -52
- data/test/plugin/test_out_elasticsearch_dynamic.rb +17 -23
- metadata +2 -3
- data/lib/fluent/plugin/generate_hash_id_support.rb +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bdf35ea1b2e3e85372e0f5af8febdc9920e38090053b7e818d714d32d9df6428
|
4
|
+
data.tar.gz: f43d98b89ee686f14bfe3b544f929cefc2b50d28d064cd9c40a3502aadf0774b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d4b5829f6bfcc13d8e25a60fca57422068a1449376690776dbe6623346ae058226563b215ad4926b97680b632515516309e6d50414d2d030e4d559359ae077a
|
7
|
+
data.tar.gz: 763d3a4838093c99d92a2b4f3382335ff95ddd4e20d0c4a2378a42b3cb830a4c6654501662920035f9299a28e492372d5671792f0098f9f9e4566035d24533af
|
data/History.md
CHANGED
@@ -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 = '2.
|
6
|
+
s.version = '2.8.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}
|
@@ -13,7 +13,6 @@ require 'fluent/plugin/output'
|
|
13
13
|
require_relative 'elasticsearch_constants'
|
14
14
|
require_relative 'elasticsearch_error_handler'
|
15
15
|
require_relative 'elasticsearch_index_template'
|
16
|
-
require_relative 'generate_hash_id_support'
|
17
16
|
|
18
17
|
module Fluent::Plugin
|
19
18
|
class ElasticsearchOutput < Output
|
@@ -24,6 +23,8 @@ module Fluent::Plugin
|
|
24
23
|
Fluent::Plugin.register_output('elasticsearch', self)
|
25
24
|
|
26
25
|
DEFAULT_BUFFER_TYPE = "memory"
|
26
|
+
DEFAULT_ELASTICSEARCH_VERSION = 5 # For compatibility.
|
27
|
+
DEFAULT_TYPE_NAME = "_doc".freeze
|
27
28
|
|
28
29
|
config_param :host, :string, :default => 'localhost'
|
29
30
|
config_param :port, :integer, :default => 9200
|
@@ -33,7 +34,10 @@ module Fluent::Plugin
|
|
33
34
|
config_param :scheme, :string, :default => 'http'
|
34
35
|
config_param :hosts, :string, :default => nil
|
35
36
|
config_param :target_index_key, :string, :default => nil
|
36
|
-
config_param :target_type_key, :string, :default => nil
|
37
|
+
config_param :target_type_key, :string, :default => nil,
|
38
|
+
:deprecated => <<EOC
|
39
|
+
Elasticsearch 7.x or above will ignore this config. Please use fixed type_name instead.
|
40
|
+
EOC
|
37
41
|
config_param :time_key_format, :string, :default => nil
|
38
42
|
config_param :time_precision, :integer, :default => 9
|
39
43
|
config_param :include_timestamp, :bool, :default => false
|
@@ -42,7 +46,7 @@ module Fluent::Plugin
|
|
42
46
|
config_param :logstash_prefix_separator, :string, :default => '-'
|
43
47
|
config_param :logstash_dateformat, :string, :default => "%Y.%m.%d"
|
44
48
|
config_param :utc_index, :bool, :default => true
|
45
|
-
config_param :type_name, :string, :default =>
|
49
|
+
config_param :type_name, :string, :default => DEFAULT_TYPE_NAME
|
46
50
|
config_param :index_name, :string, :default => "fluentd"
|
47
51
|
config_param :id_key, :string, :default => nil
|
48
52
|
config_param :write_operation, :string, :default => "index"
|
@@ -84,7 +88,6 @@ module Fluent::Plugin
|
|
84
88
|
end
|
85
89
|
|
86
90
|
include Fluent::ElasticsearchIndexTemplate
|
87
|
-
include Fluent::Plugin::GenerateHashIdSupport
|
88
91
|
include Fluent::Plugin::ElasticsearchConstants
|
89
92
|
|
90
93
|
def initialize
|
@@ -151,6 +154,17 @@ module Fluent::Plugin
|
|
151
154
|
log_level = conf['@log_level'] || conf['log_level']
|
152
155
|
log.warn "Consider to specify log_level with @log_level." unless log_level
|
153
156
|
end
|
157
|
+
|
158
|
+
@last_seen_major_version = detect_es_major_version rescue DEFAULT_ELASTICSEARCH_VERSION
|
159
|
+
if @last_seen_major_version >= 7 && @type_name != DEFAULT_TYPE_NAME
|
160
|
+
log.warn "Detected ES 7.x or above: `_doc` will be used as the document `_type`."
|
161
|
+
@type_name = '_doc'.freeze
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def detect_es_major_version
|
166
|
+
@_es_info ||= client.info
|
167
|
+
@_es_info["version"]["number"].to_i
|
154
168
|
end
|
155
169
|
|
156
170
|
def convert_compat_id_key(key)
|
@@ -356,6 +370,7 @@ module Fluent::Plugin
|
|
356
370
|
tag = chunk.metadata.tag
|
357
371
|
logstash_prefix, index_name, type_name = expand_placeholders(chunk.metadata)
|
358
372
|
@error = Fluent::Plugin::ElasticsearchErrorHandler.new(self)
|
373
|
+
@last_seen_major_version = detect_es_major_version rescue DEFAULT_ELASTICSEARCH_VERSION
|
359
374
|
|
360
375
|
chunk.msgpack_each do |time, record|
|
361
376
|
@error.records += 1
|
@@ -404,8 +419,20 @@ module Fluent::Plugin
|
|
404
419
|
target_type_parent, target_type_child_key = @target_type_key ? get_parent_of(record, @target_type_key) : nil
|
405
420
|
if target_type_parent && target_type_parent[target_type_child_key]
|
406
421
|
target_type = target_type_parent.delete(target_type_child_key)
|
422
|
+
if @last_seen_major_version == 6
|
423
|
+
log.warn "Detected ES 6.x: `@type_name` will be used as the document `_type`."
|
424
|
+
target_type = type_name
|
425
|
+
elsif @last_seen_major_version >= 7
|
426
|
+
log.warn "Detected ES 7.x or above: `_doc` will be used as the document `_type`."
|
427
|
+
target_type = '_doc'.freeze
|
428
|
+
end
|
407
429
|
else
|
408
|
-
target_type
|
430
|
+
if @last_seen_major_version >= 7 && target_type != DEFAULT_TYPE_NAME
|
431
|
+
log.warn "Detected ES 7.x or above: `_doc` will be used as the document `_type`."
|
432
|
+
target_type = '_doc'.freeze
|
433
|
+
else
|
434
|
+
target_type = type_name
|
435
|
+
end
|
409
436
|
end
|
410
437
|
|
411
438
|
meta.clear
|
@@ -453,6 +480,7 @@ module Fluent::Plugin
|
|
453
480
|
if retries < 2
|
454
481
|
retries += 1
|
455
482
|
@_es = nil
|
483
|
+
@_es_info = nil
|
456
484
|
log.warn "Could not push logs to Elasticsearch, resetting connection and trying again. #{e.message}"
|
457
485
|
sleep 2**retries
|
458
486
|
retry
|
@@ -460,6 +488,7 @@ module Fluent::Plugin
|
|
460
488
|
raise ConnectionFailure, "Could not push logs to Elasticsearch after #{retries} retries. #{e.message}"
|
461
489
|
rescue Exception
|
462
490
|
@_es = nil if @reconnect_on_error
|
491
|
+
@_es_info = nil if @reconnect_on_error
|
463
492
|
raise
|
464
493
|
end
|
465
494
|
end
|
@@ -13,8 +13,6 @@ module Fluent::Plugin
|
|
13
13
|
DYNAMIC_PARAM_NAMES = %W[hosts host port include_timestamp logstash_format logstash_prefix logstash_dateformat time_key utc_index index_name tag_key type_name id_key parent_key routing_key write_operation]
|
14
14
|
DYNAMIC_PARAM_SYMBOLS = DYNAMIC_PARAM_NAMES.map { |n| "@#{n}".to_sym }
|
15
15
|
|
16
|
-
include Fluent::Plugin::GenerateHashIdSupport
|
17
|
-
|
18
16
|
attr_reader :dynamic_config
|
19
17
|
|
20
18
|
def configure(conf)
|
@@ -19,7 +19,14 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
19
19
|
log.out.logs.slice!(0, log.out.logs.length)
|
20
20
|
end
|
21
21
|
|
22
|
-
def driver(conf='')
|
22
|
+
def driver(conf='', es_version=5)
|
23
|
+
# For request stub to detect compatibility.
|
24
|
+
@es_version ||= es_version
|
25
|
+
Fluent::Plugin::ElasticsearchOutput.module_eval(<<-CODE)
|
26
|
+
def detect_es_major_version
|
27
|
+
#{@es_version}
|
28
|
+
end
|
29
|
+
CODE
|
23
30
|
@driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutput) {
|
24
31
|
# v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
|
25
32
|
if !defined?(Fluent::Plugin::Output)
|
@@ -232,6 +239,14 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
232
239
|
}
|
233
240
|
end
|
234
241
|
|
242
|
+
test 'Detected Elasticsearch 7' do
|
243
|
+
config = %{
|
244
|
+
type_name changed
|
245
|
+
}
|
246
|
+
instance = driver(config, 7).instance
|
247
|
+
assert_equal '_doc', instance.type_name
|
248
|
+
end
|
249
|
+
|
235
250
|
test 'lack of tag in chunk_keys' do
|
236
251
|
assert_raise_message(/'tag' in chunk_keys is required./) do
|
237
252
|
driver(Fluent::Config::Element.new(
|
@@ -252,21 +267,6 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
252
267
|
end
|
253
268
|
end
|
254
269
|
|
255
|
-
test 'with invaild generate id config' do
|
256
|
-
assert_raise_message(/Use bundled filter-elasticsearch-genid instead./) do
|
257
|
-
driver.configure(Fluent::Config::Element.new(
|
258
|
-
'ROOT', '', {
|
259
|
-
'@type' => 'elasticsearch',
|
260
|
-
'id_key' =>'id_mismatch',
|
261
|
-
}, [
|
262
|
-
Fluent::Config::Element.new('hash', '', {
|
263
|
-
'hash_id_key' => '_hash',
|
264
|
-
}, [])
|
265
|
-
]
|
266
|
-
))
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
270
|
def test_template_already_present
|
271
271
|
config = %{
|
272
272
|
host logs.google.com
|
@@ -665,7 +665,7 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
665
665
|
driver.run(default_tag: 'test') do
|
666
666
|
driver.feed(sample_record)
|
667
667
|
end
|
668
|
-
assert_equal('
|
668
|
+
assert_equal('_doc', index_cmds.first['index']['_type'])
|
669
669
|
end
|
670
670
|
|
671
671
|
def test_writes_to_speficied_index
|
@@ -678,27 +678,6 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
678
678
|
assert_equal('myindex', index_cmds.first['index']['_index'])
|
679
679
|
end
|
680
680
|
|
681
|
-
class AdditionalHashIdMechanismTest < self
|
682
|
-
data("default" => {"hash_id_key" => '_id'},
|
683
|
-
"custom hash_id_key" => {"hash_id_key" => '_hash_id'},
|
684
|
-
)
|
685
|
-
def test_writes_with_genrate_hash(data)
|
686
|
-
assert_raise_message(/Use bundled filter-elasticsearch-genid instead./) do
|
687
|
-
driver.configure(Fluent::Config::Element.new(
|
688
|
-
'ROOT', '', {
|
689
|
-
'@type' => 'elasticsearch',
|
690
|
-
'id_key' => data["hash_id_key"],
|
691
|
-
}, [
|
692
|
-
Fluent::Config::Element.new('hash', '', {
|
693
|
-
'keys' => ['request_id'],
|
694
|
-
'hash_id_key' => data["hash_id_key"],
|
695
|
-
}, [])
|
696
|
-
]
|
697
|
-
))
|
698
|
-
end
|
699
|
-
end
|
700
|
-
end
|
701
|
-
|
702
681
|
class IndexNamePlaceholdersTest < self
|
703
682
|
def test_writes_to_speficied_index_with_tag_placeholder
|
704
683
|
driver.configure("index_name myindex.${tag}\n")
|
@@ -836,35 +815,46 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
836
815
|
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
837
816
|
end
|
838
817
|
|
839
|
-
|
840
|
-
|
818
|
+
data("border" => {"es_version" => 6, "_type" => "mytype"},
|
819
|
+
"fixed_behavior"=> {"es_version" => 7, "_type" => "_doc"},
|
820
|
+
)
|
821
|
+
def test_writes_to_speficied_type(data)
|
822
|
+
driver('', data["es_version"]).configure("type_name mytype\n")
|
841
823
|
stub_elastic_ping
|
842
824
|
stub_elastic
|
843
825
|
driver.run(default_tag: 'test') do
|
844
826
|
driver.feed(sample_record)
|
845
827
|
end
|
846
|
-
assert_equal('
|
828
|
+
assert_equal(data['_type'], index_cmds.first['index']['_type'])
|
847
829
|
end
|
848
830
|
|
849
|
-
|
850
|
-
|
831
|
+
data("border" => {"es_version" => 6, "_type" => "mytype.test"},
|
832
|
+
"fixed_behavior"=> {"es_version" => 7, "_type" => "_doc"},
|
833
|
+
)
|
834
|
+
def test_writes_to_speficied_type_with_placeholders(data)
|
835
|
+
driver('', data["es_version"]).configure("type_name mytype.${tag}\n")
|
851
836
|
stub_elastic_ping
|
852
837
|
stub_elastic
|
853
838
|
driver.run(default_tag: 'test') do
|
854
839
|
driver.feed(sample_record)
|
855
840
|
end
|
856
|
-
assert_equal('
|
841
|
+
assert_equal(data['_type'], index_cmds.first['index']['_type'])
|
857
842
|
end
|
858
843
|
|
859
|
-
|
860
|
-
|
844
|
+
data("old" => {"es_version" => 2, "_type" => "local-override"},
|
845
|
+
"old_behavior" => {"es_version" => 5, "_type" => "local-override"},
|
846
|
+
"border" => {"es_version" => 6, "_type" => "_doc"},
|
847
|
+
"fixed_behavior"=> {"es_version" => 7, "_type" => "_doc"},
|
848
|
+
)
|
849
|
+
def test_writes_to_target_type_key(data)
|
850
|
+
driver('', data["es_version"]).configure("target_type_key @target_type\n")
|
861
851
|
stub_elastic_ping
|
862
852
|
stub_elastic
|
863
853
|
record = sample_record.clone
|
864
854
|
driver.run(default_tag: 'test') do
|
865
855
|
driver.feed(sample_record.merge('@target_type' => 'local-override'))
|
866
856
|
end
|
867
|
-
assert_equal(
|
857
|
+
assert_equal(data["_type"], index_cmds.first['index']['_type'])
|
868
858
|
assert_nil(index_cmds[1]['@target_type'])
|
869
859
|
end
|
870
860
|
|
@@ -875,7 +865,7 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
875
865
|
driver.run(default_tag: 'test') do
|
876
866
|
driver.feed(sample_record)
|
877
867
|
end
|
878
|
-
assert_equal('
|
868
|
+
assert_equal('_doc', index_cmds.first['index']['_type'])
|
879
869
|
end
|
880
870
|
|
881
871
|
def test_writes_to_target_type_key_fallack_to_type_name
|
@@ -889,8 +879,13 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
889
879
|
assert_equal('mytype', index_cmds.first['index']['_type'])
|
890
880
|
end
|
891
881
|
|
892
|
-
|
893
|
-
|
882
|
+
data("old" => {"es_version" => 2, "_type" => "local-override"},
|
883
|
+
"old_behavior" => {"es_version" => 5, "_type" => "local-override"},
|
884
|
+
"border" => {"es_version" => 6, "_type" => "_doc"},
|
885
|
+
"fixed_behavior"=> {"es_version" => 7, "_type" => "_doc"},
|
886
|
+
)
|
887
|
+
def test_writes_to_target_type_key_nested(data)
|
888
|
+
driver('', data["es_version"]).configure("target_type_key kubernetes.labels.log_type\n")
|
894
889
|
stub_elastic_ping
|
895
890
|
stub_elastic
|
896
891
|
driver.run(default_tag: 'test') do
|
@@ -900,7 +895,7 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
900
895
|
}
|
901
896
|
}))
|
902
897
|
end
|
903
|
-
assert_equal(
|
898
|
+
assert_equal(data["_type"], index_cmds.first['index']['_type'])
|
904
899
|
assert_nil(index_cmds[1]['kubernetes']['labels']['log_type'])
|
905
900
|
end
|
906
901
|
|
@@ -915,7 +910,7 @@ class ElasticsearchOutput < Test::Unit::TestCase
|
|
915
910
|
}
|
916
911
|
}))
|
917
912
|
end
|
918
|
-
assert_equal('
|
913
|
+
assert_equal('_doc', index_cmds.first['index']['_type'])
|
919
914
|
end
|
920
915
|
|
921
916
|
def test_writes_to_speficied_host
|
@@ -16,7 +16,14 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
|
|
16
16
|
@driver = nil
|
17
17
|
end
|
18
18
|
|
19
|
-
def driver(conf='')
|
19
|
+
def driver(conf='', es_version=5)
|
20
|
+
# For request stub to detect compatibility.
|
21
|
+
@es_version ||= es_version
|
22
|
+
Fluent::Plugin::ElasticsearchOutputDynamic.module_eval(<<-CODE)
|
23
|
+
def detect_es_major_version
|
24
|
+
#{@es_version}
|
25
|
+
end
|
26
|
+
CODE
|
20
27
|
@driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutputDynamic) {
|
21
28
|
# v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
|
22
29
|
if !defined?(Fluent::Plugin::Output)
|
@@ -105,6 +112,14 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
|
|
105
112
|
}
|
106
113
|
end
|
107
114
|
|
115
|
+
test 'Detected Elasticsearch 7' do
|
116
|
+
config = %{
|
117
|
+
type_name changed
|
118
|
+
}
|
119
|
+
instance = driver(config, 7).instance
|
120
|
+
assert_equal '_doc', instance.type_name
|
121
|
+
end
|
122
|
+
|
108
123
|
def test_defaults
|
109
124
|
config = %{
|
110
125
|
host logs.google.com
|
@@ -260,7 +275,7 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
|
|
260
275
|
driver.run(default_tag: 'test') do
|
261
276
|
driver.feed(sample_record)
|
262
277
|
end
|
263
|
-
assert_equal('
|
278
|
+
assert_equal('_doc', index_cmds.first['index']['_type'])
|
264
279
|
end
|
265
280
|
|
266
281
|
def test_writes_to_specified_index
|
@@ -343,27 +358,6 @@ class ElasticsearchOutputDynamic < Test::Unit::TestCase
|
|
343
358
|
assert_equal(2000, total)
|
344
359
|
end
|
345
360
|
|
346
|
-
class AdditionalHashIdMechanismTest < self
|
347
|
-
data("default" => {"hash_id_key" => '_id'},
|
348
|
-
"custom hash_id_key" => {"hash_id_key" => '_hash_id'},
|
349
|
-
)
|
350
|
-
def test_writes_with_genrate_hash(data)
|
351
|
-
assert_raise_message(/Use bundled filter-elasticsearch-genid instead./) do
|
352
|
-
driver.configure(Fluent::Config::Element.new(
|
353
|
-
'ROOT', '', {
|
354
|
-
'@type' => 'elasticsearch',
|
355
|
-
'id_key' => data["hash_id_key"],
|
356
|
-
}, [
|
357
|
-
Fluent::Config::Element.new('hash', '', {
|
358
|
-
'keys' => ['request_id'],
|
359
|
-
'hash_id_key' => data["hash_id_key"],
|
360
|
-
}, [])
|
361
|
-
]
|
362
|
-
))
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
361
|
def test_makes_bulk_request
|
368
362
|
stub_elastic_ping
|
369
363
|
stub_elastic
|
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: 2.
|
4
|
+
version: 2.8.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: 2018-
|
12
|
+
date: 2018-03-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fluentd
|
@@ -148,7 +148,6 @@ files:
|
|
148
148
|
- lib/fluent/plugin/elasticsearch_error_handler.rb
|
149
149
|
- lib/fluent/plugin/elasticsearch_index_template.rb
|
150
150
|
- lib/fluent/plugin/filter_elasticsearch_genid.rb
|
151
|
-
- lib/fluent/plugin/generate_hash_id_support.rb
|
152
151
|
- lib/fluent/plugin/out_elasticsearch.rb
|
153
152
|
- lib/fluent/plugin/out_elasticsearch_dynamic.rb
|
154
153
|
- test/helper.rb
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
require 'base64'
|
3
|
-
|
4
|
-
module Fluent
|
5
|
-
module Plugin
|
6
|
-
module GenerateHashIdSupport
|
7
|
-
def self.included(klass)
|
8
|
-
klass.instance_eval {
|
9
|
-
config_section :hash, param_name: :hash_config, required: false, multi: false do
|
10
|
-
config_param :hash_id_key, :string, default: '_hash',
|
11
|
-
obsoleted: "Use bundled filter-elasticsearch-genid instead."
|
12
|
-
end
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
def generate_hash_id_key(record)
|
17
|
-
s = ""
|
18
|
-
s += Base64.strict_encode64(SecureRandom.uuid)
|
19
|
-
record[@hash_config.hash_id_key] = s
|
20
|
-
record
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|