fluent-plugin-metricsense 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|