vanity 1.3.0 → 1.4.0.beta

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.
Files changed (99) hide show
  1. data/CHANGELOG +61 -3
  2. data/Gemfile +22 -14
  3. data/README.rdoc +9 -4
  4. data/Rakefile +72 -12
  5. data/bin/vanity +16 -4
  6. data/lib/vanity.rb +7 -5
  7. data/lib/vanity/adapters/abstract_adapter.rb +135 -0
  8. data/lib/vanity/adapters/mock_adapter.rb +157 -0
  9. data/lib/vanity/adapters/mongo_adapter.rb +162 -0
  10. data/lib/vanity/adapters/redis_adapter.rb +154 -0
  11. data/lib/vanity/backport.rb +0 -17
  12. data/lib/vanity/commands/upgrade.rb +34 -0
  13. data/lib/vanity/experiment/ab_test.rb +46 -41
  14. data/lib/vanity/experiment/base.rb +13 -15
  15. data/lib/vanity/frameworks/rails.rb +5 -9
  16. data/lib/vanity/metric/active_record.rb +10 -4
  17. data/lib/vanity/metric/base.rb +46 -23
  18. data/lib/vanity/metric/google_analytics.rb +7 -0
  19. data/lib/vanity/metric/remote.rb +53 -0
  20. data/lib/vanity/playground.rb +133 -49
  21. data/test/{ab_test_test.rb → experiment/ab_test.rb} +47 -3
  22. data/test/{experiment_test.rb → experiment/base_test.rb} +8 -8
  23. data/test/metric/active_record_test.rb +253 -0
  24. data/test/metric/base_test.rb +293 -0
  25. data/test/metric/google_analytics_test.rb +104 -0
  26. data/test/metric/remote_test.rb +108 -0
  27. data/test/myapp/app/controllers/application_controller.rbc +66 -0
  28. data/test/myapp/app/controllers/main_controller.rb +3 -3
  29. data/test/myapp/app/controllers/main_controller.rbc +347 -0
  30. data/test/myapp/config/boot.rbc +2534 -0
  31. data/test/myapp/config/environment.rbc +403 -0
  32. data/test/myapp/config/routes.rbc +174 -0
  33. data/test/myapp/log/production.log +2601 -0
  34. data/test/passenger_test.rb +14 -5
  35. data/test/passenger_test.rbc +0 -0
  36. data/test/playground_test.rbc +256 -0
  37. data/test/rails_test.rb +75 -22
  38. data/test/rails_test.rbc +4086 -0
  39. data/test/test_helper.rb +30 -7
  40. data/test/test_helper.rbc +4297 -0
  41. data/vanity.gemspec +6 -2
  42. metadata +74 -73
  43. data/lib/vanity/commands.rb +0 -2
  44. data/lib/vanity/mock_redis.rb +0 -76
  45. data/test/metric_test.rb +0 -622
  46. data/vendor/cache/RedCloth-4.2.2.gem +0 -0
  47. data/vendor/cache/actionmailer-2.3.5.gem +0 -0
  48. data/vendor/cache/actionpack-2.3.5.gem +0 -0
  49. data/vendor/cache/activerecord-2.3.5.gem +0 -0
  50. data/vendor/cache/activeresource-2.3.5.gem +0 -0
  51. data/vendor/cache/activesupport-2.3.5.gem +0 -0
  52. data/vendor/cache/autotest-4.2.7.gem +0 -0
  53. data/vendor/cache/autotest-fsevent-0.2.1.gem +0 -0
  54. data/vendor/cache/autotest-growl-0.2.0.gem +0 -0
  55. data/vendor/cache/bundler-0.9.7.gem +0 -0
  56. data/vendor/cache/classifier-1.3.1.gem +0 -0
  57. data/vendor/cache/directory_watcher-1.3.1.gem +0 -0
  58. data/vendor/cache/fastthread-1.0.7.gem +0 -0
  59. data/vendor/cache/garb-0.7.0.gem +0 -0
  60. data/vendor/cache/happymapper-0.3.0.gem +0 -0
  61. data/vendor/cache/jekyll-0.5.7.gem +0 -0
  62. data/vendor/cache/libxml-ruby-1.1.3.gem +0 -0
  63. data/vendor/cache/liquid-2.0.0.gem +0 -0
  64. data/vendor/cache/maruku-0.6.0.gem +0 -0
  65. data/vendor/cache/mocha-0.9.8.gem +0 -0
  66. data/vendor/cache/open4-1.0.1.gem +0 -0
  67. data/vendor/cache/passenger-2.2.9.gem +0 -0
  68. data/vendor/cache/rack-1.0.1.gem +0 -0
  69. data/vendor/cache/rails-2.3.5.gem +0 -0
  70. data/vendor/cache/rake-0.8.7.gem +0 -0
  71. data/vendor/cache/rubygems-update-1.3.5.gem +0 -0
  72. data/vendor/cache/shoulda-2.10.3.gem +0 -0
  73. data/vendor/cache/sqlite3-ruby-1.2.5.gem +0 -0
  74. data/vendor/cache/stemmer-1.0.1.gem +0 -0
  75. data/vendor/cache/syntax-1.0.0.gem +0 -0
  76. data/vendor/cache/sys-uname-0.8.4.gem +0 -0
  77. data/vendor/cache/timecop-0.3.4.gem +0 -0
  78. data/vendor/redis-rb/LICENSE +0 -20
  79. data/vendor/redis-rb/README.markdown +0 -36
  80. data/vendor/redis-rb/Rakefile +0 -62
  81. data/vendor/redis-rb/bench.rb +0 -44
  82. data/vendor/redis-rb/benchmarking/suite.rb +0 -24
  83. data/vendor/redis-rb/benchmarking/worker.rb +0 -71
  84. data/vendor/redis-rb/bin/distredis +0 -33
  85. data/vendor/redis-rb/examples/basic.rb +0 -16
  86. data/vendor/redis-rb/examples/incr-decr.rb +0 -18
  87. data/vendor/redis-rb/examples/list.rb +0 -26
  88. data/vendor/redis-rb/examples/sets.rb +0 -36
  89. data/vendor/redis-rb/lib/dist_redis.rb +0 -124
  90. data/vendor/redis-rb/lib/hash_ring.rb +0 -128
  91. data/vendor/redis-rb/lib/pipeline.rb +0 -21
  92. data/vendor/redis-rb/lib/redis.rb +0 -370
  93. data/vendor/redis-rb/lib/redis/raketasks.rb +0 -1
  94. data/vendor/redis-rb/profile.rb +0 -22
  95. data/vendor/redis-rb/redis-rb.gemspec +0 -30
  96. data/vendor/redis-rb/spec/redis_spec.rb +0 -637
  97. data/vendor/redis-rb/spec/spec_helper.rb +0 -4
  98. data/vendor/redis-rb/speed.rb +0 -16
  99. data/vendor/redis-rb/tasks/redis.tasks.rb +0 -140
