-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add HTTP::Client logging and basic instrumentation #9756
Add HTTP::Client logging and basic instrumentation #9756
Conversation
I think it's simpler to do something like |
Also, using |
Would it be better to have only around? or around + before + after? |
Something like this: (I'm surprised it works with just class Foo
def foo
around_foo do
1
end
end
protected def around_foo
yield
end
macro def_around_foo
protected def around_foo
previous_def do
{{yield}}
end
end
end
end
class Foo
def_around_foo do
time = Time.local
value = yield
puts Time.local - time
value
end
end
Foo.new.foo Also with a macro it's simpler, the internal protected name doesn't matter anymore, and the way hooks are defined could be changed later on if needed. And the macro can be documented. |
I think it's simpler to have just In this way, you could create an http client, enable logging, or introduce a proxy, whatever, without affecting other clients. So instead of just adding logging I would try to focus on the general solution (if there's time, and someone wants to do it). |
The around macro has as a drawback that the block argument is an ast node and hence it must be The example to measure the elapsed time can be done in either way after the last commit class HTTP::Client
def_around_exec do |request|
start = Time.monotonic
begin
yield
ensure
elapsed = Time.monotonic - start.not_nil!
Log.debug &.emit("Finished request",
method: {{request}}.method,
host: host,
port: port,
resource: {{request}}.resource,
elapsed: "#{elapsed.total_seconds.humanize(precision: 2, significant: false)}s"
)
end
end
end or class HTTP::Client
def_around_exec do |request|
start = Time.monotonic
res = yield
elapsed = Time.monotonic - start
Log.debug &.emit("Finished request",
method: {{request}}.method,
host: host,
port: port,
resource: {{request}}.resource,
elapsed: "#{elapsed.total_seconds.humanize(precision: 2, significant: false)}s"
)
res
end
end The other alternative is to move the around method to |
Yeah, I agree it's ugly. Another alternative is to continue using Also, how do I try this out? I can't setup logging... |
e9f88f3
to
50d51a7
Compare
@asterite by default only info severity is advertised. You can do Log.setup_from_env
HTTP::Client.get("https://google.com")
HTTP::Client.get("http://example.org") do |resp|
end
|
It's possible to do it like this: macro def_around_exec(&block)
protected def around_exec(%request)
previous_def do
{% if block.args.size != 1 %}
{% raise "wrong number of block arguments (given #{block.args.size}, expected: 1)" %}
{% end %}
{{ block.args.first.id }} = %request
{{block.body}}
end
end
end Then you can use whatever name you want in the block. |
I have this, I'm not seeing any logs in stdout: require "http/client"
class HTTP::Client
def_around_exec do |request|
start = Time.monotonic
value = yield request
elapsed = Time.monotonic - start.not_nil!
Log.error &.emit("Finished request",
method: request.method,
host: host,
port: port,
resource: request.resource,
elapsed: "#{elapsed.total_seconds.humanize(precision: 2, significant: false)}s"
)
value
end
end
Log.setup_from_env
HTTP::Client.get("https://www.example.com").to_io(STDOUT) |
@asterite it's example.org not example.com. I sent that patch. It can work that way I think 👍 |
example.com works for me I changed it to |
This adds protected methods HTTP::Client#before_exec and #after_exec that can be used to hook into the lifecycle of the http client. A first utility for this is adding a http.client log source to know a request is starting. This enables some basic instrumentation to monitor the activity of the application without monkey patching sensitive parts of the http client
3230216
to
892428e
Compare
Rebased on master. Ready for review. |
The final state of this PR is This adds the macro HTTP::Client.def_around_exec that can be used to hook into the lifecycle of the http client. A first utility for this is adding a http.client log source to know a request is starting. This enables some basic instrumentation to monitor the activity of the application without monkey patching sensitive parts of the http client. As an example if one wants to log also when a request is completed and measure the elapsed time the app could define class HTTP::Client
def_around_exec do |request|
start = Time.monotonic
res = yield
elapsed = Time.monotonic - start
Log.debug &.emit("Finished request",
method: request.method,
host: host,
port: port,
resource: request.resource,
elapsed: "#{elapsed.total_seconds.humanize(precision: 2, significant: false)}s"
)
res
end
end |
(Update: see #9756 (comment) for the final state of the PR)
This adds protected methods HTTP::Client#before_exec and #after_exec that can be used to hook into the lifecycle of the http client.
A first utility for this is adding a http.client log source to know a request is starting.
This enables some basic instrumentation to monitor the activity of the application without monkey patching sensitive parts of the http client.
As an example if one wants to log also when a request is completed and measure the elapsed time the app could define