appstats 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.4.0)
4
+ appstats (0.6.0)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
@@ -0,0 +1,12 @@
1
+ class CreateAppstatsTestObject < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :appstats_test_objects do |t|
4
+ t.string :name
5
+ t.timestamps
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :appstats_test_objects
11
+ end
12
+ end
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 20110208210921) do
13
+ ActiveRecord::Schema.define(:version => 20110210185911) do
14
14
 
15
15
  create_table "appstats_actions", :force => true do |t|
16
16
  t.string "name"
@@ -66,4 +66,10 @@ ActiveRecord::Schema.define(:version => 20110208210921) do
66
66
 
67
67
  add_index "appstats_log_collectors", ["host"], :name => "index_appstats_log_collectors_on_host"
68
68
 
69
+ create_table "appstats_test_objects", :force => true do |t|
70
+ t.string "name"
71
+ t.datetime "created_at"
72
+ t.datetime "updated_at"
73
+ end
74
+
69
75
  end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'active_record'
3
+ require "#{File.dirname(__FILE__)}/appstats/acts_as_appstatsable"
3
4
  require "#{File.dirname(__FILE__)}/appstats/code_injections"
4
5
  require "#{File.dirname(__FILE__)}/appstats/entry"
5
6
  require "#{File.dirname(__FILE__)}/appstats/entry_date"
@@ -10,6 +11,7 @@ require "#{File.dirname(__FILE__)}/appstats/tasks"
10
11
  require "#{File.dirname(__FILE__)}/appstats/logger"
11
12
  require "#{File.dirname(__FILE__)}/appstats/log_collector"
12
13
  require "#{File.dirname(__FILE__)}/appstats/query"
14
+ require "#{File.dirname(__FILE__)}/appstats/test_object"
13
15
 
14
16
  # required in the appstats.gemspec
15
17
  unless Appstats.const_defined?(:VERSION)
@@ -0,0 +1,72 @@
1
+ module ActsAsAppstatsable
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def acts_as_appstatsable(options = {})
10
+ self.cattr_accessor :appstats_after_create, :appstats_after_destroy, :appstats_after_update
11
+
12
+ class_eval <<-EOV
13
+ include ActsAsAppstatsable::InstanceMethods
14
+
15
+ after_create :track_create
16
+ after_destroy :track_destroy
17
+ after_update :track_update
18
+ EOV
19
+
20
+ acts_as_appstatsable_options(options)
21
+
22
+ end
23
+
24
+ def acts_as_appstatsable_options(options = {})
25
+ if !options[:include].nil?
26
+ self.appstats_after_create = options[:include].include?(:create)
27
+ self.appstats_after_destroy = options[:include].include?(:destroy)
28
+ self.appstats_after_update = options[:include].include?(:update)
29
+ elsif !options[:except].nil?
30
+ self.appstats_after_create = !options[:except].include?(:create)
31
+ self.appstats_after_destroy = !options[:except].include?(:destroy)
32
+ self.appstats_after_update = !options[:except].include?(:update)
33
+ else
34
+ self.appstats_after_create = true
35
+ self.appstats_after_destroy = true
36
+ self.appstats_after_update = true
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ module InstanceMethods
43
+
44
+ def track_create
45
+ return false unless self.appstats_after_create
46
+ track('object-created', :class_name => self.class.name, :class_id => self.id, :details => self.to_s)
47
+ end
48
+
49
+ def track_destroy
50
+ return false unless self.appstats_after_destroy
51
+ track('object-destroyed', :class_name => self.class.name, :class_id => self.id, :details => self.to_s)
52
+ end
53
+
54
+ def track_update
55
+ return false unless self.appstats_after_update
56
+ track('object-updated', :class_name => self.class.name, :class_id => self.id, :details => self.to_s)
57
+ end
58
+
59
+ def track(action,contexts)
60
+ begin
61
+ Appstats::Logger.entry(action,contexts)
62
+ true
63
+ rescue Exception => e
64
+ Appstats::Logger.exception_entry(e,:on => action)
65
+ false
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+ ActiveRecord::Base.class_eval { include ActsAsAppstatsable }
@@ -65,6 +65,10 @@ module Appstats
65
65
  raw_write(entry_to_s(action,contexts))
66
66
  end
67
67
 
68
+ def self.exception_entry(error,contexts = {})
69
+ raw_write(entry_to_s("appstats-exception",contexts.merge({:error => error.message})))
70
+ end
71
+
68
72
  def self.today