@@ -24,20 +24,3 @@ class Date
24
24
  end
25
25
  end
26
26
 
27
- class Symbol
28
- unless method_defined?(:to_proc)
29
- # Backported from Ruby 1.9.
30
- def to_proc
31
- Proc.new { |*args| args.shift.__send__(self, *args) }
32
- end
33
- end
34
- end
35
-
36
- class Array
37
- unless method_defined?(:minmax)
38
- # Backported from Ruby 1.9.
39
- def minmax
40
- [min, max]
41
- end
42
- end
43
- end
@@ -0,0 +1,34 @@
1
+ module Vanity
2
+ module Commands
3
+ class << self
4
+ # Upgrade to newer version of Vanity (this usually means doing magic in
5
+ # the database)
6
+ def upgrade
7
+ if Vanity.playground.connection.respond_to?(:redis)
8
+ redis = Vanity.playground.connection.redis
9
+ # Upgrade metrics from 1.3 to 1.4
10
+ keys = redis.keys("metrics:*")
11
+ if keys.empty?
12
+ puts "No metrics to upgrade"
13
+ else
14
+ puts "Updating #{keys.map { |name| name.split(":")[1] }.uniq.length} metrics"
15
+ keys.each do |key|
16
+ key << ":value:0" if key[/\d{4}-\d{2}-\d{2}$/]
17
+ redis.renamenx key, "vanity:#{key}"
18
+ end
19
+ end
20
+ # Upgrade experiments from 1.3 to 1.4
21
+ keys = redis.keys("vanity:1:*")
22
+ if keys.empty?
23
+ puts "No experiments to upgrade"
24
+ else
25
+ puts "Updating #{keys.map { |name| name.split(":")[2] }.uniq.length} experiments"
26
+ keys.each do |key|
27
+ redis.renamenx key, key.gsub(":1:", ":experiments:")
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -93,7 +93,6 @@ module Vanity
93
93
 
94
94
  def initialize(*args)
95
95
  super
96
- @alternatives = [false, true]
97
96
  end
98
97
 
99
98
 
@@ -130,22 +129,18 @@ module Vanity
130
129
  # alts = experiment(:background_color).alternatives
131
130
  # puts "#{alts.count} alternatives, with the colors: #{alts.map(&:value).join(", ")}"
132
131
  def alternatives(*args)
133
- unless args.empty?
134
- @alternatives = args.clone
135
- end
132
+ @alternatives = args.empty? ? [true, false] : args.clone
136
133
  class << self
137
134
  define_method :alternatives, instance_method(:_alternatives)
138
135
  end
139
- alternatives
136
+ nil
140
137
  end
141
138
 
142
139
  def _alternatives
143
140
  alts = []
144
141
  @alternatives.each_with_index do |value, i|
145
- participants = redis.scard(key("alts:#{i}:participants")).to_i
146
- converted = redis.scard(key("alts:#{i}:converted")).to_i
147
- conversions = redis[key("alts:#{i}:conversions")].to_i
148
- alts << Alternative.new(self, i, value, participants, converted, conversions)
142
+ counts = @playground.collecting? ? connection.ab_counts(@id, i) : Hash.new(0)
143
+ alts << Alternative.new(self, i, value, counts[:participants], counts[:converted], counts[:conversions])
149
144
  end
150
145
  alts
151
146
  end
@@ -186,16 +181,22 @@ module Vanity
186
181
  # @example
187
182
  # color = experiment(:which_blue).choose
188
183
  def choose
189
- if active?
190
- identity = identity()
191
- index = redis[key("participant:#{identity}:show")]
192
- unless index
193
- index = alternative_for(identity)
194
- redis.sadd key("alts:#{index}:participants"), identity
195
- check_completion!
184
+ if @playground.collecting?
185
+ if active?
186
+ identity = identity()
187
+ index = connection.ab_showing(@id, identity)
188
+ unless index
189
+ index = alternative_for(identity)
190
+ connection.ab_add_participant @id, index, identity
191
+ check_completion!
192
+ end
193
+ else
194
+ index = connection.ab_get_outcome(@id) || alternative_for(identity)
196
195
  end
197
196
  else
198
- index = redis[key("outcome")] || alternative_for(identity)
197
+ identity = identity()
198
+ @showing ||= {}
199
+ @showing[identity] ||= alternative_for(identity)
199
200
  end
200
201
  @alternatives[index.to_i]
201
202
  end
@@ -227,12 +228,17 @@ module Vanity
227
228
  # experiment(:green_button).select(nil)
228
229
  # end
229
230
  def chooses(value)
230
- if value.nil?
231
- redis.del key("participant:#{identity}:show")
231
+ if @playground.collecting?
232
+ if value.nil?
233
+ connection.ab_not_showing @id, identity
234
+ else
235
+ index = @alternatives.index(value)
236
+ raise ArgumentError, "No alternative #{value.inspect} for #{name}" unless index
237
+ connection.ab_show @id, identity, index
238
+ end
232
239
  else
233
- index = @alternatives.index(value)
234
- raise ArgumentError, "No alternative #{value.inspect} for #{name}" unless index
235
- redis[key("participant:#{identity}:show")] = index
240
+ @showing ||= {}
241
+ @showing[identity] = value.nil? ? nil : @alternatives.index(value)
236
242
  end
237
243
  self
238
244
  end
@@ -240,8 +246,12 @@ module Vanity
240
246
  # True if this alternative is currently showing (see #chooses).
241
247
  def showing?(alternative)
242
248
  identity = identity()
243
- index = redis[key("participant:#{identity}:show")]
244
- index && index.to_i == alternative.id
249
+ if @playground.collecting?
250
+ connection.ab_showing(@id, identity) == alternative.id
251
+ else
252
+ @showing ||= {}
253
+ @showing[identity] == alternative.id
254
+ end
245
255
  end
246
256
 
247
257
 
@@ -358,12 +368,13 @@ module Vanity
358
368
 
359
369
  # Alternative chosen when this experiment completed.
360
370
  def outcome
