appstats 0.0.13 → 0.0.14
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/.gitignore +2 -0
- data/Gemfile.lock +8 -2
- data/appstats.gemspec +2 -1
- data/db/config.yml +1 -1
- data/db/migrations/20110203151136_create_appstats_contexts.rb +16 -0
- data/db/migrations/20110203151635_rework_appstats_entries.rb +21 -0
- data/db/migrations/20110204183259_create_log_collectors.rb +16 -0
- data/db/schema.rb +23 -4
- data/lib/appstats.rb +14 -2
- data/lib/appstats/context.rb +26 -0
- data/lib/appstats/entry.rb +31 -2
- data/lib/appstats/log_collector.rb +124 -0
- data/lib/appstats/version.rb +1 -1
- data/lib/daemons/appstats_log_collector +0 -0
- data/lib/daemons/appstats_log_collector.rb +42 -0
- data/lib/daemons/appstats_log_collector_ctl +25 -0
- data/spec/context_spec.rb +123 -0
- data/spec/entry_spec.rb +162 -17
- data/spec/log_collector_spec.rb +284 -0
- data/spec/logger_spec.rb +16 -17
- metadata +50 -10
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Appstats
|
4
|
+
describe Context do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@context = Appstats::Context.new
|
8
|
+
@time = Time.parse('2010-01-02 10:20:30')
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#initialize" do
|
12
|
+
|
13
|
+
it "should set context_key to nil" do
|
14
|
+
@context.context_key.should == nil
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should set context_value to nil" do
|
18
|
+
@context.context_value.should == nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set context_int to nil" do
|
22
|
+
@context.context_int.should == nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should set context_float to nil" do
|
26
|
+
@context.context_float.should == nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should set on constructor" do
|
30
|
+
context = Appstats::Context.new(:context_key => 'a', :context_value => "b", :context_int => 1, :context_float => 1.3)
|
31
|
+
context.context_key.should == 'a'
|
32
|
+
context.context_value.should == 'b'
|
33
|
+
context.context_int.should == nil
|
34
|
+
context.context_float.should == nil
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#context_int" do
|
40
|
+
|
41
|
+
it "should be nil if not an int" do
|
42
|
+
@context.context_int.should == nil
|
43
|
+
@context.context_value = "1"
|
44
|
+
@context.context_int.should == 1
|
45
|
+
|
46
|
+
@context.context_value = "2"
|
47
|
+
@context.context_int.should == 2
|
48
|
+
|
49
|
+
@context.context_value = "c"
|
50
|
+
@context.context_int.should == nil
|
51
|
+
|
52
|
+
@context.context_value = nil
|
53
|
+
@context.context_int.should == nil
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#context_float" do
|
60
|
+
|
61
|
+
it "should be nil if not an int" do
|
62
|
+
@context.context_float.should == nil
|
63
|
+
@context.context_value = "1"
|
64
|
+
@context.context_float.should == 1.0
|
65
|
+
|
66
|
+
@context.context_value = "2.1"
|
67
|
+
@context.context_float.should == 2.1
|
68
|
+
|
69
|
+
@context.context_value = "c"
|
70
|
+
@context.context_float.should == nil
|
71
|
+
|
72
|
+
@context.context_value = nil
|
73
|
+
@context.context_float.should == nil
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#entry" do
|
79
|
+
|
80
|
+
before(:each) do
|
81
|
+
@entry = Appstats::Entry.new(:action => "a")
|
82
|
+
@entry.save.should == true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should have an entry" do
|
86
|
+
@context.entry.should == nil
|
87
|
+
@context.entry = @entry
|
88
|
+
@context.save.should == true
|
89
|
+
@context.reload
|
90
|
+
@context.entry.should == @entry
|
91
|
+
|
92
|
+
@context = Context.last
|
93
|
+
@context.entry.should == @entry
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "#to_s" do
|
99
|
+
|
100
|
+
before(:each) do
|
101
|
+
@context = Appstats::Context.new
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should return no context if no key" do
|
105
|
+
@context.to_s.should == 'No Context'
|
106
|
+
@context.context_key = ''
|
107
|
+
@context.to_s.should == 'No Context'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should return the context_key name if no date" do
|
111
|
+
@context.context_key = "Blah"
|
112
|
+
@context.to_s.should == 'Blah[]'
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should return context_key and context_value if available" do
|
116
|
+
@context.context_key = "More Blah"
|
117
|
+
@context.context_value = "true"
|
118
|
+
@context.to_s.should == "More Blah[true]"
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/spec/entry_spec.rb
CHANGED
@@ -3,32 +3,62 @@ require 'spec_helper'
|
|
3
3
|
module Appstats
|
4
4
|
describe Entry do
|
5
5
|
|
6
|
+
before(:each) do
|
7
|
+
@time = Time.parse('2010-01-02 10:20:30')
|
8
|
+
@entry = Appstats::Entry.new
|
9
|
+
Time.stub!(:now).and_return(@time)
|
10
|
+
end
|
11
|
+
|
6
12
|
describe "#initialize" do
|
7
13
|
|
8
|
-
|
9
|
-
@entry
|
10
|
-
end
|
11
|
-
|
12
|
-
it "should set entry_type to nil" do
|
13
|
-
@entry.entry_type.should == nil
|
14
|
+
it "should set action to nil" do
|
15
|
+
@entry.action.should == nil
|
14
16
|
end
|
15
17
|
|
16
|
-
it "should set
|
17
|
-
@entry.
|
18
|
+
it "should set occurred_at to nil" do
|
19
|
+
@entry.occurred_at.should == nil
|
18
20
|
end
|
19
|
-
|
20
|
-
it "should set
|
21
|
-
@entry.
|
21
|
+
|
22
|
+
it "should set raw_entry to nil" do
|
23
|
+
@entry.raw_entry.should == nil
|
22
24
|
end
|
23
25
|
|
24
26
|
it "should set on constructor" do
|
25
|
-
entry = Appstats::Entry.new(:
|
26
|
-
entry.
|
27
|
-
entry.
|
28
|
-
|
27
|
+
entry = Appstats::Entry.new(:action => 'a', :occurred_at => @time, :raw_entry => 'b')
|
28
|
+
entry.action.should == 'a'
|
29
|
+
entry.occurred_at.should == @time
|
30
|
+
entry.raw_entry.should == 'b'
|
29
31
|
end
|
30
32
|
|
31
33
|
end
|
34
|
+
|
35
|
+
describe "#contexts" do
|
36
|
+
|
37
|
+
it "should have none by default" do
|
38
|
+
@entry.contexts.size.should == 0
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should be able add contexts" do
|
42
|
+
context = Appstats::Context.new(:context_key => 'a', :context_value => 'one')
|
43
|
+
context.save.should == true
|
44
|
+
@entry.contexts<< context
|
45
|
+
@entry.save.should == true
|
46
|
+
@entry.reload
|
47
|
+
@entry.contexts.size.should == 1
|
48
|
+
@entry.contexts[0].should == context
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should alphabetize them" do
|
52
|
+
zzz = Appstats::Context.create(:context_key => 'zzz', :context_value => 'one')
|
53
|
+
aaa = Appstats::Context.create(:context_key => 'aaa', :context_value => 'one')
|
54
|
+
@entry.contexts<< zzz
|
55
|
+
@entry.contexts<< aaa
|
56
|
+
@entry.save.should == true
|
57
|
+
@entry.reload
|
58
|
+
@entry.contexts.should == [aaa,zzz]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
32
62
|
|
33
63
|
describe "#to_s" do
|
34
64
|
|
@@ -36,9 +66,124 @@ module Appstats
|
|
36
66
|
@entry = Appstats::Entry.new
|
37
67
|
end
|
38
68
|
|
39
|
-
it "should
|
40
|
-
@entry.to_s.should == 'Entry
|
69
|
+
it "should return no entry if no action" do
|
70
|
+
@entry.to_s.should == 'No Entry'
|
71
|
+
@entry.action = ''
|
72
|
+
@entry.to_s.should == 'No Entry'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should return the action name if no date" do
|
76
|
+
@entry.action = "Blah"
|
77
|
+
@entry.to_s.should == 'Blah'
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return action and date if available" do
|
81
|
+
@entry.action = "More Blah"
|
82
|
+
@entry.occurred_at = @time
|
83
|
+
@entry.to_s.should == "More Blah at 2010-01-02 10:20:30"
|
41
84
|
end
|
85
|
+
|
42
86
|
end
|
87
|
+
|
88
|
+
describe "#load_from_logger_file" do
|
89
|
+
|
90
|
+
before(:each) do
|
91
|
+
@before_count = Entry.count
|
92
|
+
Appstats::Logger.reset
|
93
|
+
Time.stub!(:now).and_return(Time.parse('2010-09-21 23:15:20'))
|
94
|
+
end
|
95
|
+
|
96
|
+
after(:each) do
|
97
|
+
File.delete(Appstats::Logger.filename) if File.exists?(Appstats::Logger.filename)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should handle nil" do
|
101
|
+
Entry.load_from_logger_file(nil).should == false
|
102
|
+
Entry.count.should == @before_count
|
103
|
+
Entry.count.should == @before_count
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should handle unknown files" do
|
107
|
+
File.exists?("should_not_exist.txt").should == false
|
108
|
+
Entry.load_from_logger_file("should_not_exist.txt").should == false
|
109
|
+
Entry.count.should == @before_count
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should handle appstat files" do
|
113
|
+
Appstats::Logger.entry("test_action")
|
114
|
+
Appstats::Logger.entry("another_test_action")
|
115
|
+
Entry.load_from_logger_file(Appstats::Logger.filename).should == true
|
116
|
+
Entry.count.should == @before_count + 2
|
117
|
+
Entry.last.action.should == "another_test_action"
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
describe "#load_from_logger_entry" do
|
124
|
+
|
125
|
+
before(:each) do
|
126
|
+
@before_count = Entry.count
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should handle nil" do
|
130
|
+
Entry.load_from_logger_entry(nil).should == false
|
131
|
+
Entry.count.should == @before_count
|
132
|
+
|
133
|
+
Entry.load_from_logger_entry("").should == false
|
134
|
+
Entry.count.should == @before_count
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should create an unknown for unknown entries" do
|
138
|
+
entry = Entry.load_from_logger_entry("blah")
|
139
|
+
Entry.count.should == @before_count + 1
|
140
|
+
entry.action.should == "UNKNOWN_ACTION"
|
141
|
+
entry.raw_entry.should == "blah"
|
142
|
+
entry.occurred_at.should == nil
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should understand an entry without contexts" do
|
146
|
+
entry = Entry.load_from_logger_entry("0.0.14 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
|
147
|
+
Entry.count.should == @before_count + 1
|
148
|
+
entry.action.should == "address_search"
|
149
|
+
entry.raw_entry.should == "0.0.14 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
|
150
|
+
entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should understand contexts" do
|
154
|
+
entry = Entry.load_from_logger_entry("0.0.14 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
|
155
|
+
Entry.count.should == @before_count + 1
|
156
|
+
entry.action.should == "address_filter"
|
157
|
+
entry.raw_entry.should == "0.0.14 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
|
158
|
+
entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
|
159
|
+
entry.contexts.size.should == 2
|
160
|
+
entry.contexts[0].context_key = "app_name"
|
161
|
+
entry.contexts[0].context_value = "Market"
|
162
|
+
entry.contexts[1].context_key = "server"
|
163
|
+
entry.contexts[1].context_value = "Live"
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#log_collector" do
|
169
|
+
|
170
|
+
before(:each) do
|
171
|
+
@log_collector = Appstats::LogCollector.new(:host => "a")
|
172
|
+
@log_collector.save.should == true
|
173
|
+
end
|
174
|
+
|
175
|
+
it "should have a log_collector" do
|
176
|
+
@entry.log_collector.should == nil
|
177
|
+
@entry.log_collector = @log_collector
|
178
|
+
@entry.save.should == true
|
179
|
+
@entry.reload
|
180
|
+
@entry.log_collector.should == @log_collector
|
181
|
+
|
182
|
+
@entry = Entry.last
|
183
|
+
@entry.log_collector.should == @log_collector
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
43
188
|
end
|
44
189
|
end
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Appstats
|
4
|
+
describe LogCollector do
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
LogCollector.delete_all
|
8
|
+
@log_collector = Appstats::LogCollector.new
|
9
|
+
@login = { :host => "myhost.localnet", :user => "deployer", :password => "pass" }
|
10
|
+
@login2 = { :host => "yourhost.localnet", :user => "deployer", :password => "ssap" }
|
11
|
+
@logins = [@login2, @login]
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
LogCollector.all.each do |log_collector|
|
16
|
+
File.delete(log_collector.local_filename) if File.exists?(log_collector.local_filename)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def simple_path(local_path_to_filename)
|
21
|
+
File.expand_path("#{File.dirname(__FILE__)}/#{local_path_to_filename}")
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#initialize" do
|
25
|
+
|
26
|
+
it "should set host to nil" do
|
27
|
+
@log_collector.host.should == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set filename to nil" do
|
31
|
+
@log_collector.filename.should == nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should set status to unprocessed" do
|
35
|
+
@log_collector.status.should == nil
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should set on constructor" do
|
39
|
+
log_collector = Appstats::LogCollector.new(:host => 'a', :filename => 'b', :status => 'c')
|
40
|
+
log_collector.host.should == 'a'
|
41
|
+
log_collector.filename.should == 'b'
|
42
|
+
log_collector.status.should == 'c'
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#find_remote_files" do
|
48
|
+
|
49
|
+
before(:each) do
|
50
|
+
@before_count = LogCollector.count
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should log all transactions" do
|
54
|
+
ssh = mock(Net::SSH)
|
55
|
+
Net::SSH.should_receive(:start).with("myhost.localnet","deployer",{ :password => "pass"}).and_yield(ssh)
|
56
|
+
ssh.should_receive(:exec!).with("cd /my/path/log && ls | grep mystats").and_return("mystats1\nmystats2")
|
57
|
+
|
58
|
+
Appstats.should_receive(:log).with(:info, "Looking for logs in [deployer@myhost.localnet:/my/path/log] labelled [mystats]")
|
59
|
+
Appstats.should_receive(:log).with(:info, "About to analyze 2 file(s).")
|
60
|
+
Appstats.should_receive(:log).with(:info, " - deployer@myhost.localnet:/my/path/log/mystats1")
|
61
|
+
Appstats.should_receive(:log).with(:info, " - deployer@myhost.localnet:/my/path/log/mystats2")
|
62
|
+
Appstats.should_receive(:log).with(:info, "Loaded 2 file(s).")
|
63
|
+
LogCollector.find_remote_files(@login,"/my/path/log","mystats").should == 2
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should talk to remote server" do
|
67
|
+
ssh = mock(Net::SSH)
|
68
|
+
Net::SSH.should_receive(:start).with("myhost.localnet","deployer",{ :password => "pass"}).and_yield(ssh)
|
69
|
+
ssh.should_receive(:exec!).with("cd /my/path/log && ls | grep mystats").and_return("mystats1\nmystats2")
|
70
|
+
|
71
|
+
LogCollector.find_remote_files(@login,"/my/path/log","mystats").should == 2
|
72
|
+
LogCollector.count.should == @before_count + 2
|
73
|
+
|
74
|
+
log_collector = LogCollector.last
|
75
|
+
log_collector.host.should == "myhost.localnet"
|
76
|
+
log_collector.filename.should == "/my/path/log/mystats2"
|
77
|
+
log_collector.status.should == "unprocessed"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should fail silently for bad connections" do
|
81
|
+
Net::SSH.should_receive(:start).with("myhost.localnet","deployer",{ :password => "pass"}).and_raise("Some bad message")
|
82
|
+
Appstats.should_receive(:log).with(:info, "Looking for logs in [deployer@myhost.localnet:/my/path/log] labelled [mystats]")
|
83
|
+
Appstats.should_receive(:log).with(:error,"Something bad occurred during Appstats::LogCollector#find_remote_files")
|
84
|
+
Appstats.should_receive(:log).with(:error,"Some bad message")
|
85
|
+
LogCollector.find_remote_files(@login,"/my/path/log","mystats").should == 0
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#load_remote_files" do
|
91
|
+
|
92
|
+
before(:each) do
|
93
|
+
@before_count = LogCollector.count
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should log if nothing to load" do
|
97
|
+
log = LogCollector.create(:status => "not_unprocessed")
|
98
|
+
Appstats.should_receive(:log).with(:info,"No remote logs to load.")
|
99
|
+
LogCollector.load_remote_files(@login,"/my/path/log",[]).should == 0
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
it "should log the files loaded" do
|
104
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app2"]).should == 1
|
105
|
+
|
106
|
+
Appstats.should_receive(:log).with(:info, "About to analyze 3 file(s).")
|
107
|
+
Appstats.should_receive(:log).with(:info, " - deployer@myhost.localnet:/my/path/log/app1")
|
108
|
+
Appstats.should_receive(:log).with(:info, " - ALREADY LOADED deployer@myhost.localnet:/my/path/log/app2")
|
109
|
+
Appstats.should_receive(:log).with(:info, " - deployer@myhost.localnet:/my/path/log/app3")
|
110
|
+
Appstats.should_receive(:log).with(:info, "Loaded 2 file(s).")
|
111
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1","app2","app3"]).should == 2
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should create an unprocessed record per file" do
|
115
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1","app2","app3"]).should == 3
|
116
|
+
LogCollector.count.should == @before_count + 3
|
117
|
+
log_collector = LogCollector.last
|
118
|
+
|
119
|
+
log_collector.host.should == "myhost.localnet"
|
120
|
+
log_collector.filename.should == "/my/path/log/app3"
|
121
|
+
log_collector.status.should == "unprocessed"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should ignore the same file" do
|
125
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1","app3"]).should == 2
|
126
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1","app2","app3"]).should == 1
|
127
|
+
LogCollector.count.should == @before_count + 3
|
128
|
+
log_collector = LogCollector.last
|
129
|
+
|
130
|
+
log_collector.host.should == "myhost.localnet"
|
131
|
+
log_collector.filename.should == "/my/path/log/app2"
|
132
|
+
log_collector.status.should == "unprocessed"
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#local_filename" do
|
138
|
+
|
139
|
+
it "should return a standardized name with the log collector id" do
|
140
|
+
log = LogCollector.create
|
141
|
+
log.local_filename.should == simple_path("../log/appstats_remote_log_#{log.id}.log")
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#download_remote_files" do
|
147
|
+
|
148
|
+
before(:each) do
|
149
|
+
@before_count = LogCollector.count
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should only process unprocessed files" do
|
153
|
+
log = LogCollector.create(:status => "not_unprocessed")
|
154
|
+
Appstats.should_receive(:log).with(:info,"No remote logs to download.")
|
155
|
+
LogCollector.download_remote_files(@logins).should == 0
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should log exceptions" do
|
159
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1"]).should == 1
|
160
|
+
log1 = LogCollector.find_by_filename("/my/path/log/app1")
|
161
|
+
|
162
|
+
scp = mock(Net::SCP)
|
163
|
+
Net::SCP.should_receive(:start).with("myhost.localnet","deployer",{ :password => "pass"}).and_yield(scp)
|
164
|
+
scp.should_receive(:download!).with("/my/path/log/app1",simple_path("../log/appstats_remote_log_#{log1.id}.log")).and_raise("Something bad happened again")
|
165
|
+
|
166
|
+
Appstats.should_receive(:log).with(:info,"About to download 1 file(s).")
|
167
|
+
Appstats.should_receive(:log).with(:error,"Something bad occurred during Appstats::LogCollector#download_remote_files")
|
168
|
+
Appstats.should_receive(:log).with(:error,"Something bad happened again")
|
169
|
+
Appstats.should_receive(:log).with(:error, "File #{simple_path("../log/appstats_remote_log_#{log1.id}.log")} did not download.")
|
170
|
+
Appstats.should_receive(:log).with(:info,"Downloaded 0 file(s).")
|
171
|
+
LogCollector.download_remote_files(@logins).should == 0
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should ignore if file not downloaded" do
|
175
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1"]).should == 1
|
176
|
+
log1 = LogCollector.find_by_filename("/my/path/log/app1")
|
177
|
+
|
178
|
+
scp = mock(Net::SCP)
|
179
|
+
Net::SCP.should_receive(:start).with("myhost.localnet","deployer",{ :password => "pass"}).and_yield(scp)
|
180
|
+
scp.should_receive(:download!).with("/my/path/log/app1",simple_path("../log/appstats_remote_log_#{log1.id}.log"))
|
181
|
+
|
182
|
+
Appstats.should_receive(:log).with(:info,"About to download 1 file(s).")
|
183
|
+
Appstats.should_receive(:log).with(:error, "File #{simple_path("../log/appstats_remote_log_#{log1.id}.log")} did not download.")
|
184
|
+
Appstats.should_receive(:log).with(:info,"Downloaded 0 file(s).")
|
185
|
+
LogCollector.download_remote_files(@logins).should == 0
|
186
|
+
log1.reload
|
187
|
+
log1.status.should == "failed_download"
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should copy the file based on the log_collector id" do
|
191
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app1","app2"]).should == 2
|
192
|
+
|
193
|
+
log1 = LogCollector.find_by_filename("/my/path/log/app1")
|
194
|
+
log2 = LogCollector.find_by_filename("/my/path/log/app2")
|
195
|
+
|
196
|
+
File.open(log1.local_filename, 'w') {|f| f.write("testfile - delete") }
|
197
|
+
File.open(log2.local_filename, 'w') {|f| f.write("testfile - delete") }
|
198
|
+
|
199
|
+
|
200
|
+
scp = mock(Net::SCP)
|
201
|
+
1.upto(3) do
|
202
|
+
Net::SCP.should_receive(:start).with("myhost.localnet","deployer",{ :password => "pass"}).and_yield(scp)
|
203
|
+
end
|
204
|
+
scp.should_receive(:download!).with("/my/path/log/app1",simple_path("../log/appstats_remote_log_#{log1.id}.log"))
|
205
|
+
scp.should_receive(:download!).with("/my/path/log/app2",simple_path("../log/appstats_remote_log_#{log2.id}.log"))
|
206
|
+
|
207
|
+
LogCollector.download_remote_files(@logins).should == 2
|
208
|
+
|
209
|
+
log1.reload and log2.reload
|
210
|
+
log1.status.should == "downloaded"
|
211
|
+
log2.status.should == "downloaded"
|
212
|
+
|
213
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["app3"]).should == 1
|
214
|
+
log3 = LogCollector.find_by_filename("/my/path/log/app3")
|
215
|
+
File.open(log3.local_filename, 'w') {|f| f.write("testfile - delete") }
|
216
|
+
|
217
|
+
localfile = simple_path("../log/appstats_remote_log_#{log3.id}.log")
|
218
|
+
scp.should_receive(:download!).with("/my/path/log/app3",localfile)
|
219
|
+
|
220
|
+
Appstats.should_receive(:log).with(:info,"About to download 1 file(s).")
|
221
|
+
Appstats.should_receive(:log).with(:info, " - deployer@myhost.localnet:/my/path/log/app3 > #{localfile}")
|
222
|
+
Appstats.should_receive(:log).with(:info,"Downloaded 1 file(s).")
|
223
|
+
LogCollector.download_remote_files(@logins).should == 1
|
224
|
+
log3.reload and log3.reload
|
225
|
+
log3.status.should == "downloaded"
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "#process_local_files" do
|
231
|
+
|
232
|
+
before(:each) do
|
233
|
+
@entry_count = Entry.count
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should only process downloaded files" do
|
237
|
+
log = LogCollector.create(:status => "not_downloaded")
|
238
|
+
Appstats.should_receive(:log).with(:info,"No local logs to process.")
|
239
|
+
LogCollector.process_local_files.should == 0
|
240
|
+
end
|
241
|
+
|
242
|
+
it "should process downloaded files into entries" do
|
243
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["appstats1"]).should == 1
|
244
|
+
log3 = LogCollector.find_by_filename("/my/path/log/appstats1")
|
245
|
+
log3.status = "downloaded" and log3.save.should == true
|
246
|
+
File.open(log3.local_filename, 'w') {|f| f.write(Appstats::Logger.entry_to_s("test_action1") + "\n" + Appstats::Logger.entry_to_s("test_action2")) }
|
247
|
+
|
248
|
+
Appstats.should_receive(:log).with(:info,"About to process 1 file(s).")
|
249
|
+
Appstats.should_receive(:log).with(:info," - 2 entr(ies) in #{log3.local_filename}.")
|
250
|
+
Appstats.should_receive(:log).with(:info,"Processed 1 file(s) with 2 entr(ies).")
|
251
|
+
LogCollector.process_local_files.should == 1
|
252
|
+
|
253
|
+
log3.reload
|
254
|
+
log3.status.should == "processed"
|
255
|
+
Entry.count.should == @entry_count + 2
|
256
|
+
entry = Entry.last
|
257
|
+
entry.log_collector.should == log3
|
258
|
+
entry.action.should == "test_action2"
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should deal with exceptions" do
|
262
|
+
LogCollector.load_remote_files(@login,"/my/path/log",["appstats1"]).should == 1
|
263
|
+
log3 = LogCollector.find_by_filename("/my/path/log/appstats1")
|
264
|
+
log3.status = "downloaded" and log3.save.should == true
|
265
|
+
File.open(log3.local_filename, 'w') {|f| f.write(Appstats::Logger.entry_to_s("test_action1") + "\n" + Appstats::Logger.entry_to_s("test_action2")) }
|
266
|
+
|
267
|
+
File.stub!(:open).and_raise("bad error")
|
268
|
+
|
269
|
+
Appstats.should_receive(:log).with(:info,"About to process 1 file(s).")
|
270
|
+
Appstats.should_receive(:log).with(:error,"Something bad occurred during Appstats::LogCollector#process_local_files")
|
271
|
+
Appstats.should_receive(:log).with(:error,"bad error")
|
272
|
+
Appstats.should_receive(:log).with(:info,"Processed 0 file(s) with 0 entr(ies).")
|
273
|
+
LogCollector.process_local_files.should == 0
|
274
|
+
|
275
|
+
log3.reload
|
276
|
+
log3.status.should == "downloaded"
|
277
|
+
Entry.count.should == @entry_count
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
end
|
284
|
+
end
|