metry 1.1.0 → 1.2.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.
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