361
- outcome = redis[key("outcome")]
362
- outcome && alternatives[outcome.to_i]
371
+ return unless @playground.collecting?
372
+ outcome = connection.ab_get_outcome(@id)
373
+ outcome && _alternatives[outcome]
363
374
  end
364
375
 
365
376
  def complete!
366
- return unless active?
377
+ return unless @playground.collecting? && active?
367
378
  super
368
379
  if @outcome_is
369
380
  begin
@@ -377,24 +388,20 @@ module Vanity
377
388
  outcome = best.id if best
378
389
  end
379
390
  # TODO: logging
380
- redis.setnx key("outcome"), outcome || 0
391
+ connection.ab_set_outcome @id, outcome || 0
381
392
  end
382
393
 
383
394
 
384
395
  # -- Store/validate --
385
396
 
386
397
  def destroy
387
- @alternatives.size.times do |i|
388
- redis.del key("alts:#{i}:participants")
389
- redis.del key("alts:#{i}:converted")
390
- redis.del key("alts:#{i}:conversions")
391
- end
392
- redis.del key(:outcome)
398
+ connection.destroy_experiment @id
393
399
  super
394
400
  end
395
401
 
396
402
  def save
397
- fail "Experiment #{name} needs at least two alternatives" unless alternatives.size >= 2
403
+ true_false unless @alternatives
404
+ fail "Experiment #{name} needs at least two alternatives" unless @alternatives.size >= 2
398
405
  super
399
406
  if @metrics.nil? || @metrics.empty?
400
407
  warn "Please use metrics method to explicitly state which metric you are measuring against."
@@ -411,10 +418,9 @@ module Vanity
411
418
  return unless active?
412
419
  identity = identity() rescue nil
413
420
  if identity
414
- return if redis[key("participants:#{identity}:show")]
421
+ return if connection.ab_showing(@id, identity)
415
422
  index = alternative_for(identity)
416
- redis.sadd key("alts:#{index}:converted"), identity if redis.sismember(key("alts:#{index}:participants"), identity)
417
- redis.incrby key("alts:#{index}:conversions"), count
423
+ connection.ab_add_conversion @id, index, identity, count
418
424
  check_completion!
419
425
  end
420
426
  end
@@ -432,13 +438,12 @@ module Vanity
432
438
  participants.times do |identity|
433
439
  index = @alternatives.index(value)
434
440
  raise ArgumentError, "No alternative #{value.inspect} for #{name}" unless index
435
- redis.sadd key("alts:#{index}:participants"), identity
441
+ connection.ab_add_participant @id, index, "#{index}:#{identity}"
436
442
  end
437
443
  conversions.times do |identity|
438
444
  index = @alternatives.index(value)
439
445
  raise ArgumentError, "No alternative #{value.inspect} for #{name}" unless index
440
- redis.sadd key("alts:#{index}:converted"), identity
441
- redis.incr key("alts:#{index}:conversions")
446
+ connection.ab_add_conversion @id, index, "#{index}:#{identity}"
442
447
  end
443
448
  end
444
449
  end
@@ -68,7 +68,6 @@ module Vanity
68
68
  @playground = playground
69
69
  @id, @name = id.to_sym, name
70
70
  @options = options || {}
71
- @namespace = "#{@playground.namespace}:#{@id}"
72
71
  @identify_block = method(:default_identify)
73
72
  end
74
73
 
@@ -139,35 +138,35 @@ module Vanity
139
138
 
140
139
  # Force experiment to complete.
141
140
  def complete!
142
- redis.setnx key(:completed_at), Time.now.to_i
143
- @completed_at = redis[key(:completed_at)]
144
141
  @playground.logger.info "vanity: completed experiment #{id}"
142
+ return unless @playground.collecting?
143
+ connection.set_experiment_completed_at @id, Time.now
144
+ @completed_at = connection.get_experiment_completed_at(@id)
145
145
  end
146
146
 
147
147
  # Time stamp when experiment was completed.
148
148
  def completed_at
149
- @completed_at ||= redis[key(:completed_at)]
150
- @completed_at && Time.at(@completed_at.to_i)
149
+ @completed_at ||= connection.get_experiment_completed_at(@id)
151
150
  end
152
151
 
153
152
  # Returns true if experiment active, false if completed.
154
153
  def active?
155
- !redis.exists(key(:completed_at))
154
+ !@playground.collecting? || !connection.is_experiment_completed?(@id)
156
155
  end
