fluent-plugin-norikra 0.1.1 → 0.1.2
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 +4 -4
- data/README.md +4 -0
- data/fluent-plugin-norikra.gemspec +1 -1
- data/lib/fluent/plugin/norikra/config_section.rb +5 -1
- data/lib/fluent/plugin/norikra/output.rb +1 -1
- data/lib/fluent/plugin/norikra/target.rb +10 -2
- data/test/test_config_section.rb +37 -0
- data/test/test_target.rb +13 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17d22de3fa94371d074467e259195bcf675198da
|
4
|
+
data.tar.gz: cfe8d59434ca08f513000b392e95f39af82d3b4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
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|
|
@@ -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
|
data/test/test_config_section.rb
CHANGED
@@ -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
|
-
|
64
|
-
|
65
|
-
|
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.
|
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-
|
11
|
+
date: 2014-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: norikra-client
|