httplog 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -4,6 +4,18 @@ Log outgoing HTTP requests made from your application.
4
4
  See the {blog post}[http://trusche.github.com/blog/2011/09/29/logging-outgoing-http-requests/]
5
5
  for more details.
6
6
 
7
+ So far this gem works with the following HTTP libraries:
8
+
9
+ * Net::HTTP
10
+ * OpenURI
11
+ * HTTPClient
12
+
13
+ In theory, it should also work with any library built on top of these. But since
14
+ the difference between theory and practice is bigger in practice than in theory, YMMV.
15
+
16
+ *PLEASE NOTE* that this is very much a development tool; it is *not recommended* to
17
+ use this in a production environment.
18
+
7
19
  === Installation
8
20
 
9
21
  gem install httplog
@@ -27,7 +39,7 @@ You can override the following default options:
27
39
  HttpLog.options[:log_status] = true
28
40
  HttpLog.options[:log_response] = true
29
41
  HttpLog.options[:log_benchmark] = true
30
- HttpLog.options[:compact_log] = false = setting this to true will make all "log_*" options redundant
42
+ HttpLog.options[:compact_log] = false # setting this to true will make all "log_*" options redundant
31
43
 
32
44
  So if you want to use this in a Rails app:
33
45
 
@@ -55,8 +67,8 @@ With the default configuration, the log output might look like this:
55
67
 
56
68
  === Known Issues
57
69
 
58
- When using open-uri, the reading of the HTTP response body is deferred,
59
- so it is not available for logging. This will be noted in the logging statement:
70
+ * When using open-uri, the reading of the HTTP response body is deferred,
71
+ so it is not available for logging. This will be noted in the logging statement:
60
72
 
61
73
  D, [2012-11-21T15:09:03.547005 #6857] DEBUG -- : [httplog] Connecting: localhost
62
74
  D, [2012-11-21T15:09:03.547938 #6857] DEBUG -- : [httplog] Sending: GET http://localhost:9292/index.html
@@ -64,11 +76,12 @@ so it is not available for logging. This will be noted in the logging statement:
64
76
  D, [2012-11-21T15:09:03.548662 #6857] DEBUG -- : [httplog] Benchmark: 0.000617 seconds
65
77
  D, [2012-11-21T15:09:03.548695 #6857] DEBUG -- : [httplog] Response: (not available yet)
66
78
 
79
+ * When using HTTPClient, the +:log_connect+ option has no effect.
67
80
 
68
81
  === Running the specs
69
82
 
70
- Make sure you have the necessary dependencies installed by running `bundle install`.
71
- Then simple run `bundle exec rspec spec`.
83
+ Make sure you have the necessary dependencies installed by running +bundle install+.
84
+ Then simply run +bundle exec rspec spec+.
72
85
  This will launch a simple rack server on port 9292 and run all tests locally against that server.
73
86
 
74
87
  === Contributing
@@ -77,4 +90,12 @@ If you have any issues with httplog,
77
90
  or feature requests,
78
91
  please {add an issue}[https://github.com/trusche/httplog/issues] on GitHub
79
92
  or fork the project and send a pull request.
80
- Please include passing specs with all pull requests.
93
+ Please include passing specs with all pull requests.
94
+
95
+ === Contributors
96
+
97
+ Thanks to these fine folks for contributing pull requests:
98
+
99
+ * {Eric Cohen}[https://github.com/eirc]
100
+ * {Nikos Dimitrakopoulos}[https://github.com/nikosd]
101
+ * {Marcos Hack}[https://github.com/marcoshack]
@@ -1,80 +1,109 @@
1
1
  require "net/http"
2
2
  require "logger"
3
+ require "benchmark"
3
4
 
4
5
  module HttpLog
6
+ DEFAULT_LOGGER = Logger.new($stdout)
7
+ DEFAULT_OPTIONS = {
8
+ :logger => DEFAULT_LOGGER,
9
+ :severity => Logger::Severity::DEBUG,
10
+ :log_connect => true,
11
+ :log_request => true,
12
+ :log_headers => false,
13
+ :log_data => true,
14
+ :log_status => true,
15
+ :log_response => true,
16
+ :log_benchmark => true,
17
+ :compact_log => false
18
+ }
19
+
20
+ class << self
21
+ def options
22
+ @@options ||= DEFAULT_OPTIONS.clone
23
+ end
5
24
 
6
- def self.options
7
- @@options ||= {
8
- :logger => Logger.new($stdout),
9
- :severity => Logger::Severity::DEBUG,
10
- :log_connect => true,
11
- :log_request => true,
12
- :log_headers => false,
13
- :log_data => true,
14
- :log_status => true,
15
- :log_response => true,
16
- :log_benchmark => true,
17
- :log_compact => false
18
- }
19
- end
25
+ def reset_options!
26
+ @@options = DEFAULT_OPTIONS.clone
27
+ end
20
28
 
21
- def self.log(msg)
22
- @@options[:logger].add(@@options[:severity]) { "[httplog] #{msg}" }
23
- end
29
+ def log(msg)
30
+ @@options[:logger].add(@@options[:severity]) { "[httplog] #{msg}" }
31
+ end
32
+
33
+ def log_request(method, uri)
34
+ return if options[:compact_log] || !options[:log_request]
35
+ log("Sending: #{method.to_s.upcase} #{uri}")
36
+ end
37
+
38
+ def log_headers(headers = {})
39
+ return if options[:compact_log] || !options[:log_headers]
40
+ headers.each do |key,value|
41
+ log("Header: #{key}: #{value}")
42
+ end
43
+ end
44
+
45
+ def log_status(status)
46
+ return if options[:compact_log] || !options[:log_status]
47
+ log("Status: #{status}")
48
+ end
49
+
50
+ def log_benchmark(seconds)
51
+ return if options[:compact_log] || !options[:log_benchmark]
52
+ log("Benchmark: #{seconds} seconds")
53
+ end
54
+
55
+ def log_body(body)
56
+ return if options[:compact_log] || !options[:log_response]
57
+ if body.is_a?(Net::ReadAdapter)
58
+ # open-uri wraps the response in a Net::ReadAdapter that defers reading
59
+ # the content, so the reponse body is not available here.
60
+ log("Response: (not available yet)")
61
+ else
62
+ log("Response:\n#{body.to_s}")
63
+ end
64
+ end
24
65
 
66
+ def log_data(data)
67
+ return if options[:compact_log] || !options[:log_data]
68
+ log("Data: #{data}")
69
+ end
70
+
71
+ def log_compact(method, uri, status, seconds)
72
+ return unless options[:compact_log]
73
+ log("#{method} #{uri} completed with status code #{status} in #{seconds} seconds")
74
+ end
75
+ end
25
76
  end
26
77
 
27
78
  module Net
28
-
29
79
  class HTTP
30
80
  alias_method(:orig_request, :request) unless method_defined?(:orig_request)
31
81
  alias_method(:orig_connect, :connect) unless method_defined?(:orig_connect)
32
82
 
33
83
  def request(req, body = nil, &block)
34
84
 
85
+ url = "http://#{@address}:#{@port}#{req.path}"
86
+
35
87
  if started? && !HttpLog.options[:compact_log]
36
- if HttpLog.options[:log_request]
37
- HttpLog::log("Sending: #{req.method} http://#{@address}:#{@port}#{req.path}")
38
- end
39
-
40
- if HttpLog.options[:log_headers]
41
- req.each_header do |key,value|
42
- HttpLog::log("Header: #{key}: #{value}")
43
- end
44
- end
45
-
46
- if req.method == "POST" && HttpLog.options[:log_data]
47
- # A bit convoluted becase post_form uses form_data= to assign the data, so
48
- # in that case req.body will be empty.
49
- data = req.body.nil? || req.body.size == 0 ? body : req.body
50
- HttpLog::log("Data: #{data}")
51
- end
88
+ HttpLog.log_request(req.method, url)
89
+ HttpLog.log_headers(req.each_header.collect)
90
+ # A bit convoluted becase post_form uses form_data= to assign the data, so
91
+ # in that case req.body will be empty.
92
+ HttpLog::log_data(req.body.nil? || req.body.size == 0 ? body : req.body) if req.method == 'POST'
52
93
  end
53
94
 
54
- ts_start = Time.now
55
- response = orig_request(req, body, &block)
56
- benchmark = Time.now - ts_start
95
+ bm = Benchmark.realtime do
96
+ @response = orig_request(req, body, &block)
97
+ end
57
98
 
58
99
  if started?
59
- if HttpLog.options[:compact_log]
60
- HttpLog::log("#{req.method} http://#{@address}:#{@port}#{req.path} completed with status code #{response.code} in #{benchmark} seconds")
61
- else
62
- HttpLog::log("Status: #{response.code}") if HttpLog.options[:log_status]
63
- HttpLog::log("Benchmark: #{benchmark} seconds") if HttpLog.options[:log_benchmark]
64
-
65
- if HttpLog.options[:log_response]
66
- if response.body.is_a?(Net::ReadAdapter)
67
- # open-uri wraps the response in a Net::ReadAdapter that defers reading
68
- # the contrent, so the reponse body is not available here.
69
- HttpLog::log("Response: (not available yet)")
70
- else
71
- HttpLog::log("Response:\n#{response.body.to_s}")
72
- end
73
- end
74
- end
100
+ HttpLog.log_compact(req.method, url, @response.code, bm)
101
+ HttpLog.log_status(@response.code)
102
+ HttpLog.log_benchmark(bm)
103
+ HttpLog.log_body(@response.body)
75
104
  end
76
105
 
77
- response
106
+ @response
78
107
  end
79
108
 
80
109
  def connect
@@ -86,3 +115,27 @@ module Net
86
115
  end
87
116
 
88
117
  end
118
+
119
+ if defined?(::HTTPClient)
120
+ class HTTPClient
121
+ private
122
+ alias_method :orig_do_request, :do_request
123
+
124
+ def do_request(method, uri, query, body, header, &block)
125
+ HttpLog.log_request(method, uri)
126
+ HttpLog.log_headers(header)
127
+ HttpLog.log_data(body) if method == :post
128
+
129
+ bm = Benchmark.realtime do
130
+ @response = orig_do_request(method, uri, query, body, header, &block)
131
+ end
132
+
133
+ HttpLog.log_compact(method, uri, @response.status, bm)
134
+ HttpLog.log_status(@response.status)
135
+ HttpLog.log_benchmark(bm)
136
+ HttpLog.log_body(@response.body)
137
+
138
+ @response
139
+ end
140
+ end
141
+ end
@@ -1,3 +1,4 @@
1
1
  module HttpLog
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
4
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httplog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: