fluent-plugin-metricsense 0.3.1 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ebe8e81e18307cb99946d1440e937b23426a7fa3
4
- data.tar.gz: f8ea8e769f2b91ee8d8f738f19698c88d4f5803c
2
+ SHA256:
3
+ metadata.gz: 7371bfe5a22e6d5bcad59eb8519ee42b74ca08f563a914cb3e81c14d0920599a
4
+ data.tar.gz: 66f6e9c5c425419c6f8aad48a8a2fc7d2eadddfed2777341e164a692d6a4b48b
5
5
  SHA512:
6
- metadata.gz: ef1fdac5be54fce8d388345123e65639801901898f47561b0026d2f6f1a514280bac5073601b5819c918e04dee0ccd01db4a0536c2ee87ca58334125774640b4
7
- data.tar.gz: d73a48b3091533eae618bde06f3cb9166e781854c9e06853953daeddcca64d5fb58966bba09f74c7919de84790ba83adbfb4377bdf83940c9f8f47e18f924d08
6
+ metadata.gz: 817364fce002c27ad75bea81cafc6f002253688c7feb39077ba5927f2b8611d16e6cd65880f4961f1fafdca6b4898fb88507bd7691242343f953fcd2fb0e6833
7
+ data.tar.gz: 896b4d773cda010e95ab7d617945f63ee44707213c1c2cecb65bbdc938842bb5b541caa4afb4ceee19d5fd6d18a450742b5e8cd656ef45e4e4b69dbf7517fd77
data/Rakefile CHANGED
@@ -1,13 +1,13 @@
1
1
  require 'bundler'
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- #require 'rake/testtask'
5
- #
6
- #Rake::TestTask.new(:test) do |test|
7
- # test.libs << 'lib' << 'test'
8
- # test.test_files = FileList['test/plugin/*.rb']
9
- # test.verbose = true
10
- #end
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |test|
7
+ test.libs << 'lib' << 'test'
8
+ test.test_files = FileList['test/plugin/*.rb']
9
+ test.verbose = true
10
+ end
11
11
 
12
12
  #task :coverage do |t|
13
13
  # ENV['SIMPLE_COV'] = '1'
data/SECURITY.md ADDED
@@ -0,0 +1,7 @@
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ Treasure Data values the security of its customers and is committed to ensuring that the systems and products are secure. We invite all bug bounty researchers to join our efforts in identifying and reporting vulnerabilities in our systems.
6
+
7
+ Submit your findings to our dedicated bug bounty email address [vulnerabilities@treasuredata.com](mailto:vulnerabilities@treasuredata.com) and help us keep Treasure Data secure. Let’s work together to make the Internet a safer place!
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.4.0
@@ -16,9 +16,10 @@ Gem::Specification.new do |s|
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
 
19
- s.add_dependency "fluentd", ">= 0.10.6"
19
+ s.add_dependency "fluentd", [">= 0.14.0", "< 2"]
20
20
  s.add_dependency "dogapi"
21
21
  s.add_development_dependency "rake", ">= 0.8.7"
22
22
  s.add_development_dependency 'bundler', ['>= 1.0.0']
23
- s.add_development_dependency "simplecov", ">= 0.5.4"
23
+ s.add_development_dependency "test-unit", ">= 3.1.1"
24
+ s.add_development_dependency "simplecov", ">= 0.10.0"
24
25
  end
@@ -18,9 +18,19 @@
18
18
  #
19
19
  module Fluent
20
20
 
21
- class MetricSenseOutput < Fluent::BufferedOutput
21
+ class MetricSenseOutput < Fluent::Plugin::Output
22
22
  Fluent::Plugin.register_output('metricsense', self)
23
23
 
24
+ helpers :compat_parameters
25
+
26
+ def formatted_to_msgpack_binary?
27
+ true
28
+ end
29
+
30
+ def compat_parameters_default_chunk_key
31
+ ""
32
+ end
33
+
24
34
  BACKENDS = {}
25
35
 
26
36
  def self.register_backend(name, klass)
@@ -36,7 +46,7 @@ module Fluent
36
46
 
37
47
  class Backend
38
48
  UpdateMode = MetricSenseOutput::UpdateMode
39
- include Configurable
49
+ include Fluent::Configurable
40
50
 
41
51
  attr_accessor :log
42
52
 
@@ -69,11 +79,8 @@ module Fluent
69
79
 
