fluent-plugin-flowcounter 0.1.0
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.
- data/.document +5 -0
- data/.gitignore +51 -0
- data/AUTHORS +1 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +13 -0
- data/README.rdoc +70 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/lib/fluent/plugin/out_flowcounter.rb +128 -0
- data/test/helper.rb +19 -0
- data/test/plugin/test_out_flowcounter.rb +199 -0
- metadata +161 -0
data/.document
ADDED
data/.gitignore
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# rcov generated
|
|
2
|
+
coverage
|
|
3
|
+
|
|
4
|
+
# rdoc generated
|
|
5
|
+
rdoc
|
|
6
|
+
|
|
7
|
+
# yard generated
|
|
8
|
+
doc
|
|
9
|
+
.yardoc
|
|
10
|
+
|
|
11
|
+
# bundler
|
|
12
|
+
.bundle
|
|
13
|
+
|
|
14
|
+
# jeweler generated
|
|
15
|
+
pkg
|
|
16
|
+
|
|
17
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
|
18
|
+
#
|
|
19
|
+
# * Create a file at ~/.gitignore
|
|
20
|
+
# * Include files you want ignored
|
|
21
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
|
22
|
+
#
|
|
23
|
+
# After doing this, these files will be ignored in all your git projects,
|
|
24
|
+
# saving you from having to 'pollute' every project you touch with them
|
|
25
|
+
#
|
|
26
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
|
27
|
+
#
|
|
28
|
+
# For MacOS:
|
|
29
|
+
#
|
|
30
|
+
.DS_Store
|
|
31
|
+
|
|
32
|
+
# For TextMate
|
|
33
|
+
*.tmproj
|
|
34
|
+
tmtags
|
|
35
|
+
|
|
36
|
+
# For emacs:
|
|
37
|
+
*~
|
|
38
|
+
\#*
|
|
39
|
+
.\#*
|
|
40
|
+
|
|
41
|
+
# For vim:
|
|
42
|
+
*.swp
|
|
43
|
+
|
|
44
|
+
# For redcar:
|
|
45
|
+
#.redcar
|
|
46
|
+
|
|
47
|
+
# For rubinius:
|
|
48
|
+
#*.rbc
|
|
49
|
+
|
|
50
|
+
Gemfile.lock
|
|
51
|
+
vendor
|
data/AUTHORS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
TAGOMORI Satoshi <tagomoris _at_ gmail.com>
|
data/Gemfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
source "http://rubygems.org"
|
|
2
|
+
# Add dependencies required to use your gem here.
|
|
3
|
+
# Example:
|
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
|
5
|
+
|
|
6
|
+
# Add dependencies to develop your gem here.
|
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
|
8
|
+
group :development do
|
|
9
|
+
gem "shoulda", ">= 0"
|
|
10
|
+
gem "bundler", "~> 1.0.0"
|
|
11
|
+
gem "jeweler", "~> 1.6.4"
|
|
12
|
+
gem "simplecov", ">= 0"
|
|
13
|
+
gem "rdoc"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
gem "fluentd"
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright (c) 2012- TAGOMORI Satoshi
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
= fluent-plugin-flowcounter
|
|
2
|
+
|
|
3
|
+
== Component
|
|
4
|
+
|
|
5
|
+
=== FlowCounterOutput
|
|
6
|
+
|
|
7
|
+
Count metricses below about matches.
|
|
8
|
+
|
|
9
|
+
- Messages per min/hour/day
|
|
10
|
+
- Bytes per min/hour/day
|
|
11
|
+
- Messages per second (average every min/hour/day)
|
|
12
|
+
- Bytes per second (average every min/hour/day)
|
|
13
|
+
|
|
14
|
+
FlowCounterOutput emits messages contains results data, so you can output these message (with 'flowcount' tag by default) to any outputs you want.
|
|
15
|
+
|
|
16
|
+
output ex1 (aggragates all inputs): {"count":300, "bytes":3660, "count_rate":5, "bytes_rate":61}
|
|
17
|
+
output ex2 (aggragates per tag): {"test_count":300, "test_bytes":3660, "test_count_rate":5, "test_bytes_rate":61, "service1_count":180, "service1_bytes":7260, "service1_count_rate":3, "service1_bytes_rate":121}
|
|
18
|
+
|
|
19
|
+
'input_tag_remove_prefix' option available if you want to remove tag prefix from output field names.
|
|
20
|
+
|
|
21
|
+
== Configuration
|
|
22
|
+
|
|
23
|
+
=== FlowCounterOutput
|
|
24
|
+
|
|
25
|
+
Counts from fields 'field1' and 'field2', per minute(default), aggregates per tags(default), output with tag 'flowcount'(default).
|
|
26
|
+
|
|
27
|
+
<match **>
|
|
28
|
+
copy
|
|
29
|
+
<store>
|
|
30
|
+
# original output configurations...
|
|
31
|
+
</store>
|
|
32
|
+
<store>
|
|
33
|
+
type flowcounter
|
|
34
|
+
count_keys field1,field2
|
|
35
|
+
</store>
|
|
36
|
+
</match>
|
|
37
|
+
|
|
38
|
+
<match flowcount>
|
|
39
|
+
# output configurations where to send count results
|
|
40
|
+
</match>
|
|
41
|
+
|
|
42
|
+
Counts from field 'message', per hour, aggregates all tags, output with tag 'fluentd.traffic'.
|
|
43
|
+
|
|
44
|
+
<match **>
|
|
45
|
+
copy
|
|
46
|
+
<store>
|
|
47
|
+
# original output configurations...
|
|
48
|
+
</store>
|
|
49
|
+
<store>
|
|
50
|
+
type flowcounter
|
|
51
|
+
count_keys message
|
|
52
|
+
unit hour
|
|
53
|
+
aggregate all
|
|
54
|
+
tag fluentd.traffic
|
|
55
|
+
</store>
|
|
56
|
+
</match>
|
|
57
|
+
|
|
58
|
+
<match flowcount>
|
|
59
|
+
# output configurations where to send count results
|
|
60
|
+
</match>
|
|
61
|
+
|
|
62
|
+
== TODO
|
|
63
|
+
|
|
64
|
+
- consider what to do next
|
|
65
|
+
- patches welcome!
|
|
66
|
+
|
|
67
|
+
== Copyright
|
|
68
|
+
|
|
69
|
+
Copyright:: Copyright (c) 2012- TAGOMORI Satoshi (tagomoris)
|
|
70
|
+
License:: Apache License, Version 2.0
|
data/Rakefile
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'bundler'
|
|
5
|
+
begin
|
|
6
|
+
Bundler.setup(:default, :development)
|
|
7
|
+
rescue Bundler::BundlerError => e
|
|
8
|
+
$stderr.puts e.message
|
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
|
10
|
+
exit e.status_code
|
|
11
|
+
end
|
|
12
|
+
require 'rake'
|
|
13
|
+
|
|
14
|
+
require 'jeweler'
|
|
15
|
+
Jeweler::Tasks.new do |gem|
|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
|
17
|
+
gem.name = "fluent-plugin-flowcounter"
|
|
18
|
+
gem.description = "Plugin to counts messages/bytes that matches, per minutes/hours/days"
|
|
19
|
+
gem.homepage = "http://github.com/tagomoris/fluent-plugin-flowcounter"
|
|
20
|
+
gem.summary = gem.description
|
|
21
|
+
gem.email = "tagomoris@gmail.com"
|
|
22
|
+
gem.authors = ["TAGOMORI Satoshi"]
|
|
23
|
+
gem.has_rdoc = "false"
|
|
24
|
+
# dependencies defined in Gemfile
|
|
25
|
+
gem.files = `git ls-files`.split("\n")
|
|
26
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
27
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
28
|
+
gem.require_paths = ['lib']
|
|
29
|
+
gem.add_dependency "fluentd", "~> 0.10.8"
|
|
30
|
+
gem.add_development_dependency "rake", ">= 0.9.2"
|
|
31
|
+
gem.add_development_dependency "simplecov", ">= 0.5.4"
|
|
32
|
+
end
|
|
33
|
+
Jeweler::RubygemsDotOrgTasks.new
|
|
34
|
+
|
|
35
|
+
require 'rake/testtask'
|
|
36
|
+
Rake::TestTask.new(:test) do |test|
|
|
37
|
+
test.libs << 'lib' << 'test'
|
|
38
|
+
test.pattern = 'test/**/test_*.rb'
|
|
39
|
+
test.verbose = true
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
task :default => :test
|
|
43
|
+
|
|
44
|
+
require 'rdoc/task'
|
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
|
47
|
+
|
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
49
|
+
rdoc.title = "fluent-plugin-flowcounter #{version}"
|
|
50
|
+
rdoc.rdoc_files.include('README*')
|
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
52
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
class Fluent::FlowCounterOutput < Fluent::Output
|
|
2
|
+
Fluent::Plugin.register_output('flowcounter', self)
|
|
3
|
+
|
|
4
|
+
config_param :unit, :string, :default => 'minute'
|
|
5
|
+
config_param :aggregate, :string, :default => 'tag'
|
|
6
|
+
config_param :tag, :string, :default => 'flowcount'
|
|
7
|
+
config_param :input_tag_remove_prefix, :string, :default => nil
|
|
8
|
+
config_param :count_keys, :string
|
|
9
|
+
|
|
10
|
+
attr_accessor :counts
|
|
11
|
+
attr_accessor :last_checked
|
|
12
|
+
|
|
13
|
+
def configure(conf)
|
|
14
|
+
super
|
|
15
|
+
|
|
16
|
+
@unit = case @unit
|
|
17
|
+
when 'minute' then :minute
|
|
18
|
+
when 'hour' then :hour
|
|
19
|
+
when 'day' then :day
|
|
20
|
+
else
|
|
21
|
+
raise Fluent::ConfigError, "flowcounter unit allows minute/hour/day"
|
|
22
|
+
end
|
|
23
|
+
@aggregate = case @aggregate
|
|
24
|
+
when 'tag' then :tag
|
|
25
|
+
when 'all' then :all
|
|
26
|
+
else
|
|
27
|
+
raise Fluent::ConfigError, "flowcounter aggregate allows tag/all"
|
|
28
|
+
end
|
|
29
|
+
if @input_tag_remove_prefix
|
|
30
|
+
@removed_prefix_string = @input_tag_remove_prefix + '.'
|
|
31
|
+
@removed_length = @removed_prefix_string.length
|
|
32
|
+
end
|
|
33
|
+
@count_keys = @count_keys.split(',')
|
|
34
|
+
|
|
35
|
+
@counts = count_initialized
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def start
|
|
39
|
+
super
|
|
40
|
+
@counts = count_initialized
|
|
41
|
+
start_watch
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def shutdown
|
|
45
|
+
super
|
|
46
|
+
@watcher.terminate
|
|
47
|
+
@watcher.join
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def count_initialized(keys=nil)
|
|
51
|
+
if @aggregate == :all
|
|
52
|
+
{'count' => 0, 'bytes' => 0}
|
|
53
|
+
elsif keys
|
|
54
|
+
Hash[[keys, [0]*(keys.length)].transpose]
|
|
55
|
+
else
|
|
56
|
+
{}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def countup(name, counts, bytes)
|
|
61
|
+
c = 'count'
|
|
62
|
+
b = 'bytes'
|
|
63
|
+
if @aggregate == :tag
|
|
64
|
+
c = name + '_count'
|
|
65
|
+
b = name + '_bytes'
|
|
66
|
+
end
|
|
67
|
+
@counts[c] = (@counts[c] || 0) + counts
|
|
68
|
+
@counts[b] = (@counts[b] || 0) + bytes
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def generate_output(counts, step)
|
|
72
|
+
rates = {}
|
|
73
|
+
counts.keys.each {|key|
|
|
74
|
+
rates[key + '_rate'] = ((counts[key] * 100.0) / (1.00 * step)).floor / 100.0
|
|
75
|
+
}
|
|
76
|
+
counts.update(rates)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def flush(step)
|
|
80
|
+
flushed,@counts = @counts,count_initialized(@counts.keys)
|
|
81
|
+
generate_output(flushed, step)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def flush_emit(step)
|
|
85
|
+
Fluent::Engine.emit(@tag, Fluent::Engine.now, flush(step))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def start_watch
|
|
89
|
+
# for internal, or tests only
|
|
90
|
+
@watcher = Thread.new(&method(:watch))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def watch
|
|
94
|
+
# instance variable, and public accessable, for test
|
|
95
|
+
@last_checked = Fluent::Engine.now
|
|
96
|
+
tick = case @unit
|
|
97
|
+
when :minute then 60
|
|
98
|
+
when :hour then 3600
|
|
99
|
+
when :day then 86400
|
|
100
|
+
else
|
|
101
|
+
raise RuntimeError, "@unit must be one of minute/hour/day"
|
|
102
|
+
end
|
|
103
|
+
while true
|
|
104
|
+
sleep 0.5
|
|
105
|
+
if Fluent::Engine.now - @last_checked >= tick
|
|
106
|
+
now = Fluent::Engine.now
|
|
107
|
+
flush_emit(now - @last_checked)
|
|
108
|
+
@last_checked = now
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def emit(tag, es, chain)
|
|
114
|
+
name = tag
|
|
115
|
+
if @input_tag_remove_prefix and
|
|
116
|
+
( (tag.start_with?(@removed_prefix_string) and tag.length > @removed_length) or tag == @input_tag_remove_prefix)
|
|
117
|
+
name = tag[@removed_length..-1]
|
|
118
|
+
end
|
|
119
|
+
c,b = 0,0
|
|
120
|
+
es.each {|time,record|
|
|
121
|
+
c += 1
|
|
122
|
+
b += @count_keys.inject(0){|s,k| s + record[k].bytesize}
|
|
123
|
+
}
|
|
124
|
+
countup(name, c, b)
|
|
125
|
+
|
|
126
|
+
chain.next
|
|
127
|
+
end
|
|
128
|
+
end
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'bundler'
|
|
3
|
+
begin
|
|
4
|
+
Bundler.setup(:default, :development)
|
|
5
|
+
rescue Bundler::BundlerError => e
|
|
6
|
+
$stderr.puts e.message
|
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
|
8
|
+
exit e.status_code
|
|
9
|
+
end
|
|
10
|
+
require 'test/unit'
|
|
11
|
+
require 'shoulda'
|
|
12
|
+
|
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
15
|
+
require 'fluent/test'
|
|
16
|
+
require 'fluent/plugin/out_flowcounter'
|
|
17
|
+
|
|
18
|
+
class Test::Unit::TestCase
|
|
19
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
require 'helper'
|
|
2
|
+
|
|
3
|
+
class FlowCounterOutputTest < Test::Unit::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
Fluent::Test.setup
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
CONFIG = %[
|
|
9
|
+
unit day
|
|
10
|
+
aggregate tag
|
|
11
|
+
tag flowcount
|
|
12
|
+
input_tag_remove_prefix test
|
|
13
|
+
count_keys message
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
def create_driver(conf=CONFIG,tag='test')
|
|
17
|
+
Fluent::Test::OutputTestDriver.new(Fluent::FlowCounterOutput, tag).configure(conf)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_configure
|
|
21
|
+
assert_raise(Fluent::ConfigError) {
|
|
22
|
+
d = create_driver('')
|
|
23
|
+
}
|
|
24
|
+
assert_raise(Fluent::ConfigError) {
|
|
25
|
+
d = create_driver %[
|
|
26
|
+
count_keys message,message2
|
|
27
|
+
unit week
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
d = create_driver %[
|
|
31
|
+
count_keys message
|
|
32
|
+
]
|
|
33
|
+
assert_equal :minute, d.instance.unit
|
|
34
|
+
assert_equal :tag, d.instance.aggregate
|
|
35
|
+
assert_equal 'flowcount', d.instance.tag
|
|
36
|
+
assert_nil d.instance.input_tag_remove_prefix
|
|
37
|
+
assert_equal ['message'], d.instance.count_keys
|
|
38
|
+
|
|
39
|
+
d = create_driver %[
|
|
40
|
+
count_keys field1,field2
|
|
41
|
+
]
|
|
42
|
+
assert_equal :minute, d.instance.unit
|
|
43
|
+
assert_equal :tag, d.instance.aggregate
|
|
44
|
+
assert_equal 'flowcount', d.instance.tag
|
|
45
|
+
assert_nil d.instance.input_tag_remove_prefix
|
|
46
|
+
assert_equal ['field1', 'field2'], d.instance.count_keys
|
|
47
|
+
|
|
48
|
+
d = create_driver %[
|
|
49
|
+
unit hour
|
|
50
|
+
count_keys message
|
|
51
|
+
]
|
|
52
|
+
assert_equal :hour, d.instance.unit
|
|
53
|
+
assert_equal :tag, d.instance.aggregate
|
|
54
|
+
assert_equal 'flowcount', d.instance.tag
|
|
55
|
+
assert_nil d.instance.input_tag_remove_prefix
|
|
56
|
+
assert_equal ['message'], d.instance.count_keys
|
|
57
|
+
|
|
58
|
+
d = create_driver %[
|
|
59
|
+
unit day
|
|
60
|
+
aggregate all
|
|
61
|
+
tag test.flowcount
|
|
62
|
+
input_tag_remove_prefix test
|
|
63
|
+
count_keys message
|
|
64
|
+
]
|
|
65
|
+
assert_equal :day, d.instance.unit
|
|
66
|
+
assert_equal :all, d.instance.aggregate
|
|
67
|
+
assert_equal 'test.flowcount', d.instance.tag
|
|
68
|
+
assert_equal 'test', d.instance.input_tag_remove_prefix
|
|
69
|
+
assert_equal ['message'], d.instance.count_keys
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_count_initialized
|
|
73
|
+
d = create_driver %[
|
|
74
|
+
aggregate all
|
|
75
|
+
count_keys f1,f2,f3
|
|
76
|
+
]
|
|
77
|
+
assert_equal 0, d.instance.counts['count']
|
|
78
|
+
assert_equal 0, d.instance.counts['bytes']
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_countup
|
|
82
|
+
d = create_driver
|
|
83
|
+
assert_nil d.instance.counts['message_count']
|
|
84
|
+
assert_nil d.instance.counts['message_bytes']
|
|
85
|
+
|
|
86
|
+
d.instance.countup('message', 30, 50)
|
|
87
|
+
assert_equal 30, d.instance.counts['message_count']
|
|
88
|
+
assert_equal 50, d.instance.counts['message_bytes']
|
|
89
|
+
|
|
90
|
+
d.instance.countup('message', 10, 70)
|
|
91
|
+
assert_equal 40, d.instance.counts['message_count']
|
|
92
|
+
assert_equal 120, d.instance.counts['message_bytes']
|
|
93
|
+
|
|
94
|
+
d = create_driver %[
|
|
95
|
+
aggregate all
|
|
96
|
+
count_keys message,field
|
|
97
|
+
]
|
|
98
|
+
assert_equal 0, d.instance.counts['count']
|
|
99
|
+
assert_equal 0, d.instance.counts['bytes']
|
|
100
|
+
|
|
101
|
+
d.instance.countup('message', 30, 50)
|
|
102
|
+
assert_equal 30, d.instance.counts['count']
|
|
103
|
+
assert_equal 50, d.instance.counts['bytes']
|
|
104
|
+
|
|
105
|
+
d.instance.countup('field', 10, 70)
|
|
106
|
+
assert_equal 40, d.instance.counts['count']
|
|
107
|
+
assert_equal 120, d.instance.counts['bytes']
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_generate_output
|
|
111
|
+
d = create_driver %[
|
|
112
|
+
unit minute
|
|
113
|
+
count_keys message
|
|
114
|
+
]
|
|
115
|
+
r1 = d.instance.generate_output({'count' => 600, 'bytes' => 18000}, 60)
|
|
116
|
+
assert_equal 10.00, r1['count_rate']
|
|
117
|
+
assert_equal 300.00, r1['bytes_rate']
|
|
118
|
+
r2 = d.instance.generate_output({'count' => 100, 'bytes' => 1000}, 60)
|
|
119
|
+
assert_equal 1.66, r2['count_rate']
|
|
120
|
+
assert_equal 16.66, r2['bytes_rate']
|
|
121
|
+
|
|
122
|
+
d = create_driver %[
|
|
123
|
+
unit hour
|
|
124
|
+
count_keys f1,f2
|
|
125
|
+
]
|
|
126
|
+
r3 = d.instance.generate_output({'xx_count' => 1800, 'xx_bytes' => 600000}, 3600)
|
|
127
|
+
assert_equal 0.50, r3['xx_count_rate']
|
|
128
|
+
assert_equal 166.66, r3['xx_bytes_rate']
|
|
129
|
+
|
|
130
|
+
r4 = d.instance.generate_output({'t1_count' => 7200, 't1_bytes' => 14400, 't2_count' => 14400, 't2_bytes' => 288000}, 3600)
|
|
131
|
+
assert_equal 2.00, r4['t1_count_rate']
|
|
132
|
+
assert_equal 4.00, r4['t1_bytes_rate']
|
|
133
|
+
assert_equal 4.00, r4['t2_count_rate']
|
|
134
|
+
assert_equal 80.00, r4['t2_bytes_rate']
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def test_emit
|
|
138
|
+
d1 = create_driver(CONFIG, 'test.tag1')
|
|
139
|
+
time = Time.parse("2012-01-02 13:14:15").to_i
|
|
140
|
+
d1.run do
|
|
141
|
+
3600.times do
|
|
142
|
+
d1.emit({'message'=> 'a' * 100})
|
|
143
|
+
d1.emit({'message'=> 'b' * 100})
|
|
144
|
+
d1.emit({'message'=> 'c' * 100})
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
r1 = d1.instance.flush(3600 * 24)
|
|
148
|
+
assert_equal 3600*3, r1['tag1_count']
|
|
149
|
+
assert_equal 3600*3*100, r1['tag1_bytes']
|
|
150
|
+
assert_equal (300/24.0).floor / 100.0, r1['tag1_count_rate'] # 3 * 3600 / (60 * 60 * 24) as xx.xx
|
|
151
|
+
assert_equal (30000/24.0).floor / 100.0, r1['tag1_bytes_rate'] # 300 * 3600 / (60 * 60 * 24) xx.xx
|
|
152
|
+
|
|
153
|
+
d3 = create_driver( %[
|
|
154
|
+
unit minute
|
|
155
|
+
aggregate all
|
|
156
|
+
tag flow
|
|
157
|
+
count_keys f1,f2,f3
|
|
158
|
+
], 'test.tag1')
|
|
159
|
+
time = Time.parse("2012-01-02 13:14:15").to_i
|
|
160
|
+
d3.run do
|
|
161
|
+
60.times do
|
|
162
|
+
d3.emit({'f1'=>'1'*10, 'f2'=>'2'*20, 'f3'=>'3'*10})
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
r3 = d3.instance.flush(60)
|
|
166
|
+
assert_equal 60, r3['count']
|
|
167
|
+
assert_equal 60*40, r3['bytes']
|
|
168
|
+
assert_equal 1.0, r3['count_rate']
|
|
169
|
+
assert_equal 40.0, r3['bytes_rate']
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def test_emit2
|
|
173
|
+
d2 = create_driver( %[
|
|
174
|
+
unit minute
|
|
175
|
+
aggregate all
|
|
176
|
+
tag flowcount
|
|
177
|
+
input_tag_remove_prefix test
|
|
178
|
+
count_keys f1,f2,f3
|
|
179
|
+
], 'test.tag2')
|
|
180
|
+
time = Time.now.to_i
|
|
181
|
+
d2.run do
|
|
182
|
+
60.times do
|
|
183
|
+
d2.emit({'f1' => 'abcde', 'f2' => 'vwxyz', 'f3' => '0123456789'})
|
|
184
|
+
d2.emit({'f1' => 'abcde', 'f2' => 'vwxyz', 'f3' => '0123456789'})
|
|
185
|
+
d2.emit({'f1' => 'abcde', 'f2' => 'vwxyz', 'f3' => '0123456789'})
|
|
186
|
+
d2.emit({'f1' => 'abcde', 'f2' => 'vwxyz', 'f3' => '0123456789'})
|
|
187
|
+
d2.emit({'f1' => 'abcde', 'f2' => 'vwxyz', 'f3' => '0123456789'})
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
d2.instance.flush_emit(60)
|
|
191
|
+
emits = d2.emits
|
|
192
|
+
assert_equal 1, emits.length
|
|
193
|
+
p emits[0].to_json
|
|
194
|
+
data = emits[0]
|
|
195
|
+
assert_equal 'flowcount', data[0] # tag
|
|
196
|
+
assert_equal 60*5, data[2]['count']
|
|
197
|
+
assert_equal 60*5*20, data[2]['bytes']
|
|
198
|
+
end
|
|
199
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fluent-plugin-flowcounter
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- TAGOMORI Satoshi
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-02-18 00:00:00.000000000Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: fluentd
|
|
16
|
+
requirement: &2152296260 !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: *2152296260
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: shoulda
|
|
27
|
+
requirement: &2152295780 !ruby/object:Gem::Requirement
|
|
28
|
+
none: false
|
|
29
|
+
requirements:
|
|
30
|
+
- - ! '>='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: *2152295780
|
|
36
|
+
- !ruby/object:Gem::Dependency
|
|
37
|
+
name: bundler
|
|
38
|
+
requirement: &2152295300 !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
40
|
+
requirements:
|
|
41
|
+
- - ~>
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 1.0.0
|
|
44
|
+
type: :development
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: *2152295300
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: jeweler
|
|
49
|
+
requirement: &2152294820 !ruby/object:Gem::Requirement
|
|
50
|
+
none: false
|
|
51
|
+
requirements:
|
|
52
|
+
- - ~>
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 1.6.4
|
|
55
|
+
type: :development
|
|
56
|
+
prerelease: false
|
|
57
|
+
version_requirements: *2152294820
|
|
58
|
+
- !ruby/object:Gem::Dependency
|
|
59
|
+
name: simplecov
|
|
60
|
+
requirement: &2152294340 !ruby/object:Gem::Requirement
|
|
61
|
+
none: false
|
|
62
|
+
requirements:
|
|
63
|
+
- - ! '>='
|
|
64
|
+
- !ruby/object:Gem::Version
|
|
65
|
+
version: '0'
|
|
66
|
+
type: :development
|
|
67
|
+
prerelease: false
|
|
68
|
+
version_requirements: *2152294340
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rdoc
|
|
71
|
+
requirement: &2152293860 !ruby/object:Gem::Requirement
|
|
72
|
+
none: false
|
|
73
|
+
requirements:
|
|
74
|
+
- - ! '>='
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
type: :development
|
|
78
|
+
prerelease: false
|
|
79
|
+
version_requirements: *2152293860
|
|
80
|
+
- !ruby/object:Gem::Dependency
|
|
81
|
+
name: fluentd
|
|
82
|
+
requirement: &2152293380 !ruby/object:Gem::Requirement
|
|
83
|
+
none: false
|
|
84
|
+
requirements:
|
|
85
|
+
- - ~>
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: 0.10.8
|
|
88
|
+
type: :runtime
|
|
89
|
+
prerelease: false
|
|
90
|
+
version_requirements: *2152293380
|
|
91
|
+
- !ruby/object:Gem::Dependency
|
|
92
|
+
name: rake
|
|
93
|
+
requirement: &2152292900 !ruby/object:Gem::Requirement
|
|
94
|
+
none: false
|
|
95
|
+
requirements:
|
|
96
|
+
- - ! '>='
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: 0.9.2
|
|
99
|
+
type: :development
|
|
100
|
+
prerelease: false
|
|
101
|
+
version_requirements: *2152292900
|
|
102
|
+
- !ruby/object:Gem::Dependency
|
|
103
|
+
name: simplecov
|
|
104
|
+
requirement: &2152292420 !ruby/object:Gem::Requirement
|
|
105
|
+
none: false
|
|
106
|
+
requirements:
|
|
107
|
+
- - ! '>='
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 0.5.4
|
|
110
|
+
type: :development
|
|
111
|
+
prerelease: false
|
|
112
|
+
version_requirements: *2152292420
|
|
113
|
+
description: Plugin to counts messages/bytes that matches, per minutes/hours/days
|
|
114
|
+
email: tagomoris@gmail.com
|
|
115
|
+
executables: []
|
|
116
|
+
extensions: []
|
|
117
|
+
extra_rdoc_files:
|
|
118
|
+
- LICENSE.txt
|
|
119
|
+
- README.rdoc
|
|
120
|
+
files:
|
|
121
|
+
- .document
|
|
122
|
+
- .gitignore
|
|
123
|
+
- AUTHORS
|
|
124
|
+
- Gemfile
|
|
125
|
+
- LICENSE.txt
|
|
126
|
+
- README.rdoc
|
|
127
|
+
- Rakefile
|
|
128
|
+
- VERSION
|
|
129
|
+
- lib/fluent/plugin/out_flowcounter.rb
|
|
130
|
+
- test/helper.rb
|
|
131
|
+
- test/plugin/test_out_flowcounter.rb
|
|
132
|
+
homepage: http://github.com/tagomoris/fluent-plugin-flowcounter
|
|
133
|
+
licenses: []
|
|
134
|
+
post_install_message:
|
|
135
|
+
rdoc_options: []
|
|
136
|
+
require_paths:
|
|
137
|
+
- lib
|
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
139
|
+
none: false
|
|
140
|
+
requirements:
|
|
141
|
+
- - ! '>='
|
|
142
|
+
- !ruby/object:Gem::Version
|
|
143
|
+
version: '0'
|
|
144
|
+
segments:
|
|
145
|
+
- 0
|
|
146
|
+
hash: 3390482931615998912
|
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
|
+
none: false
|
|
149
|
+
requirements:
|
|
150
|
+
- - ! '>='
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
153
|
+
requirements: []
|
|
154
|
+
rubyforge_project:
|
|
155
|
+
rubygems_version: 1.8.6
|
|
156
|
+
signing_key:
|
|
157
|
+
specification_version: 3
|
|
158
|
+
summary: Plugin to counts messages/bytes that matches, per minutes/hours/days
|
|
159
|
+
test_files:
|
|
160
|
+
- test/helper.rb
|
|
161
|
+
- test/plugin/test_out_flowcounter.rb
|