ramaze-fnordmetric 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +16 -0
- data/.rvmrc +1 -0
- data/Gemfile +3 -0
- data/LICENSE +19 -0
- data/README.md +321 -0
- data/Rakefile +17 -0
- data/examples/README.md +25 -0
- data/examples/example.rb +82 -0
- data/examples/fn.rb +118 -0
- data/lib/ramaze/helper/fnordmetric.rb +306 -0
- data/lib/ramaze/helper/fnordmetric/spec/bacon/color_output.rb +39 -0
- data/lib/ramaze/helper/fnordmetric/spec/helper.rb +6 -0
- data/pkg/.gitkeep +0 -0
- data/ramaze-fnordmetric.gemspec +25 -0
- data/spec/helper.rb +2 -0
- data/spec/ramaze_fnordmetric/fnordmetric.rb +209 -0
- data/task/bacon.rake +16 -0
- data/task/build.rake +34 -0
- data/task/clean.rake +4 -0
- data/task/test.rake +8 -0
- metadata +215 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use --create 1.9.2@ramaze_fnordmetric
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2012, Michel Blanc / ERASME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,321 @@
|
|
1
|
+
Ramaze::Helper::Fnordmetric
|
2
|
+
===========================
|
3
|
+
|
4
|
+
[![Build Status](https://secure.travis-ci.org/leucos/ramaze-fnordmetric.png?branch=master)](http://travis-ci.org/leucos/ramaze-fnordmetric)
|
5
|
+
|
6
|
+
__A [Ramaze][1] helper that makes it easy to use [Fnordmetric][2] in your
|
7
|
+
Ramaze web-applications__
|
8
|
+
|
9
|
+
----
|
10
|
+
|
11
|
+
Features
|
12
|
+
--------
|
13
|
+
|
14
|
+
|
15
|
+
Usage
|
16
|
+
-----
|
17
|
+
|
18
|
+
### Using in your code ###
|
19
|
+
|
20
|
+
#### Loading the helper ####
|
21
|
+
|
22
|
+
Since this is a Ramaze helper, you can use it just like another helper :
|
23
|
+
|
24
|
+
class Users < Controller
|
25
|
+
helper :fnordmetric
|
26
|
+
...
|
27
|
+
end
|
28
|
+
|
29
|
+
#### Redis configuration ####
|
30
|
+
|
31
|
+
Since Fnordmetric uses Redis, you can configure the server to use using traits
|
32
|
+
in your controller :
|
33
|
+
|
34
|
+
trait :fnord_redis_url => "redis://redis.example.com:6332"
|
35
|
+
|
36
|
+
If not, Fnordmetric will use the default redis stuff (`redis://localhost:6379`).
|
37
|
+
|
38
|
+
You can also set how long the helper internal structures (timers, see below)
|
39
|
+
will be kept in Redis using `trait :fnord_helper_key_ttl => 3600`
|
40
|
+
|
41
|
+
By default, they will be kept `Innate::Session.options.ttl` seconds.
|
42
|
+
|
43
|
+
#### Events and sessions ####
|
44
|
+
|
45
|
+
All Fnordmetric events are linked to the session (`innate.sid`) of the currently
|
46
|
+
handled request. This makes it easy to track which events occured in which
|
47
|
+
session.
|
48
|
+
|
49
|
+
If you're dealing with authenticated users, you might want to associate a name
|
50
|
+
to the user sessions so your Fnormetric app displays a user name instead of a
|
51
|
+
session id :
|
52
|
+
|
53
|
+
# Associates a user name to the current innate.sid
|
54
|
+
set_name("#{user.name} #{user.surname}")
|
55
|
+
|
56
|
+
You can also set a picture for the current session, using the gravatar helper for instance :
|
57
|
+
|
58
|
+
# Fnordmetric will display a picture next to the user
|
59
|
+
set_picture(gravatar(user.email.to_s)) if user.email
|
60
|
+
|
61
|
+
### Sending an event ###
|
62
|
+
|
63
|
+
To send an event to Fnordmetric, use the `event` method :
|
64
|
+
|
65
|
+
event(:user_login, :is_admin => "yes")
|
66
|
+
|
67
|
+
### Recording page views
|
68
|
+
|
69
|
+
You can record a pageview Fnordmetric event using `pageview` :
|
70
|
+
|
71
|
+
pageview '/some/page/path'
|
72
|
+
|
73
|
+
Since all events are sent along with the current session id, this leaves a nice
|
74
|
+
per-session audit trail.
|
75
|
+
|
76
|
+
### Measuring execution time for code section ###
|
77
|
+
|
78
|
+
If you want to measure the time taken for a particular section of code, you can start a timer before your code, and stop it when you're done.
|
79
|
+
|
80
|
+
# Measuring code execution times
|
81
|
+
# We just start a stopwatch
|
82
|
+
push_timer(:performance, :field => :whatever_you_want_here)
|
83
|
+
|
84
|
+
# Oh well, I'm doing something here that needs to be measured
|
85
|
+
sleep(1)
|
86
|
+
|
87
|
+
# Let's stop the stopwatch
|
88
|
+
# This automatically sends an event to Fnordmetric
|
89
|
+
pop_timer
|
90
|
+
|
91
|
+
`push_timer` and `pop_timer` can be nested :
|
92
|
+
|
93
|
+
def login
|
94
|
+
@title = "Connect"
|
95
|
+
|
96
|
+
redirect_referer if logged_in?
|
97
|
+
return unless request.post?
|
98
|
+
|
99
|
+
# Let's push a timer to get the overall login timings
|
100
|
+
# We add some data to the event so we wan easily see what piece of code
|
101
|
+
# is involved in our Fnordmetric app
|
102
|
+
|
103
|
+
push_timer(:timing_data, :controller => :user, :method => :login)
|
104
|
+
user_login(request.subset(:email, :password))
|
105
|
+
|
106
|
+
# This is good, but we also want to see how much the following piece of
|
107
|
+
# code takes too
|
108
|
+
|
109
|
+
if logged_in?
|
110
|
+
# Ok, now let's say we want to pre-fill some kind of cache for the user
|
111
|
+
# and measure how long it takes
|
112
|
+
|
113
|
+
# Let's fire another stopwatch
|
114
|
+
push_timer(:timing_data, :code => :cache_retrieval)
|
115
|
+
fill_cache(user)
|
116
|
+
|
117
|
+
# Let's stop the last stopwatch, and send the event
|
118
|
+
pop_timer
|
119
|
+
|
120
|
+
else
|
121
|
+
flash[:error] = "Can't log in, invalid data"
|
122
|
+
end
|
123
|
+
|
124
|
+
# Ok, we've done our job, let's stop the first stopwatch we started and
|
125
|
+
# send metric
|
126
|
+
pop_timer
|
127
|
+
|
128
|
+
redirect_referrer
|
129
|
+
end
|
130
|
+
|
131
|
+
Easy peasy lemon squeezy.
|
132
|
+
|
133
|
+
### Measuring execution time for block ###
|
134
|
+
|
135
|
+
But the helper comes with block (like in &) timing methods too, so we can meke
|
136
|
+
the above code event simpler, replacing the inner `push_timer` and `pop_timer`
|
137
|
+
calls with the `times` method :
|
138
|
+
|
139
|
+
# Ok, now let's say we want to pre-fill some kind of cache for the user
|
140
|
+
# and measure how long it takes
|
141
|
+
|
142
|
+
# Let's fire another stopwatch
|
143
|
+
times(:timing_data, :code => :cache_retrieval) do
|
144
|
+
fill_cache(user)
|
145
|
+
end
|
146
|
+
|
147
|
+
Easier than before. The block passed to `times` will be measured.
|
148
|
+
|
149
|
+
### Measuring execution time for an action (controller method) ###
|
150
|
+
|
151
|
+
While the above block thing is nice, it could be great to do the same for a
|
152
|
+
whole method. The helper can do this too with the `clock` method :
|
153
|
+
|
154
|
+
def login
|
155
|
+
@title = "Connect"
|
156
|
+
|
157
|
+
# code code ...
|
158
|
+
|
159
|
+
redirect_referrer
|
160
|
+
end
|
161
|
+
clock :login, :timing_data, :controller => :user,
|
162
|
+
|
163
|
+
This will automagically measure execution time for the :login method (first
|
164
|
+
arg), sending an event named `timing_data` with some arbitrary argument
|
165
|
+
(controller in our case).
|
166
|
+
|
167
|
+
Note that `clock` always sets the `:method` key value in the arguments sent in
|
168
|
+
the event, so the tracked method is recorded in Fnordmetric.
|
169
|
+
|
170
|
+
Summing up, we can user all those methods like that :
|
171
|
+
|
172
|
+
def login
|
173
|
+
@title = "Connect"
|
174
|
+
|
175
|
+
redirect_referer if logged_in?
|
176
|
+
return unless request.post?
|
177
|
+
|
178
|
+
# Log in this fellow
|
179
|
+
user_login(request.subset(:email, :password))
|
180
|
+
|
181
|
+
# This is good, but we also want to see how much the following piece of
|
182
|
+
# code takes too
|
183
|
+
|
184
|
+
if logged_in?
|
185
|
+
# Hey, nice, user is logged in. Let'a associate name and picture as
|
186
|
+
# shown already
|
187
|
+
|
188
|
+
set_name("#{user.name} #{user.surname}")
|
189
|
+
set_picture(gravatar(user.email.to_s)) if user.email
|
190
|
+
|
191
|
+
# Ok, now let's say we want to pre-fill some kind of cache for the user
|
192
|
+
# and measure how long it takes
|
193
|
+
|
194
|
+
# Let's fire another stopwatch
|
195
|
+
push_timer(:timing_data, :code => :cache_retrieval)
|
196
|
+
fill_cache(user)
|
197
|
+
|
198
|
+
# Let's stop the last stopwatch, and send the event
|
199
|
+
pop_timer
|
200
|
+
|
201
|
+
else
|
202
|
+
flash[:error] = "Can't log in, invalid data"
|
203
|
+
end
|
204
|
+
|
205
|
+
# Ok, we've done our job, let's stop the first stopwatch we started and
|
206
|
+
# send metric
|
207
|
+
pop_timer
|
208
|
+
|
209
|
+
redirect_referrer
|
210
|
+
end
|
211
|
+
# We want to measure the whole method
|
212
|
+
clock :login, :timing_data, :controller => :user,
|
213
|
+
|
214
|
+
|
215
|
+
### Measuring all your actions time ###
|
216
|
+
|
217
|
+
Using Ramaze before/after controller facilities, you can easily measure
|
218
|
+
everything, send events before each method onvocation, etc...
|
219
|
+
|
220
|
+
class Controller < Ramaze::Controller
|
221
|
+
layout :default
|
222
|
+
helper :fnordmetric
|
223
|
+
|
224
|
+
# Let's record all pageviews for all controllers
|
225
|
+
before_all do
|
226
|
+
pageview request.env['REQUEST_PATH']
|
227
|
+
end
|
228
|
+
|
229
|
+
### Starting the Fnordmetric app ###
|
230
|
+
|
231
|
+
Ok, now that we measure everything we want, how do we see the stuff ?
|
232
|
+
Well, you have to write a Fnordmetric app.
|
233
|
+
|
234
|
+
This is quite simple, and is explained in detail in the [Fnordmetric][2] docs.
|
235
|
+
|
236
|
+
Here is a small example the show pages views :
|
237
|
+
|
238
|
+
|
239
|
+
#!/usr/bin/env ruby
|
240
|
+
#
|
241
|
+
require 'fnordmetric'
|
242
|
+
|
243
|
+
FnordMetric.namespace :myapp do
|
244
|
+
|
245
|
+
# Unique pageviews
|
246
|
+
gauge :pageviews_daily_unique, :tick => 1.day.to_i,
|
247
|
+
:unique => true,
|
248
|
+
:title => "Unique Visits (Daily)"
|
249
|
+
|
250
|
+
# _pageview is a special Fnordmetric event
|
251
|
+
# and as such starts with `_`
|
252
|
+
event :_pageview do
|
253
|
+
# increment the daily_uniques gauge by 1 if session_key hasn't been seen
|
254
|
+
# in this tick yet
|
255
|
+
incr :pageviews_daily_unique
|
256
|
+
# increment the pageviews_per_url_daily gauge by 1 where key = 'page2'
|
257
|
+
incr_field :pageviews_per_url_daily, data[:url]
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
# Widgets
|
262
|
+
widget 'Overview', {
|
263
|
+
:title => "Visits per day",
|
264
|
+
:type => :timeline,
|
265
|
+
:plot_style => :areaspline,
|
266
|
+
:gauges => :pageviews_daily_unique,
|
267
|
+
:include_current => true,
|
268
|
+
:autoupdate => 10
|
269
|
+
}
|
270
|
+
|
271
|
+
See the `examples/` directory for a worging example.
|
272
|
+
|
273
|
+
Caveats
|
274
|
+
-------
|
275
|
+
|
276
|
+
If sid changes (e.g. when a user logs in), timers won't pop properly. This
|
277
|
+
doesn't break, but will leave a nasty line in your logs. The next version will
|
278
|
+
take care of this.
|
279
|
+
|
280
|
+
Contributing
|
281
|
+
------------
|
282
|
+
|
283
|
+
fork / make a feature branch / change / specs / commit / send PR (devel branch)
|
284
|
+
|
285
|
+
Ack
|
286
|
+
---
|
287
|
+
|
288
|
+
Thanks to manveru & yorick for [Ramaze][1]. Man, those Rails zealots just don't
|
289
|
+
realize their pathetic fate :)
|
290
|
+
|
291
|
+
License
|
292
|
+
-------
|
293
|
+
|
294
|
+
`ramaze-fnordmetric` is licensed under the MIT license :
|
295
|
+
|
296
|
+
Copyright (c) 2012, Michel Blanc
|
297
|
+
|
298
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
299
|
+
of this software and associated documentation files (the "Software"), to deal
|
300
|
+
in the Software without restriction, including without limitation the rights
|
301
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
302
|
+
copies of the Software, and to permit persons to whom the Software is
|
303
|
+
furnished to do so, subject to the following conditions:
|
304
|
+
|
305
|
+
The above copyright notice and this permission notice shall be included in
|
306
|
+
all copies or substantial portions of the Software.
|
307
|
+
|
308
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
309
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
310
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
311
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
312
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
313
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
314
|
+
THE SOFTWARE.
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
[1]: https://github.com/ramaze/ramaze
|
319
|
+
[2]: https://github.com/paulasmuth/fnordmetric
|
320
|
+
|
321
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
task_dir = File.expand_path('../task', __FILE__)
|
2
|
+
|
3
|
+
Dir.glob("#{task_dir}/*.rake").each do |f|
|
4
|
+
import(f)
|
5
|
+
end
|
6
|
+
|
7
|
+
#require File.expand_path('../../lib/ramaze/helper/fnordmetric', __FILE__)
|
8
|
+
|
9
|
+
module Ramaze
|
10
|
+
module Helper
|
11
|
+
module Fnordmetric
|
12
|
+
Gemspec = Gem::Specification::load(
|
13
|
+
File.expand_path('../ramaze-fnordmetric.gemspec', __FILE__)
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/examples/README.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Fnordmetric Helper Example
|
2
|
+
==========================
|
3
|
+
|
4
|
+
__Some basic messy example__
|
5
|
+
|
6
|
+
----
|
7
|
+
|
8
|
+
Running it
|
9
|
+
----------
|
10
|
+
|
11
|
+
Start the web app :
|
12
|
+
|
13
|
+
cd examples
|
14
|
+
ruby example.rb
|
15
|
+
|
16
|
+
In another terminal, start the fnordmetric app :
|
17
|
+
|
18
|
+
cd examples
|
19
|
+
ruby fn.rb
|
20
|
+
|
21
|
+
Usage
|
22
|
+
-----
|
23
|
+
|
24
|
+
Point your browser to [http://localhost:7000] and you're set !
|
25
|
+
|
data/examples/example.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'ramaze'
|
2
|
+
|
3
|
+
# use : require 'ramaze-fnordmetric-helper' IRL
|
4
|
+
require __DIR__('../lib/ramaze/helper/fnordmetric')
|
5
|
+
|
6
|
+
|
7
|
+
class MainController < Ramaze::Controller
|
8
|
+
include Ramaze::Traited
|
9
|
+
map '/'
|
10
|
+
helper :fnordmetric
|
11
|
+
|
12
|
+
# trait :fnord_redis_url => "redis://localhost:6379"
|
13
|
+
|
14
|
+
# We just use push_timer to mesure some time
|
15
|
+
def index
|
16
|
+
p request.inspect
|
17
|
+
push_timer :stupid_sleep
|
18
|
+
sleep 2
|
19
|
+
pop_timer
|
20
|
+
|
21
|
+
<<EOF
|
22
|
+
<h2>push_timer/pop_timer methods</h2>
|
23
|
+
This example uses push_timer/pop_timer methods
|
24
|
+
|
25
|
+
<pre>
|
26
|
+
def index
|
27
|
+
push_timer :stupid_sleep
|
28
|
+
sleep 2
|
29
|
+
pop_timer
|
30
|
+
end
|
31
|
+
</pre>
|
32
|
+
|
33
|
+
If you run 'fn.rb' (bundle exec fn.rb run), you can check this <a href='http://localhost:4242' target='_blank'>link</a> to get the Fnordmetric dashboard.
|
34
|
+
<p />
|
35
|
+
Sorry for the wait... but congratulations won a vanilla Icecream <a href='/icecream'>Icecream</a> ! May be you prefer <a href='/icecream/strawberry'>strawberry</a>. ?
|
36
|
+
EOF
|
37
|
+
end
|
38
|
+
|
39
|
+
# Here we just interested in counting icecreams
|
40
|
+
def icecream(flavor="vanilla")
|
41
|
+
event(:icecream, :flavor => flavor)
|
42
|
+
|
43
|
+
<<EOF2
|
44
|
+
<h2>event method</h2>
|
45
|
+
This example uses event to send an event to Fnordmetric.
|
46
|
+
|
47
|
+
<pre>
|
48
|
+
def icecream(flavor="vanilla")
|
49
|
+
event(:icecream, :flavor => flavor)
|
50
|
+
end
|
51
|
+
</pre>
|
52
|
+
|
53
|
+
If you run 'fn.rb' (bundle exec fn.rb run), you can check the icecreams <a href='http://localhost:4242/example#dashboard/Overview' target='_blank'>page</a><p />
|
54
|
+
Sorry for the wait... You won a vanilla Icecream <a href='/icecream'>Icecream</a>. May be you prefer <a href='/icecream/strawberry'>strawberry</a> ? <p />
|
55
|
+
If you wish, we can <a href='/deliver'>deliver</a> the icecream to your door, but it might take some time, be patient.
|
56
|
+
|
57
|
+
EOF2
|
58
|
+
end
|
59
|
+
|
60
|
+
def deliver
|
61
|
+
sleep(1 + rand)
|
62
|
+
|
63
|
+
<<EOF3
|
64
|
+
<h2>clock class method</h2>
|
65
|
+
This example uses 'clock' to measure the time taken by a controller method.
|
66
|
+
|
67
|
+
<pre>
|
68
|
+
def deliver
|
69
|
+
sleep(rand * 10)
|
70
|
+
end
|
71
|
+
clock :deliver, :delivery_performance
|
72
|
+
</pre>
|
73
|
+
|
74
|
+
If you run 'fn.rb' (bundle exec fn.rb run), you can check the performance <a href='http://localhost:4242/example#dashboard/Performance' target='_blank'>tab</a><p />
|
75
|
+
Your icecream has been delivered. You can get <a href='/deliver'>another one</a> or go to the <a href='/'>index</a> page.<p />
|
76
|
+
EOF3
|
77
|
+
end
|
78
|
+
clock :deliver, :delivery_performance
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
Ramaze.start(:root => Ramaze.options.roots)
|