70
80
  config_param :aggregate_interval, :time, :default => 60
71
81
 
72
- unless method_defined?(:log)
73
- define_method(:log) { $log }
74
- end
75
-
76
82
  def configure(conf)
83
+ compat_parameters_convert(conf, :buffer)
77
84
  super
78
85
 
79
86
  if @remove_tag_prefix
@@ -111,81 +118,62 @@ module Fluent
111
118
  end
112
119
 
113
120
  def shutdown
114
- super
115
121
  @backend.shutdown
122
+ super
116
123
  end
117
124
 
118
- def format_stream(tag, es)
119
- # modify tag
125
+ def format(tag, time, record)
120
126
  tag = tag.sub(@remove_tag_prefix, '') if @remove_tag_prefix
121
- tag = "#{add_tag_prefix}.#{tag}" if @add_tag_prefix
122
-
123
- out = ''
124
- es.each do |time,record|
125
- # dup record to modify
126
- record = record.dup
127
+ tag = "#{@add_tag_prefix}.#{tag}" if @add_tag_prefix
127
128
 
128
- # get value
129
- value = record.delete(@value_key)
129
+ record = record.dup
130
130
 
131
- # ignore record if value is missing
132
- next if value.nil?
131
+ value = record.delete(@value_key)
132
+ return nil if value.nil?
133
133
 
134
- # ignore record if value is invalid
135
- begin
136
- fv = value.to_f
137
- rescue
138
- next
139
- end
140
- next if fv.nan? || fv.infinite?
141
-
142
- # use integer if value.to_f == value.to_f.to_i
143
- iv = fv.to_i
144
- if iv.to_f == fv
145
- value = iv
146
- else
147
- value = fv
148
- end
149
-
150
- # get update_mode key
151
- update_mode = record.delete(@update_mode_key)
152
- case update_mode
153
- when "max"
154
- update_mode = UpdateMode::MAX
155
- when "average"
156
- update_mode = UpdateMode::AVERAGE
157
- when "count"
158
- update_mode = UpdateMode::COUNT
159
- else
160
- # default is add
161
- update_mode = UpdateMode::ADD
162
- end
134
+ begin
135
+ fv = value.to_f
136
+ rescue
137
+ return nil
138
+ end
139
+ return nil if fv.nan? || fv.infinite?
140
+
141
+ iv = fv.to_i
142
+ value = iv.to_f == fv ? iv : fv
143
+
144
+ update_mode = record.delete(@update_mode_key)
145
+ case update_mode
146
+ when "max"
147
+ update_mode = UpdateMode::MAX
148
+ when "average"
149
+ update_mode = UpdateMode::AVERAGE
150
+ when "count"
151
+ update_mode = UpdateMode::COUNT
152
+ else
153
+ update_mode = UpdateMode::ADD
154
+ end
163
155
 
164
- # get segments
165
- if @no_segment_keys
156
+ if @no_segment_keys
157
+ segments = {}
158
+ else
159
+ if @only_segment_keys
166
160
  segments = {}
161
+ @only_segment_keys.each {|key|
162
+ if v = record[key]
163
+ segments[key] = v
164
+ end
165
+ }
167
166
  else
168
- if @only_segment_keys
169
- segments = {}
170
- @only_segment_keys.each {|key|
171
- if v = record[key]
172
- segments[key] = v
173
- end
174
- }
175
- else
176
- segments = record
177
- end
178
- if @exclude_segment_keys
179
- @exclude_segment_keys.each {|key|
180
- segments.delete(key)
181
- }
182
- end
167
+ segments = record
168
+ end
169
+ if @exclude_segment_keys
170
+ @exclude_segment_keys.each {|key|
171
+ segments.delete(key)
172
+ }
183
173
  end
184
-
185
- [tag, time, value, segments, update_mode].to_msgpack(out)
186
174
  end
187
175
 
188
- out
176
+ [tag, time.to_i, value, segments, update_mode].to_msgpack
189
177
  end
190
178
 
191
179
  class AddUpdater
@@ -262,30 +250,34 @@ module Fluent
262
250
 
263
251
  # select sum(value) from chunk group by tag, time/60, seg_val, seg_key