69
73
  "#{Time.now.strftime('%Y-%m-%d')}"
70
74
  end
@@ -0,0 +1,14 @@
1
+ module Appstats
2
+ class TestObject < ActiveRecord::Base
3
+ set_table_name "appstats_test_objects"
4
+ acts_as_appstatsable
5
+
6
+ attr_accessible :name
7
+
8
+ def to_s
9
+ return "NILL" if name.nil?
10
+ "[#{name}]"
11
+ end
12
+
13
+ end
14
+ end
@@ -1,3 +1,3 @@
1
1
  module Appstats
2
- VERSION = "0.4.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsAppstatsable do
4
+
5
+ before(:each) do
6
+ Appstats::Logger.reset
7
+ Time.stub!(:now).and_return(Time.parse('2010-09-21 23:15:20'))
8
+ Appstats::TestObject.acts_as_appstatsable_options
9
+ end
10
+
11
+ after(:each) do
12
+ File.delete(Appstats::Logger.filename) if File.exists?(Appstats::Logger.filename)
13
+ end
14
+
15
+ describe "should be settable in the options" do
16
+
17
+ it "should only track included options" do
18
+ Appstats::TestObject.acts_as_appstatsable_options(:include => [:create,:destroy])
19
+ @obj = Appstats::TestObject.create(:name => "x")
20
+ @obj.name = "y"
21
+ @obj.save
22
+ @obj.destroy
23
+ Appstats::Logger.raw_read.should == [
24
+ Appstats::Logger.entry_to_s("object-created", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[x]"),
25
+ Appstats::Logger.entry_to_s("object-destroyed", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[y]")
26
+ ]
27
+ end
28
+
29
+ it "should exclude track excluded options" do
30
+ Appstats::TestObject.acts_as_appstatsable_options(:except => [:create,:destroy])
31
+ @obj = Appstats::TestObject.create(:name => "x")
32
+ @obj.name = "y"
33
+ @obj.save
34
+ @obj.destroy
35
+ Appstats::Logger.raw_read.should == [Appstats::Logger.entry_to_s("object-updated", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[y]")]
36
+ end
37
+ end
38
+
39
+ describe "default behaviour" do
40
+
41
+ it "should track after_save" do
42
+ @obj = Appstats::TestObject.create(:name => "x")
43
+ Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("object-created", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[x]")
44
+ end
45
+
46
+ it "should track after_destroy" do
47
+ Appstats::TestObject.acts_as_appstatsable(:include => [:destroy])
48
+ @obj = Appstats::TestObject.create(:name => "x")
49
+ @obj.destroy
50
+ Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("object-destroyed", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[x]")
51
+ end
52
+
53
+ it "should track after_update" do
54
+ Appstats::TestObject.acts_as_appstatsable(:include => [:update])
55
+ @obj = Appstats::TestObject.create(:name => "x")
56
+ @obj.name = "y"
57
+ @obj.save
58
+ Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("object-updated", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[y]")
59
+ end
60
+
61
+
62
+ it "should handle exceptions" do
63
+ @cheating = Appstats::TestObject.create(:name => "y")
64
+ Appstats::Logger.stub!(:entry).with("object-created", :class_name => "Appstats::TestObject", :class_id => @cheating.id + 1, :details => "[x]").and_raise("something bad")
65
+ @obj = Appstats::TestObject.create(:name => "x")
66
+ Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("appstats-exception", :on => "object-created", :error => "something bad")
67
+ end
68
+ end
69
+
70
+ end
@@ -188,18 +188,18 @@ module Appstats
188
188
  end
189
189
 
190
190
  it "should understand an entry without contexts" do
191
- entry = Entry.load_from_logger_entry("0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
191
+ entry = Entry.load_from_logger_entry("0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
192
192
  Entry.count.should == @before_count + 1
193
193
  entry.action.should == "address_search"
194
- entry.raw_entry.should == "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
194
+ entry.raw_entry.should == "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
195
195
  entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
196
196
  end
197
197
 
198
198
  it "should understand contexts" do
199
- entry = Entry.load_from_logger_entry("0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
199
+ entry = Entry.load_from_logger_entry("0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
200
200
  Entry.count.should == @before_count + 1
201
201
  entry.action.should == "address_filter"
202
- entry.raw_entry.should == "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
202
+ entry.raw_entry.should == "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
203
203
  entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
204
204
  entry.contexts.size.should == 2
205
205
  entry.contexts[0].context_key = "app_name"
@@ -112,9 +112,23 @@ module Appstats
112
112
  Appstats::Logger.entry("address_search")
113
113
  Appstats::Logger.raw_read.should == ["entry_to_s called"]
114
114
  end
115
+
116
+ it "should accept numbers" do
117
+ Appstats::Logger.entry(5, :blah => 6)
118
+ Appstats::Logger.raw_read.should == ["0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
119
+ end
115
120
 
116
121
  end
117
122
 
123
+ describe "#exception_entry" do
124
+
125
+ it "should look similar to regular entry" do
126
+ Appstats::Logger.exception_entry(RuntimeError.new("blah"),:on => "login")
127
+ Appstats::Logger.raw_read.should == ["0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
128
+ end
129
+
130
+ end
131
+
118
132
  describe "#entry_to_hash" do
119
133
 
120
134
  it "should handle nil" do
@@ -127,29 +141,29 @@ module Appstats
127
141
 
128
142
  it "should handle a statistics entry" do
129
143
  expected = { :action => "address_search", :timestamp => "2010-09-21 23:15:20" }
130
- actual = Appstats::Logger.entry_to_hash("0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
144
+ actual = Appstats::Logger.entry_to_hash("0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
131
145
  actual.should == expected
132
146
  end
133
147
 
134
148
  it "should handle contexts" do
135
149
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
136
- actual = Appstats::Logger.entry_to_hash("0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
150
+ actual = Appstats::Logger.entry_to_hash("0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
137
151
  actual.should == expected
138
152
  end
139
153
 
140
154
  it "should handle actions with the delimiter (and change the delimiter)" do
141
155
  expected = { :action => "address:=search-n", :timestamp => "2010-09-21 23:15:20" }
142
- actual = Appstats::Logger.entry_to_hash("0.4.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
156
+ actual = Appstats::Logger.entry_to_hash("0.6.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
143
157
  actual.should == expected
144
158
 
145
159
  expected = { :action => "address::search==--n", :timestamp => "2010-09-21 23:15:20" }
146
- actual = Appstats::Logger.entry_to_hash("0.4.0 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
160
+ actual = Appstats::Logger.entry_to_hash("0.6.0 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
147
161
  actual.should == expected
148
162
  end
149
163
 
150
164
  it "should handle contexts with the delimiter (and change the delimiter)" do
151
165
  expected = { :action => "address", :timestamp => "2010-09-21 23:15:20", :server => "market:eval=-n" }
152
- actual = Appstats::Logger.entry_to_hash("0.4.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
166
+ actual = Appstats::Logger.entry_to_hash("0.6.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
153
167
  actual.should == expected
154
168
  end
155
169
 
@@ -158,66 +172,66 @@ module Appstats
158
172
  describe "#entry_to_s" do
159
173
 
160
174
  it "should handle a statistics entry" do
161
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
175
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
162
176
  actual = Appstats::Logger.entry_to_s("address_search")
163
177
  actual.should == expected
164
178
  end
165
179
 
166
180
  it "should handle numbers" do
167
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
181
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
168
182
  actual = Appstats::Logger.entry_to_s(1,:note => 2.2)
169
183
  actual.should == expected
170
184
  end
171
185
 
172
186
  it "should handle default contexts" do
173
187
  Appstats::Logger.default_contexts[:app_name] = "market"
174
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
188
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
175
189
  actual = Appstats::Logger.entry_to_s("address_search")
176
190
  actual.should == expected
177
191
  end
178
192
 
179
193
  it "should handle contexts (and sort them by symbol)" do
180
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
194
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
181
195
  actual = Appstats::Logger.entry_to_s("address_filter", { :server => "Live", :app_name => 'Market' })
182
196
  actual.should == expected
183
197
  end
184
198
 
185
199
  it "should handle actions with the delimiter (and change the delimiter)" do
186
- expected = "0.4.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
200
+ expected = "0.6.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
187
201
  actual = Appstats::Logger.entry_to_s("address:=search-n")
188
202
  actual.should == expected
189
203
 
190
- expected = "0.4.0 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
204
+ expected = "0.6.0 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
191
205
  actual = Appstats::Logger.entry_to_s("address::search==--n")
192
206
  actual.should == expected
193
207
  end
194
208
 
195
209
  it "should handle contexts with the delimiter (and change the delimiter)" do
196
- expected = "0.4.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
210
+ expected = "0.6.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
197
211
  actual = Appstats::Logger.entry_to_s("address", :server => 'market:eval=-n')
198
212
  actual.should == expected
199
213
  end
200
214
 
201
215
  it "should ignore spaces" do
202
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
216
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
203
217
  actual = Appstats::Logger.entry_to_s("address search")
204
218
  actual.should == expected
205
219
  end
206
220
 
207
221
  it "should convert newlines in action" do
208
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
222
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
209
223
  actual = Appstats::Logger.entry_to_s("address_\nsearch")
210
224
  actual.should == expected
211
225
  end
212
226
 
213
227
  it "should convert newlines in context" do
214
- expected = "0.4.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
228
+ expected = "0.6.0 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
215
229
  actual = Appstats::Logger.entry_to_s("address_search",:blah => "some\nlong\nstatement")
216
230
  actual.should == expected
217
231
  end
218
232
 
219
233
  it "should convert newlines based on the delimiter" do
220
- expected = "0.4.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
234
+ expected = "0.6.0 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
221
235
  actual = Appstats::Logger.entry_to_s("address:=\nsearch-n")
222
236
  actual.should == expected
223
237
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module Appstats
4
+ describe TestObject do
5
+
6
+ before(:each) do
7
+ @obj = Appstats::TestObject.new
8
+ end
9
+
10
+ describe "#initialize" do
11
+
12
+ it "should set name to nil" do
13
+ @obj.name.should == nil
14
+ end
15
+
16
+ it "should set on constructor" do
17
+ obj = Appstats::TestObject.new(:name => 'a')
18
+ obj.name.should == 'a'
19
+ end
20
+
21
+ end
22
+
23
+ describe "#to_s" do
24
+
25
+ it "should support nil" do
26
+ obj = Appstats::TestObject.new
27
+ obj.to_s.should == "NILL"
28
+ obj.name = ""
29
+ obj.to_s.should == "[]"
30
+ end
31
+
32
+ it "should display the name" do
33
+ Appstats::TestObject.new(:name => 'x').to_s.should == '[x]'
34
+ end
35
+
36
+ end
37
+ end
38
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appstats
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 4
8
+ - 6
9
9
  - 0
10
- version: 0.4.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Forward
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-09 00:00:00 -05:00
18
+ date: 2011-02-10 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -149,9 +149,11 @@ files:
149
149
  - db/migrations/20110207200431_add_indexes.rb
150
150
  - db/migrations/20110207213514_create_appstats_actions.rb
151
151
  - db/migrations/20110208210921_align_entry_time_names.rb
152
+ - db/migrations/20110210185911_create_appstats_test_object.rb
152
153
  - db/schema.rb
153
154
  - lib/appstats.rb
154
155
  - lib/appstats/action.rb
156
+ - lib/appstats/acts_as_appstatsable.rb
155
157
  - lib/appstats/code_injections.rb
156
158
  - lib/appstats/context.rb
157
159
  - lib/appstats/date_range.rb
@@ -161,6 +163,7 @@ files:
161
163
  - lib/appstats/logger.rb
162
164
  - lib/appstats/query.rb
163
165
  - lib/appstats/tasks.rb
166
+ - lib/appstats/test_object.rb
164
167
  - lib/appstats/version.rb
165
168
  - lib/daemons/appstats_log_collector.rb
166
169
  - lib/daemons/appstats_log_collector_ctl
@@ -182,6 +185,7 @@ files:
182
185
  - script/destroy
183
186
  - script/generate
184
187
  - spec/action_spec.rb
188
+ - spec/acts_as_appstatsble_spec.rb
185
189
  - spec/appstats_spec.rb
186
190
  - spec/context_spec.rb
187
191
  - spec/date_range_spec.rb
@@ -191,6 +195,7 @@ files:
191
195
  - spec/logger_spec.rb
192
196
  - spec/query_spec.rb
193
197
  - spec/spec_helper.rb
198
+ - spec/test_object_spec.rb
194
199
  has_rdoc: true
195
200
  homepage: http://github.com/aforward/appstats
196
201
  licenses: []
@@ -227,6 +232,7 @@ specification_version: 3
227
232
  summary: Provide usage statistics about how your application is being used
228
233
  test_files:
229
234
  - spec/action_spec.rb
235
+ - spec/acts_as_appstatsble_spec.rb
230
236
  - spec/appstats_spec.rb
231
237
  - spec/context_spec.rb
232
238
  - spec/date_range_spec.rb
@@ -236,3 +242,4 @@ test_files:
236
242
  - spec/logger_spec.rb
237
243
  - spec/query_spec.rb
238
244
  - spec/spec_helper.rb
245
+ - spec/test_object_spec.rb