fluent-plugin-hash-forward 0.0.1 → 0.0.2

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: 34a4f0ca25be43b69b64a1338daabc8372a2008b
4
- data.tar.gz: be4337ab0434d3fe45be14de13dc381580d8d49d
3
+ metadata.gz: 38bfa4c2b8ecb078ef39859c02f535d445f6abc5
4
+ data.tar.gz: 14a48e69abed66f8ed07ae185286d82d91c3aa21
5
5
  SHA512:
6
- metadata.gz: e037f72f0fa5fbc9980e11a7a9ec94a336488b05dc45eeb69589182fa404a5c02921ae210277b0288e20eaf60002102a7e18d1051834830851a7b2af729ac0a4
7
- data.tar.gz: 7a20b3102b6a98e193608b2f21aa45b0ebd5b5dfef0222a39ef8ad50f6a01ad4336a5ad4d63539ae96d6b601f47398969ea540dc471a69026ee6029131ac13e1
6
+ metadata.gz: 993925c2ddb9e8909c7f1bd508f14b6d0ab22b63d4c267b01808d8bd9c3dd4789b871cc7388e20db5d132469fe19c8d00749a37b116e6d2841572c024c0ef441
7
+ data.tar.gz: e738d73bdc48f65f64e23287ba1fa8c941a6a5d777686aff5f6c7c82e144919494e9ec925f130cbd4f050420ac744c846fe9b86ebff5bd913347f3bdfb05a2c5
data/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # 0.0.2 (2013/10/31)
2
+
3
+ Changes
4
+
5
+ * Change `hash_key` option to `hash_key_slice` option. Stopped to use a placeholder.
6
+
7
+ # 0.0.1 (2013/10/31)
8
+
9
+ * Initial release
10
+
data/README.md CHANGED
@@ -35,21 +35,32 @@ Basically same with out\_forward plugin. See [http://docs.fluentd.org/articles/o
35
35
 
36
36
  Following parameters are additionally available:
37
37
 
38
- * hash\_key
38
+ * hash\_key\_slice *min*..*max*
39
39
 
40
- Specify a placeholder string to be used as a key for hashing. See Placeholders section for more details. Default uses `${tag}`as a hash key.
40
+ Use sliced `tag` as a hash key to determine a forwarding node. Default: use entire `tag`.
41
41
 
42
- ### Placeholders
42
+ For example, assume tags of input messages are like
43
43
 
44
- You can use following placeholders:
44
+ foo.bar.host1
45
+ foo.bar.host2
45
46
 
46
- * ${tag} input tag
47
- * ${tags} input tag splitted by '.'
47
+ but, you want to forward these messages to the same node, configure like
48
48
 
49
- It is also possible to write a ruby code in placeholders, so you may write some codes as
49
+ hash_key_slice 0..-2
50
50
 
51
- * ${tags[0]}
52
- * ${tags.last}
51
+ then, hash\_key becomes as `foo.bar` which results in forwarding these messages to the same node.
52
+
53
+ FYI: This option behaves like `tag.split('.').slice(min..max)`.
54
+
55
+ ## ToDo
56
+
57
+ * Consistent hashing
58
+
59
+ * Consistent hashing is useful on adding or removing nodes dynamically, but currently `out_hash_forward` does not support such a dynamical feature, so consistent hashing is just useless now. To effectively support consistent hashing, this plugin must support ways to add or remove nodes dynamically by preparing http api or reading nodes information from redis or memcached, etc.
60
+
61
+ ## ChangeLog
62
+
63
+ See [CHANGELOG.md](CHANGELOG.md) for details.
53
64
 
54
65
  ## Copyright
55
66
 
@@ -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-hash-forward"
6
- s.version = "0.0.1"
6
+ s.version = "0.0.2"
7
7
  s.authors = ["Ryosuke IWANAGA", "Naotoshi SEO"]
8
8
  s.email = ["riywo.jp@gmail.com", "sonots@gmail.com"]
9
9
  s.homepage = "https://github.com/riywo/fluent-plugin-hash-forward"
@@ -3,15 +3,28 @@ require 'fluent/plugin/out_forward'
3
3
  class Fluent::HashForwardOutput < Fluent::ForwardOutput
4
4
  Fluent::Plugin.register_output('hash_forward', self)
5
5
 
6
- config_param :hash_key, :string, :default => nil
6
+ config_param :hash_key_slice, :string, :default => nil
7
7
 
8
8
  def configure(conf)
9
9
  super
10
10
  @standby_nodes, @regular_nodes = @nodes.partition {|n| n.standby? }
11
+
12
+ if @hash_key_slice
13
+ lindex, rindex = @hash_key_slice.split('..', 2)
14
+ if lindex.nil? or rindex.nil? or lindex !~ /^-?\d+$/ or rindex !~ /^-?\d+$/
15
+ raise Fluent::ConfigError, "out_hash_forard: hash_key_slice must be formatted like [num]..[num]"
16
+ else
17
+ @hash_key_slice_lindex = lindex.to_i
18
+ @hash_key_slice_rindex = rindex.to_i
19
+ end
20
+ end
11
21
  end
12
22
 
23
+ # for test
13
24
  attr_reader :regular_nodes
14
25
  attr_reader :standby_nodes
26
+ attr_accessor :hash_key_slice_lindex
27
+ attr_accessor :hash_key_slice_rindex
15
28
 
16
29
  # Override
17
30
  def write_objects(tag, chunk)
@@ -47,7 +60,7 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
47
60
 
48
61
  # Get nodes (a regular_node and a standby_node if available) using hash algorithm
49
62
  def nodes(tag)
50
- hash_key = @hash_key ? expand_placeholder(@hash_key, tag) : tag
63
+ hash_key = @hash_key_slice ? perform_hash_key_slice(tag) : tag
51
64
  regular_index = get_index(hash_key, regular_nodes.size)
52
65
  standby_index = standby_nodes.size > 0 ? get_index(hash_key, standby_nodes.size) : 0
53
66
  [regular_nodes[regular_index], standby_nodes[standby_index]].compact
@@ -59,21 +72,9 @@ class Fluent::HashForwardOutput < Fluent::ForwardOutput
59
72
  MurmurHash3::V32.str_hash(key) % size
60
73
  end
61
74
 
62
- # Replace ${tag} and ${tags} placeholders in a string
63
- #
64
- # @param [String] str the string to be expanded
65
- # @param [String] tag tag of a message
66
- def expand_placeholder(str, tag)
67
- struct = UndefOpenStruct.new
68
- struct.tag = tag
69
- struct.tags = tag.split('.')
70
- str = str.gsub(/\$\{([^}]+)\}/, '#{\1}') # ${..} => #{..}
71
- eval "\"#{str}\"", struct.instance_eval { binding }
72
- end
73
-
74
- class UndefOpenStruct < OpenStruct
75
- (Object.instance_methods).each do |m|
76
- undef_method m unless m.to_s =~ /^__|respond_to_missing\?|object_id|public_methods|instance_eval|method_missing|define_singleton_method|respond_to\?|new_ostruct_member/
77
- end
75
+ def perform_hash_key_slice(tag)
76
+ tags = tag.split('.')
77
+ sliced = tags[@hash_key_slice_lindex..@hash_key_slice_rindex]
78
+ return sliced.nil? ? "" : sliced.join('.')
78
79
  end