264
252
  chunk.msgpack_each {|tag,time,value,segments,update_mode|
265
- time = time / @aggregate_interval * @aggregate_interval
266
-
267
- case update_mode
268
- when UpdateMode::ADD
269
- updater = AddUpdater
270
- when UpdateMode::MAX
271
- updater = MaxUpdater
272
- when UpdateMode::AVERAGE # AVERAGE uses MaxUpdater and calculate average on server-side aggregation
273
- updater = AverageUpdater
274
- when UpdateMode::COUNT
275
- updater = CountUpdater
276
- else # default is AddUpdater
277
- updater = AddUpdater
278
- end
279
-
280
- # simple values
281
- ak = AggregationKey.new(tag, time, nil, nil)
282
- (simple_counters[ak] ||= updater.new).add(value)
253
+ begin
254
+ time = time / @aggregate_interval * @aggregate_interval
255
+
256
+ case update_mode
257
+ when UpdateMode::ADD
258
+ updater = AddUpdater
259
+ when UpdateMode::MAX
260
+ updater = MaxUpdater
261
+ when UpdateMode::AVERAGE # AVERAGE uses MaxUpdater and calculate average on server-side aggregation
262
+ updater = AverageUpdater
263
+ when UpdateMode::COUNT
264
+ updater = CountUpdater
265
+ else # default is AddUpdater
266
+ updater = AddUpdater
267
+ end
283
268
 
284
- # segmented values
285
- segments.each_pair {|seg_key,seg_val|
286
- ak = AggregationKey.new(tag, time, seg_val, seg_key)
287
- (segmented_counters[ak] ||= updater.new).add(value)
288
- }
269
+ # simple values
270
+ ak = AggregationKey.new(tag, time, nil, nil)
271
+ (simple_counters[ak] ||= updater.new).add(value)
272
+
273
+ # segmented values
274
+ segments.each_pair {|seg_key,seg_val|
275
+ ak = AggregationKey.new(tag, time, seg_val, seg_key)
276
+ (segmented_counters[ak] ||= updater.new).add(value)
277
+ }
278
+ rescue StandardError => e
279
+ log.warn("ignoring broken chunk: #{e.inspect} - " + [tag, time, value, segments, update_mode].inspect)
280
+ end
289
281
  }
290
282
 
291
283
  counters = segmented_counters
@@ -0,0 +1,118 @@
1
+ require 'test-unit'
2
+ require 'fluent/test'
3
+ require 'fluent/test/driver/output'
4
+ require 'fluent/test/helpers'
5
+ require 'fluent/plugin/out_metricsense'
6
+
7
+ class MetricsenseOutputTest < Test::Unit::TestCase
8
+ include Fluent::Test::Helpers
9
+
10
+ class TestBackend < Fluent::MetricSenseOutput::Backend
11
+ Fluent::MetricSenseOutput.register_backend('test', self)
12
+
13
+ @@data = []
14
+
15
+ def self.data
16
+ @@data
17
+ end
18
+
19
+ def self.clear
20
+ @@data = []
21
+ end
22
+
23
+ def write(data)
24
+ @@data << data
25
+ end
26
+ end
27
+
28
+ CONFIG = %Q[
29
+ backend test
30
+ ]
31
+
32
+ def setup
33
+ Fluent::Test.setup
34
+ TestBackend.clear
35
+ end
36
+
37
+ def create_driver(conf = CONFIG)
38
+ Fluent::Test::Driver::Output.new(Fluent::MetricSenseOutput).configure(conf)
39
+ end
40
+
41
+ def test_emit
42
+ now = Time.now.to_i
43
+ d = create_driver
44
+ d.run(default_tag: 'test') do
45
+ d.feed(now, {'value' => 1, 'user_id' => 23456, 'path' => '/auth/login'})
46
+ end
47
+
48
+ t = now / 60 * 60
49
+ assert_true TestBackend.data.length > 0
50
+ TestBackend.data.each do |written|
51
+ assert_equal ['test', t, 1, 'user_id', 23456, 0], written.shift
52
+ assert_equal ['test', t, 1, 'path', "/auth/login", 0], written.shift
53
+ assert_equal ['test', t, 1, nil, nil, 0], written.shift
54
+ end
55
+ end
56
+
57
+ # server restart can cause broken buffer and broken chunk.
58
+ # out_metricsense should ignore the chunk with warning log.
59
+ # Note: v1 driver validates inputs, so we hand-roll a corrupt chunk
60
+ # to exercise write's error handling directly.
61
+ def test_skip_broken_chunk
62
+ d = create_driver
63
+
64
+ corrupt_chunk = Object.new
65
+ def corrupt_chunk.msgpack_each
66
+ yield ['test', 'not_a_number', 1, {}, 0]
67
+ end
68
+
69
+ assert_nothing_raised do
70
+ d.instance.write(corrupt_chunk)
71
+ end
72
+ assert_equal [[]], TestBackend.data
73
+ end
74
+
75
+ def test_format_skips_nil_value
76
+ now = Time.now.to_i
77
+ d = create_driver
78
+ d.run(default_tag: 'test') do
79
+ d.feed(now, {'no_value_key' => 'x'})
80
+ d.feed(now, {'value' => 1})
81
+ end
82
+
83
+ assert_nil d.formatted.first
84
+ assert_equal 1, d.formatted.compact.length
85
+ assert_equal 1, TestBackend.data.flatten(1).length
86
+ end
87
+
88
+ def test_format_skips_nan_value
89
+ now = Time.now.to_i
90
+ d = create_driver
91
+ d.run(default_tag: 'test') do
92
+ d.feed(now, {'value' => Float::NAN})
93
+ d.feed(now, {'value' => 1})
94
+ end
95
+
96
+ assert_nil d.formatted.first
97
+ assert_equal 1, d.formatted.compact.length
98
+ assert_equal 1, TestBackend.data.flatten(1).length
99
+ end
100
+
101
+ def test_format_skips_infinite_value
102
+ now = Time.now.to_i
103
+ d = create_driver
104
+ d.run(default_tag: 'test') do
105
+ d.feed(now, {'value' => Float::INFINITY})
106
+ d.feed(now, {'value' => 1})
107
+ end
108
+
109
+ assert_nil d.formatted.first
110
+ assert_equal 1, d.formatted.compact.length
111
+ assert_equal 1, TestBackend.data.flatten(1).length
112
+ end
113
+
114
+ def test_reloadable
115
+ d = create_driver
116
+ assert_true d.instance.reloadable_plugin?
117
+ end
118
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-metricsense
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-06 00:00:00.000000000 Z
11
+ date: 2026-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fluentd
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.10.6
19
+ version: 0.14.0
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: 0.10.6
29
+ version: 0.14.0
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: dogapi
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -66,20 +72,34 @@ dependencies:
66
72
  - - ">="
