bipbip 0.6.7 → 0.6.8
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 +4 -4
- data/README.md +5 -1
- data/bin/bipbip +5 -6
- data/lib/bipbip.rb +6 -2
- data/lib/bipbip/agent.rb +2 -5
- data/lib/bipbip/config.rb +4 -7
- data/lib/bipbip/helper.rb +1 -2
- data/lib/bipbip/plugin.rb +21 -29
- data/lib/bipbip/plugin/apache2.rb +4 -6
- data/lib/bipbip/plugin/command.rb +10 -13
- data/lib/bipbip/plugin/elasticsearch.rb +56 -59
- data/lib/bipbip/plugin/fastcgi_php_apc.rb +4 -6
- data/lib/bipbip/plugin/fastcgi_php_fpm.rb +5 -7
- data/lib/bipbip/plugin/fastcgi_php_opcache.rb +15 -17
- data/lib/bipbip/plugin/gearman.rb +4 -6
- data/lib/bipbip/plugin/log_parser.rb +11 -15
- data/lib/bipbip/plugin/memcached.rb +5 -7
- data/lib/bipbip/plugin/mongodb.rb +39 -37
- data/lib/bipbip/plugin/monit.rb +12 -13
- data/lib/bipbip/plugin/mysql.rb +21 -23
- data/lib/bipbip/plugin/network.rb +3 -5
- data/lib/bipbip/plugin/nginx.rb +11 -13
- data/lib/bipbip/plugin/php_apc.rb +4 -6
- data/lib/bipbip/plugin/postfix.rb +2 -4
- data/lib/bipbip/plugin/puppet.rb +16 -18
- data/lib/bipbip/plugin/redis.rb +9 -11
- data/lib/bipbip/plugin/resque.rb +9 -9
- data/lib/bipbip/plugin/socket_redis.rb +7 -8
- data/lib/bipbip/storage.rb +5 -8
- data/lib/bipbip/storage/copperegg.rb +8 -11
- data/lib/bipbip/version.rb +1 -1
- data/lib/interruptible_sleep.rb +1 -1
- metadata +17 -3
@@ -1,11 +1,9 @@
|
|
1
1
|
module Bipbip
|
2
|
-
|
3
2
|
class Plugin::FastcgiPhpApc < Plugin
|
4
|
-
|
5
3
|
def metrics_schema
|
6
4
|
[
|
7
|
-
|
8
|
-
|
5
|
+
{ name: 'opcode_mem_size', type: 'gauge', unit: 'b' },
|
6
|
+
{ name: 'user_mem_size', type: 'gauge', unit: 'b' }
|
9
7
|
]
|
10
8
|
end
|
11
9
|
|
@@ -21,10 +19,10 @@ module Bipbip
|
|
21
19
|
ENV.replace(env_backup)
|
22
20
|
|
23
21
|
body = response.split(/\r?\n\r?\n/)[1]
|
24
|
-
|
22
|
+
fail "FastCGI response has no body: #{response}" unless body
|
25
23
|
stats = JSON.parse(body)
|
26
24
|
|
27
|
-
{:
|
25
|
+
{ opcode_mem_size: stats['opcode_mem_size'].to_i, user_mem_size: stats['user_mem_size'].to_i }
|
28
26
|
end
|
29
27
|
end
|
30
28
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
module Bipbip
|
2
|
-
|
3
2
|
class Plugin::FastcgiPhpFpm < Plugin
|
4
|
-
|
5
3
|
def metrics_schema
|
6
4
|
[
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
{ name: 'accepted conn', type: 'counter', unit: 'Connections' },
|
6
|
+
{ name: 'listen queue', type: 'gauge', unit: 'Connections' },
|
7
|
+
{ name: 'active processes', type: 'gauge', unit: 'Processes' }
|
10
8
|
]
|
11
9
|
end
|
12
10
|
|
@@ -23,10 +21,10 @@ module Bipbip
|
|
23
21
|
ENV.replace(env_backup)
|
24
22
|
|
25
23
|
body = response.split(/\r?\n\r?\n/)[1]
|
26
|
-
|
24
|
+
fail "FastCGI response has no body: #{response}" unless body
|
27
25
|
status = JSON.parse(body)
|
28
26
|
|
29
|
-
status.reject{|k,
|
27
|
+
status.reject { |k, _v| !metrics_names.include?(k) }
|
30
28
|
end
|
31
29
|
end
|
32
30
|
end
|
@@ -1,16 +1,14 @@
|
|
1
1
|
module Bipbip
|
2
|
-
|
3
2
|
class Plugin::FastcgiPhpOpcache < Plugin
|
4
|
-
|
5
3
|
def metrics_schema
|
6
4
|
[
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
{ name: 'free_memory', type: 'gauge', unit: 'b' },
|
6
|
+
{ name: 'current_wasted_percentage', type: 'gauge', unit: '%' },
|
7
|
+
{ name: 'num_cached_keys', type: 'gauge', unit: 'Keys' },
|
8
|
+
{ name: 'hit_rate', type: 'gauge', unit: '%' },
|
9
|
+
{ name: 'misses', type: 'counter', unit: 'Misses' },
|
10
|
+
{ name: 'hits', type: 'counter', unit: 'Hits' },
|
11
|
+
{ name: 'oom_restarts', type: 'counter', unit: 'Restarts' }
|
14
12
|
]
|
15
13
|
end
|
16
14
|
|
@@ -26,7 +24,7 @@ module Bipbip
|
|
26
24
|
ENV.replace(env_backup)
|
27
25
|
|
28
26
|
body = response.split(/\r?\n\r?\n/)[1]
|
29
|
-
|
27
|
+
fail "FastCGI response has no body: #{response}" unless body
|
30
28
|
stats = JSON.parse(body)
|
31
29
|
@data_previous ||= stats
|
32
30
|
|
@@ -36,13 +34,13 @@ module Bipbip
|
|
36
34
|
|
37
35
|
@data_previous = stats
|
38
36
|
{
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
37
|
+
free_memory: stats_memory['free_memory'].to_i,
|
38
|
+
current_wasted_percentage: stats_memory['current_wasted_percentage'].to_i,
|
39
|
+
num_cached_keys: stats_statistics['num_cached_keys'].to_i,
|
40
|
+
hit_rate: hit_rate,
|
41
|
+
misses: stats_statistics['misses'].to_i,
|
42
|
+
hits: stats_statistics['hits'].to_i,
|
43
|
+
oom_restarts: stats_statistics['oom_restarts'].to_i
|
46
44
|
}
|
47
45
|
end
|
48
46
|
|
@@ -3,12 +3,10 @@ class GearmanServer < Gearman::Server
|
|
3
3
|
end
|
4
4
|
|
5
5
|
module Bipbip
|
6
|
-
|
7
6
|
class Plugin::Gearman < Plugin
|
8
|
-
|
9
7
|
def metrics_schema
|
10
8
|
[
|
11
|
-
|
9
|
+
{ name: 'jobs_queued_total', type: 'gauge', unit: 'Jobs' }
|
12
10
|
]
|
13
11
|
end
|
14
12
|
|
@@ -17,13 +15,13 @@ module Bipbip
|
|
17
15
|
stats = gearman.status
|
18
16
|
|
19
17
|
jobs_queued_total = 0
|
20
|
-
stats.each do |
|
21
|
-
data.each do |queue,
|
18
|
+
stats.each do |_function_name, data|
|
19
|
+
data.each do |queue, _stats|
|
22
20
|
jobs_queued_total += queue.to_i
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
26
|
-
{:jobs_queued_total
|
24
|
+
{ jobs_queued_total: jobs_queued_total }
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
@@ -1,12 +1,10 @@
|
|
1
1
|
require 'rb-inotify'
|
2
2
|
|
3
3
|
module Bipbip
|
4
|
-
|
5
4
|
class Plugin::LogParser < Plugin
|
6
|
-
|
7
5
|
def metrics_schema
|
8
6
|
config['matchers'].map do |matcher|
|
9
|
-
{:
|
7
|
+
{ name: matcher['name'], type: 'gauge', unit: 'Boolean' }
|
10
8
|
end
|
11
9
|
end
|
12
10
|
|
@@ -14,7 +12,7 @@ module Bipbip
|
|
14
12
|
begin
|
15
13
|
io = IO.select([notifier.to_io], [], [], 0)
|
16
14
|
rescue Errno::EBADF => e
|
17
|
-
log(Logger::WARN,
|
15
|
+
log(Logger::WARN, 'Selecting from inotify IO gives EBADF, resetting notifier')
|
18
16
|
reset_notifier
|
19
17
|
end
|
20
18
|
|
@@ -35,7 +33,7 @@ module Bipbip
|
|
35
33
|
config['matchers'].map do |matcher|
|
36
34
|
name = matcher['name']
|
37
35
|
regexp = Regexp.new(matcher['regexp'])
|
38
|
-
value = lines.
|
36
|
+
value = lines.count { |line| !line.match(regexp).nil? }
|
39
37
|
[name, value]
|
40
38
|
end
|
41
39
|
]
|
@@ -46,7 +44,7 @@ module Bipbip
|
|
46
44
|
def notifier
|
47
45
|
if @notifier.nil?
|
48
46
|
file_stat = File.stat(config['path'])
|
49
|
-
|
47
|
+
fail "Cannot read file `#{config['path']}`" unless file_stat.readable?
|
50
48
|
@lines = []
|
51
49
|
@size = file_stat.size
|
52
50
|
@notifier = create_notifier
|
@@ -70,15 +68,14 @@ module Bipbip
|
|
70
68
|
end
|
71
69
|
|
72
70
|
def reset_notifier
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
80
|
-
@notifier = nil
|
71
|
+
return if @notifier.nil?
|
72
|
+
@notifier.stop
|
73
|
+
begin
|
74
|
+
@notifier.close
|
75
|
+
rescue SystemCallError => e
|
76
|
+
log(Logger::WARN, "Cannot close notifier: `#{e.message}`")
|
81
77
|
end
|
78
|
+
@notifier = nil
|
82
79
|
end
|
83
80
|
|
84
81
|
def roll_file
|
@@ -90,6 +87,5 @@ module Bipbip
|
|
90
87
|
end
|
91
88
|
file.close
|
92
89
|
end
|
93
|
-
|
94
90
|
end
|
95
91
|
end
|
@@ -3,16 +3,14 @@ class MemcachedClient < Memcached
|
|
3
3
|
end
|
4
4
|
|
5
5
|
module Bipbip
|
6
|
-
|
7
6
|
class Plugin::Memcached < Plugin
|
8
|
-
|
9
7
|
def metrics_schema
|
10
8
|
[
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
{ name: 'cmd_get', type: 'counter' },
|
10
|
+
{ name: 'cmd_set', type: 'counter' },
|
11
|
+
{ name: 'get_misses', type: 'counter' },
|
12
|
+
{ name: 'bytes', type: 'gauge', unit: 'b' },
|
13
|
+
{ name: 'evictions', type: 'counter' }
|
16
14
|
]
|
17
15
|
end
|
18
16
|
|
@@ -1,28 +1,26 @@
|
|
1
1
|
require 'mongo'
|
2
2
|
|
3
3
|
module Bipbip
|
4
|
-
|
5
4
|
class Plugin::Mongodb < Plugin
|
6
|
-
|
7
5
|
def metrics_schema
|
8
6
|
[
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
7
|
+
{ name: 'flushing_last_ms', type: 'gauge', unit: 'ms' },
|
8
|
+
{ name: 'btree_misses', type: 'gauge', unit: 'misses' },
|
9
|
+
{ name: 'op_inserts', type: 'counter' },
|
10
|
+
{ name: 'op_queries', type: 'counter' },
|
11
|
+
{ name: 'op_updates', type: 'counter' },
|
12
|
+
{ name: 'op_deletes', type: 'counter' },
|
13
|
+
{ name: 'op_getmores', type: 'counter' },
|
14
|
+
{ name: 'op_commands', type: 'counter' },
|
15
|
+
{ name: 'connections_current', type: 'gauge' },
|
16
|
+
{ name: 'mem_resident', type: 'gauge', unit: 'MB' },
|
17
|
+
{ name: 'mem_mapped', type: 'gauge', unit: 'MB' },
|
18
|
+
{ name: 'mem_pagefaults', type: 'counter', unit: 'faults' },
|
19
|
+
{ name: 'globalLock_currentQueue', type: 'gauge' },
|
20
|
+
{ name: 'replication_lag', type: 'gauge', unit: 'Seconds' },
|
21
|
+
{ name: 'slow_queries_count', type: 'gauge_f', unit: 'Queries' },
|
22
|
+
{ name: 'slow_queries_time_avg', type: 'gauge_f', unit: 'Seconds' },
|
23
|
+
{ name: 'slow_queries_time_max', type: 'gauge_f', unit: 'Seconds' }
|
26
24
|
]
|
27
25
|
end
|
28
26
|
|
@@ -64,7 +62,7 @@ module Bipbip
|
|
64
62
|
end
|
65
63
|
|
66
64
|
data['slow_queries_count'] = slow_queries_status['total']['count']
|
67
|
-
data['slow_queries_time_avg'] = slow_queries_status['total']['
|
65
|
+
data['slow_queries_time_avg'] = slow_queries_status['total']['time'].to_f / (slow_queries_status['total']['count'].to_f.nonzero? || 1)
|
68
66
|
data['slow_queries_time_max'] = slow_queries_status['max']['time']
|
69
67
|
|
70
68
|
data
|
@@ -79,10 +77,10 @@ module Bipbip
|
|
79
77
|
# @return [Mongo::Client]
|
80
78
|
def mongodb_client
|
81
79
|
options = {
|
82
|
-
|
83
|
-
|
80
|
+
'hostname' => 'localhost',
|
81
|
+
'port' => 27_017
|
84
82
|
}.merge(config)
|
85
|
-
@mongodb_client ||= Mongo::Client.new([options['hostname'] + ':' + options['port'].to_s], :
|
83
|
+
@mongodb_client ||= Mongo::Client.new([options['hostname'] + ':' + options['port'].to_s], socket_timeout: 2, slave_ok: true)
|
86
84
|
end
|
87
85
|
|
88
86
|
# @return [Mongo::DB]
|
@@ -109,30 +107,34 @@ module Bipbip
|
|
109
107
|
timestamp_last_check = slow_query_last_check
|
110
108
|
time_period = Time.now - timestamp_last_check
|
111
109
|
|
112
|
-
database_names_ignore =
|
110
|
+
database_names_ignore = %w(admin system local)
|
113
111
|
database_list = (mongodb_client.database_names - database_names_ignore).map { |name| mongodb_database(name) }
|
114
112
|
|
115
|
-
stats = database_list.reduce(
|
116
|
-
|
113
|
+
stats = database_list.reduce('total' => { 'count' => 0, 'time' => 0 }, 'max' => { 'time' => 0 }) do |memo, database|
|
117
114
|
results = database['system.profile'].find.aggregate(
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
115
|
+
[
|
116
|
+
{ '$match' => { 'millis' => { '$gte' => slow_query_threshold }, 'ts' => { '$gt' => timestamp_last_check } } },
|
117
|
+
{ '$group' => {
|
118
|
+
'_id' => 'null',
|
119
|
+
'total_count' => { '$sum' => 1 },
|
120
|
+
'total_time' => { '$sum' => '$millis' },
|
121
|
+
'max_time' => { '$max' => '$millis' }
|
122
|
+
} }
|
123
|
+
])
|
122
124
|
|
123
125
|
unless results.count == 0
|
124
126
|
result = results.first
|
125
|
-
max_time = result['max_time'].to_f/1000
|
127
|
+
max_time = result['max_time'].to_f / 1000
|
126
128
|
|
127
129
|
memo['total']['count'] += result['total_count']
|
128
|
-
memo['total']['time'] += result['total_time'].to_f/1000
|
130
|
+
memo['total']['time'] += result['total_time'].to_f / 1000
|
129
131
|
memo['max']['time'] = max_time if memo['max']['time'] < max_time
|
130
132
|
end
|
131
133
|
|
132
134
|
memo
|
133
135
|
end
|
134
136
|
|
135
|
-
stats['total'].each { |metric, value| stats['total'][metric] = value/time_period }
|
137
|
+
stats['total'].each { |metric, value| stats['total'][metric] = value / time_period }
|
136
138
|
|
137
139
|
stats
|
138
140
|
end
|
@@ -140,11 +142,11 @@ module Bipbip
|
|
140
142
|
def replication_lag
|
141
143
|
status = fetch_replica_status
|
142
144
|
member_list = status['members']
|
143
|
-
primary = member_list.
|
144
|
-
secondary = member_list.
|
145
|
+
primary = member_list.find { |member| member['stateStr'] == 'PRIMARY' }
|
146
|
+
secondary = member_list.find { |member| member['stateStr'] == 'SECONDARY' && member['self'] == true }
|
145
147
|
|
146
|
-
|
147
|
-
|
148
|
+
fail "No primary member in replica `#{status['set']}`" if primary.nil?
|
149
|
+
fail "Cannot find itself as secondary member in replica `#{status['set']}`" if secondary.nil?
|
148
150
|
|
149
151
|
(secondary['optime'].seconds - primary['optime'].seconds)
|
150
152
|
end
|
data/lib/bipbip/plugin/monit.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'monit'
|
2
2
|
|
3
3
|
module Bipbip
|
4
|
-
|
5
4
|
class Plugin::Monit < Plugin
|
6
|
-
|
7
5
|
# See https://bitbucket.org/tildeslash/monit/src/d60968cf7972cc902e5b6e2961d44456e1d9b736/src/monit.h?at=master#monit.h-145
|
8
6
|
STATE_FAILED = '1'
|
9
7
|
|
@@ -12,27 +10,28 @@ module Bipbip
|
|
12
10
|
|
13
11
|
def metrics_schema
|
14
12
|
[
|
15
|
-
|
16
|
-
|
13
|
+
{ name: 'Running', type: 'gauge', unit: 'Boolean' },
|
14
|
+
{ name: 'All_Services_ok', type: 'gauge', unit: 'Boolean' }
|
17
15
|
]
|
18
16
|
end
|
19
17
|
|
20
18
|
def monitor
|
21
|
-
status =
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
19
|
+
status = ::Monit::Status.new({
|
20
|
+
host: 'localhost',
|
21
|
+
port: 2812,
|
22
|
+
ssl: false,
|
23
|
+
auth: false,
|
24
|
+
username: nil,
|
25
|
+
password: nil
|
28
26
|
}.merge(config))
|
29
27
|
|
30
28
|
data = Hash.new(0)
|
31
29
|
|
32
30
|
begin
|
33
31
|
data['Running'] = status.get ? 1 : 0
|
34
|
-
data['All_Services_ok'] = status.services.any?
|
35
|
-
service.monitor == MONITOR_NOT || service.status == STATE_FAILED
|
32
|
+
data['All_Services_ok'] = status.services.any? do |service|
|
33
|
+
service.monitor == MONITOR_NOT || service.status == STATE_FAILED
|
34
|
+
end ? 0 : 1
|
36
35
|
rescue
|
37
36
|
data['Running'] = 0
|
38
37
|
data['All_Services_ok'] = 0
|
data/lib/bipbip/plugin/mysql.rb
CHANGED
@@ -1,43 +1,41 @@
|
|
1
1
|
require 'mysql2'
|
2
2
|
|
3
3
|
module Bipbip
|
4
|
-
|
5
4
|
class Plugin::Mysql < Plugin
|
6
|
-
|
7
5
|
def metrics_schema
|
8
6
|
[
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
{ name: 'Max_used_connections', type: 'gauge', unit: 'Connections' },
|
8
|
+
{ name: 'Connections', type: 'counter', unit: 'Connections' },
|
9
|
+
{ name: 'Threads_connected', type: 'gauge', unit: 'Threads' },
|
12
10
|
|
13
|
-
|
14
|
-
|
11
|
+
{ name: 'Slave_running', type: 'gauge', unit: 'Boolean' },
|
12
|
+
{ name: 'Seconds_Behind_Master', type: 'gauge', unit: 'Seconds' },
|
15
13
|
|
16
|
-
|
14
|
+
{ name: 'Created_tmp_disk_tables', type: 'counter', unit: 'Tables' },
|
17
15
|
|
18
|
-
|
19
|
-
|
16
|
+
{ name: 'Queries', type: 'counter', unit: 'Queries' },
|
17
|
+
{ name: 'Slow_queries', type: 'counter', unit: 'Queries' },
|
20
18
|
|
21
|
-
|
22
|
-
|
19
|
+
{ name: 'Table_locks_immediate', type: 'counter', unit: 'Locks' },
|
20
|
+
{ name: 'Table_locks_waited', type: 'counter', unit: 'Locks' },
|
23
21
|
|
24
|
-
|
25
|
-
|
22
|
+
{ name: 'Processlist', type: 'gauge', unit: 'Processes' },
|
23
|
+
{ name: 'Processlist_Locked', type: 'gauge', unit: 'Processes' },
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
{ name: 'Com_select', type: 'counter', unit: 'Commands' },
|
26
|
+
{ name: 'Com_delete', type: 'counter', unit: 'Commands' },
|
27
|
+
{ name: 'Com_insert', type: 'counter', unit: 'Commands' },
|
28
|
+
{ name: 'Com_update', type: 'counter', unit: 'Commands' },
|
29
|
+
{ name: 'Com_replace', type: 'counter', unit: 'Commands' }
|
32
30
|
]
|
33
31
|
end
|
34
32
|
|
35
33
|
def monitor
|
36
34
|
mysql = Mysql2::Client.new(
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
host: config['hostname'],
|
36
|
+
port: config['port'],
|
37
|
+
username: config['username'],
|
38
|
+
password: config['password']
|
41
39
|
)
|
42
40
|
|
43
41
|
stats = Hash.new(0)
|