157
156
 
158
157
  # -- Store/validate --
159
158
 
160
159
  # Get rid of all experiment data.
161
160
  def destroy
162
- redis.del key(:created_at)
163
- redis.del key(:completed_at)
161
+ connection.destroy_experiment @id
164
162
  @created_at = @completed_at = nil
165
163
  end
166
164
 
167
165
  # Called by Playground to save the experiment definition.
168
166
  def save
169
- redis.setnx key(:created_at), Time.now.to_i
170
- @created_at = Time.at(redis[key(:created_at)].to_i)
167
+ return unless @playground.collecting?
168
+ connection.set_experiment_created_at @id, Time.now
169
+ @created_at = connection.get_experiment_created_at(@id)
171
170
  end
172
171
 
173
172
  protected
@@ -199,15 +198,14 @@ module Vanity
199
198
  # key => "vanity:experiments:green_button"
200
199
  # key("participants") => "vanity:experiments:green_button:participants"
201
200
  def key(name = nil)
202
- name ? "#{@namespace}:#{name}" : @namespace
201
+ "#{@id}:#{name}"
203
202
  end
204
203
 
205
- # Shortcut for Vanity.playground.redis
206
- def redis
207
- @playground.redis
204
+ # Shortcut for Vanity.playground.connection
205
+ def connection
206
+ @playground.connection
208
207
  end
209
208
 
210
209
  end
211
210
  end
212
211
  end
213
-
@@ -193,14 +193,10 @@ if defined?(Rails)
193
193
  # Use Rails logger by default.
194
194
  Vanity.playground.logger ||= Rails.logger
195
195
  Vanity.playground.load_path = Rails.root + Vanity.playground.load_path
196
- config_file = Rails.root + "config/redis.yml"
197
- if !Vanity.playground.connected? && config_file.exist?
198
- config = YAML.load_file(config_file)[Rails.env.to_s]
199
- Vanity.playground.redis = config if config
200
- end
196
+ Vanity.playground.collecting = Rails.env.production?
201
197
 
202
- # Do this at the very end of initialization, allowing test environment to do
203
- # Vanity.playground.mock! before any database access takes place.
198
+ # Do this at the very end of initialization, allowing you to change
199
+ # connection adapter, turn collection on/off, etc.
204
200
  Rails.configuration.after_initialize do
205
201
  Vanity.playground.load!
206
202
  end
@@ -213,9 +209,9 @@ if defined?(PhusionPassenger)
213
209
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
214
210
  if forked
215
211
  begin
216
- Vanity.playground.reconnect!
212
+ Vanity.playground.establish_connection if Vanity.playground.collecting?
217
213
  rescue Exception=>ex
218
- Rails.logger.error "Error reconnecting Redis: #{ex.to_s}"
214
+ Rails.logger.error "Error reconnecting: #{ex.to_s}"
219
215
  end
220
216
  end
221
217
  end
@@ -62,15 +62,21 @@ module Vanity
62
62
  end
63
63
 
64
64
  # This track! method stores nothing, but calls the hooks.
65
- def track!(*args)
66
- count = args.first || 1
67
- call_hooks Time.now, count if count > 0
65
+ def track!(args = nil)
66
+ return unless @playground.collecting?
67
+ call_hooks *track_args(args)
68
+ end
69
+
70
+ def last_update_at
71
+ record = @ar_scoped.find(:first, :order=>"#@ar_timestamp DESC", :limit=>1, :select=>@ar_timestamp)
72
+ record && record.send(@ar_timestamp)
68
73
  end
69
74
 
70
75
  # AR model after_create callback notifies all the hooks.
71
76
  def after_create(record)
77
+ return unless @playground.collecting?
72
78
  count = @ar_column ? (record.send(@ar_column) || 0) : 1
73
- call_hooks record.send(@ar_timestamp), count if count > 0 && @ar_scoped.exists?(record)
79
+ call_hooks record.send(@ar_timestamp), nil, [count] if count > 0 && @ar_scoped.exists?(record)
74
80
  end
75
81
  end
76
82
  end
@@ -4,9 +4,9 @@ module Vanity
4
4
  # can also respond to addition methods (+track!+, +bounds+, etc), these are
5
5
  # optional.
6
6
  #