67
73
  - !ruby/object:Gem::Version
68
74
  version: 1.0.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: test-unit
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: 3.1.1
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 3.1.1
69
89
  - !ruby/object:Gem::Dependency
70
90
  name: simplecov
71
91
  requirement: !ruby/object:Gem::Requirement
72
92
  requirements:
73
93
  - - ">="
74
94
  - !ruby/object:Gem::Version
75
- version: 0.5.4
95
+ version: 0.10.0
76
96
  type: :development
77
97
  prerelease: false
78
98
  version_requirements: !ruby/object:Gem::Requirement
79
99
  requirements:
80
100
  - - ">="
81
101
  - !ruby/object:Gem::Version
82
- version: 0.5.4
102
+ version: 0.10.0
83
103
  description: MetricSense - application metrics aggregation plugin for Fluentd
84
104
  email: sf@treasure-data.com
85
105
  executables: []
@@ -91,6 +111,7 @@ files:
91
111
  - LICENSE
92
112
  - README.rdoc
93
113
  - Rakefile
114
+ - SECURITY.md
94
115
  - VERSION
95
116
  - fluent-plugin-metricsense.gemspec
96
117
  - lib/fluent/plugin/backends/datadog_backend.rb
@@ -98,6 +119,7 @@ files:
98
119
  - lib/fluent/plugin/backends/rdb_tsdb_backend.rb
99
120
  - lib/fluent/plugin/backends/stdout_backend.rb
100
121
  - lib/fluent/plugin/out_metricsense.rb
122
+ - test/plugin/test_out_metricsense.rb
101
123
  homepage: https://github.com/treasure-data/fluent-plugin-metricsense
102
124
  licenses:
103
125
  - Apache-2.0
@@ -117,9 +139,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
139
  - !ruby/object:Gem::Version
118
140
  version: '0'
119
141
  requirements: []
120
- rubyforge_project:
121
- rubygems_version: 2.5.1
142
+ rubygems_version: 3.0.3.1
122
143
  signing_key:
123
144
  specification_version: 4
124
145
  summary: MetricSense - application metrics aggregation plugin for Fluentd
125
- test_files: []
146
+ test_files:
147
+ - test/plugin/test_out_metricsense.rb