litestack 0.2.6 → 0.3.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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +1 -1
- data/assets/event_page.png +0 -0
- data/assets/index_page.png +0 -0
- data/assets/topic_page.png +0 -0
- data/lib/action_cable/subscription_adapter/litecable.rb +1 -11
- data/lib/generators/litestack/install/templates/database.yml +5 -1
- data/lib/litestack/liteboard/liteboard.rb +172 -35
- data/lib/litestack/liteboard/views/index.erb +52 -20
- data/lib/litestack/liteboard/views/layout.erb +189 -38
- data/lib/litestack/liteboard/views/litecable.erb +118 -0
- data/lib/litestack/liteboard/views/litecache.erb +144 -0
- data/lib/litestack/liteboard/views/litedb.erb +168 -0
- data/lib/litestack/liteboard/views/litejob.erb +151 -0
- data/lib/litestack/litecable.rb +24 -34
- data/lib/litestack/litecable.sql.yml +1 -1
- data/lib/litestack/litecache.rb +6 -17
- data/lib/litestack/litedb.rb +11 -2
- data/lib/litestack/litemetric.rb +43 -66
- data/lib/litestack/litemetric.sql.yml +14 -12
- data/lib/litestack/litemetric_collector.sql.yml +4 -4
- data/lib/litestack/litequeue.rb +9 -20
- data/lib/litestack/litesupport.rb +41 -20
- data/lib/litestack/version.rb +1 -1
- data/lib/litestack.rb +1 -1
- metadata +9 -2
@@ -0,0 +1,168 @@
|
|
1
|
+
<div class = "row">
|
2
|
+
|
3
|
+
<div class = "col">
|
4
|
+
<div class="card">
|
5
|
+
<div class="card-header">
|
6
|
+
Size
|
7
|
+
</div>
|
8
|
+
<div class="card-body">
|
9
|
+
<h1><%=round(@size)%>MB</h1>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class = "col">
|
15
|
+
<div class="card">
|
16
|
+
<div class="card-header">
|
17
|
+
Tables
|
18
|
+
</div>
|
19
|
+
<div class="card-body">
|
20
|
+
<h1><%=@tables%></h1>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class = "col">
|
26
|
+
<div class="card">
|
27
|
+
<div class="card-header">
|
28
|
+
Indexes
|
29
|
+
</div>
|
30
|
+
<div class="card-body">
|
31
|
+
<h1><%=@indexes%></h1>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<div class = "col">
|
37
|
+
<div class="card">
|
38
|
+
<div class="card-header">
|
39
|
+
Read queries
|
40
|
+
</div>
|
41
|
+
<div class="card-body">
|
42
|
+
<h1><%=format(@reads)%></h1>
|
43
|
+
</div>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<div class = "col">
|
48
|
+
<div class="card">
|
49
|
+
<div class="card-header">
|
50
|
+
Write queries
|
51
|
+
</div>
|
52
|
+
<div class="card-body">
|
53
|
+
<h1><%=format(@writes)%></h1>
|
54
|
+
</div>
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
|
58
|
+
|
59
|
+
</div>
|
60
|
+
|
61
|
+
<div class = "row">
|
62
|
+
<br/>
|
63
|
+
</div>
|
64
|
+
|
65
|
+
<div class = "row">
|
66
|
+
|
67
|
+
<div class = "col">
|
68
|
+
<div class="card">
|
69
|
+
<div class="card-header">
|
70
|
+
Reads vs writes over time
|
71
|
+
</div>
|
72
|
+
<div class="card-body">
|
73
|
+
<span class="hidden inlinecolumn"><%=Oj.dump([["Time", "Reads", "Writes"]] + @reads_vs_writes)%></span>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
<div class = "col-6">
|
79
|
+
<div class="card">
|
80
|
+
<div class="card-header">
|
81
|
+
Reads vs writes
|
82
|
+
</div>
|
83
|
+
<div class="card-body">
|
84
|
+
<span class="hidden inlinepie"><%=[["name", "value"],["reads", @reads],["writes", @writes]]%></span>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
</div>
|
88
|
+
|
89
|
+
</div>
|
90
|
+
|
91
|
+
<div class = "row">
|
92
|
+
<br/>
|
93
|
+
</div>
|
94
|
+
|
95
|
+
<div class = "row">
|
96
|
+
|
97
|
+
<div class = "col">
|
98
|
+
<div class="card">
|
99
|
+
<div class="card-header">
|
100
|
+
Query execution time over time
|
101
|
+
</div>
|
102
|
+
<div class="card-body">
|
103
|
+
<span class="hidden inlinecolumn"><%=Oj.dump([["Time", "Reads execution time", {'role' => 'tooltip'}, "Writes execution time", {'role' => 'tooltip'}]] + @reads_vs_writes_times)%></span>
|
104
|
+
</div>
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
|
108
|
+
<div class = "col-6">
|
109
|
+
<div class="card">
|
110
|
+
<div class="card-header">
|
111
|
+
Query time
|
112
|
+
</div>
|
113
|
+
<div class="card-body">
|
114
|
+
<span class="hidden inlinepie"><%=[["name", "value"],["total reads time", @read_times],["total writes time", @write_times]]%></span>
|
115
|
+
</div>
|
116
|
+
</div>
|
117
|
+
</div>
|
118
|
+
|
119
|
+
</div>
|
120
|
+
|
121
|
+
<div class = "row">
|
122
|
+
<br/>
|
123
|
+
</div>
|
124
|
+
|
125
|
+
<div class = "row">
|
126
|
+
|
127
|
+
<div class = "col-6">
|
128
|
+
<div class="card">
|
129
|
+
<div class="card-header">
|
130
|
+
Slowest queries
|
131
|
+
</div>
|
132
|
+
<div class="card-body">
|
133
|
+
<table class="table">
|
134
|
+
<%@slowest.each do |r| %>
|
135
|
+
<tr>
|
136
|
+
<td><%=r['key']%></td>
|
137
|
+
<td align="right"><h6><%=format(r['ravg'].truncate(4))%> sec</h6></td>
|
138
|
+
</tr>
|
139
|
+
<% end %>
|
140
|
+
</table>
|
141
|
+
</div>
|
142
|
+
</div>
|
143
|
+
</div>
|
144
|
+
|
145
|
+
<div class = "col-6">
|
146
|
+
<div class="card">
|
147
|
+
<div class="card-header">
|
148
|
+
Most expensive queries (execution time x frequency)
|
149
|
+
</div>
|
150
|
+
<div class="card-body">
|
151
|
+
<table class="table">
|
152
|
+
<%@popular.each do |r| %>
|
153
|
+
<tr>
|
154
|
+
<td><%=r['key']%></td>
|
155
|
+
<td align="right"><h6><%=format(r['rtotal'].truncate(4))%> sec</h6></td>
|
156
|
+
</tr>
|
157
|
+
<% end %>
|
158
|
+
</table>
|
159
|
+
</div>
|
160
|
+
</div>
|
161
|
+
</div>
|
162
|
+
|
163
|
+
</div>
|
164
|
+
|
165
|
+
<div class = "row">
|
166
|
+
<br/>
|
167
|
+
</div>
|
168
|
+
|
@@ -0,0 +1,151 @@
|
|
1
|
+
<div class = "row">
|
2
|
+
|
3
|
+
<div class = "col">
|
4
|
+
<div class="card">
|
5
|
+
<div class="card-header">
|
6
|
+
Size
|
7
|
+
</div>
|
8
|
+
<div class="card-body">
|
9
|
+
<h1><%=format(round(@size))%> MB</h1>
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class = "col">
|
15
|
+
<div class="card">
|
16
|
+
<div class="card-header">
|
17
|
+
Active queues
|
18
|
+
</div>
|
19
|
+
<div class="card-body">
|
20
|
+
<h1><%=format(@queues.length)%></h1>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<div class = "col">
|
26
|
+
<div class="card">
|
27
|
+
<div class="card-header">
|
28
|
+
Outstanding jobs
|
29
|
+
</div>
|
30
|
+
<div class="card-body">
|
31
|
+
<h1><%=format(@jobs)%></h1>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<div class = "row">
|
39
|
+
<br/>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
|
43
|
+
<div class="row">
|
44
|
+
|
45
|
+
<div class = "col">
|
46
|
+
<div class="card">
|
47
|
+
<div class="card-header">
|
48
|
+
Processed jobs
|
49
|
+
</div>
|
50
|
+
<div class="card-body">
|
51
|
+
<h1><%=format(@processed_count)%> jobs</h1>
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
|
56
|
+
<div class = "col">
|
57
|
+
<div class="card">
|
58
|
+
<div class="card-header">
|
59
|
+
Total processing time
|
60
|
+
</div>
|
61
|
+
<div class="card-body">
|
62
|
+
<h1><%=format(@processing_time)%> sec</h1>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
|
67
|
+
<div class = "col">
|
68
|
+
<div class="card">
|
69
|
+
<div class="card-header">
|
70
|
+
Average processing time per job
|
71
|
+
</div>
|
72
|
+
<div class="card-body">
|
73
|
+
<h1><%=(@processing_time.to_f / @processed_count).truncate(4) rescue 0%> sec</h1>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
</div>
|
79
|
+
|
80
|
+
<div class = "row">
|
81
|
+
<br/>
|
82
|
+
</div>
|
83
|
+
|
84
|
+
<div class="row">
|
85
|
+
|
86
|
+
<div class = "col">
|
87
|
+
<div class="card">
|
88
|
+
<div class="card-header">
|
89
|
+
Processed jobs by queue
|
90
|
+
</div>
|
91
|
+
<div class="card-body">
|
92
|
+
<span class="hidden inlinepie">
|
93
|
+
<%=[["name", "value"]] + @processed_count_by_queue.to_a%>
|
94
|
+
</span>
|
95
|
+
</div>
|
96
|
+
</div>
|
97
|
+
</div>
|
98
|
+
|
99
|
+
<div class = "col">
|
100
|
+
<div class="card">
|
101
|
+
<div class="card-header">
|
102
|
+
Job processing time by queue
|
103
|
+
</div>
|
104
|
+
<div class="card-body">
|
105
|
+
<span class="hidden inlinepie">
|
106
|
+
<%=[["name", "value"]] + @processing_time_by_queue.to_a%>
|
107
|
+
</span>
|
108
|
+
</div>
|
109
|
+
</div>
|
110
|
+
</div>
|
111
|
+
|
112
|
+
</div>
|
113
|
+
|
114
|
+
<div class = "row">
|
115
|
+
<br/>
|
116
|
+
</div>
|
117
|
+
|
118
|
+
<div class="row">
|
119
|
+
|
120
|
+
<div class = "col">
|
121
|
+
<div class="card">
|
122
|
+
<div class="card-header">
|
123
|
+
Processed jobs by queue over time
|
124
|
+
</div>
|
125
|
+
<div class="card-body">
|
126
|
+
<span class="hidden inlinestackedcolumn">
|
127
|
+
<%=@processed_count_over_time_by_queues.to_a%>
|
128
|
+
</span>
|
129
|
+
</div>
|
130
|
+
</div>
|
131
|
+
</div>
|
132
|
+
|
133
|
+
<div class = "col">
|
134
|
+
<div class="card">
|
135
|
+
<div class="card-header">
|
136
|
+
Job processing time by queue over time
|
137
|
+
</div>
|
138
|
+
<div class="card-body">
|
139
|
+
<span class="hidden inlinestackedcolumn">
|
140
|
+
<%=@processing_time_over_time_by_queues.to_a%>
|
141
|
+
</span>
|
142
|
+
</div>
|
143
|
+
</div>
|
144
|
+
</div>
|
145
|
+
|
146
|
+
</div>
|
147
|
+
|
148
|
+
<div class = "row">
|
149
|
+
<br/>
|
150
|
+
</div>
|
151
|
+
|
data/lib/litestack/litecable.rb
CHANGED
@@ -24,52 +24,54 @@ class Litecable
|
|
24
24
|
}
|
25
25
|
|
26
26
|
def initialize(options = {})
|
27
|
-
@messages = []
|
27
|
+
@messages = Litesupport::Pool.new(1){[]}
|
28
28
|
init(options)
|
29
|
+
collect_metrics if @options[:metrics]
|
29
30
|
end
|
30
31
|
|
31
32
|
# broadcast a message to a specific channel
|
32
33
|
def broadcast(channel, payload=nil)
|
33
34
|
# group meesages and only do broadcast every 10 ms
|
34
|
-
#run_stmt(:publish, channel.to_s, Oj.dump(payload), @pid)
|
35
35
|
# but broadcast locally normally
|
36
|
-
@
|
36
|
+
@messages.acquire{|msgs| msgs << [channel.to_s, Oj.dump(payload)]}
|
37
|
+
capture(:broadcast, channel)
|
37
38
|
local_broadcast(channel, payload)
|
38
39
|
end
|
39
40
|
|
40
41
|
# subscribe to a channel, optionally providing a success callback proc
|
41
42
|
def subscribe(channel, subscriber, success_callback = nil)
|
42
|
-
@
|
43
|
-
|
44
|
-
|
43
|
+
@subscribers.acquire do |subs|
|
44
|
+
subs[channel] = {} unless subs[channel]
|
45
|
+
subs[channel][subscriber] = true
|
45
46
|
end
|
47
|
+
capture(:subscribe, channel)
|
46
48
|
end
|
47
49
|
|
48
50
|
# unsubscribe from a channel
|
49
51
|
def unsubscribe(channel, subscriber)
|
50
|
-
@
|
51
|
-
|
52
|
-
end
|
52
|
+
@subscribers.acquire{|subs| subs[channel].delete(subscriber) rescue nil }
|
53
|
+
capture(:unsubscribe, channel)
|
53
54
|
end
|
54
55
|
|
55
56
|
private
|
56
|
-
|
57
|
+
|
58
|
+
# broadcast the message to local subscribers
|
57
59
|
def local_broadcast(channel, payload=nil)
|
58
|
-
return unless @subscribers[channel]
|
59
60
|
subscribers = []
|
60
|
-
@
|
61
|
-
|
61
|
+
@subscribers.acquire do |subs|
|
62
|
+
return unless subs[channel]
|
63
|
+
subscribers = subs[channel].keys
|
62
64
|
end
|
63
65
|
subscribers.each do |subscriber|
|
64
66
|
subscriber.call(payload)
|
67
|
+
capture(:message, channel)
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
68
71
|
def setup
|
69
72
|
super # create connection
|
70
73
|
@pid = Process.pid
|
71
|
-
@subscribers = {}
|
72
|
-
@mutex = Litesupport::Mutex.new
|
74
|
+
@subscribers = Litesupport::Pool.new(1){{}}
|
73
75
|
@running = true
|
74
76
|
@listener = create_listener
|
75
77
|
@pruner = create_pruner
|
@@ -80,14 +82,14 @@ class Litecable
|
|
80
82
|
def create_broadcaster
|
81
83
|
Litesupport.spawn do
|
82
84
|
while @running do
|
83
|
-
@
|
84
|
-
if
|
85
|
+
@messages.acquire do |msgs|
|
86
|
+
if msgs.length > 0
|
85
87
|
run_sql("BEGIN IMMEDIATE")
|
86
|
-
while msg =
|
88
|
+
while msg = msgs.shift
|
87
89
|
run_stmt(:publish, msg[0], msg[1], @pid)
|
88
90
|
end
|
89
91
|
run_sql("END")
|
90
|
-
end
|
92
|
+
end
|
91
93
|
end
|
92
94
|
sleep 0.02
|
93
95
|
end
|
@@ -107,7 +109,6 @@ class Litecable
|
|
107
109
|
Litesupport.spawn do
|
108
110
|
while @running do
|
109
111
|
@last_fetched_id ||= (run_stmt(:last_id)[0][0] || 0)
|
110
|
-
@logger.info @last_fetched_id
|
111
112
|
run_stmt(:fetch, @last_fetched_id, @pid).to_a.each do |msg|
|
112
113
|
@logger.info "RECEIVED #{msg}"
|
113
114
|
@last_fetched_id = msg[0]
|
@@ -119,20 +120,9 @@ class Litecable
|
|
119
120
|
end
|
120
121
|
|
121
122
|
def create_connection
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
version = conn.get_first_value("PRAGMA user_version")
|
126
|
-
sql["schema"].each_pair do |v, obj|
|
127
|
-
if v > version
|
128
|
-
conn.transaction do
|
129
|
-
obj.each{|k, s| conn.execute(s)}
|
130
|
-
conn.user_version = v
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
sql["stmts"].each { |k, v| conn.stmts[k.to_sym] = conn.prepare(v) }
|
135
|
-
conn
|
123
|
+
super("#{__dir__}/litecable.sql.yml") do |conn|
|
124
|
+
conn.wal_autocheckpoint = 10000
|
125
|
+
end
|
136
126
|
end
|
137
127
|
|
138
128
|
end
|
@@ -17,7 +17,7 @@ stmts:
|
|
17
17
|
|
18
18
|
last_id: SELECT max(id) FROM messages
|
19
19
|
|
20
|
-
fetch: SELECT id, channel, value FROM messages WHERE id > $1 and pid != $2
|
20
|
+
fetch: SELECT id, channel, value, created_at FROM messages WHERE id > $1 and pid != $2
|
21
21
|
|
22
22
|
prune: DELETE FROM messages WHERE created_at < (unixepoch() - $1)
|
23
23
|
|
data/lib/litestack/litecache.rb
CHANGED
@@ -236,23 +236,12 @@ class Litecache
|
|
236
236
|
end
|
237
237
|
|
238
238
|
def create_connection
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
version = conn.get_first_value("PRAGMA user_version")
|
246
|
-
sql["schema"].each_pair do |v, obj|
|
247
|
-
if v > version
|
248
|
-
conn.transaction do
|
249
|
-
obj.each{|k, s| conn.execute(s)}
|
250
|
-
conn.user_version = v
|
251
|
-
end
|
252
|
-
end
|
253
|
-
end
|
254
|
-
sql["stmts"].each { |k, v| conn.stmts[k.to_sym] = conn.prepare(v) }
|
255
|
-
conn
|
239
|
+
super("#{__dir__}/litecache.sql.yml") do |conn|
|
240
|
+
conn.cache_size = 2000
|
241
|
+
conn.journal_size_limit = [(@options[:size]/2).to_i, @options[:min_size]].min
|
242
|
+
conn.max_page_count = (@options[:size] / conn.page_size).to_i
|
243
|
+
conn.case_sensitive_like = true
|
244
|
+
end
|
256
245
|
end
|
257
246
|
|
258
247
|
end
|
data/lib/litestack/litedb.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# all components should require the support module
|
2
2
|
require_relative 'litesupport'
|
3
3
|
|
4
|
+
# all measurable components should require the litemetric class
|
5
|
+
require_relative 'litemetric'
|
6
|
+
|
4
7
|
# Litedb inherits from the SQLite3::Database class and adds a few initialization options
|
5
8
|
class Litedb < ::SQLite3::Database
|
6
9
|
|
@@ -34,7 +37,11 @@ class Litedb < ::SQLite3::Database
|
|
34
37
|
|
35
38
|
# return the size of the database file
|
36
39
|
def size
|
37
|
-
execute("SELECT s.page_size * c.page_count FROM pragma_page_size()
|
40
|
+
execute("SELECT s.page_size * c.page_count FROM pragma_page_size() AS s, pragma_page_count() AS c")[0][0]
|
41
|
+
end
|
42
|
+
|
43
|
+
def schema_object_count(type = nil)
|
44
|
+
execute("SELECT count(*) FROM SQLITE_MASTER WHERE iif(?1 IS NOT NULL, type = ?1, TRUE)", type)[0][0]
|
38
45
|
end
|
39
46
|
|
40
47
|
# collect snapshot information
|
@@ -44,7 +51,9 @@ class Litedb < ::SQLite3::Database
|
|
44
51
|
path: filename,
|
45
52
|
journal_mode: journal_mode,
|
46
53
|
synchronous: synchronous,
|
47
|
-
size: size
|
54
|
+
size: size.to_f / (1024 * 1024),
|
55
|
+
tables: schema_object_count('table'),
|
56
|
+
indexes: schema_object_count('index')
|
48
57
|
}
|
49
58
|
}
|
50
59
|
end
|
data/lib/litestack/litemetric.rb
CHANGED
@@ -55,9 +55,12 @@ class Litemetric
|
|
55
55
|
## event capturing
|
56
56
|
##################
|
57
57
|
|
58
|
+
def current_time_slot
|
59
|
+
(Time.now.to_i / 300) * 300
|
60
|
+
end
|
58
61
|
|
59
62
|
def capture(topic, event, key=event, value=nil)
|
60
|
-
@collector.capture(topic, event, key, value)
|
63
|
+
@collector.capture(topic, event, key, value, current_time_slot)
|
61
64
|
end
|
62
65
|
|
63
66
|
def capture_snapshot(topic, state)
|
@@ -83,18 +86,18 @@ class Litemetric
|
|
83
86
|
def events_summaries(topic, resolution, order, dir, search, count)
|
84
87
|
search = "%#{search}%" if search
|
85
88
|
if dir.downcase == "desc"
|
86
|
-
|
89
|
+
run_stmt_hash(:events_summaries, topic, resolution, order, search, count)
|
87
90
|
else
|
88
|
-
|
91
|
+
run_stmt_hash(:events_summaries_asc, topic, resolution, order, search, count)
|
89
92
|
end
|
90
93
|
end
|
91
94
|
|
92
95
|
def keys_summaries(topic, event, resolution, order, dir, search, count)
|
93
96
|
search = "%#{search}%" if search
|
94
97
|
if dir.downcase == "desc"
|
95
|
-
|
98
|
+
run_stmt_hash(:keys_summaries, topic, event, resolution, order, search, count).to_a
|
96
99
|
else
|
97
|
-
|
100
|
+
run_stmt_hash(:keys_summaries_asc, topic, event, resolution, order, search, count).to_a
|
98
101
|
end
|
99
102
|
end
|
100
103
|
|
@@ -103,11 +106,11 @@ class Litemetric
|
|
103
106
|
end
|
104
107
|
|
105
108
|
def event_data_points(step, count, resolution, topic, event)
|
106
|
-
|
109
|
+
run_stmt_hash(:event_data_points, step, count, resolution, topic, event).to_a
|
107
110
|
end
|
108
111
|
|
109
112
|
def key_data_points(step, count, resolution, topic, event, key)
|
110
|
-
|
113
|
+
run_stmt_hash(:key_data_points, step, count, resolution, topic, event, key).to_a
|
111
114
|
end
|
112
115
|
|
113
116
|
def snapshot(topic)
|
@@ -130,7 +133,21 @@ class Litemetric
|
|
130
133
|
###################
|
131
134
|
|
132
135
|
private
|
133
|
-
|
136
|
+
|
137
|
+
def run_stmt_hash(stmt, *args)
|
138
|
+
res = run_stmt(stmt, *args)
|
139
|
+
cols = run_stmt_method(stmt, :columns)
|
140
|
+
hashes = []
|
141
|
+
res.each do | row |
|
142
|
+
hash = {}
|
143
|
+
row.each_with_index do |field, i|
|
144
|
+
hash[cols[i]] = field
|
145
|
+
end
|
146
|
+
hashes << hash
|
147
|
+
end
|
148
|
+
hashes
|
149
|
+
end
|
150
|
+
|
134
151
|
def exit_callback
|
135
152
|
STDERR.puts "--- Litemetric detected an exit, flushing metrics"
|
136
153
|
@running = false
|
@@ -156,25 +173,9 @@ class Litemetric
|
|
156
173
|
end
|
157
174
|
|
158
175
|
def create_connection
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
version = conn.get_first_value("PRAGMA user_version")
|
163
|
-
sql["schema"].each_pair do |v, obj|
|
164
|
-
if v > version
|
165
|
-
begin
|
166
|
-
conn.transaction do
|
167
|
-
obj.each{|k, s| conn.execute(s)}
|
168
|
-
conn.user_version = v
|
169
|
-
end
|
170
|
-
rescue Exception => e
|
171
|
-
STDERR.puts e.message
|
172
|
-
raise e
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
sql["stmts"].each { |k, v| conn.stmts[k.to_sym] = conn.prepare(v) }
|
177
|
-
conn
|
176
|
+
super("#{__dir__}/litemetric.sql.yml") do |conn|
|
177
|
+
conn.wal_autocheckpoint = 10000 # checkpoint after 10000 pages are written
|
178
|
+
end
|
178
179
|
end
|
179
180
|
|
180
181
|
def create_flusher
|
@@ -228,13 +229,16 @@ class Litemetric
|
|
228
229
|
end
|
229
230
|
|
230
231
|
def measure(event, key=event)
|
231
|
-
|
232
|
+
unless @litemetric
|
233
|
+
yield
|
234
|
+
return 0
|
235
|
+
end
|
232
236
|
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
233
|
-
|
237
|
+
yield
|
234
238
|
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
235
|
-
value =
|
239
|
+
value = t2 - t1
|
236
240
|
capture(event, key, value)
|
237
|
-
|
241
|
+
value # return value so other events can reuse it
|
238
242
|
end
|
239
243
|
|
240
244
|
def capture_snapshot
|
@@ -273,16 +277,16 @@ class Litemetric
|
|
273
277
|
init(options)
|
274
278
|
end
|
275
279
|
|
276
|
-
def capture(topic, event, key, value=nil)
|
280
|
+
def capture(topic, event, key, value=nil, time=nil)
|
277
281
|
if key.is_a? Array
|
278
|
-
key.each{|k| capture_single_key(topic, event, k, value)}
|
282
|
+
key.each{|k| capture_single_key(topic, event, k, value, time)}
|
279
283
|
else
|
280
|
-
capture_single_key(topic, event, key, value)
|
284
|
+
capture_single_key(topic, event, key, value, time)
|
281
285
|
end
|
282
286
|
end
|
283
287
|
|
284
|
-
def capture_single_key(topic, event, key, value)
|
285
|
-
run_stmt(:capture_event, topic.to_s, event.to_s, key.to_s,
|
288
|
+
def capture_single_key(topic, event, key, value, time=nil)
|
289
|
+
run_stmt(:capture_event, topic.to_s, event.to_s, key.to_s, time ,1, value)
|
286
290
|
end
|
287
291
|
|
288
292
|
def flush
|
@@ -302,37 +306,10 @@ class Litemetric
|
|
302
306
|
end
|
303
307
|
|
304
308
|
def create_connection
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
sql = YAML.load_file("#{__dir__}/litemetric_collector.sql.yml")
|
309
|
-
version = conn.get_first_value("PRAGMA user_version")
|
310
|
-
sql["schema"].each_pair do |v, obj|
|
311
|
-
if v > version
|
312
|
-
conn.transaction do
|
313
|
-
obj.each do |k, s|
|
314
|
-
begin
|
315
|
-
conn.execute(s)
|
316
|
-
rescue Exception => e
|
317
|
-
STDERR.puts "Error parsing #{k}"
|
318
|
-
STDERR.puts s
|
319
|
-
raise e
|
320
|
-
end
|
321
|
-
end
|
322
|
-
conn.user_version = v
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
sql["stmts"].each do |k, v|
|
327
|
-
begin
|
328
|
-
conn.stmts[k.to_sym] = conn.prepare(v)
|
329
|
-
rescue Exception => e
|
330
|
-
STDERR.puts "Error parsing #{k}"
|
331
|
-
STDERR.puts v
|
332
|
-
raise e
|
333
|
-
end
|
309
|
+
super("#{__dir__}/litemetric_collector.sql.yml") do |conn|
|
310
|
+
conn.execute("ATTACH ? as m", @options[:dbpath].to_s)
|
311
|
+
conn.wal_autocheckpoint = 10000
|
334
312
|
end
|
335
|
-
conn
|
336
313
|
end
|
337
314
|
|
338
315
|
end
|