request_recorder 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Appraisals CHANGED
@@ -1,7 +1,9 @@
1
1
  appraise "rails2" do
2
+ gem "rack", "~> 1.1.6"
2
3
  gem "activerecord", "~>2.3.14"
3
4
  end
4
5
 
5
6
  appraise "rails3" do
7
+ gem "rack", ">= 1.5.2"
6
8
  gem "activerecord", "~>3.2.7"
7
9
  end
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
  gemspec
3
3
 
4
4
  gem "appraisal"
@@ -8,3 +8,4 @@ gem "rspec", "~>2"
8
8
  gem "activerecord"
9
9
  gem "sqlite3"
10
10
  gem "fakeredis"
11
+ gem "json"
data/Gemfile.lock CHANGED
@@ -1,35 +1,50 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- request_recorder (0.1.2)
4
+ request_recorder (0.2.0)
5
5
  activerecord
6
+ multi_json
6
7
  rack
7
8
 
8
9
  GEM
9
- remote: http://rubygems.org/
10
+ remote: https://rubygems.org/
10
11
  specs:
11
- activerecord (2.3.14)
12
- activesupport (= 2.3.14)
13
- activesupport (2.3.14)
14
- appraisal (0.4.1)
12
+ activemodel (3.2.13)
13
+ activesupport (= 3.2.13)
14
+ builder (~> 3.0.0)
15
+ activerecord (3.2.13)
16
+ activemodel (= 3.2.13)
17
+ activesupport (= 3.2.13)
18
+ arel (~> 3.0.2)
19
+ tzinfo (~> 0.3.29)
20
+ activesupport (3.2.13)
21
+ i18n (= 0.6.1)
22
+ multi_json (~> 1.0)
23
+ appraisal (0.5.2)
15
24
  bundler
16
25
  rake
17
- bump (0.3.5)
18
- diff-lcs (1.1.3)
19
- fakeredis (0.4.0)
26
+ arel (3.0.2)
27
+ builder (3.0.4)
28
+ bump (0.4.1)
29
+ diff-lcs (1.2.3)
30
+ fakeredis (0.4.2)
20
31
  redis (~> 3.0.0)
21
- rack (1.4.1)
22
- rake (0.9.2)
23
- redis (3.0.1)
24
- rspec (2.6.0)
25
- rspec-core (~> 2.6.0)
26
- rspec-expectations (~> 2.6.0)
27
- rspec-mocks (~> 2.6.0)
28
- rspec-core (2.6.4)
29
- rspec-expectations (2.6.0)
30
- diff-lcs (~> 1.1.2)
31
- rspec-mocks (2.6.0)
32
- sqlite3 (1.3.6)
32
+ i18n (0.6.1)
33
+ json (1.7.7)
34
+ multi_json (1.7.2)
35
+ rack (1.5.2)
36
+ rake (10.0.4)
37
+ redis (3.0.3)
38
+ rspec (2.13.0)
39
+ rspec-core (~> 2.13.0)
40
+ rspec-expectations (~> 2.13.0)
41
+ rspec-mocks (~> 2.13.0)
42
+ rspec-core (2.13.1)
43
+ rspec-expectations (2.13.0)
44
+ diff-lcs (>= 1.1.3, < 2.0)
45
+ rspec-mocks (2.13.1)
46
+ sqlite3 (1.3.7)
47
+ tzinfo (0.3.37)
33
48
 
34
49
  PLATFORMS
35
50
  ruby
@@ -39,6 +54,7 @@ DEPENDENCIES
39
54
  appraisal
40
55
  bump
41
56
  fakeredis
57
+ json
42
58
  rake
43
59
  request_recorder!
44
60
  rspec (~> 2)
data/Readme.md CHANGED
@@ -1,4 +1,4 @@
1
- Record your rack/rails requests and store them for future inspection
1
+ Record your rack/rails requests and store them for future inspection + see them in your chrome console.
2
2
 
3
3
  Install
4
4
  =======
@@ -10,28 +10,30 @@ Add to your middleware stack:
10
10
  require "request_recorder"
11
11
 
12
12
  require "request_recorder/cache_logger"
13
- use RequestRecorder::Middleware, :store => RequestRecorder::CacheLogger.new(Rails.cache)
14
-
15
- -- or --
16
-
17
- require "request_recorder/redis_logger"
18
- use RequestRecorder::Middleware, :store => RequestRecorder::RedisLogger.new(Redis.new)
13
+ use RequestRecorder::Middleware,
14
+ :store => RequestRecorder::CacheLogger.new(Rails.cache),
15
+ :frontend_auth => lambda { |env| Rails.env.development? } # TODO use something like `env.warden.user.is_admin?` in production
19
16
 
20
17
  Usage
21
18
  =====
22
19
 
23
- - request a page with `/something?request_recorder=10|my-session-name` -> record next 10 requests from my browser
20
+ - request a page with `/something?request_recorder=10-my_session_name` -> record next 10 requests from my browser
24
21
  - all the debug-level logging info from rails + activerecord gets stored
25
22
  - get log directly from the store or use the frontend
26
23
 
27
- Frontend
28
- ========
24
+ Chrome console
25
+ ==============
26
+ (needs `:frontend_auth`)
29
27
 
30
- Add :frontend_auth and find out if the current user is authorized
28
+ - Install [Chrome extension](https://chrome.google.com/webstore/detail/chrome-logger/noaneddfkdjfnfdakjjmocngnfkfehhd)
29
+ - Enable it<br/> ![Enable](http://cdn.craig.is/img/chromelogger/toggle.gif)
30
+ - Open console<br/> ![Profit](https://dl.dropboxusercontent.com/u/2670385/Web/request_recorder_output.png)
31
31
 
32
- use RequestRecorder::Middleware, :frontent_auth => lambda{|env| env.warden.user.is_admin? }
33
-
34
- Go to `/request_recorder/<key>` and see the recorded log.
32
+ Frontend
33
+ ========
34
+ (needs `:frontend_auth`)
35
+ See the log of all requests in an entire session: `/request_recorder/my_session_name`.
36
+ This also includes requests that did not get shown in the chrome logger like redirects.
35
37
 
36
38
  Author
37
39
  ======
@@ -1,6 +1,6 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source :rubygems
3
+ source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
6
  gem "bump"
@@ -8,6 +8,8 @@ gem "rake"
8
8
  gem "rspec", "~>2"
9
9
  gem "sqlite3"
10
10
  gem "fakeredis"
11
+ gem "json"
12
+ gem "rack", "~> 1.1.6"
11
13
  gem "activerecord", "~>2.3.14"
12
14
 
13
15
  gemspec :path=>"../"
@@ -1,35 +1,38 @@
1
1
  PATH
2
2
  remote: /Users/mgrosser/code/tools/request_recorder
3
3
  specs:
4
- request_recorder (0.1.1)
4
+ request_recorder (0.1.2)
5
5
  activerecord
6
+ multi_json
6
7
  rack
7
8
 
8
9
  GEM
9
- remote: http://rubygems.org/
10
+ remote: https://rubygems.org/
10
11
  specs:
11
- activerecord (2.3.14)
12
- activesupport (= 2.3.14)
13
- activesupport (2.3.14)
14
- appraisal (0.4.1)
12
+ activerecord (2.3.18)
13
+ activesupport (= 2.3.18)
14
+ activesupport (2.3.18)
15
+ appraisal (0.5.2)
15
16
  bundler
16
17
  rake
17
- bump (0.3.5)
18
- diff-lcs (1.1.3)
19
- fakeredis (0.4.1)
18
+ bump (0.4.1)
19
+ diff-lcs (1.2.3)
20
+ fakeredis (0.4.2)
20
21
  redis (~> 3.0.0)
21
- rack (1.4.1)
22
- rake (0.9.2.2)
23
- redis (3.0.2)
24
- rspec (2.11.0)
25
- rspec-core (~> 2.11.0)
26
- rspec-expectations (~> 2.11.0)
27
- rspec-mocks (~> 2.11.0)
28
- rspec-core (2.11.1)
29
- rspec-expectations (2.11.3)
30
- diff-lcs (~> 1.1.3)
31
- rspec-mocks (2.11.3)
32
- sqlite3 (1.3.6)
22
+ json (1.7.7)
23
+ multi_json (1.7.2)
24
+ rack (1.1.6)
25
+ rake (10.0.4)
26
+ redis (3.0.3)
27
+ rspec (2.13.0)
28
+ rspec-core (~> 2.13.0)
29
+ rspec-expectations (~> 2.13.0)
30
+ rspec-mocks (~> 2.13.0)
31
+ rspec-core (2.13.1)
32
+ rspec-expectations (2.13.0)
33
+ diff-lcs (>= 1.1.3, < 2.0)
34
+ rspec-mocks (2.13.1)
35
+ sqlite3 (1.3.7)
33
36
 
34
37
  PLATFORMS
35
38
  ruby
@@ -39,6 +42,8 @@ DEPENDENCIES
39
42
  appraisal
40
43
  bump
41
44
  fakeredis
45
+ json
46
+ rack (~> 1.1.6)
42
47
  rake
43
48
  request_recorder!
44
49
  rspec (~> 2)
@@ -1,6 +1,6 @@
1
1
  # This file was generated by Appraisal
2
2
 
3
- source :rubygems
3
+ source "https://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
6
  gem "bump"
@@ -8,6 +8,8 @@ gem "rake"
8
8
  gem "rspec", "~>2"
9
9
  gem "sqlite3"
10
10
  gem "fakeredis"
11
+ gem "json"
12
+ gem "rack", ">= 1.5.2"
11
13
  gem "activerecord", "~>3.2.7"
12
14
 
13
15
  gemspec :path=>"../"
@@ -1,48 +1,50 @@
1
1
  PATH
2
2
  remote: /Users/mgrosser/code/tools/request_recorder
3
3
  specs:
4
- request_recorder (0.1.1)
4
+ request_recorder (0.1.2)
5
5
  activerecord
6
+ multi_json
6
7
  rack
7
8
 
8
9
  GEM
9
- remote: http://rubygems.org/
10
+ remote: https://rubygems.org/
10
11
  specs:
11
- activemodel (3.2.8)
12
- activesupport (= 3.2.8)
12
+ activemodel (3.2.13)
13
+ activesupport (= 3.2.13)
13
14
  builder (~> 3.0.0)
14
- activerecord (3.2.8)
15
- activemodel (= 3.2.8)
16
- activesupport (= 3.2.8)
15
+ activerecord (3.2.13)
16
+ activemodel (= 3.2.13)
17
+ activesupport (= 3.2.13)
17
18
  arel (~> 3.0.2)
18
19
  tzinfo (~> 0.3.29)
19
- activesupport (3.2.8)
20
- i18n (~> 0.6)
20
+ activesupport (3.2.13)
21
+ i18n (= 0.6.1)
21
22
  multi_json (~> 1.0)
22
- appraisal (0.4.1)
23
+ appraisal (0.5.2)
23
24
  bundler
24
25
  rake
25
26
  arel (3.0.2)
26
27
  builder (3.0.4)
27
- bump (0.3.5)
28
- diff-lcs (1.1.3)
29
- fakeredis (0.4.1)
28
+ bump (0.4.1)
29
+ diff-lcs (1.2.3)
30
+ fakeredis (0.4.2)
30
31
  redis (~> 3.0.0)
31
32
  i18n (0.6.1)
32
- multi_json (1.3.6)
33
- rack (1.4.1)
34
- rake (0.9.2.2)
35
- redis (3.0.2)
36
- rspec (2.11.0)
37
- rspec-core (~> 2.11.0)
38
- rspec-expectations (~> 2.11.0)
39
- rspec-mocks (~> 2.11.0)
40
- rspec-core (2.11.1)
41
- rspec-expectations (2.11.3)
42
- diff-lcs (~> 1.1.3)
43
- rspec-mocks (2.11.3)
44
- sqlite3 (1.3.6)
45
- tzinfo (0.3.33)
33
+ json (1.7.7)
34
+ multi_json (1.7.2)
35
+ rack (1.5.2)
36
+ rake (10.0.4)
37
+ redis (3.0.3)
38
+ rspec (2.13.0)
39
+ rspec-core (~> 2.13.0)
40
+ rspec-expectations (~> 2.13.0)
41
+ rspec-mocks (~> 2.13.0)
42
+ rspec-core (2.13.1)
43
+ rspec-expectations (2.13.0)
44
+ diff-lcs (>= 1.1.3, < 2.0)
45
+ rspec-mocks (2.13.1)
46
+ sqlite3 (1.3.7)
47
+ tzinfo (0.3.37)
46
48
 
47
49
  PLATFORMS
48
50
  ruby
@@ -52,6 +54,8 @@ DEPENDENCIES
52
54
  appraisal
53
55
  bump
54
56
  fakeredis
57
+ json
58
+ rack (>= 1.5.2)
55
59
  rake
56
60
  request_recorder!
57
61
  rspec (~> 2)
@@ -4,12 +4,16 @@ require "rack/response"
4
4
  require "request_recorder/repeater"
5
5
  require "request_recorder/frontend"
6
6
  require "active_record"
7
+ require "rack"
8
+ require "rack/body_proxy" if defined?(Rack.release) && Rack.release >= "1.5"
9
+ require "base64"
10
+ require "multi_json"
7
11
 
8
12
  module RequestRecorder
9
13
  class Middleware
10
14
  MARKER = "request_recorder"
11
15
  MAX_STEPS = 100
12
- SEPARATOR = "|"
16
+ SEPARATOR = "-"
13
17
  NEED_AUTOFLUSH = (ActiveRecord::VERSION::MAJOR == 2)
14
18
  AUTH = :frontend_auth
15
19
 
@@ -41,9 +45,10 @@ module RequestRecorder
41
45
  id = persist_log(id, log)
42
46
 
43
47
  if result.is_a?(Exception)
44
- raise result
48
+ raise result # Do not mess up the apps normal exception behavior
45
49
  else
46
- response_with_data_in_cookie(result, steps_left, id)
50
+ extra_headers = chrome_logger_headers(log) if @auth && @auth.call(env)
51
+ response_with_data_in_cookie(result, steps_left, id, extra_headers)
47
52
  end
48
53
  end
49
54
  end
@@ -77,9 +82,9 @@ module RequestRecorder
77
82
  [steps.to_i, id]
78
83
  end
79
84
 
80
- def response_with_data_in_cookie(result, to_go, id)
85
+ def response_with_data_in_cookie(result, to_go, id, extra_headers)
81
86
  status, headers, body = result
82
- response = Rack::Response.new(body, status, headers)
87
+ response = Rack::Response.new(body, status, headers.merge(extra_headers || {}))
83
88
  if to_go <= 1
84
89
  response.delete_cookie(MARKER)
85
90
  else
@@ -89,6 +94,24 @@ module RequestRecorder
89
94
  response.finish # finish writes out the response in the expected format.
90
95
  end
91
96
 
97
+ def chrome_logger_headers(log)
98
+ data = {
99
+ 'version' => "0.1.1",
100
+ 'columns' => [ 'log' , 'backtrace' , 'type' ],
101
+ 'rows' =>
102
+ [
103
+ [["Rails log"],"xxx.rb:1","group"],
104
+ *log.split("\n").map{|line| [remove_console_colors(line).split(" "), "xxx.rb:1", ""] },
105
+ [[], "xxx.rb:1", "groupEnd"],
106
+ ]
107
+ }
108
+ {"X-ChromeLogger-Data" => Base64.encode64(MultiJson.dump(data).encode("UTF-8")).gsub("\n", "")}
109
+ end
110
+
111
+ def remove_console_colors(string)
112
+ string.gsub(/\e\[[\d;]+m/, "")
113
+ end
114
+
92
115
  def capture_logging
93
116
  old = [
94
117
  ActiveRecord::Base.logger.instance_variable_get("@log"),
@@ -1,3 +1,3 @@
1
1
  module RequestRecorder
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -10,5 +10,6 @@ Gem::Specification.new name, RequestRecorder::VERSION do |s|
10
10
  s.files = `git ls-files`.split("\n")
11
11
  s.license = "MIT"
12
12
  s.add_runtime_dependency "rack"
13
+ s.add_runtime_dependency "multi_json"
13
14
  s.add_runtime_dependency "activerecord"
14
15
  end
@@ -63,7 +63,7 @@ describe RequestRecorder do
63
63
  end
64
64
 
65
65
  it "starts with a given key" do
66
- middleware.call({"QUERY_STRING" => "request_recorder=10|abcdefg"})
66
+ middleware.call({"QUERY_STRING" => "request_recorder=10-abcdefg"})
67
67
  redis.hget(redis_key, "abcdefg").should include "SELECT"
68
68
  end
69
69
 
@@ -77,12 +77,12 @@ describe RequestRecorder do
77
77
  it "sets cookie in first step" do
78
78
  status, headers, body = middleware.call(activate_logger)
79
79
  generated_id = stored.keys.last
80
- headers["Set-Cookie"].should include "request_recorder=9%7C#{generated_id.gsub(":", "%3A").gsub(" ", "+")}; expires="
80
+ headers["Set-Cookie"].should include "request_recorder=9-#{generated_id.gsub(":", "%3A").gsub(" ", "+")}; expires="
81
81
  headers["Set-Cookie"].should include "; HttpOnly"
82
82
  end
83
83
 
84
84
  it "appends to existing log" do
85
- middleware.call("HTTP_COOKIE" => "request_recorder=8|#{existing_request_id}")
85
+ middleware.call("HTTP_COOKIE" => "request_recorder=8-#{existing_request_id}")
86
86
  existing_request = redis.hget(redis_key, existing_request_id)
87
87
  existing_request.should include "SELECT"
88
88
  existing_request.should include "BEFORE"
@@ -91,20 +91,20 @@ describe RequestRecorder do
91
91
  it "creates a new log if redis dies" do
92
92
  existing_request_id # store key
93
93
  redis.flushall
94
- middleware.call("HTTP_COOKIE" => "request_recorder=8|#{existing_request_id}")
94
+ middleware.call("HTTP_COOKIE" => "request_recorder=8-#{existing_request_id}")
95
95
  existing_request = redis.hget(redis_key, existing_request_id)
96
96
  existing_request.should include "SELECT"
97
97
  existing_request.should_not include "BEFORE"
98
98
  end
99
99
 
100
100
  it "decrements cookie on each step" do
101
- status, headers, body = middleware.call("HTTP_COOKIE" => "request_recorder=2|#{existing_request_id};foo=bar")
102
- headers["Set-Cookie"].should include "request_recorder=1%7C#{existing_request_id}; expires="
101
+ status, headers, body = middleware.call("HTTP_COOKIE" => "request_recorder=2-#{existing_request_id};foo=bar")
102
+ headers["Set-Cookie"].sub(" max-age=0;", "").should include "request_recorder=1-#{existing_request_id}; expires="
103
103
  end
104
104
 
105
105
  it "removes cookie if final step is reached" do
106
- status, headers, body = middleware.call("HTTP_COOKIE" => "request_recorder=1|#{existing_request_id};foo=bar")
107
- headers["Set-Cookie"].should include "request_recorder=; expires="
106
+ status, headers, body = middleware.call("HTTP_COOKIE" => "request_recorder=1-#{existing_request_id};foo=bar")
107
+ headers["Set-Cookie"].sub(" max-age=0;", "").should include "request_recorder=; expires="
108
108
  end
109
109
  end
110
110
 
@@ -168,13 +168,36 @@ describe RequestRecorder do
168
168
  status.should == 500
169
169
  body.should include(":frontend_auth")
170
170
  end
171
+
172
+ context "chrome logger" do
173
+ it "logs into chrome logger" do
174
+ status, headers, body = middleware.call("QUERY_STRING" => "request_recorder=10-xxx", "success" => true)
175
+ headers["X-ChromeLogger-Data"].should_not == nil
176
+ data = MultiJson.load(Base64.decode64(headers["X-ChromeLogger-Data"]))
177
+ data["rows"][1][0][2..-1] = "---" # remove timing information + activerecord 2/3 diff
178
+ data.should == {
179
+ "version"=>"0.1.1",
180
+ "columns"=>["log", "backtrace", "type"],
181
+ "rows"=>[
182
+ [["Rails log"], "xxx.rb:1", "group"],
183
+ [["Car", "Load", "---"], "xxx.rb:1", ""],
184
+ [[], "xxx.rb:1", "groupEnd"]
185
+ ]
186
+ }
187
+ end
188
+
189
+ it "does not log without frontend_auth" do
190
+ status, headers, body = middleware.call("QUERY_STRING" => "request_recorder=10-xxx")
191
+ headers["X-ChromeLogger-Data"].should == nil
192
+ end
193
+ end
171
194
  end
172
195
 
173
196
  it "integrates" do
174
197
  stored.size.should == 0
175
198
 
176
199
  # request 1 - start + decrement + log
177
- status, headers, body = middleware.call({"QUERY_STRING" => "request_recorder=3"})
200
+ status, headers, body = middleware.call({"QUERY_STRING" => "request_recorder=3-foo"})
178
201
  stored.size.should == 1
179
202
  stored.values.last.scan("SELECT").size.should == 1
180
203
  cookie = headers["Set-Cookie"].split(";").first
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: request_recorder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-15 00:00:00.000000000 Z
12
+ date: 2013-04-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: multi_json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: activerecord
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -87,7 +103,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
87
103
  version: '0'
88
104
  segments:
89
105
  - 0
90
- hash: 2574127840943451255
106
+ hash: -617741979871775185
91
107
  required_rubygems_version: !ruby/object:Gem::Requirement
92
108
  none: false
93
109
  requirements:
@@ -96,10 +112,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
112
  version: '0'
97
113
  segments:
98
114
  - 0
99
- hash: 2574127840943451255
115
+ hash: -617741979871775185
100
116
  requirements: []
101
117
  rubyforge_project:
102
- rubygems_version: 1.8.24
118
+ rubygems_version: 1.8.25
103
119
  signing_key:
104
120
  specification_version: 3
105
121
  summary: Record your rack/rails requests and store them for future inspection