metry 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ === 1.2.0 / 2009-07-30
2
+
3
+ * Added Psycho for viewing Metry results.
4
+ * Hooked up Psycho to Radiant authentication.
5
+
1
6
  === 1.1.0 / 2009-07-11
2
7
 
3
8
  * Moved Radiant initialization into the extension.
data/README.txt CHANGED
@@ -31,6 +31,7 @@ Metry aims to close the gap between knowing you ought to be making decisions bas
31
31
  * Tokyo Cabinet
32
32
  * Tokyo Cabinet Ruby Binding
33
33
  * Rack
34
+ * ffi gem
34
35
 
35
36
  == INSTALL:
36
37
 
data/TODO CHANGED
@@ -1,12 +1,12 @@
1
- More unit tests
1
+ Switch to MongoDB
2
+ Add ability to track goals in Psycho
3
+ Allow ignoring requests in Metry, and have Psycho requests ignored
4
+ Switch to submodules for vendor'd libs
2
5
 
3
- Add a slick Sinatra app for viewing tracking data.
6
+ More unit tests
4
7
 
5
8
  Add support for non-pageview event tracking
6
9
  Via in-process call
7
10
  Via web request
8
11
 
9
- Add support for MongoDB
10
- Add support for Tokyo Tyrant
11
-
12
12
  Metry visitors can be spoofed - fix it
data/example/example.rb CHANGED
@@ -4,9 +4,9 @@ require 'sinatra'
4
4
  require File.dirname(__FILE__) + '/../lib/metry'
5
5
 
6
6
  configure do
7
- Metry.init Metry::Tokyo.new("tracking")
8
- #Metry.init Metry::Memory.new
7
+ Metry.init(ENV["USE_MEMORY"] ? Metry::Memory.new : Metry::Tokyo.new("tracking"))
9
8
  use Metry::Rack::Tracking
9
+ use Metry::Psycho, {:path => "/admin/metry"}
10
10
  end
11
11
 
12
12
  get '/' do
@@ -1,5 +1,5 @@
1
1
  Feature: Access Tracking
2
- In order to how users are using my site
2
+ In order to know how users are using my site
3
3
  As an web application creator
4
4
  I want to have all accesses to my application tracked
5
5
 
@@ -38,6 +38,7 @@ Feature: Access Tracking
38
38
  And there should be a tracking event "2":
39
39
  | key | value |
40
40
  | visitor | 1 |
41
+ And there should be a visitor "1"
41
42
 
42
43
  Scenario: Two visitors are tracked
43
44
  Given I view "/"
@@ -49,6 +50,9 @@ Feature: Access Tracking
49
50
  And there should be a tracking event "2":
50
51
  | key | value |
51
52
  | visitor | 2 |
53
+ And there should be 2 visitors
54
+ And there should be a visitor "1"
55
+ And there should be a visitor "2"
52
56
 
53
57
  Scenario: All facets should be tracked
54
58
  When I view "/"
@@ -6,6 +6,10 @@ Then /^there should be (\d+) tracking events?$/ do |event_count|
6
6
  assert_equal(event_count.to_i, Metry.current.event_count)
7
7
  end
8
8
 
9
+ Then /^there should be (\d+) visitors$/ do |visitor_count|
10
+ assert_equal(visitor_count.to_i, Metry.current.visitor_count)
11
+ end
12
+
9
13
  When /^there should be a tracking event "(\d+)":$/ do |id, table|
10
14
  event = Metry.current[id]
11
15
  assert event, "Unable to lookup event #{id}."
@@ -33,3 +37,7 @@ Then /^there should be a visitor "([^\"]*)":$/ do |id, table|
33
37
  end
34
38
  end
35
39
  end
40
+
41
+ Then /^there should be a visitor "([^\"]*)"$/ do |id|
42
+ assert Metry.current.visitor(id)
43
+ end
@@ -16,7 +16,5 @@ World(Webrat::Matchers)
16
16
 
17
17
  require File.dirname(__FILE__) + '/../../example/example.rb'
18
18
  def app
19
- Rack::Builder.new do
20
- run Sinatra::Application
21
- end
19
+ Sinatra::Application
22
20
  end
data/lib/metry.rb CHANGED
@@ -5,9 +5,10 @@ require 'metry/rack/tracking'
5
5
  require 'metry/memory'
6
6
  require 'metry/tokyo'
7
7
  require 'metry/experiment'
8
+ require 'metry/psycho'
8
9
 
9
10
  module Metry
10
- VERSION = '1.1.0'
11
+ VERSION = '1.2.0'
11
12
 
