fluent-plugin-statsite 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -8
- data/README.md +2 -2
- data/fluent-plugin-statsite.gemspec +1 -1
- data/lib/fluent/plugin/statsite/metric.rb +13 -28
- data/lib/fluent/plugin/statsite/metric_format.rb +37 -0
- data/test/test_formatter.rb +4 -4
- data/test/test_metric.rb +50 -26
- data/test/test_metric_format.rb +37 -0
- data/test/test_out_statsite_filter.rb +2 -2
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18bf875092d09bd490fd29b12b3749aeefc44248
|
4
|
+
data.tar.gz: 522741407db13e270fbd60fa523020d0428ecb5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f48dfb35f0409afa99d40aa18bc8599b98bafa13d78fdc2a177aa2404fd8bd173ee92380c08bc1e73015563fec80535768a69ecd9f7fb6ddec6a9aa0b690399
|
7
|
+
data.tar.gz: e61528aee4cd10d6ad2821d1cdbe5ecd48d4ef02c97b0f04fa7f3dbf87addeef6528c149ecba9897236f9d7edd5e642001b0080dc464b8e8a1f59b06547959d4
|
data/.travis.yml
CHANGED
@@ -4,12 +4,9 @@ rvm:
|
|
4
4
|
- 1.9.3
|
5
5
|
- 2.0.0
|
6
6
|
- 2.1
|
7
|
-
- ruby-head
|
8
|
-
- rbx-2
|
9
7
|
|
10
8
|
os:
|
11
9
|
- linux
|
12
|
-
- osx
|
13
10
|
|
14
11
|
branches:
|
15
12
|
only:
|
@@ -19,8 +16,3 @@ gemfile:
|
|
19
16
|
- Gemfile
|
20
17
|
|
21
18
|
script: bundle exec rake
|
22
|
-
|
23
|
-
matrix:
|
24
|
-
allow_failures:
|
25
|
-
- rvm: ruby-head
|
26
|
-
- rvm: rbx-2
|
data/README.md
CHANGED
@@ -30,10 +30,10 @@ It is strongly recommended to use '[V1 config format](http://docs.fluentd.org/ar
|
|
30
30
|
tag statsite
|
31
31
|
metrics [
|
32
32
|
"${status}:1|c",
|
33
|
-
{"key": "request_time", "
|
33
|
+
{"key": "request_time", "value": "request_time", "type": "ms"}
|
34
34
|
]
|
35
35
|
histograms [
|
36
|
-
{"prefix": "request_time" "min": 0, "max": 1, "width": 0.1}
|
36
|
+
{"prefix": "request_time", "min": 0, "max": 1, "width": 0.1}
|
37
37
|
]
|
38
38
|
statsite_path "statsite"
|
39
39
|
statsite_flush_interval 1s
|
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "fluent-plugin-statsite"
|
7
|
-
spec.version = "0.0.
|
7
|
+
spec.version = "0.0.4"
|
8
8
|
spec.authors = ["OKUNO Akihiro"]
|
9
9
|
spec.email = ["choplin.choplin@gmail.com"]
|
10
10
|
spec.summary = %q{Fluentd statsite plugin}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'metric_format'
|
2
|
+
|
1
3
|
module Fluent
|
2
4
|
module StatsitePlugin
|
3
5
|
class Metric
|
@@ -6,34 +8,25 @@ module Fluent
|
|
6
8
|
HASH_FIELD = %w(
|
7
9
|
type
|
8
10
|
key
|
9
|
-
key_field
|
10
11
|
value
|
11
|
-
value_field
|
12
12
|
)
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
STRING_PATTERN = /^(#{FIELD}):(#{FIELD})\|(#{TYPE.join('|')})$/
|
17
|
-
STRING_EXAMPLE = "key_field:value_field|type"
|
14
|
+
STRING_PATTERN = /^(#{MetricFormat::PATTERN}):(#{MetricFormat::PATTERN})\|(#{TYPE.join('|')})$/
|
18
15
|
|
19
|
-
def initialize(key,
|
16
|
+
def initialize(key, value, type)
|
20
17
|
@key = key
|
21
|
-
@key_field = key_field
|
22
18
|
@value = value
|
23
|
-
@value_field = value_field
|
24
19
|
@type = type
|
25
20
|
end
|
26
21
|
|
27
22
|
def convert(record)
|
28
|
-
k = @key.
|
29
|
-
v = @value.
|
23
|
+
k = @key.convert(record)
|
24
|
+
v = @value.convert(record)
|
30
25
|
(k.nil? or v.nil?) ? nil : "#{k}:#{v}|#{@type}\n"
|
31
26
|
end
|
32
27
|
|
33
28
|
def to_s
|
34
|
-
|
35
|
-
v = @value.nil? ? "value_field=#{@value_field}" :"value=#{@value}"
|
36
|
-
"Metric(#{k}, #{v}, type=#{@type})"
|
29
|
+
"Metric(#{@key}, #{@value}, type=#{@type})"
|
37
30
|
end
|
38
31
|
|
39
32
|
def self.validate(m)
|
@@ -49,31 +42,23 @@ module Fluent
|
|
49
42
|
end
|
50
43
|
end
|
51
44
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
if not m.has_key?('value') ^ m.has_key?('value_field')
|
57
|
-
raise ConfigError, "metrics element must contain either one of 'value' or 'value_field'"
|
58
|
-
end
|
59
|
-
|
60
|
-
if not m.has_key?('type')
|
61
|
-
raise ConfigError, "metrics element must contain 'type'"
|
45
|
+
HASH_FIELD.each do |f|
|
46
|
+
if not m.has_key?(f)
|
47
|
+
raise ConfigError, "metrics element must contain '#{f}'"
|
48
|
+
end
|
62
49
|
end
|
63
50
|
|
64
51
|
if not TYPE.member?(m['type'])
|
65
52
|
raise ConfigError, "metrics type must be one of the following: #{TYPE.join(' ')}, but specified as #{m['type']}"
|
66
53
|
end
|
67
54
|
|
68
|
-
new(m['key'], m['
|
55
|
+
new(MetricFormat.validate(m['key']), MetricFormat.validate(m['value']), m['type'])
|
69
56
|
when String
|
70
57
|
if (STRING_PATTERN =~ m).nil?
|
71
58
|
raise ConfigError, "metrics string must be #{STRING_PATTERN}, but specified as #{m}"
|
72
59
|
end
|
73
60
|
|
74
|
-
|
75
|
-
value, value_field = $2.start_with?('$') ? [nil, $2[2..-2]] : [$2, nil]
|
76
|
-
new(key, key_field, value, value_field, $3)
|
61
|
+
new(MetricFormat.validate($1), MetricFormat.validate($2), $3)
|
77
62
|
end
|
78
63
|
end
|
79
64
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Fluent
|
2
|
+
module StatsitePlugin
|
3
|
+
# This represent a key/value format of Metric
|
4
|
+
class MetricFormat
|
5
|
+
CONSTANT_VALUE = '\w+'
|
6
|
+
SUBSTITUTE = '\$\{\w+\}'
|
7
|
+
SUBSTITUTE_REGEXP = /\$\{(\w+)\}/
|
8
|
+
ELEMENT = "(?:#{CONSTANT_VALUE}|#{SUBSTITUTE})"
|
9
|
+
PATTERN = "#{ELEMENT}+"
|
10
|
+
|
11
|
+
def initialize(str)
|
12
|
+
@str = str
|
13
|
+
@no_substitute = str.index('$').nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def convert(record)
|
17
|
+
if @no_substitute
|
18
|
+
@str
|
19
|
+
else
|
20
|
+
@str.gsub(SUBSTITUTE_REGEXP) { record.fetch($1) } rescue nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@str
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.validate(str)
|
29
|
+
if /^#{PATTERN}$/.match(str).nil?
|
30
|
+
raise ConfigError, "invalid format of key/value field, it must be #{PATTERN}, but specified as #{str}"
|
31
|
+
end
|
32
|
+
|
33
|
+
new(str)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/test/test_formatter.rb
CHANGED
@@ -6,8 +6,8 @@ include Fluent::StatsitePlugin
|
|
6
6
|
class StatsiteFormatterTest < Test::Unit::TestCase
|
7
7
|
def setup
|
8
8
|
metrics = [
|
9
|
-
Metric.validate('${k}
|
10
|
-
Metric.validate('${k}:
|
9
|
+
Metric.validate('test_${k}:test_${v}|g'),
|
10
|
+
Metric.validate('test_${k}:test_v|g')
|
11
11
|
]
|
12
12
|
@formatter = StatsiteFormatter.new(metrics)
|
13
13
|
end
|
@@ -17,9 +17,9 @@ class StatsiteFormatterTest < Test::Unit::TestCase
|
|
17
17
|
assert_equal "", @formatter.call(record)
|
18
18
|
|
19
19
|
record = {'k' => 'key'}
|
20
|
-
assert_equal "
|
20
|
+
assert_equal "test_key:test_v|g\n", @formatter.call(record)
|
21
21
|
|
22
22
|
record = {'k' => 'key', 'v' => 'value'}
|
23
|
-
assert_equal "
|
23
|
+
assert_equal "test_key:test_value|g\ntest_key:test_v|g\n", @formatter.call(record)
|
24
24
|
end
|
25
25
|
end
|
data/test/test_metric.rb
CHANGED
@@ -4,13 +4,17 @@ require 'fluent/plugin/statsite/metric'
|
|
4
4
|
include Fluent::StatsitePlugin
|
5
5
|
|
6
6
|
class Metric
|
7
|
-
attr_reader :key, :
|
7
|
+
attr_reader :key, :value, :type
|
8
8
|
end
|
9
9
|
|
10
10
|
class MetricTest < Test::Unit::TestCase
|
11
11
|
|
12
12
|
def valid_config
|
13
|
-
{'key' => 'k', 'value' => 'v', 'type' => 'kv'}
|
13
|
+
{'key' => 'test_${k}', 'value' => 'test_${v}', 'type' => 'kv'}
|
14
|
+
end
|
15
|
+
|
16
|
+
def invalid_kv_format
|
17
|
+
'test_${'
|
14
18
|
end
|
15
19
|
|
16
20
|
def test_validate_object_type
|
@@ -25,21 +29,25 @@ class MetricTest < Test::Unit::TestCase
|
|
25
29
|
end
|
26
30
|
|
27
31
|
def test_validate_key
|
28
|
-
config = (valid_config)['key_field'] = 'k'
|
29
|
-
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
30
|
-
|
31
32
|
config = (valid_config)
|
32
33
|
config.delete('key')
|
33
34
|
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
34
|
-
end
|
35
35
|
|
36
|
-
|
37
|
-
config =
|
36
|
+
# invalid key format
|
37
|
+
config = valid_config
|
38
|
+
config['key'] = invalid_kv_format
|
38
39
|
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
40
|
+
end
|
39
41
|
|
42
|
+
def test_validate_value
|
40
43
|
config = (valid_config)
|
41
44
|
config.delete('value')
|
42
45
|
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
46
|
+
|
47
|
+
# invalid value format
|
48
|
+
config = valid_config
|
49
|
+
config['key'] = invalid_kv_format
|
50
|
+
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
43
51
|
end
|
44
52
|
|
45
53
|
def test_validate_type
|
@@ -52,41 +60,51 @@ class MetricTest < Test::Unit::TestCase
|
|
52
60
|
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
53
61
|
end
|
54
62
|
|
63
|
+
def test_validate_deprecated
|
64
|
+
config = valid_config
|
65
|
+
config.delete('value')
|
66
|
+
config['value_field'] = 'v'
|
67
|
+
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
68
|
+
|
69
|
+
config = valid_config
|
70
|
+
config.delete('key')
|
71
|
+
config['key_field'] = 'k'
|
72
|
+
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
73
|
+
end
|
74
|
+
|
55
75
|
def test_validate_string
|
56
76
|
config = "foo"
|
57
77
|
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
58
78
|
|
79
|
+
# invalid type
|
59
80
|
config = "k:v|foo"
|
60
81
|
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
82
|
+
|
83
|
+
# invalid key format
|
84
|
+
config = "${k:v|foo"
|
85
|
+
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
86
|
+
|
87
|
+
# invalid value format
|
88
|
+
config = "k:v_()|foo"
|
89
|
+
assert_raises(Fluent::ConfigError) { Metric.validate(config) }
|
61
90
|
end
|
62
91
|
|
63
92
|
def test_validate_result
|
64
93
|
m = Metric.validate(valid_config)
|
65
|
-
assert_equal 'k', m.key
|
66
|
-
|
67
|
-
assert_equal 'v', m.value
|
68
|
-
assert_nil m.value_field
|
94
|
+
assert_equal 'test_${k}', m.key.to_s
|
95
|
+
assert_equal 'test_${v}', m.value.to_s
|
69
96
|
assert_equal 'kv', m.type
|
70
97
|
end
|
71
98
|
|
72
99
|
def test_validate_result_string
|
73
|
-
m = Metric.validate('k:v|kv')
|
74
|
-
assert_equal 'k', m.key
|
75
|
-
|
76
|
-
assert_equal 'v', m.value
|
77
|
-
assert_nil m.value_field
|
78
|
-
assert_equal 'kv', m.type
|
79
|
-
|
80
|
-
m = Metric.validate('${k}:${v}|kv')
|
81
|
-
assert_nil m.key
|
82
|
-
assert_equal 'k', m.key_field
|
83
|
-
assert_nil m.value
|
84
|
-
assert_equal 'v', m.value_field
|
100
|
+
m = Metric.validate('test_${k}:test_${v}|kv')
|
101
|
+
assert_equal 'test_${k}', m.key.to_s
|
102
|
+
assert_equal 'test_${v}', m.value.to_s
|
85
103
|
assert_equal 'kv', m.type
|
86
104
|
end
|
87
105
|
|
88
106
|
def test_convert
|
89
|
-
m = Metric.validate('${k}
|
107
|
+
m = Metric.validate('test_${k}:test_${v}|kv')
|
90
108
|
|
91
109
|
record = {'k' => 'key'}
|
92
110
|
assert_nil m.convert(record)
|
@@ -95,6 +113,12 @@ class MetricTest < Test::Unit::TestCase
|
|
95
113
|
assert_nil m.convert(record)
|
96
114
|
|
97
115
|
record = {'k' => 'key', 'v' => 'value'}
|
98
|
-
assert_equal "
|
116
|
+
assert_equal "test_key:test_value|kv\n", m.convert(record)
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_convert_constant
|
120
|
+
m = Metric.validate('k:v|kv')
|
121
|
+
record = {}
|
122
|
+
assert_equal "k:v|kv\n", m.convert(record)
|
99
123
|
end
|
100
124
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'fluent/plugin/statsite/metric_format'
|
3
|
+
|
4
|
+
include Fluent::StatsitePlugin
|
5
|
+
|
6
|
+
class MetricFormat
|
7
|
+
attr_reader :str, :no_substitute
|
8
|
+
end
|
9
|
+
|
10
|
+
class MetricFormatTest < Test::Unit::TestCase
|
11
|
+
def test_validate
|
12
|
+
assert_raises(Fluent::ConfigError) { MetricFormat.validate('()') }
|
13
|
+
assert_raises(Fluent::ConfigError) { MetricFormat.validate('$') }
|
14
|
+
assert_raises(Fluent::ConfigError) { MetricFormat.validate('{}}') }
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_validate_result
|
18
|
+
s = 'foo_${bar}_foobar'
|
19
|
+
mf = MetricFormat.validate(s)
|
20
|
+
assert_equal s, mf.str
|
21
|
+
assert (not mf.no_substitute)
|
22
|
+
|
23
|
+
s = 'foo_bar_foobar'
|
24
|
+
mf = MetricFormat.validate(s)
|
25
|
+
assert_equal s, mf.str
|
26
|
+
assert mf.no_substitute
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_validate_convert
|
30
|
+
s = 'foo_${bar}_foobar'
|
31
|
+
mf = MetricFormat.validate(s)
|
32
|
+
|
33
|
+
assert_equal 'foo_hoge_foobar', mf.convert({'bar' => 'hoge'})
|
34
|
+
|
35
|
+
assert_nil mf.convert({'hoge' => 'fuga'})
|
36
|
+
end
|
37
|
+
end
|
@@ -17,7 +17,7 @@ class StatsiteFilterOutputTest < Test::Unit::TestCase
|
|
17
17
|
type statsite
|
18
18
|
tag statsite
|
19
19
|
metrics [
|
20
|
-
"${status}:1|c"
|
20
|
+
"status_${status}:1|c"
|
21
21
|
]
|
22
22
|
histograms [
|
23
23
|
{"prefix": "k", "min": 0, "max": 10, "width": 1.0}
|
@@ -60,6 +60,6 @@ class StatsiteFilterOutputTest < Test::Unit::TestCase
|
|
60
60
|
|
61
61
|
count_result = emits.pop
|
62
62
|
assert_equal 'statsite', count_result[0]
|
63
|
-
assert_equal({type: 'counts', key: '
|
63
|
+
assert_equal({type: 'counts', key: 'status_200', value: 4.0}, count_result[2])
|
64
64
|
end
|
65
65
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-statsite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OKUNO Akihiro
|
@@ -73,10 +73,12 @@ files:
|
|
73
73
|
- lib/fluent/plugin/statsite/format.rb
|
74
74
|
- lib/fluent/plugin/statsite/histogram.rb
|
75
75
|
- lib/fluent/plugin/statsite/metric.rb
|
76
|
+
- lib/fluent/plugin/statsite/metric_format.rb
|
76
77
|
- test/helper.rb
|
77
78
|
- test/test_formatter.rb
|
78
79
|
- test/test_histogram.rb
|
79
80
|
- test/test_metric.rb
|
81
|
+
- test/test_metric_format.rb
|
80
82
|
- test/test_out_statsite_filter.rb
|
81
83
|
- test/test_parser.rb
|
82
84
|
homepage: https://github.com/choplin/fluent-plugin-statsite
|
@@ -108,5 +110,6 @@ test_files:
|
|
108
110
|
- test/test_formatter.rb
|
109
111
|
- test/test_histogram.rb
|
110
112
|
- test/test_metric.rb
|
113
|
+
- test/test_metric_format.rb
|
111
114
|
- test/test_out_statsite_filter.rb
|
112
115
|
- test/test_parser.rb
|