appstats 0.4.0 → 0.6.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.
@@ -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