Skip to content
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 the Stripe object name to instrumentation event payloads #1168

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ The library has various hooks that user code can tie into by passing a block to
Invoked when an HTTP request starts. Receives `RequestBeginEvent` with the
following properties:

- `object_name`: The Stripe object, if applicable. (`String`)
- `method`: HTTP method. (`Symbol`)
- `path`: Request path. (`String`)
- `user_data`: A hash on which users can set arbitrary data, and which will be
Expand All @@ -245,6 +246,7 @@ following properties:
Invoked when an HTTP request finishes, regardless of whether it terminated with
a success or error. Receives `RequestEndEvent` with the following properties:

- `object_name`: The Stripe object, if applicable. (`String`)
- `duration`: Request duration in seconds. (`Float`)
- `http_status`: HTTP response code (`Integer`) if available, or `nil` in case
of a lower level network error.
Expand All @@ -270,6 +272,7 @@ Stripe::Instrumentation.subscribe(:request_end) do |request_event|
resource = path_parts.map { |part| part.match?(/\A[a-z_]+\z/) ? part : ":id" }.join("/")

tags = {
object_name: request_event.object_name,
method: request_event.method,
resource: resource,
code: request_event.http_status,
Expand Down
3 changes: 3 additions & 0 deletions lib/stripe/api_operations/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def execute_resource_request_stream(method, url,

opts[:client] ||= StripeClient.active_client

object_name = self::OBJECT_NAME if defined?(self::OBJECT_NAME)

headers = opts.clone
api_key = headers.delete(:api_key)
api_base = headers.delete(:api_base)
Expand All @@ -52,6 +54,7 @@ def execute_resource_request_stream(method, url,
resp, opts[:api_key] = client.send(
client_request_method_sym,
method, url,
object_name: object_name,
api_base: api_base, api_key: api_key,
headers: headers, params: params,
&read_body_chunk_block
Expand Down
8 changes: 7 additions & 1 deletion lib/stripe/instrumentation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Stripe
class Instrumentation
# Event emitted on `request_begin` callback.
class RequestBeginEvent
attr_reader :object_name
attr_reader :method
attr_reader :path

Expand All @@ -17,7 +18,8 @@ class RequestBeginEvent
# set by other subscribers.
attr_reader :user_data

def initialize(method:, path:, user_data:)
def initialize(object_name:, method:, path:, user_data:)
@object_name = object_name
@method = method
@path = path
@user_data = user_data
Expand All @@ -27,6 +29,7 @@ def initialize(method:, path:, user_data:)

# Event emitted on `request_end` callback.
class RequestEndEvent
attr_reader :object_name
attr_reader :duration
attr_reader :http_status
attr_reader :method
Expand All @@ -46,6 +49,7 @@ class RequestEndEvent

def initialize(request_context:, response_context:,
num_retries:, user_data: nil)
@object_name = request_context.object_name
@duration = request_context.duration
@http_status = response_context.http_status
@method = request_context.method
Expand All @@ -62,6 +66,7 @@ def initialize(request_context:, response_context:,
end

class RequestContext
attr_reader :object_name
attr_reader :duration
attr_reader :method
attr_reader :path
Expand All @@ -70,6 +75,7 @@ class RequestContext
attr_reader :header

def initialize(duration:, context:, header:)
@object_name = context.object_name
@duration = duration
@method = context.method
@path = context.path
Expand Down
21 changes: 16 additions & 5 deletions lib/stripe/stripe_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,10 @@ def request
end

def execute_request(method, path,
object_name: nil,
api_base: nil, api_key: nil, headers: {}, params: {})
http_resp, api_key = execute_request_internal(
method, path, api_base, api_key, headers, params
method, path, object_name, api_base, api_key, headers, params
)

begin
Expand Down Expand Up @@ -242,7 +243,8 @@ def execute_request(method, path,
# block is expected to do all the necessary body processing. If no block is
# passed, then a StripeStreamResponse is returned containing an IO stream
# with the response body.
def execute_request_stream(method, path,
def execute_request_stream(method, path, # rubocop:disable Metrics/ParameterLists
object_name: nil,
api_base: nil, api_key: nil,
headers: {}, params: {},
&read_body_chunk_block)
Expand All @@ -252,7 +254,11 @@ def execute_request_stream(method, path,
end

http_resp, api_key = execute_request_internal(
method, path, api_base, api_key, headers, params, &read_body_chunk_block
method, path,
object_name,
api_base, api_key,
headers, params,
&read_body_chunk_block
)

# When the read_body_chunk_block is given, we no longer have access to the
Expand Down Expand Up @@ -430,8 +436,10 @@ def self.maybe_gc_connection_managers
pruned_contexts.count
end

private def execute_request_internal(method, path,
api_base, api_key, headers, params,
private def execute_request_internal(method, path, # rubocop:disable Metrics/ParameterLists
object_name,
api_base, api_key,
headers, params,
&read_body_chunk_block)
raise ArgumentError, "method should be a symbol" \
unless method.is_a?(Symbol)
Expand Down Expand Up @@ -477,6 +485,7 @@ def self.maybe_gc_connection_managers
context.api_version = headers["Stripe-Version"]
context.body = body_log
context.idempotency_key = headers["Idempotency-Key"]
context.object_name = object_name
context.method = method
context.path = path
context.query = query
Expand Down Expand Up @@ -646,6 +655,7 @@ def self.maybe_gc_connection_managers
return unless Instrumentation.any_subscribers?(:request_begin)

event = Instrumentation::RequestBeginEvent.new(
object_name: context.object_name,
method: context.method,
path: context.path,
user_data: {}
Expand Down Expand Up @@ -963,6 +973,7 @@ def self.maybe_gc_connection_managers
# that we can log certain information. It's useful because it means that we
# don't have to pass around as many parameters.
class RequestLogContext
attr_accessor :object_name
attr_accessor :body
attr_accessor :account
attr_accessor :api_key
Expand Down
2 changes: 2 additions & 0 deletions test/stripe/instrumentation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class InstrumentationTest < Test::Unit::TestCase
context "RequestEventBegin" do
should "return a frozen object" do
event = Stripe::Instrumentation::RequestBeginEvent.new(
object_name: "customer",
method: :get,
path: "/v1/test",
user_data: nil
Expand All @@ -59,6 +60,7 @@ class InstrumentationTest < Test::Unit::TestCase
context "RequestEventEnd" do
should "return a frozen object" do
mock_context = stub(
object_name: "customer",
duration: 0.1,
method: :get,
path: "/v1/test",
Expand Down
Loading