fluent-plugin-mongokpi 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,24 +1,144 @@
1
1
  # Fluent::Plugin::Mongokpi
2
2
 
3
- Fluent BufferedOutput plugin: counting chunk, inserting counts to make kpi count on MongoDB
3
+ ## Description
4
+ Fluent BufferedOutput plugin: counting chunk, inserting counts to MongoDB
4
5
 
5
6
  ## Installation
7
+ $ gem install fluent-plugin-mongokpi
6
8
 
7
- Add this line to your application's Gemfile:
9
+ ## Configuration
10
+ config | default | info
11
+ -------------------|-----------------|-----
12
+ address | localhost:27017 | address of mongodb (for replicaset, plz set like localhost:27017,localhost:27018,localhost:27019)
13
+ db | kpidb | db name of mongodb
14
+ collection | kpiColyyyymmdd | collection name of mongodb (yyyymmdd will be replaced based on time)
15
+ write_concern | | mongodb connection option
16
+ name | | mongodb connection option
17
+ read | | mongodb connection option
18
+ refresh_mode | | mongodb connection option
19
+ refresh_interval | | mongodb connection option
20
+ kpi_type | | use 'access' for activating access count
21
+ kpi_unit | min | time unit of count [min,hour,day]
22
+ time_key | | this time_key field or time of record is used
23
+ time_format | | (with time_key) the value of time_key will be parsed with this format
24
+ count_key | | used like group by (for multiple keys, plz set like site,host,instance)
25
+ count_name | count | the count result will be set to this field
26
+ response_threshold | 1000000 | (with kpi_type = access) used as threshold of response time
27
+ f_code | code | (with kpi_type = access) field name of response code in the log records
28
+ f_response_time | response_time | (with kpi_type = access) field name of response time in the log records
8
29
 
9
- gem 'fluent-plugin-mongokpi'
30
+ ## MongoDB document
31
+ field | notification | info
32
+ ----------------|--------------|-----
33
+ _id | | time + value of ${count_key}
34
+ yyyymmdd | |
35
+ hh | | (with kpi_unit = min or hour)
36
+ mm | | (with kpi_unit = min)
37
+ ${count_key} | |
38
+ ${count_name} | | count
39
+ count1xx | | (with kpi_type = access) count of ${f_code} = 1XX
40
+ count2xx | | (with kpi_type = access) count of ${f_code} = 2XX
41
+ count3xx | | (with kpi_type = access) count of ${f_code} = 3XX
42
+ count4xx | | (with kpi_type = access) count of ${f_code} = 4XX
43
+ count5xx | | (with kpi_type = access) count of ${f_code} = 5XX
44
+ responseTimeAve | `m(_ _)m` | (with kpi_type = access) average of ${f_response_time}
45
+ responseTimeMax | `m(_ _)m` | (with kpi_type = access) maximum of ${f_response_time}
46
+ responseTimeMin | `m(_ _)m` | (with kpi_type = access) minimum of ${f_response_time}
47
+ responseTimeSum | | (with kpi_type = access) sum of ${f_response_time}
48
+ countOver | | (with kpi_type = access) count of the access: ${f_response_time} >= ${response_threshold}
49
+ okRatio | `m(_ _)m` | (with kpi_type = access) (count - countOver) / count
50
+ counter[60] | | (with kpi_type = access & kpy_unit = min) qps for each second
51
+ qpsAve | `m(_ _)m` | (with kpi_type = access & kpy_unit = min) average of qps
52
+ qpsMax | `m(_ _)m` | (with kpi_type = access & kpy_unit = min) maximum of qps
53
+ qpsMin | `m(_ _)m` | (with kpi_type = access & kpy_unit = min) minimum of qps
10
54
 
11
- And then execute:
55
+ `m(_ _)m` : these parameters are updated by non-atmic queries, then not reliable in multi processing
12
56
 
13
- $ bundle
57
+ ## Samples
58
+ ### sample: access log (simple)
59
+ config
14
60
 
