Module: ScoutApm::Instruments::GraphQLExecuteFieldGuard

Defined in:
lib/scout_apm/instruments/graphql.rb

Overview

Prepended onto GraphQL::Tracing::ScoutTrace to guarantee that every Scout layer opened during a GraphQL multiplex is closed before control returns to the Scout Rack middleware.

graphql-ruby's interpreter calls begin_execute_field / end_execute_field around each field resolver. When an unhandled exception causes end_execute_field to be skipped (runtime.rb lines 465-479), the corresponding ScoutApm::Layer is never popped from TrackedRequest#@layers. finalized? never returns true, record! is never called, and Thread.current accumulates every subsequent request's layers without bound.

This guard snapshots the open layer count before executing the multiplex and pops any excess layers in an ensure block, independent of whichever internal trace hooks graphql-ruby happens to use. It has no dependency on MonitorTrace's field-tracing condition or event slot architecture, so it remains correct even if those internals change.

Instance Method Summary collapse

Instance Method Details

#execute_multiplex(multiplex:) ⇒ Object



48
49
50
51
52
53
54
55
# File 'lib/scout_apm/instruments/graphql.rb', line 48

def execute_multiplex(multiplex:)
  req = ScoutApm::RequestManager.lookup
  layers_before = req.layer_count
  super
ensure
  extra = req.layer_count - layers_before
  extra.times { req.stop_layer } if extra > 0
end