7
- # This class implements a basic metric that tracks data and stores it in
8
- # Redis. You can use this as the basis for your metric, or as reference for
9
- # the methods your metric must and can implement.
7
+ # This class implements a basic metric that tracks data and stores it in the
8
+ # database. You can use this as the basis for your metric, or as reference
9
+ # for the methods your metric must and can implement.
10
10
  #
11
11
  # @since 1.1.0
12
12
  class Metric
@@ -121,23 +121,42 @@ module Vanity
121
121
  @playground, @name = playground, name.to_s
122
122
  @id = (id || name.to_s.downcase.gsub(/\W+/, '_')).to_sym
123
123
  @hooks = []
124
- redis.setnx key(:created_at), Time.now.to_i
125
- @created_at = Time.at(redis[key(:created_at)].to_i)
126
124
  end
127
125
 
128
126
 
129
127
  # -- Tracking --
130
128
 
131
- # Called to track an action associated with this metric.
132
- def track!(count = 1)
133
- count ||= 1
134
- if count > 0
135
- timestamp = Time.now
136
- redis.incrby key(timestamp.to_date, "count"), count
137
- @playground.logger.info "vanity: #{@id} with count #{count}"
138
- call_hooks timestamp, count
129
+ # Called to track an action associated with this metric. Most common is not
130
+ # passing an argument, and it tracks a count of 1. You can pass a different
131
+ # value as the argument, or array of value (for multi-series metrics), or
132
+ # hash with the optional keys timestamp, identity and values.
133
+ #
134
+ # Example:
135
+ # hits.track!
136
+ # foo_and_bar.track! [5,11]
137
+ def track!(args = nil)
138
+ return unless @playground.collecting?
139
+ timestamp, identity, values = track_args(args)
140
+ connection.metric_track @id, timestamp, identity, values
141
+ @playground.logger.info "vanity: #{@id} with value #{values.join(", ")}"
142
+ call_hooks timestamp, identity, values
143
+ end
144
+
145
+ # Parses arguments to track! method and return array with timestamp,
146
+ # identity and array of values.
147
+ def track_args(args)
148
+ case args
149
+ when Hash
150
+ timestamp, identity, values = args.values_at(:timestamp, :identity, :values)
151
+ when Array
152
+ values = args
153
+ when Numeric
154
+ values = [args]
139
155
  end
156
+ identity = Vanity.context.vanity_identity rescue nil
157
+ [timestamp || Time.now, identity, values || [1]]
140
158
  end
159
+ protected :track_args
141
160
 
142
161
  # Metric definitions use this to introduce tracking hook. The hook is
143
162
  # called with metric identifier, timestamp, count and possibly additional
@@ -172,9 +191,6 @@ module Vanity
172
191
  attr_reader :name
173
192
  alias :to_s :name
174
193
 
175
- # Time stamp when metric was created.
176
- attr_reader :created_at
177
-
178
194
  # Human readable description. Use two newlines to break paragraphs.
179
195
  attr_accessor :description
180
196
 
@@ -192,28 +208,35 @@ module Vanity
192
208
  # Given two arguments, a start date and an end date (inclusive), returns an
193
209
  # array of measurements. All metrics must implement this method.
194
210
  def values(from, to)
195
- redis.mget((from.to_date..to.to_date).map { |date| key(date, "count") }).map(&:to_i)
211
+ values = connection.metric_values(@id, from, to)
212
+ values.map { |row| row.first.to_i }
213
+ end
214
+
215
+ # Returns date/time of the last update to this metric.
216
+ #
217
+ # @since 1.4.0
218
+ def last_update_at
219
+ connection.get_metric_last_update_at(@id)
196
220
  end
197
221
 
198
222
 
199
223
  # -- Storage --
200
224
 
201
225
  def destroy!
202
- redis.del redis.keys(key("*"))
226
+ connection.destroy_metric @id
203
227
  end
204
228
 
205
- def redis
206
- @playground.redis
229
+ def connection
230
+ @playground.connection
207
231
  end
208
232
 
209
233
  def key(*args)
210
234
  "metrics:#{@id}:#{args.join(':')}"
211
235
  end
212
236
 
213
- def call_hooks(timestamp, count)
214
- count ||= 1
237
+ def call_hooks(timestamp, identity, values)
215
238
  @hooks.each do |hook|
216
- hook.call @id, timestamp, count
239
+ hook.call @id, timestamp, values.first || 1
217
240
  end
218
241
  end
219
242