79
80
  end
@@ -29,6 +29,73 @@ describe Fluent::HashForwardOutput do
29
29
  context 'default behavior' do
30
30
  it { lambda{ driver }.should_not raise_error }
31
31
  end
32
+
33
+ describe 'bad hash_key_slice' do
34
+ context 'string' do
35
+ let(:config) { CONFIG + %[hash_key_slice a..b] }
36
+ it { lambda{ driver }.should raise_error(Fluent::ConfigError) }
37
+ end
38
+
39
+ context 'no rindex' do
40
+ let(:config) { CONFIG + %[hash_key_slice 0..] }
41
+ it { lambda{ driver }.should raise_error(Fluent::ConfigError) }
42
+ end
43
+
44
+ context 'no lindex' do
45
+ let(:config) { CONFIG + %[hash_key_slice ..1] }
46
+ it { lambda{ driver }.should raise_error(Fluent::ConfigError) }
47
+ end
48
+
49
+ context 'bad format' do
50
+ let(:config) { CONFIG + %[hash_key_slice 0,1] }
51
+ it { lambda{ driver }.should raise_error(Fluent::ConfigError) }
52
+ end
53
+ end
54
+ end
55
+
56
+ describe 'test perform_hash_key_slice' do
57
+ # actually the same behavior with ruby Array, so just conforming ruby Array#slice
58
+ let(:tag) { 'tag0.tag1' }
59
+ context 'larger than tags size' do
60
+ let(:config) { CONFIG + %[hash_key_slice 1..10] }
61
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq('tag1') }
62
+ end
63
+
64
+ context 'rindex is smaller than lindex' do
65
+ let(:config) { CONFIG + %[hash_key_slice 1..0] }
66
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq('') }
67
+ end
68
+
69
+ context 'rindex is -1' do
70
+ let(:config) { CONFIG + %[hash_key_slice 0..-1] }
71
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq(tag) }
72
+ end
73
+
74
+ context 'rindex is -2' do
75
+ let(:config) { CONFIG + %[hash_key_slice 0..-2] }
76
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq('tag0') }
77
+ end
78
+
79
+ context 'rindex is large negative integer' do
80
+ let(:config) { CONFIG + %[hash_key_slice 0..-10] }
81
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq('') }
82
+ end
83
+
84
+ context 'lindex is -1' do
85
+ let(:config) { CONFIG + %[hash_key_slice -1..10] }
86
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq('tag1') }
87
+ end
88
+
89
+ context 'lindex is -2' do
90
+ let(:config) { CONFIG + %[hash_key_slice -2..10] }
91
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq(tag) }
92
+ end
93
+
94
+ context 'lindex is large negatize integer' do
95
+ # this behavior looks wierd for me
96
+ let(:config) { CONFIG + %[hash_key_slice -3..10] }
97
+ it { expect(driver.instance.perform_hash_key_slice(tag)).to eq('') }
98
+ end
32
99
  end
33
100
 
34
101
  describe 'test hashing' do
@@ -57,10 +124,10 @@ describe Fluent::HashForwardOutput do
57
124
  end
58
125
  end
59
126
 
60
- context 'test hash_key' do
127
+ context 'test hash_key_slice' do
61
128
  let(:tag1) { 'test.tag1' }
62
129
  let(:tag2) { 'test.tag2' }
63
- let(:config) { CONFIG + %[hash_key ${tags[0..-2]}] }
130
+ let(:config) { CONFIG + %[hash_key_slice 0..-2] }
64
131
  before do
65
132
  @node1 = driver.instance.nodes(tag1).first
66
133
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-hash-forward
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryosuke IWANAGA
@@ -105,6 +105,7 @@ extensions: []
105
105
  extra_rdoc_files: []
106
106
  files:
107
107
  - .gitignore
108
+ - CHANGELOG.md
108
109
  - Gemfile
109
110
  - README.md
110
111
  - Rakefile