httplog 0.1.1 → 0.2.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.
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: