fluent-plugin-metricsense 0.1.1 → 0.2.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/Gemfile +2 -1
- data/VERSION +1 -1
- data/lib/fluent/plugin/{backend → backends}/librato_backend.rb +22 -12
- data/lib/fluent/plugin/{backend → backends}/rdb_tsdb_backend.rb +3 -4
- data/lib/fluent/plugin/{backend → backends}/stdout_backend.rb +2 -2
- data/lib/fluent/plugin/out_metricsense.rb +113 -38
- metadata +6 -11
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -22,7 +22,7 @@ module Fluent::MetricSenseOutput::Backends
|
|
22
22
|
require 'json'
|
23
23
|
|
24
24
|
class LibratoBackend < Fluent::MetricSenseOutput::Backend
|
25
|
-
Fluent::MetricSenseOutput
|
25
|
+
Fluent::MetricSenseOutput.register_backend('librato', self)
|
26
26
|
|
27
27
|
config_param :librato_user, :string
|
28
28
|
config_param :librato_token, :string
|
@@ -48,7 +48,7 @@ module Fluent::MetricSenseOutput::Backends
|
|
48
48
|
req.basic_auth @librato_user, @librato_token
|
49
49
|
|
50
50
|
data = []
|
51
|
-
slice.each_with_index {|(tag,time,value,seg_key,seg_val),i|
|
51
|
+
slice.each_with_index {|(tag,time,value,seg_key,seg_val,mode),i|
|
52
52
|
if seg_key
|
53
53
|
name = "#{tag}:#{seg_key}"
|
54
54
|
source = seg_val
|
@@ -63,7 +63,7 @@ module Fluent::MetricSenseOutput::Backends
|
|
63
63
|
}
|
64
64
|
h["source"] = source.to_s if source
|
65
65
|
data << h
|
66
|
-
ensure_metric_initialized(http, name)
|
66
|
+
ensure_metric_initialized(http, name, mode)
|
67
67
|
}
|
68
68
|
body = {"gauges"=>data}.to_json
|
69
69
|
|
@@ -83,22 +83,32 @@ module Fluent::MetricSenseOutput::Backends
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
|
87
|
-
"type=gauge",
|
88
|
-
"attributes[source_aggregate]=true",
|
89
|
-
"attributes[summarize_function]=sum",
|
90
|
-
"attributes[display_stacked]=true",
|
91
|
-
].join('&')
|
86
|
+
METRIC_INITIALIZE_REQUEST_PER_MODE = []
|
92
87
|
|
93
|
-
|
88
|
+
METRIC_INITIALIZE_REQUEST_PER_MODE[UpdateMode::ADD] = {
|
89
|
+
"type" => "gauge",
|
90
|
+
"attributes" => {
|
91
|
+
"source_aggregate" => true,
|
92
|
+
"summarize_function" => "sum",
|
93
|
+
}
|
94
|
+
}.to_json
|
95
|
+
|
96
|
+
METRIC_INITIALIZE_REQUEST_PER_MODE[UpdateMode::LATEST] = {
|
97
|
+
"type" => "gauge",
|
98
|
+
"attributes" => {
|
99
|
+
}
|
100
|
+
}.to_json
|
101
|
+
|
102
|
+
def ensure_metric_initialized(http, name, mode)
|
94
103
|
return if @initialized_metrics[name]
|
95
104
|
|
96
105
|
header = {}
|
97
106
|
req = Net::HTTP::Put.new("/v1/metrics/#{CGI.escape name}", header)
|
98
107
|
req.basic_auth @librato_user, @librato_token
|
99
108
|
|
100
|
-
$log.trace { "librato initialize metric: #{name}" }
|
101
|
-
req.body =
|
109
|
+
$log.trace { "librato initialize metric with mode #{mode}: #{name}" }
|
110
|
+
req.body = METRIC_INITIALIZE_REQUEST_PER_MODE[mode]
|
111
|
+
req.set_content_type("application/json")
|
102
112
|
res = http.request(req)
|
103
113
|
|
104
114
|
# TODO error handling
|
@@ -18,9 +18,7 @@
|
|
18
18
|
module Fluent::MetricSenseOutput::Backends
|
19
19
|
|
20
20
|
class RDBTSDBBackend < Fluent::MetricSenseOutput::Backend
|
21
|
-
|
22
|
-
|
23
|
-
Fluent::MetricSenseOutput::BACKENDS['rdb_tsdb'] = self
|
21
|
+
Fluent::MetricSenseOutput.register_backend('rdb_tsdb', self)
|
24
22
|
|
25
23
|
config_param :rdb_url, :string
|
26
24
|
config_param :rdb_table_prefix, :string
|
@@ -180,7 +178,8 @@ module Fluent::MetricSenseOutput::Backends
|
|
180
178
|
ensure_connect do |db|
|
181
179
|
# group by row_key (base_time,metric_id,segment_id)
|
182
180
|
rows = {}
|
183
|
-
data.each {|
|
181
|
+
data.each {|tag,time,value,seg_key,seg_val,mode|
|
182
|
+
# TODO update_mode is not supported yet
|
184
183
|
base_time = time / ROW_TIME_WINDOW
|
185
184
|
metric_id = get_metric_id(db, tag, seg_key)
|
186
185
|
segment_id = get_segment_id(db, seg_val) if seg_val
|
@@ -18,10 +18,10 @@
|
|
18
18
|
module Fluent::MetricSenseOutput::Backends
|
19
19
|
|
20
20
|
class StdoutBackend < Fluent::MetricSenseOutput::Backend
|
21
|
-
Fluent::MetricSenseOutput
|
21
|
+
Fluent::MetricSenseOutput.register_backend('stdout', self)
|
22
22
|
|
23
23
|
def write(data)
|
24
|
-
data.each {|tag,time,value,seg_key,seg_val|
|
24
|
+
data.each {|tag,time,value,seg_key,seg_val,mode|
|
25
25
|
if seg_key
|
26
26
|
puts "#{Time.at(time)} #{tag}: #{value}"
|
27
27
|
else
|
@@ -23,28 +23,43 @@ module Fluent
|
|
23
23
|
|
24
24
|
BACKENDS = {}
|
25
25
|
|
26
|
+
def self.register_backend(name, klass)
|
27
|
+
BACKENDS[name] = klass
|
28
|
+
end
|
29
|
+
|
30
|
+
module UpdateMode
|
31
|
+
ADD = 0
|
32
|
+
LATEST = 1
|
33
|
+
end
|
34
|
+
|
26
35
|
class Backend
|
36
|
+
UpdateMode = MetricSenseOutput::UpdateMode
|
27
37
|
include Configurable
|
28
|
-
|
29
38
|
def start
|
30
39
|
end
|
31
|
-
|
32
40
|
def shutdown
|
33
41
|
end
|
34
42
|
end
|
35
43
|
|
36
|
-
|
37
|
-
|
38
|
-
require
|
39
|
-
|
44
|
+
module Backends
|
45
|
+
backend_dir = "#{File.dirname(__FILE__)}/backends"
|
46
|
+
require "#{backend_dir}/librato_backend"
|
47
|
+
require "#{backend_dir}/rdb_tsdb_backend"
|
48
|
+
require "#{backend_dir}/stdout_backend"
|
49
|
+
end
|
40
50
|
|
41
|
-
config_param :segment_keys, :string, :default => nil
|
42
|
-
config_param :all_segment, :bool, :default => false
|
43
51
|
config_param :value_key, :string, :default => 'value'
|
44
52
|
|
45
|
-
config_param :
|
53
|
+
config_param :no_segment_keys, :bool, :default => false
|
54
|
+
config_param :only_segment_keys, :string, :default => nil
|
55
|
+
config_param :exclude_segment_keys, :string, :default => nil
|
56
|
+
|
57
|
+
config_param :update_mode_key, :string, :default => 'update_mode'
|
46
58
|
|
47
59
|
config_param :remove_tag_prefix, :string, :default => nil
|
60
|
+
config_param :add_tag_prefix, :string, :default => nil
|
61
|
+
|
62
|
+
config_param :backend, :string
|
48
63
|
|
49
64
|
def configure(conf)
|
50
65
|
super
|
@@ -53,16 +68,14 @@ module Fluent
|
|
53
68
|
@remove_tag_prefix = Regexp.new('^' + Regexp.escape(@remove_tag_prefix) + "\\.?")
|
54
69
|
end
|
55
70
|
|
56
|
-
|
57
|
-
|
71
|
+
@no_segment_keys = (conf.has_key?('no_segment_keys') && (conf['no_segment_keys'].empty? || conf['no_segment_keys'] == 'true'))
|
72
|
+
|
73
|
+
if @only_segment_keys
|
74
|
+
@only_segment_keys = @only_segment_keys.strip.split(/\s*,\s*/)
|
58
75
|
end
|
59
76
|
|
60
|
-
if @
|
61
|
-
@
|
62
|
-
elsif @segment_keys
|
63
|
-
@segment_keys = @segment_keys.strip.split(/\s*,\s*/)
|
64
|
-
else
|
65
|
-
@segment_keys = []
|
77
|
+
if @exclude_segment_keys
|
78
|
+
@exclude_segment_keys = @exclude_segment_keys.strip.split(/\s*,\s*/)
|
66
79
|
end
|
67
80
|
|
68
81
|
be = BACKENDS[@backend]
|
@@ -85,14 +98,27 @@ module Fluent
|
|
85
98
|
end
|
86
99
|
|
87
100
|
def format_stream(tag, es)
|
88
|
-
|
101
|
+
# modify tag
|
89
102
|
tag = tag.sub(@remove_tag_prefix, '') if @remove_tag_prefix
|
103
|
+
tag = "#{add_tag_prefix}.#{tag}" if @add_tag_prefix
|
104
|
+
|
105
|
+
out = ''
|
90
106
|
es.each do |time,record|
|
91
|
-
|
107
|
+
# dup record to modify
|
108
|
+
record = record.dup
|
92
109
|
|
93
|
-
|
110
|
+
# get value
|
111
|
+
value = record.delete(@value_key)
|
112
|
+
|
113
|
+
# ignore record if value is invalid or 0
|
114
|
+
begin
|
115
|
+
fv = value.to_f
|
116
|
+
rescue
|
117
|
+
next
|
118
|
+
end
|
94
119
|
next if fv == 0.0
|
95
120
|
|
121
|
+
# use integer if value.to_f == value.to_f.to_i
|
96
122
|
iv = fv.to_i
|
97
123
|
if iv.to_f == fv
|
98
124
|
value = iv
|
@@ -100,35 +126,71 @@ module Fluent
|
|
100
126
|
value = fv
|
101
127
|
end
|
102
128
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
129
|
+
# get update_mode key
|
130
|
+
update_mode = record.delete(@update_mode_key)
|
131
|
+
case update_mode
|
132
|
+
when "latest"
|
133
|
+
update_mode = UpdateMode::LATEST
|
134
|
+
else
|
135
|
+
# default is add
|
136
|
+
update_mode = UpdateMode::ADD
|
107
137
|
end
|
108
138
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
139
|
+
# get segments
|
140
|
+
if @no_segment_keys
|
141
|
+
segments = {}
|
142
|
+
else
|
143
|
+
if @only_segment_keys
|
144
|
+
segments = {}
|
145
|
+
@only_segment_keys.each {|key|
|
146
|
+
if v = record[key]
|
147
|
+
segments[key] = v
|
148
|
+
end
|
149
|
+
}
|
150
|
+
else
|
151
|
+
segments = record
|
114
152
|
end
|
115
|
-
|
153
|
+
if @exclude_segment_keys
|
154
|
+
@exclude_segment_keys.each {|key|
|
155
|
+
segments.delete(key)
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
116
159
|
|
117
|
-
[tag, time, value,
|
160
|
+
[tag, time, value, segments, update_mode].to_msgpack(out)
|
118
161
|
end
|
162
|
+
|
119
163
|
out
|
120
164
|
end
|
121
165
|
|
122
|
-
class
|
166
|
+
class AddUpdater
|
123
167
|
def initialize
|
124
168
|
@value = 0
|
125
169
|
end
|
170
|
+
attr_reader :value
|
126
171
|
|
127
172
|
def add(value)
|
128
173
|
@value += value
|
129
174
|
end
|
130
175
|
|
176
|
+
def mode
|
177
|
+
UpdateMode::ADD
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class LatestUpdater
|
182
|
+
def initialize
|
183
|
+
@value = 0
|
184
|
+
end
|
131
185
|
attr_reader :value
|
186
|
+
|
187
|
+
def add(value)
|
188
|
+
@value += value
|
189
|
+
end
|
190
|
+
|
191
|
+
def mode
|
192
|
+
UpdateMode::LATEST
|
193
|
+
end
|
132
194
|
end
|
133
195
|
|
134
196
|
AggregationKey = Struct.new(:tag, :time, :seg_val, :seg_key)
|
@@ -137,21 +199,34 @@ module Fluent
|
|
137
199
|
counters = {}
|
138
200
|
|
139
201
|
# select sum(value) from chunk group by tag, time/60, seg_val, seg_key
|
140
|
-
chunk.msgpack_each {|tag,time,value,
|
202
|
+
chunk.msgpack_each {|tag,time,value,segments,update_mode|
|
141
203
|
time = time / 60 * 60
|
142
204
|
|
205
|
+
case update_mode
|
206
|
+
when UpdateMode::ADD
|
207
|
+
updater = AddUpdater
|
208
|
+
when UpdateMode::LATEST
|
209
|
+
updater = LatestUpdater
|
210
|
+
else # default is AddUpdater
|
211
|
+
updater = AddUpdater
|
212
|
+
end
|
213
|
+
|
214
|
+
# total value
|
143
215
|
ak = AggregationKey.new(tag, time, nil, nil)
|
144
|
-
(counters[ak] ||=
|
216
|
+
(counters[ak] ||= updater.new).add(value)
|
217
|
+
|
218
|
+
# segmented values
|
219
|
+
segments = Hash[segments] if segments.is_a?(Array) # for backward compat
|
145
220
|
|
146
|
-
|
221
|
+
segments.each_pair {|seg_key,seg_val|
|
147
222
|
ak = AggregationKey.new(tag, time, seg_val, seg_key)
|
148
|
-
(counters[ak] ||=
|
223
|
+
(counters[ak] ||= updater.new).add(value)
|
149
224
|
}
|
150
225
|
}
|
151
226
|
|
152
227
|
data = []
|
153
|
-
counters.each_pair {|ak,
|
154
|
-
data << [ak.tag, ak.time,
|
228
|
+
counters.each_pair {|ak,up|
|
229
|
+
data << [ak.tag, ak.time, up.value, ak.seg_key, ak.seg_val, up.mode]
|
155
230
|
}
|
156
231
|
|
157
232
|
@backend.write(data)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-metricsense
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fluentd
|
@@ -87,9 +87,9 @@ files:
|
|
87
87
|
- Rakefile
|
88
88
|
- VERSION
|
89
89
|
- fluent-plugin-metricsense.gemspec
|
90
|
-
- lib/fluent/plugin/
|
91
|
-
- lib/fluent/plugin/
|
92
|
-
- lib/fluent/plugin/
|
90
|
+
- lib/fluent/plugin/backends/librato_backend.rb
|
91
|
+
- lib/fluent/plugin/backends/rdb_tsdb_backend.rb
|
92
|
+
- lib/fluent/plugin/backends/stdout_backend.rb
|
93
93
|
- lib/fluent/plugin/out_metricsense.rb
|
94
94
|
homepage: https://github.com/treasure-data/fluent-plugin-metricsense
|
95
95
|
licenses: []
|
@@ -103,18 +103,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
103
103
|
- - ! '>='
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: '0'
|
106
|
-
segments:
|
107
|
-
- 0
|
108
|
-
hash: 143460017522358519
|
109
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
107
|
none: false
|
111
108
|
requirements:
|
112
109
|
- - ! '>='
|
113
110
|
- !ruby/object:Gem::Version
|
114
111
|
version: '0'
|
115
|
-
segments:
|
116
|
-
- 0
|
117
|
-
hash: 143460017522358519
|
118
112
|
requirements: []
|
119
113
|
rubyforge_project:
|
120
114
|
rubygems_version: 1.8.23
|
@@ -122,3 +116,4 @@ signing_key:
|
|
122
116
|
specification_version: 3
|
123
117
|
summary: MetricSense - application metrics aggregation plugin for Fluentd
|
124
118
|
test_files: []
|
119
|
+
has_rdoc: false
|