15
- Or install it yourself as:
61
+ <match ***>
62
+ type mongokpi
63
+ kpi_type access
64
+ kpi_unit hourly
65
+ count_key site
66
+ time_key request_time
67
+ time_format %d/%b/%Y:%H:%M:%S %Z
68
+ </match>
16
69
 
17
- $ gem install fluent-plugin-mongokpi
70
+ log
71
+
72
+ {"request_time":"25/Nov/2013:20:03:02 +0700","code":"100","response_time":"1000","site":"git"}
73
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"200","response_time":"2000","site":"git"}
74
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"300","response_time":"3000","site":"git"}
75
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"404","response_time":"4000","site":"blog"}
76
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"500","response_time":"5000","site":"blog"}
77
+
78
+ MongoDB
79
+
80
+ db.kpiCol20131125.find()
81
+ { "_id" : "git201311252003", "count" : 3, "count1xx" : 1, "count2xx" : 1, "count3xx" : 1, "count4xx" : 0, "count5xx" : 0, "countOver" : 0,
82
+ "hh" : "20", "okRatio" : 1, "responseTimeAve" : 2000, "responseTimeMax" : 3000, "responseTimeMin" : 1000, "responseTimeSum" : 6000, "site" : "git", "yyyymmdd" : "20131125"}
83
+ { "_id" : "blog201311252003", "count" : 2, "count1xx" : 0, "count2xx" : 0, "count3xx" : 0, "count4xx" : 4, "count5xx" : 1, "countOver" : 0,
84
+ "hh" : "20", "okRatio" : 1, "responseTimeAve" : 4500, "responseTimeMax" : 5000, "responseTimeMin" : 4000, "responseTimeSum" : 9000, "site" : "blog", "yyyymmdd" : "20131125"}
85
+ { "_id" : "total201311252003", "count" : 5, "count1xx" : 0, "count2xx" : 0, "count3xx" : 0, "count4xx" : 0, "count5xx" : 0, "countOver" : 0,
86
+ "hh" : "20", "okRatio" : 1, "responseTimeAve" : 3000, "responseTimeMax" : 5000, "responseTimeMin" : 1000, "responseTimeSum" : 15000, "site" : "total", "yyyymmdd" : "20131125" }
87
+
88
+ ### sample: access log (detail)
89
+ config
90
+
91
+ <match ***>
92
+ type mongokpi
93
+ kpi_type access
94
+ count_key site
95
+ time_key request_time
96
+ time_format %d/%b/%Y:%H:%M:%S %Z
97
+ </match>
98
+
99
+ log
18
100
 
19
- ## Usage
101
+ {"request_time":"25/Nov/2013:20:03:02 +0700","code":"100","response_time":"1000","site":"git"}
102
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"200","response_time":"2000","site":"git"}
103
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"300","response_time":"3000","site":"git"}
104
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"404","response_time":"4000","site":"blog"}
105
+ {"request_time":"25/Nov/2013:20:03:03 +0700","code":"500","response_time":"5000","site":"blog"}
20
106
 