12
13
  def self.init(storage)
13
14
  @storage = storage
@@ -41,6 +41,7 @@ module Metry
41
41
  end
42
42
 
43
43
  def save_visitor(response, visitor)
44
+ @storage.save_visitor(visitor)
44
45
  response.set_cookie(COOKIE,
45
46
  :value => visitor,
46
47
  :expires => (Time.now+(60*60*24*365*20)),
data/lib/metry/tokyo.rb CHANGED
@@ -17,43 +17,71 @@ module Metry
17
17
  end
18
18
 
19
19
  def next_visitor
20
- write do |storage|
20
+ access do |storage|
21
21
  storage.incr("#{META_PREFIX}visitor")
22
22
  end
23
23
  end
24
24
 
25
25
  def visitor(id)
26
- read do |storage|
26
+ access do |storage|
27
27
  (storage[visitor_id(id)] || {})
28
28
  end
29
29
  end
30
30
 
31
- def save_visitor(id, hash)
32
- write do |storage|
33
- storage[visitor_id(id)] = hash
31
+ def visitor_count
32
+ access do |storage|
33
+ storage.query do |q|
34
+ q.add '', :starts_with, VISITOR_PREFIX
35
+ q.pk_only
36
+ end.size
37
+ end
38
+ end
39
+
40
+ def visitors
41
+ access do |storage|
42
+ r = storage.query do |q|
43
+ q.add '', :starts_with, VISITOR_PREFIX
44
+ end.to_a
45
+ r.each{|e| e[:pk].sub!(/^#{VISITOR_PREFIX}/, '')}
46
+ r
47
+ end
48
+ end
49
+
50
+ def save_visitor(id, hash={})
51
+ access do |storage|
52
+ storage[visitor_id(id)] = (visitor(id) || {}).merge(hash)
34
53
  end
35
54
  end
36
55
 
37
56
  def <<(event)
38
- write do |storage|
57
+ access do |storage|
39
58
  storage[next_event_id(storage)] = event.inject({}){|a,(k,v)| a[k] = v.to_s; a}
40
59
  end
41
60
  end
42
61
 
43
62
  def [](id)
44
- read do |storage|
63
+ access do |storage|
45
64
  storage[event_id(id)]
46
65
  end
47
66
  end
48
67
 
49
68
  def event_count
50
- read do |storage|
69
+ access do |storage|
51
70
  storage.keys(:prefix => EVENT_PREFIX).size
52
71
  end
53
72
  end
54
73
 
74
+ def events_for(visitor)
75
+ access do |storage|
76
+ storage.query do |q|
77
+ q.add '', :starts_with, EVENT_PREFIX
78
+ q.add 'visitor', :eq, visitor
79
+ end.to_a
80
+ end
81
+ end
82
+
55
83
  def last_events(count=1)
56
- read do |storage|
84
+ access do |storage|
57
85
  storage.query do |q|
58
86
  q.add '', :starts_with, EVENT_PREFIX
59
87
  q.order_by "time", :numdesc
@@ -63,7 +91,7 @@ module Metry
63
91
  end
64
92
 
65
93
  def all_events
66
- read do |storage|
94
+ access do |storage|
67
95
  storage.query do |q|
68
96
  q.add '', :starts_with, EVENT_PREFIX
69
97
  end.to_a
@@ -71,7 +99,7 @@ module Metry
71
99
  end
72
100
 
73
101
  def clear
74
- write do |storage|
102
+ access do |storage|
75
103
  storage.clear
76
104
  end
77
105
  end
@@ -82,24 +110,24 @@ module Metry
82
110
  event_id(storage.incr("#{META_PREFIX}event"))
83
111
  end
84
112
 
85
- def access(mode)
86
- storage = @store.new(@file, :mode => mode)
113
+ def access
114
+ key = "metry_storage"
115
+ created_storage ||= false
116
+ unless storage = Thread.current[key]
117
+ created_storage = true
118
+ Thread.current[key] = storage = @store.new(@file, :mode => "wc")
119
+ end
87
120
  begin
88
121
  result = yield(storage)
89
122
  ensure
90
- storage.close
123
+ if created_storage
124
+ storage.close
125
+ Thread.current[key] = nil
126
+ end
91
127
  end
92
128
  result
93
129
  end
94
130
 
95
- def read(&block)
96
- access("rc", &block)
97
- end
98
-
99
- def write(&block)
100
- access("wc", &block)
101
- end
102
-
103
131
  def visitor_id(id)
104
132
  "#{VISITOR_PREFIX}#{id}"
105
133
  end
@@ -6,7 +6,6 @@ Feature: Radiant support
6
6
  Background:
7
7
  Given an empty tracking database
8
8
  And I am a new visitor
9
- And I have a layout
10
9
  And there is an empty Radiant cache
11
10
 
12
11
  Scenario: Basic Tracking
@@ -1,9 +1,3 @@
1
- Given /^I have a layout$/ do
2
- Layout.create!(:name => "basic", :content => <<EOC)
3
- <r:content />
4
- EOC
5
- end
6
-
7
1
  Given /^a page at "([^\"]*)" containing:$/ do |path, content|
8
2
  page = Page.create!(:title => "test", :breadcrumb => "test", :slug => path, :status_id => 100)
9
3
  page.parts.create!(:name => "body", :content => content)
@@ -11,4 +5,16 @@ end
11
5
 
12
6
  When /^there is an empty Radiant cache$/ do
13
7
  Radiant::Cache.clear
8
+ end
9
+
10
+ Given /^I log in as an admin$/ do
11
+ visit '/admin/login'
12
+ fill_in 'Username', :with => 'admin'
13
+ fill_in 'Password', :with => 'radiant'
14
+ click_button 'Login'
15
+ Then(%(I should be on "/admin/pages"))
16
+ end
17
+
18
+ When /^I log out$/ do
19
+ visit "/admin/logout"
14
20
  end
@@ -6,6 +6,10 @@ Then /^there should be (\d+) tracking events?$/ do |event_count|
6
6
  assert_equal(event_count.to_i, Metry.current.event_count)
7
7
  end
8
8
 
9
+ Then /^there should be (\d+) visitors$/ do |visitor_count|
10
+ assert_equal(visitor_count.to_i, Metry.current.visitor_count)
11
+ end
12
+
9
13
  When /^there should be a tracking event "(\d+)":$/ do |id, table|
10
14
  event = Metry.current[id]
11
15
  assert event, "Unable to lookup event #{id}."
@@ -33,3 +37,7 @@ Then /^there should be a visitor "([^\"]*)":$/ do |id, table|
33
37
  end
34
38
  end
35
39
  end
40
+
41
+ Then /^there should be a visitor "([^\"]*)"$/ do |id|
42
+ assert Metry.current.visitor(id)
43
+ end
@@ -20,3 +20,7 @@ end
20
20
  Then /^I should see "([^\"]*)"$/ do |content|
21
21
  assert_contain(content)
22
22
  end
23
+
24
+ Then /^I should be on "([^\"]*)"$/ do |path|
25
+ assert_equal path, URI.parse(current_url).path
26
+ end
@@ -19,6 +19,7 @@ World(Rack::Test::Methods)
19
19
 
20
20
  $: << RAILS_ROOT + '/../../vendor/webrat/lib'
21
21
  require 'webrat'
22
+ require 'webrat/rack_test'
22
23
 
23
24
  Webrat.configure do |config|
24
25
  config.mode = :rack_test
@@ -40,6 +41,11 @@ Before do
40
41
  end
41
42
  @__cucumber_ar_connection.begin_db_transaction
42
43
  ActionMailer::Base.deliveries = [] if defined?(ActionMailer::Base)
44
+
45
+ Layout.create!(:name => "basic", :content => <<EOC)
46
+ <r:content />
47
+ EOC
48
+ User.create!(:name => "Administrator", :login => "admin", :password => "radiant", :password_confirmation => "radiant", :admin => true)
43
49
  end
44
50
 
45
51
  After do
@@ -1,5 +1,7 @@
1
1
  require 'metry'
2
2
 
3
+ load 'metry_authenticator.rb'
4
+
3
5
  class MetryExtension < Radiant::Extension
4
6
  version "1.0"
5
7
  description "Provides Metry support to Radiant."
@@ -25,5 +27,10 @@ class MetryExtension < Radiant::Extension
25
27
 
26
28
  Metry.init Metry::Tokyo.new(RAILS_ROOT + '/tracking/tracking')
27
29
  Rails.configuration.middleware.insert_after ActionController::Failsafe, Metry::Rack::Tracking
30
+ Rails.configuration.middleware.use proc{Metry::Psycho}, {
31
+ :path => "/admin/metry",
32
+ :authorize => proc{|env| MetryAuthenticator.new(env).authorized?},
33
+ :on_deny => proc {|env| MetryAuthenticator.new(env).redirect},
34
+ }
28
35
  end
29
36
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metry
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathaniel Talbott
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-11 00:00:00 -04:00
12
+ date: 2009-07-30 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency