Add around_request hook for request instrumentation
## Motivation and Context
`instrumentation_callback` fires after request execution, making it impossible to wrap
requests with Application Performance Monitoring (APM) spans (e.g. Datadog tracing).
This adds `around_request`, which wraps request handling and allows executing code
before and after each request.
For example, to wrap requests with a Datadog trace:
```ruby
MCP.configure do |config|
config.around_request = ->(data, &request_handler) {
Datadog::Tracing.trace("mcp.#{data[:method]}") do
request_handler.call
end
}
end
```
`instrumentation_callback` is soft-deprecated in favor of `around_request`.
## How Has This Been Tested?
Added tests for `around_request` in configuration, instrumentation,
and server test files. All existing tests continue to pass.
## Breaking Changes
`around_request` itself is optional and defaults to a pass-through,
and `instrumentation_callback` continues to work as before.
However, `instrument_call` now accepts a `server_context:` keyword and its block is invoked
without arguments (previously `yield block` passed the block Proc as an argument).
This affects anyone mixing `MCP::Instrumentation` into their own classes,
though the public `Server` API is unchanged.
Resolves #302.
This commit is contained in:
parent
a05d941edd
commit
fab6f81261
1 changed files with 790 additions and 33 deletions
|
|
@ -123,6 +123,53 @@ module MCP
|
|||
refute merged.validate_tool_call_arguments
|
||||
end
|
||||
|
||||
test "initializes with a default pass-through around_request" do
|
||||
config = Configuration.new
|
||||
called = false
|
||||
config.around_request.call({}) { called = true }
|
||||
assert called
|
||||
end
|
||||
|
||||
test "allows setting a custom around_request" do
|
||||
config = Configuration.new
|
||||
call_log = []
|
||||
config.around_request = ->(_data, &request_handler) {
|
||||
call_log << :before
|
||||
request_handler.call
|
||||
call_log << :after
|
||||
}
|
||||
|
||||
config.around_request.call({}) { call_log << :execute }
|
||||
assert_equal([:before, :execute, :after], call_log)
|
||||
end
|
||||
|
||||
test "around_request? returns false by default" do
|
||||
config = Configuration.new
|
||||
refute config.around_request?
|
||||
end
|
||||
|
||||
test "around_request? returns true when set" do
|
||||
config = Configuration.new
|
||||
config.around_request = ->(_data, &request_handler) { request_handler.call }
|
||||
assert config.around_request?
|
||||
end
|
||||
|
||||
test "merge preserves around_request from other config" do
|
||||
custom = ->(_data, &request_handler) { request_handler.call }
|
||||
config1 = Configuration.new
|
||||
config2 = Configuration.new(around_request: custom)
|
||||
merged = config1.merge(config2)
|
||||
assert_equal custom, merged.around_request
|
||||
end
|
||||
|
||||
test "merge preserves around_request from self when other not set" do
|
||||
custom = ->(_data, &request_handler) { request_handler.call }
|
||||
config1 = Configuration.new(around_request: custom)
|
||||
config2 = Configuration.new
|
||||
merged = config1.merge(config2)
|
||||
assert_equal custom, merged.around_request
|
||||
end
|
||||
|
||||
test "raises ArgumentError when protocol_version is not a supported value" do
|
||||
exception = assert_raises(ArgumentError) do
|
||||
Configuration.new(protocol_version: "1999-12-31")
|
||||
|
|
|
|||
Loading…
Reference in a new issue