21
- m(_ _)m
107
+ MongoDB
108
+
109
+ db.kpiCol20131125.find()
110
+ { "_id" : "git201311252003", "count" : 3, "count1xx" : 1, "count2xx" : 1, "count3xx" : 1, "count4xx" : 0, "count5xx" : 0, "countOver" : 0,
111
+ "counter" : [ 0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
112
+ "hh" : "20", "mm" : "03", "okRatio" : 1, "qpsAve" : 0, "qpsMax" : 2, "qpsMin" : 0, "responseTimeAve" : 2000, "responseTimeMax" : 3000, "responseTimeMin" : 1000, "responseTimeSum" : 6000, "site" : "git", "yyyymmdd" : "20131125"}
113
+ { "_id" : "blog201311252003", "count" : 2, "count1xx" : 0, "count2xx" : 0, "count3xx" : 0, "count4xx" : 4, "count5xx" : 1, "countOver" : 0,
114
+ "counter" : [ 0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
115
+ "hh" : "20", "mm" : "03", "okRatio" : 1, "qpsAve" : 0, "qpsMax" : 2, "qpsMin" : 0, "responseTimeAve" : 4500, "responseTimeMax" : 5000, "responseTimeMin" : 4000, "responseTimeSum" : 9000, "site" : "blog", "yyyymmdd" : "20131125"}
116
+ { "_id" : "total201311252003", "count" : 5, "count1xx" : 0, "count2xx" : 0, "count3xx" : 0, "count4xx" : 0, "count5xx" : 0, "countOver" : 0,
117
+ "counter" : [ 0,0,1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
118
+ "hh" : "20", "mm" : "03", "okRatio" : 1, "qpsAve" : 0, "qpsMax" : 4, "qpsMin" : 0, "responseTimeAve" : 3000, "responseTimeMax" : 5000, "responseTimeMin" : 1000, "responseTimeSum" : 15000, "site" : "total", "yyyymmdd" : "20131125" }
119
+
120
+ ### sample: app log
121
+ config
122
+
123
+ <match ***>
124
+ type mongokpi
125
+ count_key site
126
+ </match>
127
+
128
+ log
129
+
130
+ {"gerogero":"Let's get Rocking!","site":"git"}
131
+ {"gerogero":"Let's get Rocking!","site":"git"}
132
+ {"gerogero":"Let's get Rocking!","site":"git"}
133
+ {"gerogero":"Let's get Rocking!","site":"blog"}
134
+ {"gerogero":"Let's get Rocking!","site":"blog"}
135
+
136
+ MongoDB
137
+
138
+ db.kpiCol20131125.find()
139
+ { "_id" : "git201311252248", "count" : 3, "hh" : "22", "mm" : "48", "site" : "git", "yyyymmdd" : "20131125" }
140
+ { "_id" : "blog201311252248", "count" : 2, "hh" : "22", "mm" : "48", "site" : "blog", "yyyymmdd" : "20131125" }
141
+ { "_id" : "total201311252248","count" : 5, "hh" : "22", "mm" : "48", "site" : "total", "yyyymmdd" : "20131125" }
22
142
 
23
143
  ## Contributing
24
144
 
@@ -28,3 +148,4 @@ Or install it yourself as:
28
148
  4. Push to the branch (`git push origin my-new-feature`)
29
149
  5. Create new Pull Request
30
150
 
151
+
@@ -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-mongokpi"
7
- spec.version = "0.0.0"
7
+ spec.version = "0.0.1"
8
8
  spec.authors = ["Hatayama Hideharu"]
9
9
  spec.email = ["h.hiddy@gmail.com"]
10
10
  spec.description = %q{Fluent BufferedOutput plugin: counting chunk, inserting counts to make kpi count on MongoDB}
@@ -4,6 +4,13 @@ module Fluent
4
4
  # which is used in the configuration file.
5
5
  Plugin.register_output('mongokpi', self)
6
6
 
7
+ UNIT_DAYS = ['d', 'day', 'dayly']
8
+ UNIT_HOURS = ['h', 'hour', 'hourly']
9
+ UNIT_MINUTES = ['m', 'min', 'minute']
10
+ DAY = 'day'
11
+ HOUR = 'hour'
12
+ MIN = 'min'
13
+
7
14
  # Mongo client settings
8
15
  config_param :address, :string, :default => 'localhost:27017'
9
16
  config_param :db, :string, :default => 'kpidb'
@@ -17,18 +24,18 @@ module Fluent
17
24
  # collection options
18
25
  config_param :capped_size, :integer, :default => 0
19
26
  config_param :capped_max, :integer, :default => 0
20
- # KPI count options
27
+ # count options
28
+ config_param :kpi_type, :string, :default => nil # use 'access' for activating access count.
29
+ config_param :kpi_unit, :string, :default => 'min'
21
30
  config_param :time_key, :string, :default => nil
22
31
  config_param :time_format, :string, :default => nil
23
32
  config_param :count_key, :string, :default => 'none'
24
33
  config_param :count_name, :string, :default => 'count'
25
34
  # access count options
26
- config_param :kpi_type, :string, :default => nil # use 'access' for activating access count.
27
- config_param :responseThreshold, :integer, :default => 1000000
28
- config_param :f_code, :string, :default => 'code'
29
- config_param :f_response_time, :string, :default => 'response_time'
35
+ config_param :response_threshold, :integer, :default => 1000000
36
+ config_param :f_code, :string, :default => 'code'
37
+ config_param :f_response_time, :string, :default => 'response_time'
30
38
 
31
-
32
39
  attr_reader :collections_opts, :connection_opts
33
40
 
34
41
  def initialize
@@ -43,6 +50,7 @@ module Fluent
43
50
  # If the configuration is invalid, raise Fluent::ConfigError.
44
51
  def configure(conf)
45
52
  super
53
+ @kpi_unit = get_kpi_unit(@kpi_unit)
46
54
  @connection_opts = {}
47
55
  @connection_opts[:w] = @write_concern unless @write_concern.nil?
48
56
  @connection_opts[:name] = @name unless @name.nil?
@@ -52,12 +60,20 @@ module Fluent
52
60
  @collections_opts = {}
53
61
  if @capped_size > 0
54
62
  @collections_opts[:capped] = true
55
- @collections_opts[:size] = Config.size_value(conf['capped_size'])
56
- @collections_opts[:max] = Config.size_value(conf['capped_max']) if @capped_max
63
+ @collections_opts[:size] = @capped_size
64
+ @collections_opts[:max] = @capped_max if @capped_max
57
65
  else
58
66
  @collections_opts[:capped] = false
59
67
  end
60
68
  end
69
+
70
+ def get_kpi_unit(kpi_unit)
71
+ case kpi_unit
72
+ when *UNIT_DAYS then return DAY
73
+ when *UNIT_HOURS then return HOUR
74
+ else return MIN
75
+ end
76
+ end
61
77
 
62
78
  # This method is called when starting.
63
79
  # Open sockets or files here.
@@ -99,8 +115,8 @@ module Fluent
99
115
  # }
100
116
  #end
101
117
  def write(chunk)
102
- doc_hash = get_insert_doc_hash(@kpi_type, chunk, @time_key, @time_format, @count_key, @count_name)
103
- insert(@kpi_type, @collection, @count_key, @count_name, doc_hash)
118
+ doc_hash = get_insert_doc_hash(@kpi_type, @kpi_unit, @time_key, @time_format, @count_key, @count_name, chunk)
119
+ insert(@kpi_type, @kpi_unit, @collection, @count_key, @count_name, doc_hash)
104
120
  end
105
121
 
106
122
  def get_client(address, connection_opts)
@@ -130,14 +146,14 @@ module Fluent
130
146
  end
131
147
 
132
148
  def convert_collection_name(collection_name, yyyymmdd)
133
- return collection_name.sub('yyyymmdd', yyyymmdd)
149
+ return collection_name.sub('yyyymmdd', yyyymmdd.to_s)
134
150
  end
135
151
 
136
152
  def get_collection_from_db(client, db_name, collection_name, collections_opts)
137
153
  return client.db(db_name).collection(collection_name, @collections_opts)
138
154
  end
139
155
 
140
- def get_insert_doc_hash(kpi_type, chunk, time_key, time_format, count_key, count_name)
156
+ def get_insert_doc_hash(kpi_type, kpi_unit, time_key, time_format, count_key, count_name, chunk)
141
157
  hash_counter = {}
142
158
  chunk.msgpack_each { |tag, time, record|
143
159
  $log.debug record
@@ -148,26 +164,40 @@ module Fluent
148
164
  if 'none' != count_key
149
165
  count_key_value = ''
150
166
  count_key.split(',').each { |x| count_key_value += record[x].to_s }
151
- key_str = count_key_value + tmp_time.strftime('%Y%m%d%H%M')
167
+ key_str = count_key_value + get_time_key_value(kpi_unit, tmp_time)
152
168
  doc = hash_counter.key?(key_str) ? hash_counter[key_str]
153
- : get_doc(kpi_type, count_key, count_key_value, count_name, tmp_time)
154
- hash_counter[key_str] = count_up(kpi_type, doc, record, count_name, tmp_time)
169
+ : get_doc(kpi_type, kpi_unit, count_key, count_key_value, count_name, tmp_time)
170
+ hash_counter[key_str] = count_up(kpi_type, kpi_unit, doc, record, count_name, tmp_time)
155
171
  end
156
172
  # total
157
- total_key_str = 'total' + tmp_time.strftime('%Y%m%d%H%M')
173
+ total_key_str = 'total' + get_time_key_value(kpi_unit, tmp_time)
158
174
  total = hash_counter.key?(total_key_str) ? hash_counter[total_key_str]
159
- : get_doc(kpi_type, count_key, 'total', count_name, tmp_time)
160
- hash_counter[total_key_str] = count_up(kpi_type, total, record, count_name, tmp_time)
175
+ : get_doc(kpi_type, kpi_unit, count_key, 'total', count_name, tmp_time)
176
+ hash_counter[total_key_str] = count_up(kpi_type, kpi_unit, total, record, count_name, tmp_time)
161
177
  }
162
178
  return hash_counter
163
179
  end
164
180
 
165
- def get_doc(kpi_type, count_key, count_key_value, count_name, time)
181
+ def get_time_key_value(kpi_unit, time)
182
+ case kpi_unit
183
+ when DAY then return time.strftime('%Y%m%d')
184
+ when HOUR then return time.strftime('%Y%m%d%H')
185
+ else return time.strftime('%Y%m%d%H%M')
186
+ end
187
+ end
188
+
189
+ def get_doc(kpi_type, kpi_unit, count_key, count_key_value, count_name, time)
166
190
  doc = {}
167
191
  doc[count_key] = count_key_value
168
- doc['yyyymmdd'] = time.strftime('%Y%m%d')
169
- doc['hh'] = time.strftime('%H')
170
- doc['mm'] = time.strftime('%M')
192
+ time_field_hash = {}
193
+ time_field_hash['yyyymmdd'] = time.strftime('%Y%m%d').to_i
194
+ if HOUR == kpi_unit
195
+ time_field_hash['hh'] = time.strftime('%H').to_i
196
+ elsif MIN == kpi_unit
197
+ time_field_hash['hh'] = time.strftime('%H').to_i
198
+ time_field_hash['mm'] = time.strftime('%M').to_i
199
+ end
200
+ doc['time_field_hash'] = time_field_hash
171
201
  doc[count_name] = 0
172
202
  if 'access' == kpi_type
173
203
  doc['countOver'] = 0
@@ -178,22 +208,24 @@ module Fluent
178
208
  doc['count5xx'] = 0
179
209
  doc['responseTimeAve'] = 0
180
210
  doc['responseTimeMax'] = 0
181
- doc['responseTimeMin'] = 100000000.00
211
+ doc['responseTimeMin'] = 100000000
182
212
  doc['responseTimeSum'] = 0
183
- doc['qpsAve'] = 0
184
- doc['qpsMax'] = 0
185
- doc['qpsMin'] = 100000000
186
- doc['okRatio'] = 0.00
187
- doc['counter'] = Array.new(60, 0)
213
+ doc['okRatio'] = 0.0000
214
+ if MIN == kpi_unit
215
+ doc['qpsAve'] = 0
216
+ doc['qpsMax'] = 0
217
+ doc['qpsMin'] = 100000000
218
+ doc['counter'] = Array.new(60, 0)
219
+ end
188
220
  end
189
221
  return doc
190
222
  end
191
223
 
192
- def count_up(kpi_type, doc, record, count_name, time)
224
+ def count_up(kpi_type, kpi_unit, doc, record, count_name, time)
193
225
  doc[count_name] += 1
194
226
  if 'access' == kpi_type
195
227
  response_time = record.key?(@f_response_time) ? record[@f_response_time].to_i : 0
196
- if response_time > @responseThreshold
228
+ if response_time >= @response_threshold
197
229
  doc['countOver'] += 1
198
230
  end
199
231
  case record[@f_code].to_i / 100
@@ -210,140 +242,88 @@ module Fluent
210
242
  doc['responseTimeMin'] = response_time
211
243
  end
212
244
  doc['responseTimeSum'] += response_time
213
- doc['counter'][time.strftime('%S').to_i] += 1
245
+ doc['counter'][time.strftime('%S').to_i] += 1 if MIN == kpi_unit
214
246
  end
215
247
  return doc
216
248
  end
217
249
 
218
- def insert(kpi_type, collection_name, count_key, count_name, doc_hash)
250
+ # 2.5 or less
251
+ # http://stackoverflow.com/questions/8508663/calculate-max-value-in-an-atomic-findandmodify-operation
252
+ # TODO improve for Mongo 2.6
253
+ # $min, $max field update operators
254
+ # https://jira.mongodb.org/browse/SERVER-1534
255
+ # https://jira.mongodb.org/browse/DOCS-2012
256
+ def insert(kpi_type, kpi_unit, collection_name, count_key, count_name, doc_hash)
219
257
  begin
220
258
  doc_hash.each { |key, doc|
221
- $log.debug doc
222
- collection = get_collection(collection_name, doc['yyyymmdd'])
223
- # 2.5 or less
224
- # http://stackoverflow.com/questions/8508663/calculate-max-value-in-an-atomic-findandmodify-operation
225
- # TODO improve for Mongo 2.6
226
- # $min, $max field update operators
227
- # https://jira.mongodb.org/browse/SERVER-1534
228
- # https://jira.mongodb.org/browse/DOCS-2012
259
+ $log.debug "key: #{key}, doc: #{doc}"
260
+ collection = get_collection(collection_name, doc['time_field_hash']['yyyymmdd'])
261
+ select_hash = doc['time_field_hash']
262
+ select_hash['_id'] = key
263
+ select_hash[count_key] = doc[count_key]
229
264
  if 'access' == kpi_type
265
+ # initialize the target doc
266
+ # Without this, "0" in "counter.0' can be regarded as an child element, not as an array element.
267
+ if MIN == kpi_unit
268
+ collection.update(
269
+ select_hash,
270
+ {'$setOnInsert' => {'counter' => Array.new(60, 0)}},
271
+ {:upsert => true}
272
+ )
273
+ end
274
+ # main update
275
+ increment_hash = {}
276
+ increment_hash[count_name] = doc[count_name]
277
+ increment_hash['countOver'] = doc['countOver']
278
+ increment_hash['count1xx'] = doc['count1xx']
279
+ increment_hash['count2xx'] = doc['count2xx']
280
+ increment_hash['count3xx'] = doc['count3xx']
281
+ increment_hash['count4xx'] = doc['count4xx']
282
+ increment_hash['count5xx'] = doc['count5xx']
283
+ if MIN == kpi_unit
284
+ for sec in 0..59
285
+ increment_hash['counter.' + sec.to_s] = doc['counter'][sec]
286
+ end
287
+ end
288
+ increment_hash['responseTimeSum'] = doc['responseTimeSum']
230
289
  collection.update(
231
- {'_id' => key, count_key => doc[count_key],
232
- 'yyyymmdd' => doc['yyyymmdd'], 'hh' => doc['hh'], 'mm' => doc['mm']},
233
- {'$setOnInsert' => {'counter' => Array.new(60, 0)}},
234
- {:upsert => true}
235
- )
236
- collection.update(
237
- {'_id' => key, count_key => doc[count_key],
238
- 'yyyymmdd' => doc['yyyymmdd'], 'hh' => doc['hh'], 'mm' => doc['mm']},
239
- {'$inc' => {
240
- count_name => doc[count_name],
241
- 'countOver' => doc['countOver'],
242
- 'count1xx' => doc['count1xx'],
243
- 'count2xx' => doc['count2xx'],
244
- 'count3xx' => doc['count3xx'],
245
- 'count4xx' => doc['count4xx'],
246
- 'count5xx' => doc['count5xx'],
247
- 'responseTimeSum' => doc['responseTimeSum'],
248
- 'counter.0' => doc['counter'][0],
249
- 'counter.1' => doc['counter'][1],
250
- 'counter.2' => doc['counter'][2],
251
- 'counter.3' => doc['counter'][3],
252
- 'counter.4' => doc['counter'][4],
253
- 'counter.5' => doc['counter'][5],
254
- 'counter.6' => doc['counter'][6],
255
- 'counter.7' => doc['counter'][7],
256
- 'counter.8' => doc['counter'][8],
257
- 'counter.9' => doc['counter'][9],
258
- 'counter.10' => doc['counter'][10],
259
- 'counter.11' => doc['counter'][11],
260
- 'counter.12' => doc['counter'][12],
261
- 'counter.13' => doc['counter'][13],
262
- 'counter.14' => doc['counter'][14],
263
- 'counter.15' => doc['counter'][15],
264
- 'counter.16' => doc['counter'][16],
265
- 'counter.17' => doc['counter'][17],
266
- 'counter.18' => doc['counter'][18],
267
- 'counter.19' => doc['counter'][19],
268
- 'counter.20' => doc['counter'][20],
269
- 'counter.21' => doc['counter'][21],
270
- 'counter.22' => doc['counter'][22],
271
- 'counter.23' => doc['counter'][23],
272
- 'counter.24' => doc['counter'][24],
273
- 'counter.25' => doc['counter'][25],
274
- 'counter.26' => doc['counter'][26],
275
- 'counter.27' => doc['counter'][27],
276
- 'counter.28' => doc['counter'][28],
277
- 'counter.29' => doc['counter'][29],
278
- 'counter.30' => doc['counter'][30],
279
- 'counter.31' => doc['counter'][31],
280
- 'counter.32' => doc['counter'][32],
281
- 'counter.33' => doc['counter'][33],
282
- 'counter.34' => doc['counter'][34],
283
- 'counter.35' => doc['counter'][35],
284
- 'counter.36' => doc['counter'][36],
285
- 'counter.37' => doc['counter'][37],
286
- 'counter.38' => doc['counter'][38],
287
- 'counter.39' => doc['counter'][39],
288
- 'counter.40' => doc['counter'][40],
289
- 'counter.41' => doc['counter'][41],
290
- 'counter.42' => doc['counter'][42],
291
- 'counter.43' => doc['counter'][43],
292
- 'counter.44' => doc['counter'][44],
293
- 'counter.45' => doc['counter'][45],
294
- 'counter.46' => doc['counter'][46],
295
- 'counter.47' => doc['counter'][47],
296
- 'counter.48' => doc['counter'][48],
297
- 'counter.49' => doc['counter'][49],
298
- 'counter.50' => doc['counter'][50],
299
- 'counter.51' => doc['counter'][51],
300
- 'counter.52' => doc['counter'][52],
301
- 'counter.53' => doc['counter'][53],
302
- 'counter.54' => doc['counter'][54],
303
- 'counter.55' => doc['counter'][55],
304
- 'counter.56' => doc['counter'][56],
305
- 'counter.57' => doc['counter'][57],
306
- 'counter.58' => doc['counter'][58],
307
- 'counter.59' => doc['counter'][59]
308
- }},
290
+ select_hash,
291
+ {'$inc' => increment_hash},
309
292
  {:upsert => true}
310
293
  )
311
- updated_doc_array = collection.find({'_id' => key}).to_a
312
- $log.debug updated_doc_array
313
- continue if updated_doc_array.nil?
314
- updated_doc = updated_doc_array[0]
315
- response_time_ave = updated_doc['responseTimeSum'] / doc[count_name]
294
+ # add supplemental fields using existing data
295
+ # NOTICE: this operation is not atmic, then the field value can be wrong in distributed processing.
296
+ updated_result = collection.find({'_id' => key})
297
+ if updated_result.nil?
298
+ $log.info "there is no updated result for the key: #{key}" if updated_result.nil?
299
+ continue
300
+ end
301
+ updated_doc = updated_result.to_a[0]
302
+ set_hash = {}
303
+ set_hash['responseTimeAve'] = updated_doc['responseTimeSum'] / doc[count_name]
316
304
  if !updated_doc['responseTimeMax'].nil? && updated_doc['responseTimeMax'] > doc['responseTimeMax']
317
- response_time_max = updated_doc['responseTimeMax']
305
+ set_hash['responseTimeMax'] = updated_doc['responseTimeMax']
318
306
  else
319
- response_time_max = doc['responseTimeMax']
307
+ set_hash['responseTimeMax'] = doc['responseTimeMax']
320
308
  end
321
309
  if !updated_doc['responseTimeMin'].nil? && updated_doc['responseTimeMin'] < doc['responseTimeMin']
322
- response_time_min = updated_doc['responseTimeMin']
310
+ set_hash['responseTimeMin'] = updated_doc['responseTimeMin']
323
311
  else
324
- response_time_min = doc['responseTimeMin']
312
+ set_hash['responseTimeMin'] = doc['responseTimeMin']
313
+ end
314
+ set_hash['okRatio'] = ((updated_doc[count_name] - updated_doc['countOver']).to_f / updated_doc[count_name]).round(4)
315
+ if MIN == kpi_unit
316
+ set_hash['qpsAve'] = (updated_doc['counter'].inject(0.0){|r,i| r+=i } / updated_doc['counter'].size).round
317
+ set_hash['qpsMax'] = updated_doc['counter'].max
318
+ set_hash['qpsMin'] = updated_doc['counter'].min
325
319
  end
326
- qps_ave = (updated_doc['counter'].inject(0.0){|r,i| r+=i } / updated_doc['counter'].size).round
327
- qps_max = updated_doc['counter'].max
328
- qps_min = updated_doc['counter'].min
329
- ok_ratio = ((updated_doc[count_name] - updated_doc['countOver']).to_f / updated_doc[count_name]).round(4)
330
320
  collection.update(
331
- {'_id' => key, count_key => doc[count_key],
332
- 'yyyymmdd' => doc['yyyymmdd'], 'hh' => doc['hh'], 'mm' => doc['mm']},
333
- { '$set' => {
334
- 'responseTimeAve' => response_time_ave,
335
- 'responseTimeMax' => response_time_max,
336
- 'responseTimeMin' => response_time_min,
337
- 'qpsAve' => qps_ave,
338
- 'qpsMax' => qps_max,
339
- 'qpsMin' => qps_min,
340
- 'okRatio' => ok_ratio
341
- }}
321
+ select_hash,
322
+ { '$set' => set_hash}
342
323
  )
343
324
  else
344
325
  collection.update(
345
- {'_id' => key, count_key => doc[count_key],
346
- 'yyyymmdd' => doc['yyyymmdd'], 'hh' => doc['hh'], 'mm' => doc['mm']},
326
+ select_hash,
347
327
  {'$inc' => {count_name => doc[count_name]}},
348
328
  {:upsert => true}
349
329
  )
@@ -57,7 +57,7 @@ class DataCounterOutputTest < Test::Unit::TestCase
57
57
 
58
58
  def test_format
59
59
  d = create_driver
60
- time = Time.parse("2112-09-03 01:23:45 UTC").to_i
60
+ time = Time.parse("2112-09-03 01:23:45 UTC")
61
61
  d.emit({"gerogero" => "Let's get Rocking!", "site" => "yapoo"}, time)
62
62
  d.emit({"gerogero" => "Let's get Rocking!", "site" => "geegero"}, time)
63
63
  d.expect_format "\x93\xABdefault_tag\xCF\x00\x00\x00\x01\f[\xC8\xA1\x82\xA8gerogero\xB2Let's get Rocking!\xA4site\xA5yapoo\x93\xABdefault_tag\xCF\x00\x00\x00\x01\f[\xC8\xA1\x82\xA8gerogero\xB2Let's get Rocking!\xA4site\xA7geegero"
@@ -88,3 +88,4 @@ class DataCounterOutputTest < Test::Unit::TestCase
88
88
  end
89
89
 
90
90
 
91
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-mongokpi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
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-11-27 00:00:00.000000000 Z
12
+ date: 2013-11-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler