1
0
Fork 0
mirror of https://github.com/rest-client/rest-client.git synced 2022-11-09 13:49:40 -05:00

Add optional Resource-specific logging

This commit is contained in:
Kyle Meyer 2016-10-24 09:02:23 -07:00
parent 5269c842b8
commit 72bd7b1e04
7 changed files with 70 additions and 25 deletions

View file

@ -498,7 +498,7 @@ $ restclient put http://example.com/resource < input_body
## Logging ## Logging
To enable logging you can: To enable logging globally you can:
- set RestClient.log with a Ruby Logger, or - set RestClient.log with a Ruby Logger, or
- set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"): - set an environment variable to avoid modifying the code (in this case you can use a file name, "stdout" or "stderr"):
@ -506,7 +506,14 @@ To enable logging you can:
```ruby ```ruby
$ RESTCLIENT_LOG=stdout path/to/my/program $ RESTCLIENT_LOG=stdout path/to/my/program
``` ```
Either produces logs like this:
You can also set individual loggers when instantiating a Resource:
```ruby
resource = RestClient::Resource.new 'http://example.com/resource', log: Logger.new(STDOUT)
```
All options produce logs like this:
```ruby ```ruby
RestClient.get "http://some/resource" RestClient.get "http://some/resource"

View file

@ -131,6 +131,7 @@ module RestClient
end end
end end
@log = args[:log]
@tf = nil # If you are a raw request, this is your tempfile @tf = nil # If you are a raw request, this is your tempfile
@max_redirects = args[:max_redirects] || 10 @max_redirects = args[:max_redirects] || 10
@processed_headers = make_headers headers @processed_headers = make_headers headers
@ -525,19 +526,24 @@ module RestClient
redacted_uri.to_s redacted_uri.to_s
end end
# Default to the global logger if there's not a request-specific one
def log
@log || RestClient.log
end
def log_request def log_request
return unless RestClient.log return unless log
out = [] out = []
out << "RestClient.#{method} #{redacted_url.inspect}" out << "RestClient.#{method} #{redacted_url.inspect}"
out << payload.short_inspect if payload out << payload.short_inspect if payload
out << processed_headers.to_a.sort.map { |(k, v)| [k.inspect, v.inspect].join("=>") }.join(", ") out << processed_headers.to_a.sort.map { |(k, v)| [k.inspect, v.inspect].join("=>") }.join(", ")
RestClient.log << out.join(', ') + "\n" log << out.join(', ') + "\n"
end end
def log_response res def log_response res
return unless RestClient.log return unless log
size = if @raw_response size = if @raw_response
File.size(@tf.path) File.size(@tf.path)
@ -545,7 +551,7 @@ module RestClient
res.body.nil? ? 0 : res.body.size res.body.nil? ? 0 : res.body.size
end end
RestClient.log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes\n" log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes\n"
end end
# Return a hash of headers whose keys are capitalized strings # Return a hash of headers whose keys are capitalized strings
@ -776,13 +782,13 @@ module RestClient
http_response.read_body do |chunk| http_response.read_body do |chunk|
@tf.write chunk @tf.write chunk
size += chunk.size size += chunk.size
if RestClient.log if log
if size == 0 if size == 0
RestClient.log << "%s %s done (0 length file)\n" % [@method, @url] log << "%s %s done (0 length file)\n" % [@method, @url]
elsif total == 0 elsif total == 0
RestClient.log << "%s %s (zero content length)\n" % [@method, @url] log << "%s %s (zero content length)\n" % [@method, @url]
else else
RestClient.log << "%s %s %d%% done (%d of %d)\n" % [@method, @url, (size * 100) / total, size, total] log << "%s %s %d%% done (%d of %d)\n" % [@method, @url, (size * 100) / total, size, total]
end end
end end
end end

View file

