-
Notifications
You must be signed in to change notification settings - Fork 328
Support to log. #348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support to log. #348
Conversation
lib/http/options.rb
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just nil?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A agree. It should be either nil (I like this idea better), or at least some kind of cached null-logger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tarcieri @ixti
HTTP::Logger implicitly works like a null object. We can call HTTP::Logger#log even if its logger attribute is nil.
https://github.com/httprb/http/pull/348/files/9e0569ead67133f171b33582e515bade4185b970#diff-a32552e6c7aef4937f6b3148e3515abdR11
As an alternative we can use nil as default HTTP logger and to deal with this nil when HTTP::Logger#log is called in HTTP::Client class. 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah but you will be allocating new instance everytime Options got initialized, which is not pretty awesome ;))
|
IMHO logic of request/response formatting is better to be extracted on Request/Response object: class Request
# @param [#<<] io
def pretty_print(io: STDOUT, skip_headers: true, skip_body: true)
message = "#{verb} #{uri}"
headers.each { |k, v| message << "\n#{k}: #{v}" } unless skip_headers
message << "\n\n#{body}" unless skip_headers || skip_body
io << message
end
endThat way it will make this method possible to be used by class Request
def inspect
pretty_print(:io => "", :skip_headers => false, :skip_body => true)
end
endAlso, please, beware that printing out body in response might not be a good idea by couple of reasons:
So, I propose to allow pass |
|
@ixti About to extract the formatting logic to |
|
@prodis Sure. |
|
@ixti Great! I do all that things soon. |
852377a to
ff165dd
Compare
|
Done. |
|
The build of Ruby 2.2.0 was breaking after run all tests green and Rubocop checks were OK. https://travis-ci.org/httprb/http/builds/133830598 I changed the RVM version from |
lib/http/headers.rb
Outdated
| to_h.map do |name, value| | ||
| value = value.join("; ") if value.respond_to?(:join) | ||
| "#{name}: #{value}" | ||
| end.join(separator) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO its' better to pretty print in the form we will send those headers to server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ixti
Sorry, I didn't get it.
Do you mean use "\n" separator or do you are talking about do not join multiples values of header with "; "?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, something like:
def pretty_print(separator: "\n")
map { |k, v| "#{k}: #{v}" }.join(separator)
endThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, I was tlking about both :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, OK.
I used ", " separator to inspect method to return in a single line. Is it OK inspect methods return multiple lines?
Just confirming.
Same approach with inspect method in HTTP::Request and HTTP::Response classes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it.
I am going to do this and the name issues in the other commentaries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, @ixti.
One point about HTTP::Headers#pretty_print:
I used to_h.map {... instead of self.map {... to avoid duplicated headers with different values.
For example, for these headers:
headers.set :set_cookie, %w(hoo=ray woo=hoo)
headers.set :content_type, "application/json"I believe we expected a printable version like this:
"Set-Cookie: hoo=ray; woo=hoo\nContent-Type: application/json"
And not like this:
"Set-Cookie: hoo=ray\nSet-Cookie: woo=hoo\nContent-Type: application/json"
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not strongly against that. Although I thought it's better to print them just as they would be sent to server (we don't join them), but for pretty printing I think it worth to do so. Also, I think in this case it might worth to allow specify truncation length so that long lines would become truncated (have no opinion on this at all though). Anyway, if you think it worth join headers let' do that, but a bit more efficient way will be:
headers.group_by { |x| x[0] }.each do |key, values|
io << "\n#{key}: #{values.join '; '}"
endThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great tip, @ixti!
I have never used group_by method.
It made my day!
lib/http/printer.rb
Outdated
| # "MyHttpRequest headline" | ||
| # end | ||
| # end | ||
| module Printer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proabbly PrettyPrinter will be a bit better name? :D
lib/http/response.rb
Outdated
| private | ||
|
|
||
| def headline | ||
| "HTTP/#{@version} #{code} #{reason}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be simply: "HTTP/#{@version} #{@status}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
Thanks for all you hard work. I will try to walk through the PR and merge as soon as possible during this week. |
|
After some consideration I think we should do this a bit different. And in one-line format I would expect it to be something like: It means that
Both of those should respond to formatter = -> (obj) { "#{obj.class} | #{obj.headline}" }
logger = HTTP::Logger.new(STDOUT, :formatter => formatter)By default And the last thing I would like to note, I think HTTP.log { |obj| puts obj }.get("http://example.com")The above means that we will call |
|
@ixti Of course, if you want this feature early, feel free to delegate this task for another one. Really I would like to implement it. Just one question: in the last line of your last comment, it seems you didn't finish the phrase "I will try to...". Am I correct? |
|
@prodis heh, same here - lots of thing to handle in my life too. yeah, i haven't finished that phrase, but i forgot what i was going to say already :D |
|
Oh. I was going to say that I will try to come up with better described API description later :D |
|
Can I help with logging? |
|
I dont want to be that guy but, any updates on this end? |
|
@vassilevsky & @vjustov I think it would be acceptable to take this work, finish implementing @ixti's recommendations, and open another PR. (Retaining @prodis as the author of those commits somehow.) |
|
Sorry for long time to have this PR stopped in my side. 🙇 But @mikegee, @vassilevsky and @vjustov feel free to finish in some way before, just let me know. 😉 |
|
Just wanted to note there’s similar functionality in the Reel web server, and I always liked color coding the log output: |
|
No worries, I added gem 'httplog' and now I have logs. They're pretty good,
although a bit verbose.
|
|
I think this was addressed by #499 |
For some applications is valuable to have the option to log HTTP requests and responses. I have just added support to this.
Example using
Rails.logger:It will be logged request method, URL, headers and body, response status code, headers and body:
If necessary, I can improve it with an optional range of options to log or not headers and body, for example.
What do you think?