fluent-plugin-norikra 0.1.1 → 0.1.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: e29c9f16d25507902aaf3dd02a7b43e1596880ca
4
- data.tar.gz: bc441ac622bbeb6f9c9b40b1eefcd8fd5efc2277
3
+ metadata.gz: 17d22de3fa94371d074467e259195bcf675198da
4
+ data.tar.gz: cfe8d59434ca08f513000b392e95f39af82d3b4c
5
5
  SHA512:
6
- metadata.gz: 4b95d21010ab1989e74ccbd19407220af2855bdb1333324edbdf4082ed210e5aa6a0deec663391ea386c478480f093103f2083138fdc184645cdce6a4b72b81f
7
- data.tar.gz: c57fe2a8e659919719bf457b4b3eb7215b89d9eec56e77841cec3789ac46285dd392dd0149d397a3994c6b2a79b57c53f190609ed799e54a62504c2baa02e29d
6
+ metadata.gz: 2138b0f8de9901ec4c5d99d49a41e8e5aa3d631dada661767306b829543810d5be9f7c8517f4c55cc3c57b4cc9b344ea3fb4a9fe9b374065eef5f21c071bec6a
7
+ data.tar.gz: c4437d0720878f816954b31b2e1e523240ce941de4cad94fd0fdc59f869bdd7dc79011604679bfa39d799b755160eb457f28eeaae0d1d6c0a8865b216a8c36e2
data/README.md CHANGED
@@ -49,6 +49,7 @@ Sends events to remote Norikra server. Minimal configurations are:
49
49
  ```
50
50
 
51
51
  NorikraOutput plugin opens Norikra's target for newly incoming tags. You can specify fields to include/exclude, and specify types of each fields, for each targets (and all targets by `default`). Definitions in `<target TARGET_NAME>` overwrites `<default>` specifications.
52
+
52
53
  ```apache
53
54
  <match data.*>
54
55
  type norikra
@@ -82,6 +83,7 @@ NorikraOutput plugin opens Norikra's target for newly incoming tags. You can spe
82
83
  With default setting, all fields are defined as 'string', so you must use `field_xxxx` parameters for numerical processing in query (For more details, see Norikra and Esper's documents).
83
84
 
84
85
  If fluentd's events has so many variations of sets of fields, you can specify not to include fields automatically, with `auto_field` option:
86
+
85
87
  ```apache
86
88
  <match data.*>
87
89
  type norikra
@@ -98,6 +100,8 @@ If fluentd's events has so many variations of sets of fields, you can specify no
98
100
 
99
101
  Fields which are referred in queries are automatically registered on norikra server in spite of `auto_field false`.
100
102
 
103
+ Use `time_key FIELDNAME` to include time of Fluentd's event into data field of Norikra (by milliseconds with Norikra/Esper's rule). This is useful for queries with `.win:ext_timed_batch(FIELD, PERIOD)` views.
104
+
101
105
  ** NOTE: <default> and <target> sections in NorikraOutput ignores <query> sections. see NorikraFilterOutput **
102
106
 
103
107
  ## NorikraInput
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "fluent-plugin-norikra"
5
- spec.version = "0.1.1"
5
+ spec.version = "0.1.2"
6
6
  spec.authors = ["TAGOMORI Satoshi"]
7
7
  spec.email = ["tagomoris@gmail.com"]
8
8
  spec.description = %q{process events on fluentd with SQL like query, with built-in Norikra server if needed.}
@@ -1,6 +1,8 @@
1
1
  module Fluent::NorikraPlugin
2
2
  class ConfigSection
3
- attr_accessor :target, :target_matcher, :auto_field, :escape_fieldname, :filter_params, :field_definitions, :query_generators
3
+ attr_accessor :target, :target_matcher
4
+ attr_accessor :auto_field, :time_key, :escape_fieldname
5
+ attr_accessor :filter_params, :field_definitions, :query_generators
4
6
 
5
7
  def initialize(section, enable_auto_query=true)
6
8
  @target = nil
@@ -16,6 +18,7 @@ module Fluent::NorikraPlugin
16
18
  end
17
19
 
18
20
  @auto_field = Fluent::Config.bool_value(section['auto_field'])
21
+ @time_key = section['time_key']
19
22
  @escape_fieldname = Fluent::Config.bool_value(section['escape_fieldname'])
20
23
 
21
24
  @filter_params = {
@@ -49,6 +52,7 @@ module Fluent::NorikraPlugin
49
52
  end
50
53
  r = self.class.new(Fluent::Config::Element.new('target', (other.target ? other.target : self.target), {}, []))
51
54
  r.auto_field = (other.auto_field.nil? ? self.auto_field : other.auto_field)
55
+ r.time_key = other.time_key || self.time_key
52
56
 
53
57
  others_filter = {}
54
58
  other.filter_params.keys.each do |k|
@@ -183,7 +183,7 @@ module Fluent::NorikraPlugin
183
183
  t
184
184
  end
185
185
 
186
- event = tgt.filter(record)
186
+ event = tgt.filter(time, record)
187
187
 
188
188
  out << [tgt.escaped_name,event].to_msgpack
189
189
  end
@@ -1,6 +1,6 @@
1
1
  module Fluent::NorikraPlugin
2
2
  class Target
3
- attr_accessor :name, :auto_field, :fields, :queries
3
+ attr_accessor :name, :auto_field, :time_key, :fields, :queries
4
4
  attr_reader :escaped_name
5
5
 
6
6
  def self.escape(src)
@@ -24,15 +24,23 @@ module Fluent::NorikraPlugin
24
24
  @name = target
25
25
  @escaped_name = self.class.escape(@name)
26
26
  @auto_field = config.auto_field.nil? ? true : config.auto_field
27
+ @time_key = config.time_key
27
28
  @escape_fieldname = config.escape_fieldname
28
29
 
29
30
  @filter = RecordFilter.new(*([:include, :include_regexp, :exclude, :exclude_regexp].map{|s| config.filter_params[s]}))
30
31
  @fields = config.field_definitions
32
+ if @time_key
33
+ @fields[:integer].push @time_key
34
+ end
31
35
  @queries = config.query_generators.map{|g| g.generate(@name, @escaped_name)}
32
36
  end
33
37
 
34
- def filter(record)
38
+ def filter(time, record)
35
39
  r = @filter.filter(record)
40
+ if @time_key
41
+ # Fluentd time (sec) -> Norikra timestamp (milliseconds)
42
+ r = r.merge({ @time_key => time * 1000 })
43
+ end
36
44
  if @escape_fieldname
37
45
  escape_recursive(r)
38
46
  else
@@ -62,6 +62,38 @@ class ConfigSectionTest < Test::Unit::TestCase
62
62
  assert_equal 0, s1.query_generators.size
63
63
  end
64
64
 
65
+ def test_init_default_with_time_key
66
+ q1 = Fluent::Config::Element.new('query', nil, {
67
+ 'name' => 'q1_${target}',
68
+ 'expression' => 'SELECT * FROM ${target}.win:time_batch(10 min) WHERE q1',
69
+ 'tag' => 'q1.${target}'
70
+ }, [])
71
+ q2 = Fluent::Config::Element.new('query', nil, {
72
+ 'name' => 'q2_${target}',
73
+ 'expression' => 'SELECT * FROM ${target}.win:time_batch(50 min) WHERE q2.length() > 0',
74
+ 'tag' => 'q2.${target}'
75
+ }, [])
76
+ c1 = Fluent::Config::Element.new('default', nil, {
77
+ 'time_key' => 'timestamp',
78
+ 'include' => '*',
79
+ 'exclude' => 'flag',
80
+ 'exclude_regexp' => 'f_.*',
81
+ 'field_string' => 's1,s2,s3',
82
+ 'field_boolean' => 'bool1,bool2',
83
+ 'field_integer' => 'i1,i2,i3,i4,num1,num2',
84
+ 'field_float' => 'f1,f2,d',
85
+ }, [q1,q2])
86
+ s1 = @this.new(c1, false)
87
+
88
+ assert_nil s1.target
89
+ assert_equal({:include => '*', :include_regexp => nil, :exclude => 'flag', :exclude_regexp => 'f_.*'}, s1.filter_params)
90
+ assert_equal({
91
+ :string => %w(s1 s2 s3), :boolean => %w(bool1 bool2), :integer => %w(i1 i2 i3 i4 num1 num2),
92
+ :float => %w(f1 f2 d),
93
+ }, s1.field_definitions)
94
+ assert_equal 'timestamp', s1.time_key
95
+ end
96
+
65
97
  def test_init_target
66
98
  q3 = Fluent::Config::Element.new('query', nil, {
67
99
  'name' => 'q3_test2',
@@ -131,6 +163,7 @@ class ConfigSectionTest < Test::Unit::TestCase
131
163
  'tag' => 'q2.${target}'
132
164
  }, [])
133
165
  c1 = Fluent::Config::Element.new('default', nil, {
166
+ 'time_key' => 'ts',
134
167
  'include' => '*',
135
168
  'exclude' => 'flag',
136
169
  'exclude_regexp' => 'f_.*',
@@ -147,6 +180,7 @@ class ConfigSectionTest < Test::Unit::TestCase
147
180
  'tag' => 'q3.test'
148
181
  }, [])
149
182
  c2 = Fluent::Config::Element.new('target', 'test', {
183
+ 'time_key' => 'timestamp',
150
184
  'exclude_regexp' => '(f|g)_.*',
151
185
  'field_float' => 'd1,d2,d3,d4'
152
186
  }, [q3])
@@ -162,6 +196,7 @@ class ConfigSectionTest < Test::Unit::TestCase
162
196
  }, s.field_definitions)
163
197
  assert_equal 3, s.query_generators.size
164
198
  assert_equal (10 * 60 / 5), s.query_generators.map(&:fetch_interval).sort.first
199
+ assert_equal 'timestamp', s.time_key
165
200
  end
166
201
 
167
202
  def test_join_with_nil
@@ -207,6 +242,7 @@ class ConfigSectionTest < Test::Unit::TestCase
207
242
  'tag' => 'q2.${target}'
208
243
  }, [])
209
244
  c1 = Fluent::Config::Element.new('default', nil, {
245
+ 'time_key' => 'timestamp',
210
246
  'include' => '*',
211
247
  'exclude' => 'flag',
212
248
  'exclude_regexp' => 'f_.*',
@@ -230,5 +266,6 @@ class ConfigSectionTest < Test::Unit::TestCase
230
266
 
231
267
  s = s1 + s2
232
268
  assert_equal 0, s.query_generators.size
269
+ assert_equal 'timestamp', s.time_key
233
270
  end
234
271
  end
data/test/test_target.rb CHANGED
@@ -45,6 +45,7 @@ class TargetTest < Test::Unit::TestCase
45
45
  'tag' => 'q3.test'
46
46
  }, [])
47
47
  C2 = Fluent::Config::Element.new('target', 'test', {
48
+ 'time_key' => 'timestamp',
48
49
  'exclude_regexp' => '(f|g)_.*',
49
50
  'field_float' => 'd1,d2,d3,d4'
50
51
  }, [Q3])
@@ -55,14 +56,16 @@ class TargetTest < Test::Unit::TestCase
55
56
 
56
57
  assert_equal 'test', t.name
57
58
  assert_equal({
58
- :string => %w(s1 s2 s3), :boolean => %w(bool1 bool2), :integer => %w(i1 i2 i3 i4 num1 num2),
59
+ :string => %w(s1 s2 s3), :boolean => %w(bool1 bool2), :integer => %w(i1 i2 i3 i4 num1 num2 timestamp),
59
60
  :float => %w(f1 f2 d d1 d2 d3 d4)
60
61
  }, t.fields)
61
62
  assert_equal 3, t.queries.size
62
63
 
63
- r = t.filter({'x'=>1,'y'=>'y','z'=>'zett','flag'=>true,'f_x'=>'true','g_1'=>'g'})
64
- assert_equal 3, r.size
65
- assert_equal({'x'=>1,'y'=>'y','z'=>'zett'}, r)
64
+ now = Time.now.to_i
65
+
66
+ r = t.filter(now, {'x'=>1,'y'=>'y','z'=>'zett','flag'=>true,'f_x'=>'true','g_1'=>'g'})
67
+ assert_equal 4, r.size
68
+ assert_equal({'x'=>1,'y'=>'y','z'=>'zett','timestamp'=>(now*1000)}, r)
66
69
 
67
70
  # reserve_fields
68
71
  assert_equal({
@@ -70,7 +73,8 @@ class TargetTest < Test::Unit::TestCase
70
73
  'bool1' => 'boolean', 'bool2' => 'boolean',
71
74
  'i1' => 'integer', 'i2' => 'integer', 'i3' => 'integer', 'i4' => 'integer', 'num1' => 'integer', 'num2' => 'integer',
72
75
  'f1' => 'float', 'f2' => 'float',
73
- 'd' => 'float', 'd1' => 'float', 'd2' => 'float', 'd3' => 'float', 'd4' => 'float'
76
+ 'd' => 'float', 'd1' => 'float', 'd2' => 'float', 'd3' => 'float', 'd4' => 'float',
77
+ 'timestamp' => 'integer', # time_key
74
78
  }, t.reserve_fields)
75
79
  end
76
80
 
@@ -102,8 +106,10 @@ class TargetTest < Test::Unit::TestCase
102
106
  S4 = Fluent::NorikraPlugin::ConfigSection.new(C4)
103
107
 
104
108
  def test_escape_fieldname
109
+ now = Time.now.to_i
110
+
105
111
  t = @this.new('test.service', S3)
106
- r = t.filter({'a 1' => '1', 'b 2' => 2, 'c-1' => { 'd/1' => '1', 'd 2' => '2' }, 'f' => [1, 2, {'g+1' => 3}] })
112
+ r = t.filter(now, {'a 1' => '1', 'b 2' => 2, 'c-1' => { 'd/1' => '1', 'd 2' => '2' }, 'f' => [1, 2, {'g+1' => 3}] })
107
113
  assert_equal '1', r['a 1']
108
114
  assert_equal 2, r['b 2']
109
115
  assert_equal '1', r['c-1']['d/1']
@@ -118,7 +124,7 @@ class TargetTest < Test::Unit::TestCase
118
124
  assert_nil r['f'][2]['g_1']
119
125
 
120
126
  t = @this.new('test.service', S4)
121
- r = t.filter({'a 1' => '1', 'b 2' => 2, 'c-1' => { 'd/1' => '1', 'd 2' => '2' }, 'f' => [1, 2, {'g+1' => 3}] })
127
+ r = t.filter(now, {'a 1' => '1', 'b 2' => 2, 'c-1' => { 'd/1' => '1', 'd 2' => '2' }, 'f' => [1, 2, {'g+1' => 3}] })
122
128
  assert_nil r['a 1']
123
129
  assert_nil r['b 2']
124
130
  assert_nil r['c-1']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-norikra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - TAGOMORI Satoshi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-26 00:00:00.000000000 Z
11
+ date: 2014-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: norikra-client