@ -51,7 +51,8 @@ module RestClient
Request.execute(options.merge( Request.execute(options.merge(
:method => :get, :method => :get,
:url => url, :url => url,
:headers => headers), &(block || @block)) :headers => headers,
:log => log), &(block || @block))
end end
def head(additional_headers={}, &block) def head(additional_headers={}, &block)
@ -59,7 +60,8 @@ module RestClient
Request.execute(options.merge( Request.execute(options.merge(
:method => :head, :method => :head,
:url => url, :url => url,
:headers => headers), &(block || @block)) :headers => headers,
:log => log), &(block || @block))
end end
def post(payload, additional_headers={}, &block) def post(payload, additional_headers={}, &block)
@ -68,7 +70,8 @@ module RestClient
:method => :post, :method => :post,
:url => url, :url => url,
:payload => payload, :payload => payload,
:headers => headers), &(block || @block)) :headers => headers,
:log => log), &(block || @block))
end end
def put(payload, additional_headers={}, &block) def put(payload, additional_headers={}, &block)
@ -77,7 +80,8 @@ module RestClient
:method => :put, :method => :put,
:url => url, :url => url,
:payload => payload, :payload => payload,
:headers => headers), &(block || @block)) :headers => headers,
:log => log), &(block || @block))
end end
def patch(payload, additional_headers={}, &block) def patch(payload, additional_headers={}, &block)
@ -86,7 +90,8 @@ module RestClient
:method => :patch, :method => :patch,
:url => url, :url => url,
:payload => payload, :payload => payload,
:headers => headers), &(block || @block)) :headers => headers,
:log => log), &(block || @block))
end end
def delete(additional_headers={}, &block) def delete(additional_headers={}, &block)
@ -94,7 +99,8 @@ module RestClient
Request.execute(options.merge( Request.execute(options.merge(
:method => :delete, :method => :delete,
:url => url, :url => url,
:headers => headers), &(block || @block)) :headers => headers,
:log => log), &(block || @block))
end end
def to_s def to_s
@ -121,6 +127,10 @@ module RestClient
options[:open_timeout] options[:open_timeout]
end end
def log
options[:log] || RestClient.log
end
# Construct a subresource, preserving authentication. # Construct a subresource, preserving authentication.
# #
# Example: # Example:

View file

@ -38,6 +38,10 @@ module RestClient
"<RestClient::Response #{code.inspect} #{body_truncated(10).inspect}>" "<RestClient::Response #{code.inspect} #{body_truncated(10).inspect}>"
end end
def log
request.log
end
def self.create(body, net_http_res, request) def self.create(body, net_http_res, request)
result = self.new(body || '') result = self.new(body || '')
@ -54,8 +58,8 @@ module RestClient
begin begin
encoding = Encoding.find(charset) if charset encoding = Encoding.find(charset) if charset
rescue ArgumentError rescue ArgumentError
if RestClient.log if response.log
RestClient.log << "No such encoding: #{charset.inspect}" response.log << "No such encoding: #{charset.inspect}"
end end
end end

View file

@ -687,6 +687,12 @@ describe RestClient::Request, :include_helpers do
RestClient::Request.new(:method => :get, :url => 'http://user:password@url', :headers => {:user_agent => 'rest-client'}).log_request RestClient::Request.new(:method => :get, :url => 'http://user:password@url', :headers => {:user_agent => 'rest-client'}).log_request
expect(log[0]).to eq %Q{RestClient.get "http://user:REDACTED@url", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "User-Agent"=>"rest-client"\n} expect(log[0]).to eq %Q{RestClient.get "http://user:REDACTED@url", "Accept"=>"*/*", "Accept-Encoding"=>"gzip, deflate", "User-Agent"=>"rest-client"\n}
end end
it 'logs to a passed logger, if provided' do
logger = double('logger', '<<' => true)
expect(logger).to receive(:<<)
RestClient::Request.new(:method => :get, :url => 'http://user:password@url', log: logger).log_request
end
end end
it "strips the charset from the response content type" do it "strips the charset from the response content type" do

View file

@ -7,37 +7,37 @@ describe RestClient::Resource do
context "Resource delegation" do context "Resource delegation" do
it "GET" do it "GET" do
expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.get @resource.get
end end
it "HEAD" do it "HEAD" do
expect(RestClient::Request).to receive(:execute).with(:method => :head, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :head, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.head @resource.head
end end
it "POST" do it "POST" do
expect(RestClient::Request).to receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.post 'abc', :content_type => 'image/jpg' @resource.post 'abc', :content_type => 'image/jpg'
end end
it "PUT" do it "PUT" do
expect(RestClient::Request).to receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.put 'abc', :content_type => 'image/jpg' @resource.put 'abc', :content_type => 'image/jpg'
end end
it "PATCH" do it "PATCH" do
expect(RestClient::Request).to receive(:execute).with(:method => :patch, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :patch, :url => 'http://some/resource', :payload => 'abc', :headers => {:content_type => 'image/jpg', 'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.patch 'abc', :content_type => 'image/jpg' @resource.patch 'abc', :content_type => 'image/jpg'
end end
it "DELETE" do it "DELETE" do
expect(RestClient::Request).to receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {'X-Something' => '1'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.delete @resource.delete
end end
it "overrides resource headers" do it "overrides resource headers" do
expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '2'}, :user => 'jane', :password => 'mypass') expect(RestClient::Request).to receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {'X-Something' => '2'}, :user => 'jane', :password => 'mypass', :log => nil)
@resource.get 'X-Something' => '2' @resource.get 'X-Something' => '2'
end end
end end

View file

@ -238,4 +238,16 @@ describe RestClient::Response, :include_helpers do
end end
end end
describe "logging" do
it "uses the request's logger" do
stub_request(:get, 'http://some/resource').to_return(body: 'potato', status: 200)
logger = double('logger', '<<' => true)
request = RestClient::Request.new(url: 'http://some/resource', method: :get, log: logger)
expect(logger).to receive(:<<)
request.execute
end
end
end end